MOAB: Mesh Oriented datABase  (version 5.4.0)
TargetMetricTest.hpp
Go to the documentation of this file.
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,
00252                       MsqMatrix< DIM, DIM > A,
00253                       MsqMatrix< DIM, DIM > W,
00254                       double& value,
00255                       MsqMatrix< DIM, DIM >& dmdA,
00256                       MsqError& err )
00257     {
00258         bool rval = metric.evaluate_with_grad( A * inverse( W ), value, dmdA, err );
00259         dmdA      = dmdA * transpose( inverse( W ) );
00260         return rval;
00261     }
00262     inline bool num_grad( TMetric& metric,
00263                           MsqMatrix< DIM, DIM > A,
00264                           MsqMatrix< DIM, DIM > W,
00265                           double& value,
00266                           MsqMatrix< DIM, DIM >& dmdA,
00267                           MsqError& err )
00268     {
00269         bool rval = metric.evaluate_with_grad( A * inverse( W ), value, dmdA, err );
00270         dmdA      = dmdA * transpose( inverse( W ) );
00271         return rval;
00272     }
00273     inline bool hess( TMetric& metric,
00274                       MsqMatrix< DIM, DIM > A,
00275                       MsqMatrix< DIM, DIM > W,
00276                       double& value,
00277                       MsqMatrix< DIM, DIM >& dmdA,
00278                       MsqMatrix< DIM, DIM > d2mdA2[3],
00279                       MsqError& err )
00280     {
00281         bool rval = metric.evaluate_with_hess( A * inverse( W ), value, dmdA, d2mdA2, err );
00282         dmdA      = dmdA * transpose( inverse( W ) );
00283         for( unsigned i = 0; i < DIM * ( DIM + 1 ) / 2; ++i )
00284             d2mdA2[i] = inverse( W ) * d2mdA2[i] * transpose( inverse( W ) );
00285         return rval;
00286     }
00287     inline bool num_hess( TMetric& metric,
00288                           MsqMatrix< DIM, DIM > A,
00289                           MsqMatrix< DIM, DIM > W,
00290                           double& value,
00291                           MsqMatrix< DIM, DIM >& dmdA,
00292                           MsqMatrix< DIM, DIM > d2mdA2[3],
00293                           MsqError& err )
00294     {
00295         bool rval = metric.evaluate_with_hess( A * inverse( W ), value, dmdA, d2mdA2, err );
00296         dmdA      = dmdA * transpose( inverse( W ) );
00297         for( unsigned i = 0; i < DIM * ( DIM + 1 ) / 2; ++i )
00298             d2mdA2[i] = inverse( W ) * d2mdA2[i] * transpose( inverse( W ) );
00299         return rval;
00300     }
00301 
00302     // AWMetric
00303     inline bool eval( AWMetric& metric, MsqMatrix< DIM, DIM > A, MsqMatrix< DIM, DIM > W, double& value, MsqError& err )
00304     {
00305         bool rval = metric.evaluate( A, W, value, err );
00306         return rval;
00307     }
00308     inline bool grad( AWMetric& metric,
00309                       MsqMatrix< DIM, DIM > A,
00310                       MsqMatrix< DIM, DIM > W,
00311                       double& value,
00312                       MsqMatrix< DIM, DIM >& dmdA,
00313                       MsqError& err )
00314     {
00315         bool rval = metric.evaluate_with_grad( A, W, value, dmdA, err );
00316         return rval;
00317     }
00318     inline bool num_grad( AWMetric& metric,
00319                           MsqMatrix< DIM, DIM > A,
00320                           MsqMatrix< DIM, DIM > W,
00321                           double& value,
00322                           MsqMatrix< DIM, DIM >& dmdA,
00323                           MsqError& err )
00324     {
00325         bool rval = metric.evaluate_with_grad( A, W, value, dmdA, err );
00326         return rval;
00327     }
00328     inline bool hess( AWMetric& metric,
00329                       MsqMatrix< DIM, DIM > A,
00330                       MsqMatrix< DIM, DIM > W,
00331                       double& value,
00332                       MsqMatrix< DIM, DIM >& dmdA,
00333                       MsqMatrix< DIM, DIM > d2mdA2[3],
00334                       MsqError& err )
00335     {
00336         bool rval = metric.evaluate_with_hess( A, W, value, dmdA, d2mdA2, err );
00337         return rval;
00338     }
00339     inline bool num_hess( AWMetric& metric,
00340                           MsqMatrix< DIM, DIM > A,
00341                           MsqMatrix< DIM, DIM > W,
00342                           double& value,
00343                           MsqMatrix< DIM, DIM >& dmdA,
00344                           MsqMatrix< DIM, DIM > d2mdA2[3],
00345                           MsqError& err )
00346     {
00347         bool rval = metric.evaluate_with_hess( A, W, value, dmdA, d2mdA2, err );
00348         return rval;
00349     }
00350 };
00351 
00352 #define TMETRIC_FUNC                        \
00353     template < class Metric, unsigned DIM > \
00354     void TMetricTest< Metric, DIM >
00355 #define MAT_TYPE TMetricTest< Metric, DIM >::Matrix
00356 
00357 /*************************************************************************
00358  *          Implement actual (templatized) test code
00359  *************************************************************************/
00360 
00361 TMETRIC_FUNC::test_ideal_eval()
00362 {
00363     MsqPrintError err( std::cerr );
00364     double val, eps = 5e-5;
00365     bool valid;
00366 
00367     valid = eval( testMetric, I, I, val, err );
00368     ASSERT_NO_ERROR( err );
00369     CPPUNIT_ASSERT( valid );
00370     CPPUNIT_ASSERT_DOUBLES_EQUAL( idealVal, val, eps );
00371 
00372     valid = eval( testMetric, A, A, val, err );
00373     ASSERT_NO_ERROR( err );
00374     CPPUNIT_ASSERT( valid );
00375     CPPUNIT_ASSERT_DOUBLES_EQUAL( idealVal, val, eps );
00376 
00377     valid = eval( testMetric, B, B, val, err );
00378     ASSERT_NO_ERROR( err );
00379     CPPUNIT_ASSERT( valid );
00380     CPPUNIT_ASSERT_DOUBLES_EQUAL( idealVal, val, eps );
00381 }
00382 
00383 TMETRIC_FUNC::test_ideal_gradient()
00384 {
00385     MsqPrintError err( std::cerr );
00386     MsqMatrix< DIM, DIM > g;
00387     double val, eps = 5e-3;
00388     bool valid;
00389 
00390     valid = grad( testMetric, I, I, val, g, err );
00391     ASSERT_NO_ERROR( err );
00392     CPPUNIT_ASSERT( valid );
00393     ASSERT_MATRICES_EQUAL( Zero, g, eps );
00394 
00395     valid = grad( testMetric, A, A, val, g, err );
00396     ASSERT_NO_ERROR( err );
00397     CPPUNIT_ASSERT( valid );
00398     ASSERT_MATRICES_EQUAL( Zero, g, eps );
00399 
00400     valid = grad( testMetric, B, B, val, g, err );
00401     ASSERT_NO_ERROR( err );
00402     CPPUNIT_ASSERT( valid );
00403     ASSERT_MATRICES_EQUAL( Zero, g, eps );
00404 }
00405 
00406 TMETRIC_FUNC::test_inverted()
00407 {
00408     MsqPrintError err( std::cerr );
00409     MsqMatrix< DIM, DIM > V( 1.0 ), W( 1.0 ), g, h[6];
00410     V( DIM - 1, DIM - 1 ) = -1.0;
00411     double val;
00412     bool valid;
00413 
00414     if( Barrier )
00415     {
00416         valid = eval( testMetric, V, W, val, err );
00417         if( err.error_code() == err.BARRIER_VIOLATED ) err.clear();
00418         ASSERT_NO_ERROR( err );
00419         CPPUNIT_ASSERT( !valid );
00420 
00421         valid = grad( testMetric, V, W, val, g, err );
00422         if( err.error_code() == err.BARRIER_VIOLATED ) err.clear();
00423         ASSERT_NO_ERROR( err );
00424         CPPUNIT_ASSERT( !valid );
00425 
00426         valid = hess( testMetric, V, W, val, g, h, err );
00427         if( err.error_code() == err.BARRIER_VIOLATED ) err.clear();
00428         ASSERT_NO_ERROR( err );
00429         CPPUNIT_ASSERT( !valid );
00430     }
00431     else
00432     {
00433         valid = eval( testMetric, V, W, val, err );
00434         ASSERT_NO_ERROR( err );
00435         CPPUNIT_ASSERT( valid );
00436         CPPUNIT_ASSERT( val > idealVal );
00437 
00438         valid = grad( testMetric, V, W, val, g, err );
00439         ASSERT_NO_ERROR( err );
00440         CPPUNIT_ASSERT( valid );
00441         CPPUNIT_ASSERT( val > idealVal );
00442         CPPUNIT_ASSERT( sqr_Frobenius( g ) > 1e-6 );
00443     }
00444 }
00445 
00446 TMETRIC_FUNC::test_non_ideal( bool sensitive, Matrix J, Matrix W )
00447 {
00448     MsqPrintError err( std::cerr );
00449     MsqMatrix< DIM, DIM > g;
00450     double val, eps = 1e-5;
00451     bool valid;
00452     if( !sensitive )
00453     {
00454         valid = eval( testMetric, J, W, val, err );
00455         ASSERT_NO_ERROR( err );
00456         CPPUNIT_ASSERT( valid );
00457         CPPUNIT_ASSERT_DOUBLES_EQUAL( idealVal, val, eps );
00458 
00459         valid = grad( testMetric, J, W, val, g, err );
00460         ASSERT_NO_ERROR( err );
00461         CPPUNIT_ASSERT( valid );
00462         CPPUNIT_ASSERT_DOUBLES_EQUAL( idealVal, val, eps );
00463         ASSERT_MATRICES_EQUAL( ( MsqMatrix< DIM, DIM >( 0.0 ) ), g, eps );
00464     }
00465     else
00466     {
00467         valid = eval( testMetric, J, W, val, err );
00468         ASSERT_NO_ERROR( err );
00469         CPPUNIT_ASSERT( valid );
00470         CPPUNIT_ASSERT( val > idealVal );
00471     }
00472 }
00473 
00474 TMETRIC_FUNC::test_shape()
00475 {
00476     const double r3          = sqrt( 3.0 );
00477     const double U_vals[][9] = { { 2 / r3, 1 / r3, 1 / r3, 2 / r3 },
00478                                  { 2 / r3, 1 / r3, 0, 1 / r3, 2 / r3, 0, 0, 0, 1 } };
00479     Matrix U( U_vals[DIM - 2] ), W( 1.0 );
00480     test_non_ideal( !shapeInvariant, U, W );
00481 }
00482 
00483 TMETRIC_FUNC::test_scale()
00484 {
00485     Matrix L( 2.0 ), W( 1.0 );
00486     test_non_ideal( !sizeInvariant, L, W );
00487 }
00488 
00489 TMETRIC_FUNC::test_orient()
00490 {
00491     const double V_vals[][9] = { { 0, -1, 1, 0 }, { 0, -1, 0, 1, 0, 0, 0, 0, 1 } };
00492     Matrix V( V_vals[DIM - 2] ), W( 1.0 );
00493     test_non_ideal( !orientInvariant, V, W );
00494 }
00495 
00496 static double releps( double a )
00497 {
00498     return std::max( 1e-6, 1e-8 * fabs( a ) );
00499 }
00500 
00501 TMETRIC_FUNC::compare_eval_and_eval_with_grad()
00502 {
00503     MsqError err;
00504     Matrix g;
00505     bool valid;
00506     double gv, v;
00507 
00508     valid = grad( testMetric, I, A, gv, g, err );
00509     ASSERT_NO_ERROR( err );
00510     CPPUNIT_ASSERT( valid );
00511     valid = eval( testMetric, I, A, v, err );
00512     ASSERT_NO_ERROR( err );
00513     CPPUNIT_ASSERT( valid );
00514     CPPUNIT_ASSERT_DOUBLES_EQUAL( v, gv, releps( v ) );
00515 
00516     valid = grad( testMetric, A, B, gv, g, err );
00517     ASSERT_NO_ERROR( err );
00518     CPPUNIT_ASSERT( valid );
00519     valid = eval( testMetric, A, B, v, err );
00520     ASSERT_NO_ERROR( err );
00521     CPPUNIT_ASSERT( valid );
00522     CPPUNIT_ASSERT_DOUBLES_EQUAL( v, gv, releps( v ) );
00523 
00524     // also test inverted for non-barrier metrics
00525     if( Barrier ) return;
00526 
00527     valid = grad( testMetric, C, I, gv, g, err );
00528     ASSERT_NO_ERROR( err );
00529     CPPUNIT_ASSERT( valid );
00530     valid = eval( testMetric, C, I, v, err );
00531     ASSERT_NO_ERROR( err );
00532     CPPUNIT_ASSERT( valid );
00533     CPPUNIT_ASSERT_DOUBLES_EQUAL( v, gv, releps( v ) );
00534 }
00535 
00536 TMETRIC_FUNC::compare_eval_with_grad_and_eval_with_hess()
00537 {
00538     MsqError err;
00539     Matrix g, h, H[DIM * ( DIM + 1 ) / 2];
00540     bool valid;
00541     double gv, hv;
00542 
00543     valid = grad( testMetric, I, A, gv, g, err );
00544     ASSERT_NO_ERROR( err );
00545     CPPUNIT_ASSERT( valid );
00546     valid = hess( testMetric, I, A, hv, h, H, err );
00547     ASSERT_NO_ERROR( err );
00548     CPPUNIT_ASSERT( valid );
00549     CPPUNIT_ASSERT_DOUBLES_EQUAL( gv, hv, releps( gv ) );
00550     ASSERT_MATRICES_EQUAL( g, h, 1e-5 );
00551 
00552     valid = grad( testMetric, A, B, gv, g, err );
00553     ASSERT_NO_ERROR( err );
00554     CPPUNIT_ASSERT( valid );
00555     valid = hess( testMetric, A, B, hv, h, H, err );
00556     ASSERT_NO_ERROR( err );
00557     CPPUNIT_ASSERT( valid );
00558     CPPUNIT_ASSERT_DOUBLES_EQUAL( gv, hv, releps( gv ) );
00559     ASSERT_MATRICES_EQUAL( g, h, 1e-5 );
00560 
00561     // also test inverted for non-barrier metrics
00562     if( Barrier ) return;
00563 
00564     valid = grad( testMetric, C, I, gv, g, err );
00565     ASSERT_NO_ERROR( err );
00566     CPPUNIT_ASSERT( valid );
00567     valid = hess( testMetric, C, I, hv, h, H, err );
00568     ASSERT_NO_ERROR( err );
00569     CPPUNIT_ASSERT( valid );
00570     CPPUNIT_ASSERT_DOUBLES_EQUAL( gv, hv, releps( gv ) );
00571     ASSERT_MATRICES_EQUAL( g, h, 1e-5 );
00572 }
00573 
00574 template < typename M >
00575 double eps_mat( const M& mu )
00576 {
00577     return std::max( Frobenius( mu ) * 1e-2, 1e-4 );
00578 }
00579 
00580 TMETRIC_FUNC::compare_anaytic_and_numeric_grads()
00581 {
00582     const double EPS_VAL = 1e-6;
00583 
00584     MsqError err;
00585     Matrix num, ana;
00586     bool valid;
00587     double nval, aval;
00588 
00589     Matrix D( I );
00590     D( 0, 0 ) += 1e-5;
00591     valid = num_grad( testMetric, D, I, nval, num, err );
00592     ASSERT_NO_ERROR( err );
00593     CPPUNIT_ASSERT( valid );
00594     valid = grad( testMetric, D, 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, I, A, nval, num, err );
00601     ASSERT_NO_ERROR( err );
00602     CPPUNIT_ASSERT( valid );
00603     valid = grad( testMetric, I, A, 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     valid = num_grad( testMetric, I, B, nval, num, err );
00619     ASSERT_NO_ERROR( err );
00620     CPPUNIT_ASSERT( valid );
00621     valid = grad( testMetric, I, B, aval, ana, err );
00622     ASSERT_NO_ERROR( err );
00623     CPPUNIT_ASSERT( valid );
00624     CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL );
00625     ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) );
00626 
00627     valid = num_grad( testMetric, B, I, nval, num, err );
00628     ASSERT_NO_ERROR( err );
00629     CPPUNIT_ASSERT( valid );
00630     valid = grad( testMetric, B, I, aval, ana, err );
00631     ASSERT_NO_ERROR( err );
00632     CPPUNIT_ASSERT( valid );
00633     CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL );
00634     ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) );
00635 
00636     valid = num_grad( testMetric, A, B, nval, num, err );
00637     ASSERT_NO_ERROR( err );
00638     CPPUNIT_ASSERT( valid );
00639     valid = grad( testMetric, A, B, aval, ana, err );
00640     ASSERT_NO_ERROR( err );
00641     CPPUNIT_ASSERT( valid );
00642     CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL );
00643     ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) );
00644 
00645     valid = num_grad( testMetric, A, I, nval, num, err );
00646     ASSERT_NO_ERROR( err );
00647     CPPUNIT_ASSERT( valid );
00648     valid = grad( testMetric, A, I, aval, ana, err );
00649     ASSERT_NO_ERROR( err );
00650     CPPUNIT_ASSERT( valid );
00651     CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL );
00652     ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) );
00653 
00654     // also test inverted for non-barrier metrics
00655     if( Barrier ) return;
00656 
00657     valid = num_grad( testMetric, C, I, nval, num, err );
00658     ASSERT_NO_ERROR( err );
00659     CPPUNIT_ASSERT( valid );
00660     valid = grad( testMetric, C, I, aval, ana, err );
00661     ASSERT_NO_ERROR( err );
00662     CPPUNIT_ASSERT( valid );
00663     CPPUNIT_ASSERT_DOUBLES_EQUAL( nval, aval, EPS_VAL );
00664     ASSERT_MATRICES_EQUAL( num, ana, eps_mat( num ) );
00665 }
00666 
00667 TMETRIC_FUNC::compare_anaytic_and_numeric_hess()
00668 {
00669     const double EPS_VAL = 1e-6;
00670 
00671     MsqError err;
00672     Matrix dmdA_num, dmdA_ana, d2mdA2_num[DIM * ( DIM + 1 ) / 2], d2mdA2_ana[DIM * ( DIM + 1 ) / 2];
00673     bool valid;
00674     double val_num, val_ana;
00675 
00676     valid = num_hess( testMetric, I, I, val_num, dmdA_num, d2mdA2_num, err );
00677     ASSERT_NO_ERROR( err );
00678     CPPUNIT_ASSERT( valid );
00679     valid = hess( testMetric, I, I, val_ana, dmdA_ana, d2mdA2_ana, err );
00680     ASSERT_NO_ERROR( err );
00681     CPPUNIT_ASSERT( valid );
00682     CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL );
00683     ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) );
00684 
00685     switch( DIM )
00686     {
00687         default:
00688             ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) );
00689             ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) );
00690             ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) );
00691         case 2:
00692             ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) );
00693             ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) );
00694             ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) );
00695     }
00696 
00697     valid = num_hess( testMetric, I, A, val_num, dmdA_num, d2mdA2_num, err );
00698     ASSERT_NO_ERROR( err );
00699     CPPUNIT_ASSERT( valid );
00700     valid = hess( testMetric, I, A, val_ana, dmdA_ana, d2mdA2_ana, err );
00701     ASSERT_NO_ERROR( err );
00702     CPPUNIT_ASSERT( valid );
00703     CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL );
00704     ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) );
00705     switch( DIM )
00706     {
00707         default:
00708             ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) );
00709             ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) );
00710             ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) );
00711         case 2:
00712             ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) );
00713             ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) );
00714             ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) );
00715     }
00716 
00717     valid = num_hess( testMetric, A, I, val_num, dmdA_num, d2mdA2_num, err );
00718     ASSERT_NO_ERROR( err );
00719     CPPUNIT_ASSERT( valid );
00720     valid = hess( testMetric, A, I, val_ana, dmdA_ana, d2mdA2_ana, err );
00721     ASSERT_NO_ERROR( err );
00722     CPPUNIT_ASSERT( valid );
00723     CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL );
00724     ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) );
00725     switch( DIM )
00726     {
00727         default:
00728             ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) );
00729             ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) );
00730             ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) );
00731         case 2:
00732             ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) );
00733             ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) );
00734             ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) );
00735     }
00736 
00737     valid = num_hess( testMetric, B, I, val_num, dmdA_num, d2mdA2_num, err );
00738     ASSERT_NO_ERROR( err );
00739     CPPUNIT_ASSERT( valid );
00740     valid = hess( testMetric, B, I, val_ana, dmdA_ana, d2mdA2_ana, err );
00741     ASSERT_NO_ERROR( err );
00742     CPPUNIT_ASSERT( valid );
00743     CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL );
00744     ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) );
00745     switch( DIM )
00746     {
00747         default:
00748             ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) );
00749             ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) );
00750             ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) );
00751         case 2:
00752             ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) );
00753             ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) );
00754             ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) );
00755     }
00756 
00757     valid = num_hess( testMetric, I, B, val_num, dmdA_num, d2mdA2_num, err );
00758     ASSERT_NO_ERROR( err );
00759     CPPUNIT_ASSERT( valid );
00760     valid = hess( testMetric, I, B, val_ana, dmdA_ana, d2mdA2_ana, err );
00761     ASSERT_NO_ERROR( err );
00762     CPPUNIT_ASSERT( valid );
00763     CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL );
00764     ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) );
00765     switch( DIM )
00766     {
00767         default:
00768             ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) );
00769             ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) );
00770             ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) );
00771         case 2:
00772             ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) );
00773             ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) );
00774             ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) );
00775     }
00776 
00777     valid = num_hess( testMetric, A, B, val_num, dmdA_num, d2mdA2_num, err );
00778     ASSERT_NO_ERROR( err );
00779     CPPUNIT_ASSERT( valid );
00780     valid = hess( testMetric, A, B, val_ana, dmdA_ana, d2mdA2_ana, err );
00781     ASSERT_NO_ERROR( err );
00782     CPPUNIT_ASSERT( valid );
00783     CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL );
00784     ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) );
00785     switch( DIM )
00786     {
00787         default:
00788             ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) );
00789             ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) );
00790             ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) );
00791         case 2:
00792             ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) );
00793             ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) );
00794             ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) );
00795     }
00796 
00797     valid = num_hess( testMetric, B, A, val_num, dmdA_num, d2mdA2_num, err );
00798     ASSERT_NO_ERROR( err );
00799     CPPUNIT_ASSERT( valid );
00800     valid = hess( testMetric, B, A, val_ana, dmdA_ana, d2mdA2_ana, err );
00801     ASSERT_NO_ERROR( err );
00802     CPPUNIT_ASSERT( valid );
00803     CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL );
00804     ASSERT_MATRICES_EQUAL( dmdA_num, dmdA_ana, eps_mat( dmdA_num ) );
00805     switch( DIM )
00806     {
00807         default:
00808             ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) );
00809             ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) );
00810             ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) );
00811         case 2:
00812             ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) );
00813             ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) );
00814             ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) );
00815     }
00816 
00817     // also test inverted for non-barrier metrics
00818     if( Barrier ) return;
00819 
00820     valid = num_hess( testMetric, C, I, val_num, dmdA_num, d2mdA2_num, err );
00821     ASSERT_NO_ERROR( err );
00822     CPPUNIT_ASSERT( valid );
00823     valid = hess( testMetric, C, I, val_ana, dmdA_ana, d2mdA2_ana, err );
00824     ASSERT_NO_ERROR( err );
00825     CPPUNIT_ASSERT( valid );
00826     CPPUNIT_ASSERT_DOUBLES_EQUAL( val_num, val_ana, EPS_VAL );
00827     switch( DIM )
00828     {
00829         default:
00830             ASSERT_MATRICES_EQUAL( d2mdA2_num[3], d2mdA2_ana[3], eps_mat( d2mdA2_num[3] ) );
00831             ASSERT_MATRICES_EQUAL( d2mdA2_num[4], d2mdA2_ana[4], eps_mat( d2mdA2_num[4] ) );
00832             ASSERT_MATRICES_EQUAL( d2mdA2_num[5], d2mdA2_ana[5], eps_mat( d2mdA2_num[5] ) );
00833         case 2:
00834             ASSERT_MATRICES_EQUAL( d2mdA2_num[0], d2mdA2_ana[0], eps_mat( d2mdA2_num[0] ) );
00835             ASSERT_MATRICES_EQUAL( d2mdA2_num[1], d2mdA2_ana[1], eps_mat( d2mdA2_num[1] ) );
00836             ASSERT_MATRICES_EQUAL( d2mdA2_num[2], d2mdA2_ana[2], eps_mat( d2mdA2_num[2] ) );
00837     }
00838 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines