MOAB: Mesh Oriented datABase
(version 5.2.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 retain 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) kraftche@cae.wisc.edu 00024 00025 ***************************************************************** */ 00026 00027 /** \file TargetMetricTest.hpp 00028 * \brief Templatized common code for testing various target metric 00029 * implementation types. 00030 * \author Jason Kraftcheck 00031 */ 00032 00033 #include "UnitUtil.hpp" 00034 #include "MsqError.hpp" 00035 #include "MsqMatrix.hpp" 00036 00037 #include "TMetric.hpp" 00038 #include "TMetricBarrier.hpp" 00039 #include "AWMetric.hpp" 00040 #include "AWMetricBarrier.hpp" 00041 00042 // NOTE: Caller must define TARGET_TEST_GROUP to be a quoted string, 00043 // typically the base file name of the file containing the 00044 // calls to TEST_METRIC_* 00045 00046 // Macro arguments: 00047 // shape_invariant 00048 // size_invariant 00049 // orient_invariant 00050 // barrier 00051 00052 #define REGISTER_BASE_TESTS \ 00053 CPPUNIT_TEST( test_ideal_eval ); \ 00054 CPPUNIT_TEST( test_ideal_gradient ); \ 00055 CPPUNIT_TEST( test_inverted ); \ 00056 CPPUNIT_TEST( test_shape ); \ 00057 CPPUNIT_TEST( test_scale ); \ 00058 CPPUNIT_TEST( test_orient ) 00059 00060 #define REGISTER_GRAD_TESTS \ 00061 CPPUNIT_TEST( compare_eval_and_eval_with_grad ); \ 00062 CPPUNIT_TEST( compare_anaytic_and_numeric_grads ) 00063 00064 #define REGISTER_HESS_TESTS \ 00065 CPPUNIT_TEST( compare_eval_with_grad_and_eval_with_hess ); \ 00066 CPPUNIT_TEST( compare_anaytic_and_numeric_hess ) 00067 00068 #define BEGIN_TEST_DECL( METRIC, DIM, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00069 class METRIC##_##DIM##DTest : public TMetricTest< METRIC, DIM > \ 00070 { \ 00071 public: \ 00072 METRIC##_##DIM##DTest() \ 00073 : TMetricTest< METRIC, DIM >( ( SHAPE_INVAR ), ( SIZE_INVAR ), ( ORIENT_INVAR ), ( BARRIER ), IDEAL ) \ 00074 { \ 00075 } \ 00076 CPPUNIT_TEST_SUITE( METRIC##_##DIM##DTest ) 00077 00078 #define END_TEST_DECL( SUITE, DIM, METRIC ) \ 00079 CPPUNIT_TEST_SUITE_END(); \ 00080 } \ 00081 ; \ 00082 CPPUNIT_NS::AutoRegisterSuite< METRIC##_##DIM##DTest > METRIC##_##DIM##D_UnitRegister( "Unit" ); \ 00083 CPPUNIT_NS::AutoRegisterSuite< METRIC##_##DIM##DTest > METRIC##_##DIM##D_FileRegister( TARGET_TEST_GROUP ); \ 00084 CPPUNIT_NS::AutoRegisterSuite< METRIC##_##DIM##DTest > METRIC##_##DIM##D_BaseRegister( #SUITE "Test" ) 00085 00086 /** Register tests for metric with no derivative implementations */ 00087 #define TEST_METRIC_NO_DERIVS_2D( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00088 BEGIN_TEST_DECL( METRIC, 2, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ); \ 00089 REGISTER_BASE_TESTS; \ 00090 END_TEST_DECL( METRIC, 2, METRIC ) 00091 00092 /** Register tests for metric with no derivative implementations */ 00093 #define TEST_METRIC_NO_DERIVS_3D( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00094 BEGIN_TEST_DECL( METRIC, 3, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIE, IDEALR ); \ 00095 REGISTER_BASE_TESTS; \ 00096 END_TEST_DECL( METRIC, 3, METRIC ) 00097 00098 /** Register tests for metric with no derivative implementations */ 00099 #define TEST_METRIC_NO_DERIVS( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00100 TEST_METRIC_NO_DERIVS_2D( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ); \ 00101 TEST_METRIC_NO_DERIVS_3D( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) 00102 00103 /** Register tests for metric with implementation of analytic gradient */ 00104 #define TEST_METRIC_WITH_GRAD_2D( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00105 BEGIN_TEST_DECL( METRIC, 2, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ); \ 00106 REGISTER_BASE_TESTS; \ 00107 REGISTER_GRAD_TESTS; \ 00108 END_TEST_DECL( METRIC, 2, METRIC ) 00109 00110 /** Register tests for metric with implementation of analytic gradient */ 00111 #define TEST_METRIC_WITH_GRAD_3D( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00112 BEGIN_TEST_DECL( METRIC, 3, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ); \ 00113 REGISTER_BASE_TESTS; \ 00114 REGISTER_GRAD_TESTS; \ 00115 END_TEST_DECL( METRIC, 3, METRIC ) 00116 00117 /** Register tests for metric with implementation of analytic gradient */ 00118 #define TEST_METRIC_WITH_GRAD( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00119 TEST_METRIC_WITH_GRAD_2D( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ); \ 00120 TEST_METRIC_WITH_GRAD_3D( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) 00121 00122 #define TEST_NAMED_METRIC_WITH_HESS_2D( METRIC, NAME, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00123 BEGIN_TEST_DECL( METRIC, 2, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ); \ 00124 REGISTER_BASE_TESTS; \ 00125 REGISTER_GRAD_TESTS; \ 00126 REGISTER_HESS_TESTS; \ 00127 END_TEST_DECL( NAME, 2, METRIC ) 00128 00129 #define TEST_NAMED_METRIC_WITH_HESS_3D( METRIC, NAME, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00130 BEGIN_TEST_DECL( METRIC, 3, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ); \ 00131 REGISTER_BASE_TESTS; \ 00132 REGISTER_GRAD_TESTS; \ 00133 REGISTER_HESS_TESTS; \ 00134 END_TEST_DECL( NAME, 3, METRIC ) 00135 00136 /** Register tests for metric with implementation of analytic gradient and Hessian */ 00137 #define TEST_NAMED_METRIC_WITH_HESS( METRIC, NAME, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00138 TEST_NAMED_METRIC_WITH_HESS_2D( METRIC, NAME, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ); \ 00139 TEST_NAMED_METRIC_WITH_HESS_3D( METRIC, NAME, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) 00140 00141 /** Register tests for metric with implementation of analytic gradient and Hessian */ 00142 #define TEST_METRIC_WITH_HESS_2D( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00143 TEST_NAMED_METRIC_WITH_HESS_2D( METRIC, METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) 00144 00145 /** Register tests for metric with implementation of analytic gradient and Hessian */ 00146 #define TEST_METRIC_WITH_HESS_3D( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00147 TEST_NAMED_METRIC_WITH_HESS_3D( METRIC, METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) 00148 00149 /** Register tests for metric with implementation of analytic gradient and Hessian */ 00150 #define TEST_METRIC_WITH_HESS( METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) \ 00151 TEST_NAMED_METRIC_WITH_HESS_2D( METRIC, METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ); \ 00152 TEST_NAMED_METRIC_WITH_HESS_3D( METRIC, METRIC, SHAPE_INVAR, SIZE_INVAR, ORIENT_INVAR, BARRIER, IDEAL ) 00153 00154 #define TEST_NON_QUALITY_METRIC_WITH_HESS_2D( METRIC ) \ 00155 BEGIN_TEST_DECL( METRIC, 2, true, true, true, true, 0.0 ); \ 00156 REGISTER_GRAD_TESTS; \ 00157 REGISTER_HESS_TESTS; \ 00158 END_TEST_DECL( NAME, 2, METRIC ) 00159 00160 #define TEST_NON_QUALITY_METRIC_WITH_HESS_3D( METRIC ) \ 00161 BEGIN_TEST_DECL( METRIC, 3, true, true, true, true, 0.0 ); \ 00162 REGISTER_GRAD_TESTS; \ 00163 REGISTER_HESS_TESTS; \ 00164 END_TEST_DECL( NAME, 3, METRIC ) 00165 00166 /** Regsiter tests for a metric that doesn't really measure quality */ 00167 #define TEST_NON_QUALITY_METRIC_WITH_HESS( METRIC ) \ 00168 TEST_NON_QUALITY_METRIC_WITH_HESS_2D( METRIC ); \ 00169 TEST_NON_QUALITY_METRIC_WITH_HESS_3D( METRIC ); 00170 00171 using namespace MBMesquite; 00172 00173 const double Avals[][9] = { { 0 }, 00174 { 2 }, 00175 { 2, 1, // 2x2 values 00176 1, 2 }, 00177 { 2, 1, 1, // 3x3 values 00178 1, 2, 1, 1, 1, 2 } }; 00179 const double Bvals[][9] = { { 0 }, 00180 { -0.1 }, 00181 { -0.1, -0.15, // 2x2 values 00182 -0.25, -0.8 }, 00183 { 1.5, -0.7, -0.8, // 3x3 values 00184 0.8, -1.3, -0.7, 0.6, -0.9, -2.0 } }; 00185 const double Cvals[][9] = { { 0 }, 00186 { 0.5 }, 00187 { -1.0, 0.5, // 2x2 values 00188 0.0, 1.0 }, 00189 { 0.5, 0.0, 0.1, // 3x3 values 00190 0.5, 1.0, 0.1, 0.0, 0.0, -1.5 } }; 00191 00192 /**\brief Common tests for all target metric types 00193 * 00194 * Commont test framework for implementations of the following types: 00195 * \c TMetric , \c AWMetric 00196 */ 00197 template < class Metric, unsigned DIM > 00198 class TMetricTest : public CppUnit::TestFixture 00199 { 00200 00201 private: 00202 Metric testMetric; 00203 const double idealVal; 00204 const bool shapeInvariant, sizeInvariant, orientInvariant, Barrier; 00205 00206 public: 00207 typedef MsqMatrix< DIM, DIM > Matrix; 00208 00209 TMetricTest( bool shape_invariant, bool size_invariant, bool orient_invariant, bool barrier, double ideal_val ) 00210 : idealVal( ideal_val ), shapeInvariant( shape_invariant ), sizeInvariant( size_invariant ), 00211 orientInvariant( orient_invariant ), Barrier( barrier ), Zero( 0.0 ), I( 1.0 ), A( Avals[DIM] ), 00212 B( Bvals[DIM] ), C( Cvals[DIM] ) 00213 { 00214 } 00215 00216 // Some initial matrix values used in many tests 00217 const Matrix Zero, I, A, B, C; 00218 00219 void test_ideal_eval(); 00220 void test_ideal_gradient(); 00221 void test_inverted(); 00222 void test_shape(); 00223 void test_scale(); 00224 void test_orient(); 00225 00226 void compare_anaytic_and_numeric_grads(); 00227 void compare_anaytic_and_numeric_hess(); 00228 void compare_eval_and_eval_with_grad(); 00229 void compare_eval_with_grad_and_eval_with_hess(); 00230 00231 private: 00232 /**\brief Test if metric is or is not sensitive to difference between A and W 00233 * 00234 * Given an active matrix A and a target matrix W, test whether or 00235 * not the metric is sensitive to the difference. Fail if actual 00236 * sensitivity to difference is not equal to expected sensitivity 00237 * passed as the first argument 00238 */ 00239 void test_non_ideal( bool sensitive, Matrix A, Matrix W ); 00240 00241 /************************************************************************* 00242 * Use overloaded function names to do the stuff 00243 * that is different for different base metric types 00244 *************************************************************************/ 00245 00246 // TMetric 00247 inline bool eval( TMetric& metric, MsqMatrix< DIM, DIM > A, MsqMatrix< DIM, DIM > W, double& value, MsqError& err ) 00248 { 00249 return metric.evaluate( A * inverse( W ), value, err ); 00250 } 00251 inline bool grad( TMetric& metric, MsqMatrix< DIM, DIM > A, MsqMatrix< DIM, DIM > W, double& value, 00252 MsqMatrix< DIM, DIM >& dmdA, MsqError& err ) 00253 { 00254 bool rval = metric.evaluate_with_grad( A * inverse( W ), value, dmdA, err ); 00255 dmdA = dmdA * transpose( inverse( W ) ); 00256 return rval; 00257 } 00258 inline bool num_grad( TMetric& metric, MsqMatrix< DIM, DIM > A, MsqMatrix< DIM, DIM > W, double& value, 00259 MsqMatrix< DIM, DIM >& dmdA, MsqError& err ) 00260 { 00261 bool rval = metric.evaluate_with_grad( A * inverse( W ), value, dmdA, err ); 00262 dmdA = dmdA * transpose( inverse( W ) ); 00263 return rval; 00264 } 00265 inline bool hess( TMetric& metric, MsqMatrix< DIM, DIM > A, MsqMatrix< DIM, DIM > W, double& value, 00266 MsqMatrix< DIM, DIM >& dmdA, MsqMatrix< DIM, DIM > d2mdA2[3], MsqError& err ) 00267 { 00268 bool rval = metric.evaluate_with_hess( A * inverse( W ), value, dmdA, d2mdA2, err ); 00269 dmdA = dmdA * transpose( inverse( W ) ); 00270 for( unsigned i = 0; i < DIM * ( DIM + 1 ) / 2; ++i ) 00271 d2mdA2[i] = inverse( W ) * d2mdA2[i] * transpose( inverse( W ) ); 00272 return rval; 00273 } 00274 inline bool num_hess( TMetric& metric, MsqMatrix< DIM, DIM > A, MsqMatrix< DIM, DIM > W, double& value, 00275 MsqMatrix< DIM, DIM >& dmdA, MsqMatrix< DIM, DIM > d2mdA2[3], MsqError& err ) 00276 { 00277 bool rval = metric.evaluate_with_hess( A * inverse( W ), value, dmdA, d2mdA2, err ); 00278 dmdA = dmdA * transpose( inverse( W ) ); 00279 for( unsigned i = 0; i < DIM * ( DIM + 1 ) / 2; ++i ) 00280 d2mdA2[i] = inverse( W ) * d2mdA2[i] * transpose( inverse( W ) ); 00281 return rval; 00282 } 00283 00284 // AWMetric 00285 inline bool eval( AWMetric& metric, MsqMatrix< DIM, DIM > A, MsqMatrix< DIM, DIM > W, double& value, MsqError& err ) 00286 { 00287 bool rval = metric.evaluate( A, W, value, err ); 00288 return rval; 00289 } 00290 inline bool grad( AWMetric& metric, MsqMatrix< DIM, DIM > A, MsqMatrix< DIM, DIM > W, double& value, 00291 MsqMatrix< DIM, DIM >& dmdA, MsqError& err ) 00292 { 00293 bool rval = metric.evaluate_with_grad( A, W, value, dmdA, err ); 00294 return rval; 00295 } 00296 inline bool num_grad( AWMetric& metric, MsqMatrix< DIM, DIM > A, MsqMatrix< DIM, DIM > W, double& value, 00297 MsqMatrix< DIM, DIM >& dmdA, MsqError& err ) 00298 { 00299 bool rval = metric.evaluate_with_grad( A, W, value, dmdA, err ); 00300 return rval; 00301 } 00302 inline bool hess( AWMetric& metric, MsqMatrix< DIM, DIM > A, MsqMatrix< DIM, DIM > W, double& value, 00303 MsqMatrix< DIM, DIM >& dmdA, MsqMatrix< DIM, DIM > d2mdA2[3], MsqError& err ) 00304 { 00305 bool rval = metric.evaluate_with_hess( A, W, value, dmdA, d2mdA2, err ); 00306 return rval; 00307 } 00308 inline bool num_hess( AWMetric& metric, MsqMatrix< DIM, DIM > A, MsqMatrix< DIM, DIM > W, double& value, 00309 MsqMatrix< DIM, DIM >& dmdA, MsqMatrix< DIM, DIM > d2mdA2[3], MsqError& err ) 00310 { 00311 bool rval = metric.evaluate_with_hess( A, W, value, dmdA, d2mdA2, err ); 00312 return rval; 00313 } 00314 }; 00315 00316 #define TMETRIC_FUNC \ 00317 template < class Metric, unsigned DIM > \ 00318 void TMetricTest< Metric, DIM > 00319 #define MAT_TYPE TMetricTest< Metric, DIM >::Matrix 00320 00321 /************************************************************************* 00322 * Implement actual (templatized) test code 00323 *************************************************************************/ 00324 00325 TMETRIC_FUNC::test_ideal_eval() 00326 { 00327 MsqPrintError err( std::cerr ); 00328 double val, eps = 5e-5; 00329 bool valid; 00330 00331 valid = eval( testMetric, I, I, val, err ); 00332 ASSERT_NO_ERROR( err ); 00333 CPPUNIT_ASSERT( valid ); 00334 CPPUNIT_ASSERT_DOUBLES_EQUAL( idealVal, val, eps ); 00335 00336 valid = eval( testMetric, A, A, val, err ); 00337 ASSERT_NO_ERROR( err ); 00338 CPPUNIT_ASSERT( valid ); 00339 CPPUNIT_ASSERT_DOUBLES_EQUAL( idealVal, val, eps ); 00340 00341 valid = eval( testMetric, B, B, val, err ); 00342 ASSERT_NO_ERROR( err ); 00343 CPPUNIT_ASSERT( valid ); 00344 CPPUNIT_ASSERT_DOUBLES_EQUAL( idealVal, val, eps ); 00345 } 00346 00347 TMETRIC_FUNC::test_ideal_gradient() 00348 { 00349 MsqPrintError err( std::cerr ); 00350 MsqMatrix< DIM, DIM > g; 00351 double val, eps = 5e-3; 00352 bool valid; 00353 00354 valid = grad( testMetric, I, I, val, g, err ); 00355 ASSERT_NO_ERROR( err ); 00356 CPPUNIT_ASSERT( valid ); 00357 ASSERT_MATRICES_EQUAL( Zero, g, eps ); 00358 00359 valid = grad( testMetric, A, A, val, g, err ); 00360 ASSERT_NO_ERROR( err ); 00361 CPPUNIT_ASSERT( valid ); 00362 ASSERT_MATRICES_EQUAL( Zero, g, eps ); 00363 00364 valid = grad( testMetric, B, B, val, g, err ); 00365 ASSERT_NO_ERROR( err ); 00366 CPPUNIT_ASSERT( valid ); 00367 ASSERT_MATRICES_EQUAL( Zero, g, eps ); 00368 } 00369 00370 TMETRIC_FUNC::test_inverted() 00371 { 00372 MsqPrintError err( std::cerr ); 00373 MsqMatrix< DIM, DIM > V( 1.0 ), W( 1.0 ), g, h[6]; 00374 V( DIM - 1, DIM - 1 ) = -1.0; 00375 double val; 00376 bool valid; 00377 00378 if( Barrier ) 00379 { 00380 valid = eval( testMetric, V, W, val, err ); 00381 if( err.error_code() == err.BARRIER_VIOLATED ) err.clear(); 00382 ASSERT_NO_ERROR( err ); 00383 CPPUNIT_ASSERT( !valid ); 00384 00385 valid = grad( testMetric, V, W, val, g, err ); 00386 if( err.error_code() == err.BARRIER_VIOLATED ) err.clear(); 00387 ASSERT_NO_ERROR( err ); 00388 CPPUNIT_ASSERT( !valid ); 00389 00390 valid = hess( testMetric, V, W, val, g, h, err ); 00391 if( err.error_code() == err.BARRIER_VIOLATED ) err.clear(); 00392 ASSERT_NO_ERROR( err ); 00393 CPPUNIT_ASSERT( !valid ); 00394 } 00395 else 00396 { 00397 valid = eval( testMetric, V, W, val, err ); 00398 ASSERT_NO_ERROR( err ); 00399 CPPUNIT_ASSERT( valid ); 00400 CPPUNIT_ASSERT( val > idealVal ); 00401 00402 valid = grad( testMetric, V, W, val, g, err ); 00403 ASSERT_NO_ERROR( err ); 00404 CPPUNIT_ASSERT( valid ); 00405 CPPUNIT_ASSERT( val > idealVal ); 00406 CPPUNIT_ASSERT( sqr_Frobenius( g ) > 1e-6 ); 00407 } 00408 } 00409 00410 TMETRIC_FUNC::test_non_ideal( bool sensitive, Matrix J, Matrix W ) 00411 { 00412 MsqPrintError err( std::cerr ); 00413 MsqMatrix< DIM, DIM > g; 00414 double val, eps = 1e-5; 00415 bool valid; 00416 if( !sensitive ) 00417 { 00418 valid = eval( testMetric, J, W, val, err ); 00419 ASSERT_NO_ERROR( err ); 00420 CPPUNIT_ASSERT( valid ); 00421 CPPUNIT_ASSERT_DOUBLES_EQUAL( idealVal, val, eps ); 00422 00423 valid = grad( testMetric, J, W, val, g, err ); 00424 ASSERT_NO_ERROR( err ); 00425 CPPUNIT_ASSERT( valid ); 00426 CPPUNIT_ASSERT_DOUBLES_EQUAL( idealVal, val, eps ); 00427 ASSERT_MATRICES_EQUAL( ( MsqMatrix< DIM, DIM >( 0.0 ) ), g, eps ); 00428 } 00429 else 00430 { 00431 valid = eval( testMetric, J, W, val, err ); 00432 ASSERT_NO_ERROR( err ); 00433 CPPUNIT_ASSERT( valid ); 00434 CPPUNIT_ASSERT( val > idealVal ); 00435 } 00436 } 00437 00438 TMETRIC_FUNC::test_shape() 00439 { 00440 const double r3 = sqrt( 3.0 ); 00441 const double U_vals[][9] = { { 2 / r3, 1 / r3, 1 / r3, 2 / r3 }, 00442 { 2 / r3, 1 / r3, 0, 1 / r3, 2 / r3, 0, 0, 0, 1 } }; 00443 Matrix U( U_vals[DIM - 2] ), W( 1.0 ); 00444 test_non_ideal( !shapeInvariant, U, W ); 00445 } 00446 00447 TMETRIC_FUNC::test_scale() 00448 { 00449 Matrix L( 2.0 ), W( 1.0 ); 00450 test_non_ideal( !sizeInvariant, L, W ); 00451 } 00452 00453 TMETRIC_FUNC::test_orient() 00454 { 00455 const double V_vals[][9] = { { 0, -1, 1, 0 }, { 0, -1, 0, 1, 0, 0, 0, 0, 1 } }; 00456 Matrix V( V_vals[DIM - 2] ), W( 1.0 ); 00457 test_non_ideal( !orientInvariant, V, W ); 00458 } 00459 00460 static double releps( double a ) 00461 { 00462 return std::max( 1e-6, 1e-8 * fabs( a ) ); 00463 } 00464 00465 TMETRIC_FUNC::compare_eval_and_eval_with_grad() 00466 { 00467 MsqError err; 00468 Matrix g; 00469 bool valid; 00470 double gv, v; 00471 00472 valid = grad( testMetric, I, A, gv, g, err ); 00473 ASSERT_NO_ERROR( err ); 00474 CPPUNIT_ASSERT( valid ); 00475 valid = eval( testMetric, I, A, v, err ); 00476 ASSERT_NO_ERROR( err ); 00477 CPPUNIT_ASSERT( valid ); 00478 CPPUNIT_ASSERT_DOUBLES_EQUAL( v, gv, releps( v ) ); 00479 00480 valid = grad( testMetric, A, B, gv, g, err ); 00481 ASSERT_NO_ERROR( err ); 00482 CPPUNIT_ASSERT( valid ); 00483 valid = eval( testMetric, A, B, v, err ); 00484 ASSERT_NO_ERROR( err ); 00485 CPPUNIT_ASSERT( valid ); 00486 CPPUNIT_ASSERT_DOUBLES_EQUAL( v, gv, releps( v ) ); 00487 00488 // also test inverted for non-barrier metrics 00489 if( Barrier ) return; 00490 00491 valid = grad( testMetric, C, I, gv, g, err ); 00492 ASSERT_NO_ERROR( err ); 00493 CPPUNIT_ASSERT( valid ); 00494 valid = eval( testMetric, C, I, v, err ); 00495 ASSERT_NO_ERROR( err ); 00496 CPPUNIT_ASSERT( valid ); 00497 CPPUNIT_ASSERT_DOUBLES_EQUAL( v, gv, releps( v ) ); 00498 } 00499 00500 TMETRIC_FUNC::compare_eval_with_grad_and_eval_with_hess() 00501 { 00502 MsqError err; 00503 Matrix g, h, H[DIM * ( DIM + 1 ) / 2]; 00504 bool valid; 00505 double gv, hv; 00506 00507 valid = grad( testMetric, I, A, gv, g, err ); 00508 ASSERT_NO_ERROR( err ); 00509 CPPUNIT_ASSERT( valid ); 00510 valid = hess( testMetric, I, A, hv, h, H, err ); 00511 ASSERT_NO_ERROR( err ); 00512 CPPUNIT_ASSERT( valid ); 00513 CPPUNIT_ASSERT_DOUBLES_EQUAL( gv, hv, releps( gv ) ); 00514 ASSERT_MATRICES_EQUAL( g, h, 1e-5 ); 00515 00516 valid = grad( testMetric, A, B, gv, g, err ); 00517 ASSERT_NO_ERROR( err ); 00518 CPPUNIT_ASSERT( valid ); 00519 valid = hess( testMetric, A, B, hv, h, H, err ); 00520 ASSERT_NO_ERROR( err ); 00521 CPPUNIT_ASSERT( valid ); 00522 CPPUNIT_ASSERT_DOUBLES_EQUAL( gv, hv, releps( gv ) ); 00523 ASSERT_MATRICES_EQUAL( g, h, 1e-5 ); 00524 00525 // also test inverted for non-barrier metrics 00526 if( Barrier ) return; 00527 00528 valid = grad( testMetric, C, I, gv, g, err ); 00529 ASSERT_NO_ERROR( err ); 00530 CPPUNIT_ASSERT( valid ); 00531 valid = hess( testMetric, C, I, hv, h, H, err ); 00532 ASSERT_NO_ERROR( err ); 00533 CPPUNIT_ASSERT( valid ); 00534 CPPUNIT_ASSERT_DOUBLES_EQUAL( gv, hv, releps( gv ) ); 00535 ASSERT_MATRICES_EQUAL( g, h, 1e-5 ); 00536 } 00537 00538 template < typename M > 00539 double eps_mat( const M& mu ) 00540 { 00541 return std::max( Frobenius( mu ) * 1e-2, 1e-4 ); 00542 } 00543 00544 TMETRIC_FUNC::compare_anaytic_and_numeric_grads() 00545 { 00546 const double EPS_VAL = 1e-6; 00547 00548 MsqError err; 00549 Matrix num, ana; 00550 bool valid; 00551 double nval, aval; 00552 00553 Matrix D( I ); 00554 D( 0, 0 ) += 1e-5; 00555 valid = num_grad( testMetric, D, I, nval, num, err ); 00556 ASSERT_NO_ERROR( err ); 00557 CPPUNIT_ASSERT( valid ); 00558 valid = grad( testMetric, D, I, aval, ana, err ); 00559 ASSERT_NO_ERROR( err ); 00560 CPPUNIT_ASSERT( valid ); 00561 CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL ); 00562 ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) ); 00563 00564 valid = num_grad( testMetric, I, A, nval, num, err ); 00565 ASSERT_NO_ERROR( err ); 00566 CPPUNIT_ASSERT( valid ); 00567 valid = grad( testMetric, I, A, aval, ana, err ); 00568 ASSERT_NO_ERROR( err ); 00569 CPPUNIT_ASSERT( valid ); 00570 CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL ); 00571 ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) ); 00572 00573 valid = num_grad( testMetric, A, I, nval, num, err ); 00574 ASSERT_NO_ERROR( err ); 00575 CPPUNIT_ASSERT( valid ); 00576 valid = grad( testMetric, A, I, aval, ana, err ); 00577 ASSERT_NO_ERROR( err ); 00578 CPPUNIT_ASSERT( valid ); 00579 CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL ); 00580 ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) ); 00581 00582 valid = num_grad( testMetric, I, B, nval, num, err ); 00583 ASSERT_NO_ERROR( err ); 00584 CPPUNIT_ASSERT( valid ); 00585 valid = grad( testMetric, I, B, aval, ana, err ); 00586 ASSERT_NO_ERROR( err ); 00587 CPPUNIT_ASSERT( valid ); 00588 CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL ); 00589 ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) ); 00590 00591 valid = num_grad( testMetric, B, I, nval, num, err ); 00592 ASSERT_NO_ERROR( err ); 00593 CPPUNIT_ASSERT( valid ); 00594 valid = grad( testMetric, B, I, aval, ana, err ); 00595 ASSERT_NO_ERROR( err ); 00596 CPPUNIT_ASSERT( valid ); 00597 CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL ); 00598 ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) ); 00599 00600 valid = num_grad( testMetric, A, B, nval, num, err ); 00601 ASSERT_NO_ERROR( err ); 00602 CPPUNIT_ASSERT( valid ); 00603 valid = grad( testMetric, A, B, aval, ana, err ); 00604 ASSERT_NO_ERROR( err ); 00605 CPPUNIT_ASSERT( valid ); 00606 CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL ); 00607 ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) ); 00608 00609 valid = num_grad( testMetric, A, I, nval, num, err ); 00610 ASSERT_NO_ERROR( err ); 00611 CPPUNIT_ASSERT( valid ); 00612 valid = grad( testMetric, A, I, aval, ana, err ); 00613 ASSERT_NO_ERROR( err ); 00614 CPPUNIT_ASSERT( valid ); 00615 CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL ); 00616 ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) ); 00617 00618 // also test inverted for non-barrier metrics 00619 if( Barrier ) return; 00620 00621 valid = num_grad( testMetric, C, I, nval, num, err ); 00622 ASSERT_NO_ERROR( err ); 00623 CPPUNIT_ASSERT( valid ); 00624 valid = grad( testMetric, C, I, aval, ana, err ); 00625 ASSERT_NO_ERROR( err ); 00626 CPPUNIT_ASSERT( valid ); 00627 CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL ); 00628 ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) ); 00629 } 00630 00631 TMETRIC_FUNC::compare_anaytic_and_numeric_hess() 00632 { 00633 const double EPS_VAL = 1e-6; 00634 00635 MsqError err; 00636 Matrix dmdA_num, dmdA_ana, d2mdA2_num[DIM * ( DIM + 1 ) / 2], d2mdA2_ana[DIM * ( DIM + 1 ) / 2]; 00637 bool valid; 00638 double val_num, val_ana; 00639 00640 valid = num_hess( testMetric, I, I, val_num, dmdA_num, d2mdA2_num, err ); 00641 ASSERT_NO_ERROR( err ); 00642 CPPUNIT_ASSERT( valid ); 00643 valid = hess( testMetric, I, I, val_ana, dmdA_ana, d2mdA2_ana, err ); 00644 ASSERT_NO_ERROR( err ); 00645 CPPUNIT_ASSERT( valid ); 00646 CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL ); 00647 ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) ); 00648 00649 switch( DIM ) 00650 { 00651 default: 00652 ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) ); 00653 ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) ); 00654 ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) ); 00655 case 2: 00656 ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) ); 00657 ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) ); 00658 ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) ); 00659 } 00660 00661 valid = num_hess( testMetric, I, A, val_num, dmdA_num, d2mdA2_num, err ); 00662 ASSERT_NO_ERROR( err ); 00663 CPPUNIT_ASSERT( valid ); 00664 valid = hess( testMetric, I, A, val_ana, dmdA_ana, d2mdA2_ana, err ); 00665 ASSERT_NO_ERROR( err ); 00666 CPPUNIT_ASSERT( valid ); 00667 CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL ); 00668 ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) ); 00669 switch( DIM ) 00670 { 00671 default: 00672 ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) ); 00673 ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) ); 00674 ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) ); 00675 case 2: 00676 ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) ); 00677 ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) ); 00678 ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) ); 00679 } 00680 00681 valid = num_hess( testMetric, A, I, val_num, dmdA_num, d2mdA2_num, err ); 00682 ASSERT_NO_ERROR( err ); 00683 CPPUNIT_ASSERT( valid ); 00684 valid = hess( testMetric, A, I, val_ana, dmdA_ana, d2mdA2_ana, err ); 00685 ASSERT_NO_ERROR( err ); 00686 CPPUNIT_ASSERT( valid ); 00687 CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL ); 00688 ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) ); 00689 switch( DIM ) 00690 { 00691 default: 00692 ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) ); 00693 ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) ); 00694 ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) ); 00695 case 2: 00696 ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) ); 00697 ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) ); 00698 ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) ); 00699 } 00700 00701 valid = num_hess( testMetric, B, I, val_num, dmdA_num, d2mdA2_num, err ); 00702 ASSERT_NO_ERROR( err ); 00703 CPPUNIT_ASSERT( valid ); 00704 valid = hess( testMetric, B, I, val_ana, dmdA_ana, d2mdA2_ana, err ); 00705 ASSERT_NO_ERROR( err ); 00706 CPPUNIT_ASSERT( valid ); 00707 CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL ); 00708 ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) ); 00709 switch( DIM ) 00710 { 00711 default: 00712 ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) ); 00713 ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) ); 00714 ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) ); 00715 case 2: 00716 ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) ); 00717 ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) ); 00718 ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) ); 00719 } 00720 00721 valid = num_hess( testMetric, I, B, val_num, dmdA_num, d2mdA2_num, err ); 00722 ASSERT_NO_ERROR( err ); 00723 CPPUNIT_ASSERT( valid ); 00724 valid = hess( testMetric, I, B, val_ana, dmdA_ana, d2mdA2_ana, err ); 00725 ASSERT_NO_ERROR( err ); 00726 CPPUNIT_ASSERT( valid ); 00727 CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL ); 00728 ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) ); 00729 switch( DIM ) 00730 { 00731 default: 00732 ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) ); 00733 ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) ); 00734 ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) ); 00735 case 2: 00736 ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) ); 00737 ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) ); 00738 ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) ); 00739 } 00740 00741 valid = num_hess( testMetric, A, B, val_num, dmdA_num, d2mdA2_num, err ); 00742 ASSERT_NO_ERROR( err ); 00743 CPPUNIT_ASSERT( valid ); 00744 valid = hess( testMetric, A, B, val_ana, dmdA_ana, d2mdA2_ana, err ); 00745 ASSERT_NO_ERROR( err ); 00746 CPPUNIT_ASSERT( valid ); 00747 CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL ); 00748 ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) ); 00749 switch( DIM ) 00750 { 00751 default: 00752 ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) ); 00753 ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) ); 00754 ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) ); 00755 case 2: 00756 ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) ); 00757 ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) ); 00758 ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) ); 00759 } 00760 00761 valid = num_hess( testMetric, B, A, val_num, dmdA_num, d2mdA2_num, err ); 00762 ASSERT_NO_ERROR( err ); 00763 CPPUNIT_ASSERT( valid ); 00764 valid = hess( testMetric, B, A, val_ana, dmdA_ana, d2mdA2_ana, err ); 00765 ASSERT_NO_ERROR( err ); 00766 CPPUNIT_ASSERT( valid ); 00767 CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL ); 00768 ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) ); 00769 switch( DIM ) 00770 { 00771 default: 00772 ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) ); 00773 ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) ); 00774 ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) ); 00775 case 2: 00776 ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) ); 00777 ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) ); 00778 ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) ); 00779 } 00780 00781 // also test inverted for non-barrier metrics 00782 if( Barrier ) return; 00783 00784 valid = num_hess( testMetric, C, I, val_num, dmdA_num, d2mdA2_num, err ); 00785 ASSERT_NO_ERROR( err ); 00786 CPPUNIT_ASSERT( valid ); 00787 valid = hess( testMetric, C, I, val_ana, dmdA_ana, d2mdA2_ana, err ); 00788 ASSERT_NO_ERROR( err ); 00789 CPPUNIT_ASSERT( valid ); 00790 CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL ); 00791 switch( DIM ) 00792 { 00793 default: 00794 ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) ); 00795 ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) ); 00796 ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) ); 00797 case 2: 00798 ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) ); 00799 ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) ); 00800 ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) ); 00801 } 00802 }