OpenWalnut
1.4.0
|
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