OpenWalnut  1.4.0
WTensorSym.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WTENSORSYM_H
26 #define WTENSORSYM_H
27 
28 #include <iostream>
29 
30 #ifndef Q_MOC_RUN
31 #include <boost/array.hpp>
32 #endif
33 
34 #include "WTensorMeta.h"
35 #include "WTensorBase.h"
36 
37 // ############################# class WTensorSym<> #############################################
38 
39 /**
40  * Implements a symmetric tensor that has the same number of components in every
41  * direction. A symmetric tensor has the same value for every permutation of the indices.
42  *
43  * For example, t(i,j) = t(j,i) for a tensor of order 2, and t(i,j,k) = t(j,i,k) = t(i,k,j)
44  * = t(j,k,i) = t(k,i,j) = t(k,j,i) for a tensor of order 3.
45  *
46  * \tparam order The order of the tensor.
47  * \tparam dim The dimension of the tensor, i.e. the number of components
48  * in each direction.
49  * \tparam Data_T The datatype of the components, double by default.
50  *
51  * \note The dimension may never be 0.
52  * \note The type Data_T may not throw exceptions on construction, destruction or
53  * during any assignment operator.
54  *
55  * Access to specific elements of the tensor can be achieved in 2 ways:
56  *
57  * - operator (), whose number of parameters matches the template parameter order.
58  * - operator [], whose parameter is either an array or a std::vector of appropriate size.
59  *
60  * \note The datatype of the array or std::vector can be any type castable to std::size_t.
61  * \note There is no bounds checking for the array version of operator [].
62  * \note Operator () is not supported for orders larger than 6.
63  *
64  * This class optimizes memory usage. For example, for a symmetric tensor of order 2 and
65  * dimension 3, only 6 values (instead of 9) need to be stored. However, there is additional
66  * memory overhead per class (i.e. per allocation of the template parameters), which is of
67  * constant size and thus does not depend on the number of instances.
68  *
69  * Usage and operators are the same as with WTensor. Note that changes to an
70  * element t(i,j,k,...) also change every element whose indices are a permutation of i,j,k... .
71  * \see WTensor
72  */
73 template< std::size_t order, std::size_t dim, typename Data_T = double >
74 class WTensorSym : public WTensorFunc< WTensorBaseSym, order, dim, Data_T >
75 {
76 public:
77  /**
78  * Default constructor of the symmetric tensor.
79  */
80  WTensorSym();
81 
82  /**
83  * Constructs and initializes the symmetrical Tensor with a WValue.
84  *
85  * \note The same ordering as for the data member is required.
86  *
87  * \param data The components in same ordering as for the data member \c m_data is required, (\see m_data).
88  */
89  explicit WTensorSym( const WValue< Data_T >& data );
90 
91  /**
92  * Constructs and initializes the symmetrical Tensor with a boost array.
93  *
94  * \note The same ordering as for the data member is required.
95  *
96  * \param data The components in same ordering as for the data member \c m_data is required, (\see m_data).
97  */
98  explicit WTensorSym( const boost::array< Data_T, WTensorBaseSym< order, dim, Data_T >::dataSize >& data );
99 
100  /**
101  * Evaluate - for a given gradient - the spherical function represented by this symmetric tensor.
102  *
103  * \tparam The type that stores the gradient, must implement operator [].
104  *
105  * \param gradient The normalized vector that represents the gradient direction.
106  *
107  * \note If the gradient is not normalized, the result is undefined.
108  *
109  * Thanks to CHeine for the idea for this algorithm.
110  *
111  * \return The function value on the sphere for this tensor and the given gradient.
112  */
113  Data_T evaluateSphericalFunction( WValue< Data_T > const& gradient ) const;
114 
115  /**
116  * Evaluate - for a given gradient - the spherical function represented by this symmetric tensor.
117  *
118  * \tparam The type that stores the gradient, must implement operator [].
119  *
120  * \param gradient The normalized vector that represents the gradient direction.
121  *
122  * \note If the gradient is not normalized, the result is undefined.
123  *
124  * Thanks to CHeine for the idea for this algorithm.
125  *
126  * \return The function value on the sphere for this tensor and the given gradient.
127  */
128  Data_T evaluateSphericalFunction( WMatrixFixed< Data_T, 3, 1 > const& gradient ) const;
129 
130 protected:
131 private:
133 };
134 
135 template< std::size_t order, std::size_t dim, typename Data_T >
137  : WTensorFunc< WTensorBaseSym, order, dim, Data_T >()
138 {
139 }
140 
141 template< std::size_t order, std::size_t dim, typename Data_T >
143  : WTensorFunc< WTensorBaseSym, order, dim, Data_T >( data )
144 {
145 }
146 
147 template< std::size_t order, std::size_t dim, typename Data_T >
149  : WTensorFunc< WTensorBaseSym, order, dim, Data_T >( data )
150 {
151 }
152 
153 template< std::size_t order, std::size_t dim, typename Data_T >
155 {
156  Data_T const* tens = &m_data[ 0 ];
157  Data_T const* grad = &gradient[ 0 ];
159 }
160 
161 template< std::size_t order, std::size_t dim, typename Data_T >
163 {
164  Data_T const* tens = &m_data[ 0 ];
165  Data_T const* grad = &gradient[ 0 ];
167 }
168 
169 // ######################## stream output operators #################################
170 
171 /**
172  * Write a symmetric tensor of order 0 to an output stream.
173  *
174  * \param o An output stream.
175  * \param t A WTensorSym.
176  *
177  * \return The output stream.
178  */
179 template< std::size_t dim, typename Data_T >
180 std::ostream& operator << ( std::ostream& o, WTensorSym< 0, dim, Data_T > const& t )
181 {
182  o << t() << std::endl;
183  return o;
184 }
185 
186 /**
187  * Write a symmetric tensor of order 1 to an output stream.
188  *
189  * \param o An output stream.
190  * \param t A WTensorSym.
191  *
192  * \return The output stream.
193  */
194 template< std::size_t dim, typename Data_T >
195 std::ostream& operator << ( std::ostream& o, WTensorSym< 1, dim, Data_T > const& t )
196 {
197  for( std::size_t k = 0; k < dim; ++k )
198  {
199  o << t( k ) << " ";
200  }
201  o << std::endl;
202  return o;
203 }
204 
205 /**
206  * Write a symmetric tensor of order 2 to an output stream.
207  *
208  * \param o An output stream.
209  * \param t A WTensorSym.
210  *
211  * \return The output stream.
212  */
213 template< std::size_t dim, typename Data_T >
214 std::ostream& operator << ( std::ostream& o, WTensorSym< 2, dim, Data_T > const& t )
215 {
216  for( std::size_t k = 0; k < dim; ++k )
217  {
218  for( std::size_t l = 0; l < dim; ++l )
219  {
220  o << t( k, l ) << " ";
221  }
222  o << std::endl;
223  }
224  return o;
225 }
226 // ######################## a utility function #################################
227 
228 /**
229  * This calculates the multiplicity of the elements of a 3-dimensional
230  * symmetric tensor. (see Özarslan's paper from 2003)
231  * In a (super-)symmetric tensor, all permutations of a given set of Indices
232  * i_1, i_2, ... i_order ( i_j in 0,1,2 ) refer to the same data element.
233  * This means each data element can be identified by the amount of 0's, 1's
234  * and 2's in its index list. Permutations do not change these amounts, thus
235  * different data elements must differ in amount of 0's, 1's and 2's. The number of
236  * permutations that exist on the index list of a data element is its multiplicity.
237  *
238  * \param order The order of the tensor.
239  * \param numZeros How many elements of the permutation equal 0.
240  * \param numOnes How many elements of the permutation equal 1.
241  * \param numTwos How many elements of the permutation equal 2.
242  */
243 std::size_t calcSupersymmetricTensorMultiplicity( std::size_t order, std::size_t numZeros, std::size_t numOnes, std::size_t numTwos );
244 
245 #endif // WTENSORSYM_H
Implements a symmetric tensor that has the same number of components in every direction.
Definition: WTensorSym.h:74
Base class for all higher level values like tensors, vectors, matrices and so on. ...
Definition: WValue.h:40
Symmetric tensor base class.
Definition: WTensorBase.h:53
Implements compile-time evaluation of factorials.
A fixed size matrix class.
Definition: WMatrixFixed.h:153
Implements functions that should only be defined for certain values of order.
Definition: WTensorBase.h:1187
static Data_T evaluate(Data_T const *&tens, Data_T const *grad, Data_T w)
Multiply gradient components and divide by multiplicities.
Definition: WTensorMeta.h:96
WTensorSym()
Default constructor of the symmetric tensor.
Definition: WTensorSym.h:136
Data_T evaluateSphericalFunction(WValue< Data_T > const &gradient) const
Evaluate - for a given gradient - the spherical function represented by this symmetric tensor...
Definition: WTensorSym.h:154