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 (2006) [email protected] 00024 00025 ***************************************************************** */ 00026 00027 /** \file CompositeMetricTest.cpp 00028 * \brief unit tests for IdealWeightMeanRatio quality metric 00029 * \author Jason Kraftcheck 00030 */ 00031 00032 #include "Mesquite.hpp" 00033 #include "IdealWeightInverseMeanRatio.hpp" 00034 #include "LocalSizeQualityMetric.hpp" 00035 #include "ConditionNumberQualityMetric.hpp" 00036 #include "cppunit/extensions/HelperMacros.h" 00037 #include "QualityMetricTester.hpp" 00038 #include "AddQualityMetric.hpp" 00039 #include "MultiplyQualityMetric.hpp" 00040 #include "PowerQualityMetric.hpp" 00041 #include "ScalarAddQualityMetric.hpp" 00042 #include "ScalarMultiplyQualityMetric.hpp" 00043 #include "MsqError.hpp" 00044 #include "PatchData.hpp" 00045 #include "UnitUtil.hpp" 00046 00047 using namespace MBMesquite; 00048 00049 class CompositeMetricTestBase : public CppUnit::TestFixture 00050 { 00051 private: 00052 void test_evaluate( bool ideal, EntityTopology type ); 00053 00054 protected: 00055 QualityMetricTester tester; 00056 QualityMetric* mMetric; 00057 virtual bool evaluate( PatchData&, size_t, double&, MsqError& ) = 0; 00058 00059 public: 00060 CompositeMetricTestBase() : tester( QualityMetricTester::ALL_FE_EXCEPT_SEPTAHEDRON ), mMetric( 0 ) 00061 { 00062 tester.ideal_pyramid_base_equals_height( true ); 00063 } 00064 00065 void test_supported_types() 00066 { 00067 tester.test_supported_element_types( mMetric ); 00068 } 00069 00070 void test_ideal_element_eval() 00071 { 00072 test_evaluate( true, TRIANGLE ); 00073 test_evaluate( true, QUADRILATERAL ); 00074 test_evaluate( true, TETRAHEDRON ); 00075 test_evaluate( true, HEXAHEDRON ); 00076 test_evaluate( true, PRISM ); 00077 test_evaluate( true, PYRAMID ); 00078 } 00079 00080 void test_non_ideal_eval() 00081 { 00082 test_evaluate( false, TRIANGLE ); 00083 test_evaluate( false, QUADRILATERAL ); 00084 test_evaluate( false, TETRAHEDRON ); 00085 test_evaluate( false, HEXAHEDRON ); 00086 test_evaluate( false, PRISM ); 00087 test_evaluate( false, PYRAMID ); 00088 } 00089 00090 void test_ideal_element_grad() 00091 { 00092 tester.test_ideal_element_zero_gradient( mMetric, false ); 00093 } 00094 00095 void test_ideal_element_hess() 00096 { 00097 tester.test_ideal_element_positive_definite_Hessian( mMetric, false ); 00098 } 00099 00100 void test_valid_hessian() 00101 { 00102 tester.test_symmetric_Hessian_diagonal_blocks( mMetric ); 00103 } 00104 00105 void test_measures_quality() 00106 { 00107 tester.test_measures_quality( mMetric ); 00108 } 00109 00110 void test_gradient_reflects_quality() 00111 { 00112 tester.test_gradient_reflects_quality( mMetric ); 00113 } 00114 00115 void test_domain_deviation() 00116 { 00117 tester.test_domain_deviation_quality( mMetric ); 00118 tester.test_domain_deviation_gradient( mMetric ); 00119 } 00120 00121 void test_inverted_elements() 00122 { 00123 tester.test_evaluate_inverted_element( mMetric, false ); 00124 } 00125 00126 void test_degenerate_elements() 00127 { 00128 tester.test_evaluate_degenerate_element( mMetric, false ); 00129 } 00130 00131 void test_get_evaluations() 00132 { 00133 tester.test_get_element_evaluations( mMetric ); 00134 } 00135 00136 void test_get_element_indices() 00137 { 00138 tester.test_get_element_indices( mMetric ); 00139 } 00140 00141 void test_get_fixed_indices() 00142 { 00143 tester.test_get_indices_fixed( mMetric ); 00144 } 00145 00146 void test_eval_with_indices() 00147 { 00148 tester.compare_eval_and_eval_with_indices( mMetric ); 00149 } 00150 00151 void test_eval_with_gradient() 00152 { 00153 tester.compare_eval_with_indices_and_eval_with_gradient( mMetric ); 00154 tester.compare_analytical_and_numerical_gradients( mMetric ); 00155 } 00156 00157 void test_eval_with_hessian() 00158 { 00159 tester.compare_eval_with_indices_and_eval_with_hessian( mMetric ); 00160 tester.compare_eval_with_grad_and_eval_with_hessian( mMetric ); 00161 tester.compare_analytical_and_numerical_hessians( mMetric ); 00162 } 00163 00164 void test_location_invariant() 00165 { 00166 tester.test_location_invariant( mMetric ); 00167 tester.test_grad_location_invariant( mMetric ); 00168 tester.test_hessian_location_invariant( mMetric ); 00169 } 00170 00171 void test_scale_invariant() 00172 { 00173 tester.test_scale_invariant( mMetric ); 00174 } 00175 00176 void test_orient_invariant() 00177 { 00178 tester.test_orient_invariant( mMetric ); 00179 tester.test_grad_orient_invariant( mMetric ); 00180 } 00181 }; 00182 00183 void CompositeMetricTestBase::test_evaluate( bool ideal, EntityTopology type ) 00184 { 00185 MsqPrintError err( std::cout ); 00186 PatchData pd; 00187 double act, ex; 00188 bool rval; 00189 00190 if( ideal ) 00191 tester.get_ideal_element( type, false, pd, false ); 00192 else 00193 tester.get_nonideal_element( type, pd ); 00194 00195 rval = mMetric->evaluate( pd, 0, act, err ); 00196 ASSERT_NO_ERROR( err ); 00197 CPPUNIT_ASSERT( rval ); 00198 00199 rval = this->evaluate( pd, 0, ex, err ); 00200 ASSERT_NO_ERROR( err ); 00201 CPPUNIT_ASSERT( rval ); 00202 00203 CPPUNIT_ASSERT_DOUBLES_EQUAL( ex, act, 1e-6 ); 00204 } 00205 00206 class AddQualityMetricTest : public CompositeMetricTestBase 00207 { 00208 00209 CPPUNIT_TEST_SUITE( AddQualityMetricTest ); 00210 CPPUNIT_TEST( test_supported_types ); 00211 CPPUNIT_TEST( test_ideal_element_eval ); 00212 CPPUNIT_TEST( test_ideal_element_grad ); 00213 CPPUNIT_TEST( test_ideal_element_hess ); 00214 CPPUNIT_TEST( test_non_ideal_eval ); 00215 CPPUNIT_TEST( test_valid_hessian ); 00216 CPPUNIT_TEST( test_inverted_elements ); 00217 CPPUNIT_TEST( test_degenerate_elements ); 00218 CPPUNIT_TEST( test_get_evaluations ); 00219 CPPUNIT_TEST( test_get_element_indices ); 00220 CPPUNIT_TEST( test_get_fixed_indices ); 00221 CPPUNIT_TEST( test_eval_with_indices ); 00222 CPPUNIT_TEST( test_eval_with_gradient ); 00223 CPPUNIT_TEST( test_eval_with_hessian ); 00224 CPPUNIT_TEST_SUITE_END(); 00225 00226 private: 00227 MsqError mErr; 00228 IdealWeightInverseMeanRatio m1; 00229 IdealWeightInverseMeanRatio m2; 00230 AddQualityMetric m; 00231 00232 protected: 00233 virtual bool evaluate( PatchData&, size_t, double&, MsqError& ); 00234 00235 public: 00236 AddQualityMetricTest() : m2( mErr, 2.0 ), m( &m1, &m2, mErr ) 00237 { 00238 mMetric = &m; 00239 } 00240 void setUp() 00241 { 00242 CPPUNIT_ASSERT( !mErr ); 00243 } 00244 }; 00245 00246 bool AddQualityMetricTest::evaluate( PatchData& pd, size_t h, double& val, MsqError& err ) 00247 { 00248 double v1, v2; 00249 bool rval = true, rval1; 00250 00251 rval1 = m1.evaluate( pd, h, v1, err ); 00252 MSQ_ERRFALSE( err ); 00253 if( !rval1 ) rval = false; 00254 00255 rval1 = m2.evaluate( pd, h, v2, err ); 00256 MSQ_ERRFALSE( err ); 00257 if( !rval1 ) rval = false; 00258 00259 val = v1 + v2; 00260 return rval; 00261 } 00262 00263 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AddQualityMetricTest, "CompositeMetricTest" ); 00264 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AddQualityMetricTest, "AddQualityMetricTest" ); 00265 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AddQualityMetricTest, "Unit" ); 00266 00267 class MultiplyQualityMetricTest : public CompositeMetricTestBase 00268 { 00269 private: 00270 CPPUNIT_TEST_SUITE( MultiplyQualityMetricTest ); 00271 CPPUNIT_TEST( test_supported_types ); 00272 CPPUNIT_TEST( test_ideal_element_eval ); 00273 CPPUNIT_TEST( test_ideal_element_grad ); 00274 CPPUNIT_TEST( test_ideal_element_hess ); 00275 CPPUNIT_TEST( test_non_ideal_eval ); 00276 CPPUNIT_TEST( test_valid_hessian ); 00277 CPPUNIT_TEST( test_inverted_elements ); 00278 CPPUNIT_TEST( test_degenerate_elements ); 00279 CPPUNIT_TEST( test_get_evaluations ); 00280 CPPUNIT_TEST( test_get_element_indices ); 00281 CPPUNIT_TEST( test_get_fixed_indices ); 00282 CPPUNIT_TEST( test_eval_with_indices ); 00283 CPPUNIT_TEST( test_eval_with_gradient ); 00284 CPPUNIT_TEST( test_eval_with_hessian ); 00285 CPPUNIT_TEST_SUITE_END(); 00286 00287 MsqError mErr; 00288 IdealWeightInverseMeanRatio m1; 00289 IdealWeightInverseMeanRatio m2; 00290 MultiplyQualityMetric m; 00291 00292 protected: 00293 virtual bool evaluate( PatchData&, size_t, double&, MsqError& ); 00294 00295 public: 00296 MultiplyQualityMetricTest() : m2( mErr, 2.0 ), m( &m1, &m2, mErr ) 00297 { 00298 mMetric = &m; 00299 } 00300 void setUp() 00301 { 00302 CPPUNIT_ASSERT( !mErr ); 00303 } 00304 }; 00305 00306 bool MultiplyQualityMetricTest::evaluate( PatchData& pd, size_t h, double& val, MsqError& err ) 00307 { 00308 double v1, v2; 00309 bool rval = true, rval1; 00310 00311 rval1 = m1.evaluate( pd, h, v1, err ); 00312 MSQ_ERRFALSE( err ); 00313 if( !rval1 ) rval = false; 00314 00315 rval1 = m2.evaluate( pd, h, v2, err ); 00316 MSQ_ERRFALSE( err ); 00317 if( !rval1 ) rval = false; 00318 00319 val = v1 * v2; 00320 return rval; 00321 } 00322 00323 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MultiplyQualityMetricTest, "CompositeMetricTest" ); 00324 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MultiplyQualityMetricTest, "MultiplyQualityMetricTest" ); 00325 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MultiplyQualityMetricTest, "Unit" ); 00326 00327 template < int POWER > 00328 class PowerQualityMetricTest : public CompositeMetricTestBase 00329 { 00330 private: 00331 CPPUNIT_TEST_SUITE( PowerQualityMetricTest< POWER > ); 00332 CPPUNIT_TEST( test_supported_types ); 00333 CPPUNIT_TEST( test_ideal_element_eval ); 00334 CPPUNIT_TEST( test_ideal_element_grad ); 00335 // CPPUNIT_TEST (test_ideal_element_hess); 00336 CPPUNIT_TEST( test_non_ideal_eval ); 00337 CPPUNIT_TEST( test_valid_hessian ); 00338 CPPUNIT_TEST( test_inverted_elements ); 00339 CPPUNIT_TEST( test_degenerate_elements ); 00340 CPPUNIT_TEST( test_get_evaluations ); 00341 CPPUNIT_TEST( test_get_element_indices ); 00342 CPPUNIT_TEST( test_get_fixed_indices ); 00343 CPPUNIT_TEST( test_eval_with_indices ); 00344 CPPUNIT_TEST( test_eval_with_gradient ); 00345 CPPUNIT_TEST( test_eval_with_hessian ); 00346 CPPUNIT_TEST_SUITE_END(); 00347 00348 IdealWeightInverseMeanRatio m1; 00349 PowerQualityMetric m; 00350 00351 protected: 00352 virtual bool evaluate( PatchData&, size_t, double&, MsqError& ); 00353 00354 public: 00355 PowerQualityMetricTest() : m( &m1, POWER ) 00356 { 00357 mMetric = &m; 00358 } 00359 }; 00360 00361 template < int POWER > 00362 bool PowerQualityMetricTest< POWER >::evaluate( PatchData& pd, size_t h, double& val, MsqError& err ) 00363 { 00364 bool rval = m1.evaluate( pd, h, val, err ); 00365 MSQ_ERRFALSE( err ); 00366 val = std::pow( val, POWER ); 00367 return rval; 00368 } 00369 00370 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PowerQualityMetricTest< 1 >, "CompositeMetricTest" ); 00371 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PowerQualityMetricTest< 2 >, "CompositeMetricTest" ); 00372 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PowerQualityMetricTest< 1 >, "PowerQualityMetricTest" ); 00373 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PowerQualityMetricTest< 2 >, "PowerQualityMetricTest" ); 00374 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PowerQualityMetricTest< 1 >, "Unit" ); 00375 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PowerQualityMetricTest< 2 >, "Unit" ); 00376 00377 template < int OFFSET > 00378 class ScalarAddMetricTest : public CompositeMetricTestBase 00379 { 00380 private: 00381 CPPUNIT_TEST_SUITE( ScalarAddMetricTest< OFFSET > ); 00382 CPPUNIT_TEST( test_supported_types ); 00383 CPPUNIT_TEST( test_ideal_element_eval ); 00384 CPPUNIT_TEST( test_ideal_element_grad ); 00385 CPPUNIT_TEST( test_ideal_element_hess ); 00386 CPPUNIT_TEST( test_non_ideal_eval ); 00387 CPPUNIT_TEST( test_valid_hessian ); 00388 CPPUNIT_TEST( test_inverted_elements ); 00389 CPPUNIT_TEST( test_degenerate_elements ); 00390 CPPUNIT_TEST( test_get_evaluations ); 00391 CPPUNIT_TEST( test_get_element_indices ); 00392 CPPUNIT_TEST( test_get_fixed_indices ); 00393 CPPUNIT_TEST( test_eval_with_indices ); 00394 CPPUNIT_TEST( test_eval_with_gradient ); 00395 CPPUNIT_TEST( test_eval_with_hessian ); 00396 CPPUNIT_TEST_SUITE_END(); 00397 00398 IdealWeightInverseMeanRatio m1; 00399 ScalarAddQualityMetric m; 00400 00401 protected: 00402 virtual bool evaluate( PatchData&, size_t, double&, MsqError& ); 00403 00404 public: 00405 ScalarAddMetricTest() : m( &m1, OFFSET ) 00406 { 00407 mMetric = &m; 00408 } 00409 }; 00410 00411 template < int OFFSET > 00412 bool ScalarAddMetricTest< OFFSET >::evaluate( PatchData& pd, size_t h, double& val, MsqError& err ) 00413 { 00414 bool rval = m1.evaluate( pd, h, val, err ); 00415 MSQ_ERRFALSE( err ); 00416 val += OFFSET; 00417 return rval; 00418 } 00419 00420 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarAddMetricTest< 0 >, "CompositeMetricTest" ); 00421 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarAddMetricTest< 2 >, "CompositeMetricTest" ); 00422 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarAddMetricTest< 0 >, "ScalarAddMetricTest" ); 00423 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarAddMetricTest< 2 >, "ScalarAddMetricTest" ); 00424 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarAddMetricTest< 0 >, "Unit" ); 00425 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarAddMetricTest< 2 >, "Unit" ); 00426 00427 template < int SCALE > 00428 class ScalarMultiplyMetricTest : public CompositeMetricTestBase 00429 { 00430 private: 00431 CPPUNIT_TEST_SUITE( ScalarMultiplyMetricTest< SCALE > ); 00432 CPPUNIT_TEST( test_supported_types ); 00433 CPPUNIT_TEST( test_ideal_element_eval ); 00434 CPPUNIT_TEST( test_ideal_element_grad ); 00435 CPPUNIT_TEST( test_ideal_element_hess ); 00436 CPPUNIT_TEST( test_non_ideal_eval ); 00437 CPPUNIT_TEST( test_valid_hessian ); 00438 CPPUNIT_TEST( test_inverted_elements ); 00439 CPPUNIT_TEST( test_degenerate_elements ); 00440 CPPUNIT_TEST( test_get_evaluations ); 00441 CPPUNIT_TEST( test_get_element_indices ); 00442 CPPUNIT_TEST( test_get_fixed_indices ); 00443 CPPUNIT_TEST( test_eval_with_indices ); 00444 CPPUNIT_TEST( test_eval_with_gradient ); 00445 CPPUNIT_TEST( test_eval_with_hessian ); 00446 CPPUNIT_TEST_SUITE_END(); 00447 00448 IdealWeightInverseMeanRatio m1; 00449 ScalarMultiplyQualityMetric m; 00450 00451 protected: 00452 virtual bool evaluate( PatchData&, size_t, double&, MsqError& ); 00453 00454 public: 00455 ScalarMultiplyMetricTest() : m( &m1, SCALE ) 00456 { 00457 mMetric = &m; 00458 } 00459 }; 00460 00461 template < int SCALE > 00462 bool ScalarMultiplyMetricTest< SCALE >::evaluate( PatchData& pd, size_t h, double& val, MsqError& err ) 00463 { 00464 bool rval = m1.evaluate( pd, h, val, err ); 00465 MSQ_ERRFALSE( err ); 00466 val *= SCALE; 00467 return rval; 00468 } 00469 00470 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarMultiplyMetricTest< 1 >, "CompositeMetricTest" ); 00471 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarMultiplyMetricTest< 3 >, "CompositeMetricTest" ); 00472 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarMultiplyMetricTest< 1 >, "ScalarMultiplyMetricTest" ); 00473 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarMultiplyMetricTest< 3 >, "ScalarMultiplyMetricTest" ); 00474 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarMultiplyMetricTest< 1 >, "Unit" ); 00475 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ScalarMultiplyMetricTest< 3 >, "Unit" );