OpenWalnut 1.2.5

WTensorSym.h

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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends