MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2006 Sandia National Laboratories. Developed at the 00005 University of Wisconsin--Madison under SNL contract number 00006 624796. The U.S. Government and the University of Wisconsin 00007 retian certain rights to this software. 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 (lgpl.txt) along with this library; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 (2010) [email protected] 00024 00025 ***************************************************************** */ 00026 00027 /** \file HexLagrangeShapeTest.cpp 00028 * \brief 00029 * \author Jason Kraftcheck 00030 */ 00031 00032 #include "Mesquite.hpp" 00033 #include "HexLagrangeShape.hpp" 00034 #include "TopologyInfo.hpp" 00035 #include "MsqError.hpp" 00036 #include "IdealElements.hpp" 00037 #include "JacobianCalculator.hpp" 00038 00039 #include "UnitUtil.hpp" 00040 00041 #include <vector> 00042 #include <algorithm> 00043 #include <iostream> 00044 #include <sstream> 00045 00046 using namespace MBMesquite; 00047 using namespace std; 00048 const double epsilon = 1e-6; 00049 #define ASSERT_VALUES_EQUAL( v1, v2, location ) \ 00050 ASSERT_MESSAGE( value_message( ( location ), ( v1 ), ( v2 ) ), test_value( ( v1 ), ( v2 ) ) ) 00051 00052 static bool test_value( double v1, double v2 ) 00053 { 00054 return fabs( v1 - v2 ) < epsilon; 00055 } 00056 00057 static inline CppUnit::Message value_message( unsigned location, double v1, double v2 ) 00058 { 00059 CppUnit::Message m( "equality assertion failed" ); 00060 00061 std::ostringstream buffer1; 00062 buffer1 << "Expected : " << v1; 00063 m.addDetail( buffer1.str() ); 00064 00065 std::ostringstream buffer2; 00066 buffer2 << "Actual : " << v2; 00067 m.addDetail( buffer2.str() ); 00068 00069 std::ostringstream buffer3; 00070 buffer3 << "Location : "; 00071 if( location < 9 ) 00072 buffer3 << "Corner " << location; 00073 else if( location < 20 ) 00074 buffer3 << "Edge " << location - 8; 00075 else if( location < 26 ) 00076 buffer3 << "Face " << location - 20; 00077 else if( location == 26 ) 00078 buffer3 << "Mid-element"; 00079 else 00080 buffer3 << "INVALID!!"; 00081 m.addDetail( buffer3.str() ); 00082 return m; 00083 } 00084 00085 static bool test_value( MsqVector< 3 > v1, MsqVector< 3 > v2 ) 00086 { 00087 return length( v1 - v2 ) < epsilon; 00088 } 00089 00090 static inline CppUnit::Message value_message( unsigned location, MsqVector< 3 > v1, MsqVector< 3 > v2 ) 00091 { 00092 CppUnit::Message m( "equality assertion failed" ); 00093 00094 std::ostringstream buffer1; 00095 buffer1 << "Expected : [" << v1[0] << ", " << v1[1] << ", " << v1[2] << "]"; 00096 m.addDetail( buffer1.str() ); 00097 00098 std::ostringstream buffer2; 00099 buffer2 << "Actual : [" << v2[0] << ", " << v2[1] << ", " << v2[2] << "]"; 00100 m.addDetail( buffer2.str() ); 00101 00102 std::ostringstream buffer3; 00103 buffer3 << "Location : "; 00104 if( location < 9 ) 00105 buffer3 << "Corner " << location; 00106 else if( location < 20 ) 00107 buffer3 << "Edge " << location - 8; 00108 else if( location < 26 ) 00109 buffer3 << "Face " << location - 20; 00110 else if( location == 26 ) 00111 buffer3 << "Mid-element"; 00112 else 00113 buffer3 << "INVALID!!"; 00114 m.addDetail( buffer3.str() ); 00115 return m; 00116 } 00117 00118 class HexLagrangeShapeTest : public CppUnit::TestFixture 00119 { 00120 private: 00121 CPPUNIT_TEST_SUITE( HexLagrangeShapeTest ); 00122 00123 CPPUNIT_TEST( test_corners_coeff ); 00124 CPPUNIT_TEST( test_edges_coeff ); 00125 CPPUNIT_TEST( test_faces_coeff ); 00126 CPPUNIT_TEST( test_mid_coeff ); 00127 00128 CPPUNIT_TEST( test_corners_derivs ); 00129 CPPUNIT_TEST( test_edges_derivs ); 00130 CPPUNIT_TEST( test_faces_derivs ); 00131 CPPUNIT_TEST( test_mid_derivs ); 00132 00133 CPPUNIT_TEST( test_ideal_jacobian ); 00134 00135 CPPUNIT_TEST_SUITE_END(); 00136 00137 HexLagrangeShape sf; 00138 00139 public: 00140 void test_corner_coeff( int corner ); 00141 void test_edge_coeff( int edge ); 00142 void test_face_coeff( int face ); 00143 void test_mid_coeff(); 00144 00145 void test_corner_derivs( int corner ); 00146 void test_edge_derivs( int edge ); 00147 void test_face_derivs( int face ); 00148 void test_mid_derivs(); 00149 00150 NodeSet allNodes; 00151 void setUp() 00152 { 00153 allNodes.set_all_nodes( HEXAHEDRON ); 00154 } 00155 00156 void test_corners_coeff(); 00157 void test_edges_coeff(); 00158 void test_faces_coeff(); 00159 00160 void test_corners_derivs(); 00161 void test_edges_derivs(); 00162 void test_faces_derivs(); 00163 00164 void test_ideal_jacobian(); 00165 }; 00166 00167 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( HexLagrangeShapeTest, "HexLagrangeShapeTest" ); 00168 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( HexLagrangeShapeTest, "Unit" ); 00169 00170 // Indices 00171 enum 00172 { 00173 XI = 0, 00174 ETA = 1, 00175 ZETA = 2 00176 }; 00177 // Parameter range 00178 const double min_xi = 0; 00179 const double max_xi = 1; 00180 const double mid_xi = 0.5 * ( min_xi + max_xi ); 00181 00182 // Some lagrange polynomial terms 00183 static double l21( double xi ) 00184 { 00185 return ( 2 * xi - 1 ) * ( xi - 1 ); 00186 } 00187 static double l22( double xi ) 00188 { 00189 return 4 * xi * ( 1 - xi ); 00190 } 00191 static double l23( double xi ) 00192 { 00193 return xi * ( 2 * xi - 1 ); 00194 } 00195 // First derivatives of lagrange polynomial terms 00196 static double dl21( double xi ) 00197 { 00198 return 4 * xi - 3; 00199 } 00200 static double dl22( double xi ) 00201 { 00202 return 4 - 8 * xi; 00203 } 00204 static double dl23( double xi ) 00205 { 00206 return 4 * xi - 1; 00207 } 00208 // Indexible polynomail terms 00209 typedef double ( *f_t )( double ); 00210 f_t l[4] = { 0, &l21, &l22, &l23 }; 00211 f_t dl[4] = { 0, &dl21, &dl22, &dl23 }; 00212 const int C[][3] = { 00213 { 1, 1, 1 }, // 0 00214 { 3, 1, 1 }, // 1 00215 { 3, 3, 1 }, // 2 00216 { 1, 3, 1 }, // 3 00217 00218 { 1, 1, 3 }, // 4 00219 { 3, 1, 3 }, // 5 00220 { 3, 3, 3 }, // 6 00221 { 1, 3, 3 }, // 7 00222 00223 { 2, 1, 1 }, // 8 00224 { 3, 2, 1 }, // 9 00225 { 2, 3, 1 }, // 10 00226 { 1, 2, 1 }, // 11 00227 00228 { 1, 1, 2 }, // 12 00229 { 3, 1, 2 }, // 13 00230 { 3, 3, 2 }, // 14 00231 { 1, 3, 2 }, // 15 00232 00233 { 2, 1, 3 }, // 16 00234 { 3, 2, 3 }, // 17 00235 { 2, 3, 3 }, // 18 00236 { 1, 2, 3 }, // 19 00237 00238 { 2, 1, 2 }, // 20 00239 { 3, 2, 2 }, // 21 00240 { 2, 3, 2 }, // 22 00241 { 1, 2, 2 }, // 23 00242 00243 { 2, 2, 1 }, // 24 00244 { 2, 2, 3 }, // 25 00245 00246 { 2, 2, 2 } // 26 00247 }; 00248 00249 const double corners[8][3] = { { min_xi, min_xi, min_xi }, { max_xi, min_xi, min_xi }, { max_xi, max_xi, min_xi }, 00250 { min_xi, max_xi, min_xi }, { min_xi, min_xi, max_xi }, { max_xi, min_xi, max_xi }, 00251 { max_xi, max_xi, max_xi }, { min_xi, max_xi, max_xi } }; 00252 00253 static MsqVector< 3 > XI_corner( int i ) 00254 { 00255 return MsqVector< 3 >( corners[i] ); 00256 } 00257 00258 static MsqVector< 3 > XI_edge( int i ) 00259 { 00260 const unsigned* idx = TopologyInfo::edge_vertices( HEXAHEDRON, i ); 00261 return 0.5 * ( XI_corner( idx[0] ) + XI_corner( idx[1] ) ); 00262 } 00263 00264 static MsqVector< 3 > XI_face( int i ) 00265 { 00266 unsigned n; 00267 const unsigned* idx = TopologyInfo::face_vertices( HEXAHEDRON, i, n ); 00268 MsqVector< 3 > result = XI_corner( idx[0] ); 00269 for( unsigned j = 1; j < n; ++j ) 00270 result += XI_corner( idx[j] ); 00271 result *= 1.0 / n; 00272 return result; 00273 } 00274 00275 static MsqVector< 3 > XI_elem() 00276 { 00277 const double vals[] = { mid_xi, mid_xi, mid_xi }; 00278 return MsqVector< 3 >( vals ); 00279 } 00280 00281 static double N( int i, MsqVector< 3 > xi ) 00282 { 00283 const int* c = C[i]; 00284 return l[c[XI]]( xi[XI] ) * l[c[ETA]]( xi[ETA] ) * l[c[ZETA]]( xi[ZETA] ); 00285 } 00286 00287 static MsqVector< 3 > dN( int i, MsqVector< 3 > xi ) 00288 { 00289 MsqVector< 3 > result; 00290 const int* c = C[i]; 00291 result[XI] = dl[c[XI]]( xi[XI] ) * l[c[ETA]]( xi[ETA] ) * l[c[ZETA]]( xi[ZETA] ); 00292 result[ETA] = l[c[XI]]( xi[XI] ) * dl[c[ETA]]( xi[ETA] ) * l[c[ZETA]]( xi[ZETA] ); 00293 result[ZETA] = l[c[XI]]( xi[XI] ) * l[c[ETA]]( xi[ETA] ) * dl[c[ZETA]]( xi[ZETA] ); 00294 return result; 00295 } 00296 00297 static void get_coeffs( MsqVector< 3 > xi, double coeffs_out[27] ) 00298 { 00299 for( int i = 0; i < 27; ++i ) 00300 coeffs_out[i] = N( i, xi ); 00301 } 00302 00303 static void get_derivs( MsqVector< 3 > xi, MsqVector< 3 > derivs_out[27] ) 00304 { 00305 for( int i = 0; i < 27; ++i ) 00306 derivs_out[i] = dN( i, xi ); 00307 } 00308 00309 static void check_valid_indices( const size_t* vertices, size_t num_vtx ) 00310 { 00311 // check valid size of list (at least fout, at most all nodes) 00312 CPPUNIT_ASSERT( num_vtx <= 27 ); 00313 CPPUNIT_ASSERT( num_vtx >= 4 ); 00314 // make sure vertex indices are valid (in [0,26]) 00315 size_t vertcopy[27]; 00316 std::copy( vertices, vertices + num_vtx, vertcopy ); 00317 std::sort( vertcopy, vertcopy + num_vtx ); 00318 CPPUNIT_ASSERT( vertcopy[num_vtx - 1] <= 26 ); // max value less than 27 00319 // make sure there are no duplicates in the list 00320 const size_t* iter = std::unique( vertcopy, vertcopy + num_vtx ); 00321 CPPUNIT_ASSERT( iter == vertcopy + num_vtx ); 00322 } 00323 00324 static void check_no_zeros( const MsqVector< 3 >* derivs, size_t num_vtx ) 00325 { 00326 for( unsigned i = 0; i < num_vtx; ++i ) 00327 { 00328 CPPUNIT_ASSERT( length( derivs[i] ) > 1e-6 ); 00329 } 00330 } 00331 00332 static void compare_coefficients( const double* coeffs, 00333 const size_t* indices, 00334 size_t num_coeff, 00335 const double* expected_coeffs, 00336 unsigned loc ) 00337 { 00338 // find the location in the returned list for each node 00339 size_t revidx[27]; 00340 double test_vals[27]; 00341 for( size_t i = 0; i < 27; ++i ) 00342 { 00343 revidx[i] = std::find( indices, indices + num_coeff, i ) - indices; 00344 test_vals[i] = ( revidx[i] == num_coeff ) ? 0.0 : coeffs[revidx[i]]; 00345 } 00346 00347 // compare expected and actual coefficient values 00348 ASSERT_VALUES_EQUAL( expected_coeffs[0], test_vals[0], loc ); 00349 ASSERT_VALUES_EQUAL( expected_coeffs[1], test_vals[1], loc ); 00350 ASSERT_VALUES_EQUAL( expected_coeffs[2], test_vals[2], loc ); 00351 ASSERT_VALUES_EQUAL( expected_coeffs[3], test_vals[3], loc ); 00352 ASSERT_VALUES_EQUAL( expected_coeffs[4], test_vals[4], loc ); 00353 ASSERT_VALUES_EQUAL( expected_coeffs[5], test_vals[5], loc ); 00354 ASSERT_VALUES_EQUAL( expected_coeffs[6], test_vals[6], loc ); 00355 ASSERT_VALUES_EQUAL( expected_coeffs[7], test_vals[7], loc ); 00356 ASSERT_VALUES_EQUAL( expected_coeffs[8], test_vals[8], loc ); 00357 ASSERT_VALUES_EQUAL( expected_coeffs[9], test_vals[9], loc ); 00358 ASSERT_VALUES_EQUAL( expected_coeffs[10], test_vals[10], loc ); 00359 ASSERT_VALUES_EQUAL( expected_coeffs[11], test_vals[11], loc ); 00360 ASSERT_VALUES_EQUAL( expected_coeffs[12], test_vals[12], loc ); 00361 ASSERT_VALUES_EQUAL( expected_coeffs[13], test_vals[13], loc ); 00362 ASSERT_VALUES_EQUAL( expected_coeffs[14], test_vals[14], loc ); 00363 ASSERT_VALUES_EQUAL( expected_coeffs[15], test_vals[15], loc ); 00364 ASSERT_VALUES_EQUAL( expected_coeffs[16], test_vals[16], loc ); 00365 ASSERT_VALUES_EQUAL( expected_coeffs[17], test_vals[17], loc ); 00366 ASSERT_VALUES_EQUAL( expected_coeffs[18], test_vals[18], loc ); 00367 ASSERT_VALUES_EQUAL( expected_coeffs[19], test_vals[19], loc ); 00368 ASSERT_VALUES_EQUAL( expected_coeffs[20], test_vals[20], loc ); 00369 ASSERT_VALUES_EQUAL( expected_coeffs[21], test_vals[21], loc ); 00370 ASSERT_VALUES_EQUAL( expected_coeffs[22], test_vals[22], loc ); 00371 ASSERT_VALUES_EQUAL( expected_coeffs[23], test_vals[23], loc ); 00372 ASSERT_VALUES_EQUAL( expected_coeffs[24], test_vals[24], loc ); 00373 ASSERT_VALUES_EQUAL( expected_coeffs[25], test_vals[25], loc ); 00374 ASSERT_VALUES_EQUAL( expected_coeffs[26], test_vals[26], loc ); 00375 } 00376 00377 static void compare_derivatives( const size_t* vertices, 00378 size_t num_vtx, 00379 const MsqVector< 3 >* actual, 00380 const MsqVector< 3 >* expected, 00381 unsigned loc ) 00382 { 00383 check_valid_indices( vertices, num_vtx ); 00384 check_no_zeros( actual, num_vtx ); 00385 00386 // Input has values in dxi & deta & dzeta only for nodes in 'vertices' 00387 // Convert to values for every possible node, with zero's for 00388 // nodes that are not present. 00389 CPPUNIT_ASSERT( num_vtx <= 9 ); 00390 MsqVector< 3 > expanded[27]; 00391 std::fill( expanded, expanded + 27, MsqVector< 3 >( 0.0 ) ); 00392 for( unsigned i = 0; i < num_vtx; ++i ) 00393 { 00394 CPPUNIT_ASSERT( vertices[i] <= 26 ); 00395 expanded[vertices[i]] = actual[i]; 00396 } 00397 00398 ASSERT_VALUES_EQUAL( expected[0], expanded[0], loc ); 00399 ASSERT_VALUES_EQUAL( expected[1], expanded[1], loc ); 00400 ASSERT_VALUES_EQUAL( expected[2], expanded[2], loc ); 00401 ASSERT_VALUES_EQUAL( expected[3], expanded[3], loc ); 00402 ASSERT_VALUES_EQUAL( expected[4], expanded[4], loc ); 00403 ASSERT_VALUES_EQUAL( expected[5], expanded[5], loc ); 00404 ASSERT_VALUES_EQUAL( expected[6], expanded[6], loc ); 00405 ASSERT_VALUES_EQUAL( expected[7], expanded[7], loc ); 00406 ASSERT_VALUES_EQUAL( expected[8], expanded[8], loc ); 00407 ASSERT_VALUES_EQUAL( expected[9], expanded[9], loc ); 00408 ASSERT_VALUES_EQUAL( expected[10], expanded[10], loc ); 00409 ASSERT_VALUES_EQUAL( expected[11], expanded[11], loc ); 00410 ASSERT_VALUES_EQUAL( expected[12], expanded[12], loc ); 00411 ASSERT_VALUES_EQUAL( expected[13], expanded[13], loc ); 00412 ASSERT_VALUES_EQUAL( expected[14], expanded[14], loc ); 00413 ASSERT_VALUES_EQUAL( expected[15], expanded[15], loc ); 00414 ASSERT_VALUES_EQUAL( expected[16], expanded[16], loc ); 00415 ASSERT_VALUES_EQUAL( expected[17], expanded[17], loc ); 00416 ASSERT_VALUES_EQUAL( expected[18], expanded[18], loc ); 00417 ASSERT_VALUES_EQUAL( expected[19], expanded[19], loc ); 00418 ASSERT_VALUES_EQUAL( expected[20], expanded[20], loc ); 00419 ASSERT_VALUES_EQUAL( expected[21], expanded[21], loc ); 00420 ASSERT_VALUES_EQUAL( expected[22], expanded[22], loc ); 00421 ASSERT_VALUES_EQUAL( expected[23], expanded[23], loc ); 00422 ASSERT_VALUES_EQUAL( expected[24], expanded[24], loc ); 00423 ASSERT_VALUES_EQUAL( expected[25], expanded[25], loc ); 00424 ASSERT_VALUES_EQUAL( expected[26], expanded[26], loc ); 00425 } 00426 00427 void HexLagrangeShapeTest::test_corner_coeff( int corner ) 00428 { 00429 MsqPrintError err( std::cout ); 00430 00431 double expected[27]; 00432 get_coeffs( XI_corner( corner ), expected ); 00433 00434 double coeff[100]; 00435 size_t num_coeff = 11, indices[100]; 00436 sf.coefficients( Sample( 0, corner ), allNodes, coeff, indices, num_coeff, err ); 00437 CPPUNIT_ASSERT( !err ); 00438 00439 compare_coefficients( coeff, indices, num_coeff, expected, corner ); 00440 } 00441 00442 void HexLagrangeShapeTest::test_edge_coeff( int edge ) 00443 { 00444 MsqPrintError err( std::cout ); 00445 00446 double expected[27]; 00447 get_coeffs( XI_edge( edge ), expected ); 00448 00449 double coeff[100]; 00450 size_t num_coeff = 11, indices[100]; 00451 sf.coefficients( Sample( 1, edge ), allNodes, coeff, indices, num_coeff, err ); 00452 CPPUNIT_ASSERT( !err ); 00453 00454 compare_coefficients( coeff, indices, num_coeff, expected, edge + 8 ); 00455 } 00456 00457 void HexLagrangeShapeTest::test_face_coeff( int face ) 00458 { 00459 MsqPrintError err( std::cout ); 00460 00461 double expected[27]; 00462 get_coeffs( XI_face( face ), expected ); 00463 00464 double coeff[100]; 00465 size_t num_coeff = 11, indices[100]; 00466 sf.coefficients( Sample( 2, face ), allNodes, coeff, indices, num_coeff, err ); 00467 CPPUNIT_ASSERT( !err ); 00468 00469 compare_coefficients( coeff, indices, num_coeff, expected, face + 20 ); 00470 } 00471 00472 void HexLagrangeShapeTest::test_mid_coeff() 00473 { 00474 MsqPrintError err( std::cout ); 00475 00476 double expected[27]; 00477 get_coeffs( XI_elem(), expected ); 00478 00479 double coeff[100]; 00480 size_t num_coeff = 11, indices[100]; 00481 sf.coefficients( Sample( 3, 0 ), allNodes, coeff, indices, num_coeff, err ); 00482 CPPUNIT_ASSERT( !err ); 00483 00484 compare_coefficients( coeff, indices, num_coeff, expected, 26 ); 00485 } 00486 00487 void HexLagrangeShapeTest::test_corner_derivs( int corner ) 00488 { 00489 MsqPrintError err( std::cout ); 00490 00491 MsqVector< 3 > expected[27]; 00492 get_derivs( XI_corner( corner ), expected ); 00493 00494 size_t vertices[100], num_vtx = 23; 00495 MsqVector< 3 > derivs[100]; 00496 sf.derivatives( Sample( 0, corner ), allNodes, vertices, derivs, num_vtx, err ); 00497 CPPUNIT_ASSERT( !err ); 00498 00499 compare_derivatives( vertices, num_vtx, derivs, expected, corner ); 00500 } 00501 00502 void HexLagrangeShapeTest::test_edge_derivs( int edge ) 00503 { 00504 MsqPrintError err( std::cout ); 00505 00506 MsqVector< 3 > expected[27]; 00507 get_derivs( XI_edge( edge ), expected ); 00508 00509 size_t vertices[100], num_vtx = 23; 00510 MsqVector< 3 > derivs[100]; 00511 sf.derivatives( Sample( 1, edge ), allNodes, vertices, derivs, num_vtx, err ); 00512 CPPUNIT_ASSERT( !err ); 00513 00514 compare_derivatives( vertices, num_vtx, derivs, expected, edge + 8 ); 00515 } 00516 00517 void HexLagrangeShapeTest::test_face_derivs( int face ) 00518 { 00519 MsqPrintError err( std::cout ); 00520 00521 MsqVector< 3 > expected[27]; 00522 get_derivs( XI_face( face ), expected ); 00523 00524 size_t vertices[100], num_vtx = 23; 00525 MsqVector< 3 > derivs[100]; 00526 sf.derivatives( Sample( 2, face ), allNodes, vertices, derivs, num_vtx, err ); 00527 CPPUNIT_ASSERT( !err ); 00528 00529 compare_derivatives( vertices, num_vtx, derivs, expected, face + 20 ); 00530 } 00531 00532 void HexLagrangeShapeTest::test_mid_derivs() 00533 { 00534 MsqPrintError err( std::cout ); 00535 00536 MsqVector< 3 > expected[27]; 00537 get_derivs( XI_elem(), expected ); 00538 00539 size_t vertices[100], num_vtx = 23; 00540 MsqVector< 3 > derivs[100]; 00541 sf.derivatives( Sample( 3, 0 ), allNodes, vertices, derivs, num_vtx, err ); 00542 CPPUNIT_ASSERT( !err ); 00543 00544 compare_derivatives( vertices, num_vtx, derivs, expected, 26 ); 00545 } 00546 00547 void HexLagrangeShapeTest::test_corners_coeff() 00548 { 00549 for( unsigned i = 0; i < 8; ++i ) 00550 test_corner_coeff( i ); 00551 } 00552 00553 void HexLagrangeShapeTest::test_edges_coeff() 00554 { 00555 for( unsigned i = 0; i < 12; ++i ) 00556 test_edge_coeff( i ); 00557 } 00558 00559 void HexLagrangeShapeTest::test_faces_coeff() 00560 { 00561 for( unsigned i = 0; i < 6; ++i ) 00562 test_face_coeff( i ); 00563 } 00564 00565 void HexLagrangeShapeTest::test_corners_derivs() 00566 { 00567 for( unsigned i = 0; i < 8; ++i ) 00568 test_corner_derivs( i ); 00569 } 00570 00571 void HexLagrangeShapeTest::test_edges_derivs() 00572 { 00573 for( unsigned i = 0; i < 12; ++i ) 00574 test_edge_derivs( i ); 00575 } 00576 00577 void HexLagrangeShapeTest::test_faces_derivs() 00578 { 00579 for( unsigned i = 0; i < 6; ++i ) 00580 test_face_derivs( i ); 00581 } 00582 00583 void HexLagrangeShapeTest::test_ideal_jacobian() 00584 { 00585 MsqError err; 00586 MsqMatrix< 3, 3 > J_act, J_exp( 1.0 ); 00587 sf.ideal( Sample( 3, 0 ), J_act, err ); 00588 ASSERT_NO_ERROR( err ); 00589 00590 // Matrices should be a rotation of each other. 00591 // First, calculate tentative rotation matrix 00592 MsqMatrix< 3, 3 > R = inverse( J_exp ) * J_act; 00593 // next check that it is a rotation 00594 CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, det( R ), 1e-6 ); // no scaling 00595 ASSERT_MATRICES_EQUAL( transpose( R ), inverse( R ), 1e-6 ); // orthogonal 00596 }