00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #ifndef WTENSORSYM_H 00026 #define WTENSORSYM_H 00027 00028 #include <iostream> 00029 #include <vector> 00030 00031 #include "WTensorBase.h" 00032 00033 // ############################# class WTensorSym<> ############################################# 00034 00035 /** 00036 * Implements a symmetric tensor that has the same number of components in every 00037 * direction. A symmetric tensor has the same value for every permutation of the indices. 00038 * 00039 * 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) 00040 * = t(j,k,i) = t(k,i,j) = t(k,j,i) for a tensor of order 3. 00041 * 00042 * \tparam order The order of the tensor. 00043 * \tparam dim The dimension of the tensor, i.e. the number of components 00044 * in each direction. 00045 * \tparam Data_T The datatype of the components, double by default. 00046 * 00047 * \note The dimension may never be 0. 00048 * \note The type Data_T may not throw exceptions on construction, destruction or 00049 * during any assignment operator. 00050 * 00051 * Access to specific elements of the tensor can be achieved in 2 ways: 00052 * 00053 * - operator (), whose number of parameters matches the template parameter order. 00054 * - operator [], whose parameter is either an array or a std::vector of appropriate size. 00055 * 00056 * \note The datatype of the array or std::vector can be any type castable to std::size_t. 00057 * \note There is no bounds checking for the array version of operator []. 00058 * \note Operator () is not supported for orders larger than 6. 00059 * 00060 * This class optimizes memory usage. For example, for a symmetric tensor of order 2 and 00061 * dimension 3, only 6 values (instead of 9) need to be stored. However, there is additional 00062 * memory overhead per class (i.e. per allocation of the template parameters), which is of 00063 * constant size and thus does not depend on the number of instances. 00064 * 00065 * Usage and operators are the same as with WTensor. Note that changes to an 00066 * element t(i,j,k,...) also change every element whose indices are a permutation of i,j,k... . 00067 * \see WTensor 00068 */ 00069 template< std::size_t order, std::size_t dim, typename Data_T = double > 00070 class WTensorSym : public WTensorFunc< WTensorBaseSym, order, dim, Data_T > 00071 { 00072 public: 00073 /** 00074 * Default constructor of the symmetric tensor. 00075 */ 00076 WTensorSym(); 00077 00078 /** 00079 * Constructs and initializes the symmetrical Tensor with a WValue. 00080 * 00081 * \note The same ordering as for the data member is required. 00082 * 00083 * \param data The components in same ordering as for the data member \c m_data is required, (\see m_data). 00084 */ 00085 explicit WTensorSym( const WValue< Data_T >& data ); 00086 00087 protected: 00088 private: 00089 }; 00090 00091 template< std::size_t order, std::size_t dim, typename Data_T > 00092 WTensorSym< order, dim, Data_T >::WTensorSym() 00093 : WTensorFunc< WTensorBaseSym, order, dim, Data_T >() 00094 { 00095 } 00096 00097 template< std::size_t order, std::size_t dim, typename Data_T > 00098 WTensorSym< order, dim, Data_T >::WTensorSym( const WValue< Data_T >& data ) 00099 : WTensorFunc< WTensorBaseSym, order, dim, Data_T >( data ) 00100 { 00101 } 00102 // ######################## stream output operators ################################# 00103 00104 /** 00105 * Write a symmetric tensor of order 0 to an output stream. 00106 * 00107 * \param o An output stream. 00108 * \param t A WTensorSym. 00109 * 00110 * \return The output stream. 00111 */ 00112 template< std::size_t dim, typename Data_T > 00113 std::ostream& operator << ( std::ostream& o, WTensorSym< 0, dim, Data_T > const& t ) 00114 { 00115 o << t() << std::endl; 00116 return o; 00117 } 00118 00119 /** 00120 * Write a symmetric tensor of order 1 to an output stream. 00121 * 00122 * \param o An output stream. 00123 * \param t A WTensorSym. 00124 * 00125 * \return The output stream. 00126 */ 00127 template< std::size_t dim, typename Data_T > 00128 std::ostream& operator << ( std::ostream& o, WTensorSym< 1, dim, Data_T > const& t ) 00129 { 00130 for( std::size_t k = 0; k < dim; ++k ) 00131 { 00132 o << t( k ) << " "; 00133 } 00134 o << std::endl; 00135 return o; 00136 } 00137 00138 /** 00139 * Write a symmetric tensor of order 2 to an output stream. 00140 * 00141 * \param o An output stream. 00142 * \param t A WTensorSym. 00143 * 00144 * \return The output stream. 00145 */ 00146 template< std::size_t dim, typename Data_T > 00147 std::ostream& operator << ( std::ostream& o, WTensorSym< 2, dim, Data_T > const& t ) 00148 { 00149 for( std::size_t k = 0; k < dim; ++k ) 00150 { 00151 for( std::size_t l = 0; l < dim; ++l ) 00152 { 00153 o << t( k, l ) << " "; 00154 } 00155 o << std::endl; 00156 } 00157 return o; 00158 } 00159 // ######################## a utility function ################################# 00160 00161 /** 00162 * This calculates the multiplicity of the elements of a 3-dimensional 00163 * symmetric tensor. (see Özarslan's paper from 2003) 00164 * In a (super-)symmetric tensor, all permutations of a given set of Indices 00165 * i_1, i_2, ... i_order ( i_j in 0,1,2 ) refer to the same data element. 00166 * This means each data element can be identified by the amount of 0's, 1's 00167 * and 2's in its index list. Permutations do not change these amounts, thus 00168 * different data elements must differ in amount of 0's, 1's and 2's. The number of 00169 * permutations that exist on the index list of a data element is its multiplicity. 00170 * 00171 * \param order The order of the tensor. 00172 * \param numZeros How many elements of the permutation equal 0. 00173 * \param numOnes How many elements of the permutation equal 1. 00174 * \param numTwos How many elements of the permutation equal 2. 00175 */ 00176 std::size_t calcSupersymmetricTensorMultiplicity( std::size_t order, std::size_t numZeros, std::size_t numOnes, std::size_t numTwos ); 00177 00178 #endif // WTENSORSYM_H