OpenWalnut  1.5.0dev
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 #include <boost/array.hpp>
31 
32 #include "WTensorMeta.h"
33 #include "WTensorBase.h"
34 
35 // ############################# class WTensorSym<> #############################################
36 
37 /**
38  * Implements a symmetric tensor that has the same number of components in every
39  * direction. A symmetric tensor has the same value for every permutation of the indices.
40  *
41  * 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)
42  * = t(j,k,i) = t(k,i,j) = t(k,j,i) for a tensor of order 3.
43  *
44  * \tparam order The order of the tensor.
45  * \tparam dim The dimension of the tensor, i.e. the number of components
46  * in each direction.
47  * \tparam Data_T The datatype of the components, double by default.
48  *
49  * \note The dimension may never be 0.
50  * \note The type Data_T may not throw exceptions on construction, destruction or
51  * during any assignment operator.
52  *
53  * Access to specific elements of the tensor can be achieved in 2 ways:
54  *
55  * - operator (), whose number of parameters matches the template parameter order.
56  * - operator [], whose parameter is either an array or a std::vector of appropriate size.
57  *
58  * \note The datatype of the array or std::vector can be any type castable to std::size_t.
59  * \note There is no bounds checking for the array version of operator [].
60  * \note Operator () is not supported for orders larger than 6.
61  *
62  * This class optimizes memory usage. For example, for a symmetric tensor of order 2 and
63  * dimension 3, only 6 values (instead of 9) need to be stored. However, there is additional
64  * memory overhead per class (i.e. per allocation of the template parameters), which is of
65  * constant size and thus does not depend on the number of instances.
66  *
67  * Usage and operators are the same as with WTensor. Note that changes to an
68  * element t(i,j,k,...) also change every element whose indices are a permutation of i,j,k... .
69  * \see WTensor
70  */
71 template< std::size_t order, std::size_t dim, typename Data_T = double >
72 class WTensorSym : public WTensorFunc< WTensorBaseSym, order, dim, Data_T >
73 {
74 public:
75  /**
76  * Default constructor of the symmetric tensor.
77  */
79 
80  /**
81  * Constructs and initializes the symmetrical Tensor with a WValue.
82  *
83  * \note The same ordering as for the data member is required.
84  *
85  * \param data The components in same ordering as for the data member \c m_data is required, (\see m_data).
86  */
87  explicit WTensorSym( const WValue< Data_T >& data );
88 
89  /**
90  * Constructs and initializes the symmetrical Tensor with a boost array.
91  *
92  * \note The same ordering as for the data member is required.
93  *
94  * \param data The components in same ordering as for the data member \c m_data is required, (\see m_data).
95  */
96  explicit WTensorSym( const boost::array< Data_T, WTensorBaseSym< order, dim, Data_T >::dataSize >& data );
97 
98  /**
99  * Evaluate - for a given gradient - the spherical function represented by this symmetric tensor.
100  *
101  * \tparam The type that stores the gradient, must implement operator [].
102  *
103  * \param gradient The normalized vector that represents the gradient direction.
104  *
105  * \note If the gradient is not normalized, the result is undefined.
106  *
107  * Thanks to CHeine for the idea for this algorithm.
108  *
109  * \return The function value on the sphere for this tensor and the given gradient.
110  */
111  Data_T evaluateSphericalFunction( WValue< Data_T > const& gradient ) const;
112 
113  /**
114  * Evaluate - for a given gradient - the spherical function represented by this symmetric tensor.
115  *
116  * \tparam The type that stores the gradient, must implement operator [].
117  *
118  * \param gradient The normalized vector that represents the gradient direction.
119  *
120  * \note If the gradient is not normalized, the result is undefined.
121  *
122  * Thanks to CHeine for the idea for this algorithm.
123  *
124  * \return The function value on the sphere for this tensor and the given gradient.
125  */
127 
128 protected:
129 private:
130  using WTensorFunc< WTensorBaseSym, order, dim, Data_T >::m_data;
131 };
132 
133 template< std::size_t order, std::size_t dim, typename Data_T >
135  : WTensorFunc< WTensorBaseSym, order, dim, Data_T >()
136 {
137 }
138 
139 template< std::size_t order, std::size_t dim, typename Data_T >
141  : WTensorFunc< WTensorBaseSym, order, dim, Data_T >( data )
142 {
143 }
144 
145 template< std::size_t order, std::size_t dim, typename Data_T >
146 WTensorSym< order, dim, Data_T >::WTensorSym( const boost::array< Data_T, WTensorBaseSym< order, dim, Data_T >::dataSize >& data )
147  : WTensorFunc< WTensorBaseSym, order, dim, Data_T >( data )
148 {
149 }
150 
151 template< std::size_t order, std::size_t dim, typename Data_T >
153 {
154  Data_T const* tens = &m_data[ 0 ];
155  Data_T const* grad = &gradient[ 0 ];
157 }
158 
159 template< std::size_t order, std::size_t dim, typename Data_T >
161 {
162  Data_T const* tens = &m_data[ 0 ];
163  Data_T const* grad = &gradient[ 0 ];
165 }
166 
167 // ######################## stream output operators #################################
168 
169 /**
170  * Write a symmetric tensor of order 0 to an output stream.
171  *
172  * \param o An output stream.
173  * \param t A WTensorSym.
174  *
175  * \return The output stream.
176  */
177 template< std::size_t dim, typename Data_T >
178 std::ostream& operator << ( std::ostream& o, WTensorSym< 0, dim, Data_T > const& t )
179 {
180  o << t() << std::endl;
181  return o;
182 }
183 
184 /**
185  * Write a symmetric tensor of order 1 to an output stream.
186  *
187  * \param o An output stream.
188  * \param t A WTensorSym.
189  *
190  * \return The output stream.
191  */
192 template< std::size_t dim, typename Data_T >
193 std::ostream& operator << ( std::ostream& o, WTensorSym< 1, dim, Data_T > const& t )
194 {
195  for( std::size_t k = 0; k < dim; ++k )
196  {
197  o << t( k ) << " ";
198  }
199  o << std::endl;
200  return o;
201 }
202 
203 /**
204  * Write a symmetric tensor of order 2 to an output stream.
205  *
206  * \param o An output stream.
207  * \param t A WTensorSym.
208  *
209  * \return The output stream.
210  */
211 template< std::size_t dim, typename Data_T >
212 std::ostream& operator << ( std::ostream& o, WTensorSym< 2, dim, Data_T > const& t )
213 {
214  for( std::size_t k = 0; k < dim; ++k )
215  {
216  for( std::size_t l = 0; l < dim; ++l )
217  {
218  o << t( k, l ) << " ";
219  }
220  o << std::endl;
221  }
222  return o;
223 }
224 // ######################## a utility function #################################
225 
226 /**
227  * This calculates the multiplicity of the elements of a 3-dimensional
228  * symmetric tensor. (see Özarslan's paper from 2003)
229  * In a (super-)symmetric tensor, all permutations of a given set of Indices
230  * i_1, i_2, ... i_order ( i_j in 0,1,2 ) refer to the same data element.
231  * This means each data element can be identified by the amount of 0's, 1's
232  * and 2's in its index list. Permutations do not change these amounts, thus
233  * different data elements must differ in amount of 0's, 1's and 2's. The number of
234  * permutations that exist on the index list of a data element is its multiplicity.
235  *
236  * \param order The order of the tensor.
237  * \param numZeros How many elements of the permutation equal 0.
238  * \param numOnes How many elements of the permutation equal 1.
239  * \param numTwos How many elements of the permutation equal 2.
240  */
241 std::size_t calcSupersymmetricTensorMultiplicity( std::size_t order, std::size_t numZeros, std::size_t numOnes, std::size_t numTwos );
242 
243 #endif // WTENSORSYM_H
A fixed size matrix class.
Definition: WMatrixFixed.h:150
Implements a symmetric tensor that has the same number of components in every direction.
Definition: WTensorSym.h:73
WTensorSym()
Default constructor of the symmetric tensor.
Definition: WTensorSym.h:134
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:152
Data_T evaluateSphericalFunction(WMatrixFixed< Data_T, 3, 1 > const &gradient) const
Evaluate - for a given gradient - the spherical function represented by this symmetric tensor.
Definition: WTensorSym.h:160
WTensorSym(const WValue< Data_T > &data)
Constructs and initializes the symmetrical Tensor with a WValue.
Definition: WTensorSym.h:140
WTensorSym(const boost::array< Data_T, WTensorBaseSym< order, dim, Data_T >::dataSize > &data)
Constructs and initializes the symmetrical Tensor with a boost array.
Definition: WTensorSym.h:146
Base class for all higher level values like tensors, vectors, matrices and so on.
Definition: WValue.h:41
Implements compile-time evaluation of factorials.
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:94