OpenWalnut  1.4.0
WTensorSym_test.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_TEST_H
00026 #define WTENSORSYM_TEST_H
00027 
00028 #include <string>
00029 #include <vector>
00030 #include <algorithm>
00031 
00032 #include <cxxtest/TestSuite.h>
00033 #include "../WTensorSym.h"
00034 
00035 /**
00036  * Test class for the WTensorSym template.
00037  */
00038 class WTensorSymTest : public CxxTest::TestSuite
00039 {
00040 public:
00041     /**
00042      * Test access operator ().
00043      */
00044     void testAccessOperator1()
00045     {
00046         WTensorSym< 3, 2 > w;
00047         w( 0, 0, 0 ) = 2;
00048         w( 0, 0, 1 ) = 3;
00049         w( 0, 1, 0 ) = 0;
00050         w( 0, 1, 1 ) = 5;
00051         w( 1, 0, 0 ) = 2;
00052         w( 1, 0, 1 ) = 1;
00053         w( 1, 1, 0 ) = 8;
00054         w( 1, 1, 1 ) = 10;
00055 
00056         TS_ASSERT_EQUALS( w( 0, 0, 0 ), 2 );
00057         TS_ASSERT_EQUALS( w( 0, 0, 1 ), 2 );
00058         TS_ASSERT_EQUALS( w( 0, 1, 0 ), 2 );
00059         TS_ASSERT_EQUALS( w( 0, 1, 1 ), 8 );
00060         TS_ASSERT_EQUALS( w( 1, 0, 0 ), 2 );
00061         TS_ASSERT_EQUALS( w( 1, 0, 1 ), 8 );
00062         TS_ASSERT_EQUALS( w( 1, 1, 0 ), 8 );
00063         TS_ASSERT_EQUALS( w( 1, 1, 1 ), 10 );
00064 
00065         // test a symmetric tensor of dimension 1
00066         // this should not segfault
00067         WTensorSym< 4, 1 > t;
00068 
00069         t( 0, 0, 0, 0 ) = 2.0;
00070 
00071         TS_ASSERT_EQUALS( t( 0, 0, 0, 0 ), 2.0 );
00072     }
00073 
00074     /**
00075      * Test access operator [].
00076      */
00077     void testAccessOperator2()
00078     {
00079         std::vector< unsigned int > v( 3, 0 );
00080         WTensorSym< 3, 4 > w;
00081 
00082         for( v[ 0 ] = 0; v[ 0 ] < 4; ++v[ 0 ] )
00083         {
00084             for( v[ 1 ] = 0; v[ 1 ] < 4; ++v[ 1 ] )
00085             {
00086                 for( v[ 2 ] = 0; v[ 2 ] < 4; ++v[ 2 ] )
00087                 {
00088                     w[ v ] = v[ 0 ] + v[ 1 ] + v[ 2 ];
00089                     std::vector< unsigned int > v0 = v;
00090                     std::sort( v0.begin(), v0.end() );
00091                     TS_ASSERT_EQUALS( w[ v0 ], v[ 0 ] + v[ 1 ] + v[ 2 ] );
00092                 }
00093             }
00094         }
00095     }
00096 
00097     /**
00098      * Test the standard constructor.
00099      */
00100     void testStandardConstructor()
00101     {
00102         // create lots of tensors
00103         WTensorSym< 1, 1 > t11d;
00104         WTensorSym< 1, 2 > t12d;
00105         WTensorSym< 1, 3 > t13d;
00106         WTensorSym< 1, 4 > t14d;
00107         WTensorSym< 1, 1, float > t11f;
00108         WTensorSym< 1, 2, int > t12i;
00109         WTensorSym< 1, 3, char > t13c;
00110         WTensorSym< 1, 4, std::string > t14s;
00111         WTensorSym< 2, 1 > t21d;
00112         WTensorSym< 2, 2 > t22d;
00113         WTensorSym< 2, 3 > t23d;
00114         WTensorSym< 2, 4 > t24d;
00115         WTensorSym< 2, 1, int > t21i;
00116         WTensorSym< 2, 2, char > t22c;
00117         WTensorSym< 2, 3, float > t23f;
00118         WTensorSym< 2, 4, float > t24f;
00119         WTensorSym< 3, 5 > t35d;
00120         WTensorSym< 4, 3 > t43d;
00121         WTensorSym< 5, 2 > t52d;
00122         WTensorSym< 6, 3 > t63d;
00123 
00124         TS_ASSERT_EQUALS( t35d( 0, 4, 2 ), 0.0 );
00125         TS_ASSERT_EQUALS( t35d( 1, 4, 0 ), 0.0 );
00126         TS_ASSERT_EQUALS( t35d( 0, 3, 0 ), 0.0 );
00127         TS_ASSERT_EQUALS( t35d( 2, 4, 1 ), 0.0 );
00128         TS_ASSERT_EQUALS( t35d( 0, 2, 2 ), 0.0 );
00129         TS_ASSERT_EQUALS( t35d( 4, 1, 4 ), 0.0 );
00130         TS_ASSERT_EQUALS( t35d( 4, 4, 4 ), 0.0 );
00131         TS_ASSERT_EQUALS( t35d( 3, 4, 3 ), 0.0 );
00132 
00133         TS_ASSERT_EQUALS( t11d( 0 ), 0.0 );
00134         TS_ASSERT_EQUALS( t22d( 0, 1 ), 0.0 );
00135     }
00136 
00137     /**
00138      * Test copy constructor.
00139      */
00140     void testCopyConstructor()
00141     {
00142         WTensorSym< 2, 3 > w;
00143         w( 0, 1 ) = 2;
00144         w( 2, 1 ) = 0.456;
00145 
00146         WTensorSym< 2, 3 > m( w );
00147         TS_ASSERT_EQUALS( m( 1, 0 ), 2 );
00148         TS_ASSERT_EQUALS( m( 1, 2 ), 0.456 );
00149     }
00150 
00151     /**
00152      * Test copy operator.
00153      */
00154     void testCopyOperator()
00155     {
00156         WTensorSym< 6, 2 > w;
00157         w( 0, 0, 1, 1, 0, 1 ) = 4.0;
00158         w( 1, 1, 0, 0, 0, 0 ) = 0.56;
00159         WTensorSym< 6, 2 > m;
00160 
00161         {
00162             m = w;
00163             TS_ASSERT_EQUALS( m( 0, 1, 0, 1, 0, 1 ), 4.0 );
00164             TS_ASSERT_EQUALS( m( 1, 0, 0, 0, 1, 0 ), 0.56 );
00165             TS_ASSERT_EQUALS( m( 0, 0, 0, 1, 0, 0 ), 0.0 );
00166         }
00167     }
00168 
00169     /**
00170      * Test casts to Data_T, WValue or WMatrix, depending on the order of the Tensor.
00171      */
00172     void testCastToVariousTypes()
00173     {
00174         // make sure these casts compile
00175         // we don't actually want to thoroughly test functionality here
00176         // more sophisticated tests can be found in WTensorFuncTest
00177         // cast to Data_T
00178         {
00179             WTensorSym< 0, 0, double > t;
00180             t() = 3.0;
00181             double d = t;
00182             TS_ASSERT_EQUALS( d, 3.0 );
00183         }
00184         // cast to WValue
00185         {
00186             WTensorSym< 1, 2, int > t;
00187             t( 0 ) = 3.0;
00188             WValue< int > v = t;
00189             TS_ASSERT_EQUALS( v[ 0 ], 3.0 );
00190         }
00191         // cast to WMatrix
00192         {
00193             WTensorSym< 2, 3, float > t;
00194             t( 0, 1 ) = 3.0;
00195             WMatrix< float > m = t;
00196             TS_ASSERT_EQUALS( m( 1, 0 ), 3.0 );
00197         }
00198     }
00199 
00200     /**
00201      * The optimizations for symmetric tensors should not corrupt the result, so we
00202      * compare the optimized evaluation function to a simple implementaion.
00203      */
00204     void testEvaluateSphericalFunction()
00205     {
00206         WTensorSym< 4, 3, double > t;
00207         // the tensor
00208         t( 0, 0, 0, 0 ) = 2.5476;
00209         t( 1, 1, 1, 1 ) = 3.5476;
00210         t( 2, 2, 2, 2 ) = 4.5476;
00211         t( 0, 0, 0, 1 ) = 5.5476;
00212         t( 0, 0, 0, 2 ) = 6.5476;
00213         t( 1, 1, 1, 0 ) = 7.5476;
00214         t( 1, 1, 1, 2 ) = 8.5476;
00215         t( 2, 2, 2, 0 ) = 9.5476;
00216         t( 2, 2, 2, 1 ) = 10.5476;
00217         t( 0, 0, 1, 2 ) = 11.5476;
00218         t( 1, 1, 0, 2 ) = 12.5476;
00219         t( 2, 2, 0, 1 ) = 13.5476;
00220         t( 0, 0, 1, 1 ) = 14.5476;
00221         t( 0, 0, 2, 2 ) = 15.5476;
00222         t( 1, 1, 2, 2 ) = 16.5476;
00223 
00224         // the gradients
00225         std::vector< WVector3d > gradients;
00226         gradients.push_back( WVector3d( 1.0, 0.0, 0.0 ) );
00227         gradients.push_back( WVector3d( 0.0, 1.0, 0.0 ) );
00228         gradients.push_back( normalize( WVector3d( 1.0, 1.0, 0.0 ) ) );
00229         gradients.push_back( normalize( WVector3d( 0.3, 0.4, 0.5 ) ) );
00230         gradients.push_back( normalize( WVector3d( -7.0, 3.0, -1.0 ) ) );
00231 
00232         for( int k = 0; k < 5; ++k )
00233         {
00234             double res = calcTens( t, gradients[ k ] );
00235             TS_ASSERT_DELTA( res, t.evaluateSphericalFunction( gradients[ k ] ), 0.001 );
00236         }
00237     }
00238 
00239 private:
00240     /**
00241      * A helper function that implements the simple approach to tensor evaluation.
00242      *
00243      * \param t The tensor.
00244      * \param v The gradient.
00245      *
00246      * \return The value of the spherical function in the direction of the gradient.
00247      */
00248     double calcTens( WTensorSym< 4, 3, double > const& t, WVector3d const& v )
00249     {
00250         double res = 0.0;
00251         for( int a = 0; a < 3; ++a )
00252         {
00253             for( int b = 0; b < 3; ++b )
00254             {
00255                 for( int c = 0; c < 3; ++c )
00256                 {
00257                     for( int d = 0; d < 3; ++d )
00258                     {
00259                         res += v[ a ] * v[ b ] * v[ c ] * v[ d ] * t( a, b, c, d );
00260                     }
00261                 }
00262             }
00263         }
00264         return res;
00265     }
00266 };
00267 
00268 #endif  // WTENSORSYM_TEST_H