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) kraftche@cae.wisc.edu 00024 00025 ***************************************************************** */ 00026 00027 /*! \file AveragingQMTest.cpp 00028 00029 Unit testing for the AveragingQM class 00030 \author Jasno Kraftcheck 00031 */ 00032 #include "Mesquite.hpp" 00033 #include "AveragingQM.hpp" 00034 #include "IdealElements.hpp" 00035 #include "UnitUtil.hpp" 00036 #include "TopologyInfo.hpp" 00037 #include "PatchData.hpp" 00038 #include "cppunit/extensions/HelperMacros.h" 00039 00040 using namespace MBMesquite; 00041 00042 class AveragingQMTest : public CppUnit::TestFixture 00043 { 00044 CPPUNIT_TEST_SUITE( AveragingQMTest ); 00045 CPPUNIT_TEST( test_average_metrics_liner ); 00046 CPPUNIT_TEST( test_average_metrics_rms ); 00047 CPPUNIT_TEST( test_average_metrics_hms ); 00048 CPPUNIT_TEST( test_average_metrics_minimum ); 00049 CPPUNIT_TEST( test_average_metrics_maximum ); 00050 CPPUNIT_TEST( test_average_metrics_harmonic ); 00051 CPPUNIT_TEST( test_average_metrics_geometric ); 00052 CPPUNIT_TEST( test_average_metrics_sum ); 00053 CPPUNIT_TEST( test_average_metrics_sum_squared ); 00054 CPPUNIT_TEST( test_average_metrics_standard_deviation ); 00055 CPPUNIT_TEST( test_average_metrics_max_over_min ); 00056 CPPUNIT_TEST( test_average_metrics_max_minus_min ); 00057 CPPUNIT_TEST( test_average_metrics_sum_of_ratios_squared ); 00058 CPPUNIT_TEST( test_average_and_weights_linear ); 00059 CPPUNIT_TEST( test_average_and_weights_rms ); 00060 CPPUNIT_TEST( test_average_and_weights_hms ); 00061 CPPUNIT_TEST( test_average_and_weights_minimum ); 00062 CPPUNIT_TEST( test_average_and_weights_maximum ); 00063 CPPUNIT_TEST( test_average_and_weights_harmonic ); 00064 CPPUNIT_TEST( test_average_and_weights_geometric ); 00065 CPPUNIT_TEST( test_average_and_weights_sum ); 00066 CPPUNIT_TEST( test_average_and_weights_sum_squared ); 00067 CPPUNIT_TEST( test_average_and_weights_standard_deviation ); 00068 CPPUNIT_TEST( test_average_and_weights_max_over_min ); 00069 CPPUNIT_TEST( test_average_and_weights_max_minus_min ); 00070 CPPUNIT_TEST( test_average_and_weights_sum_of_ratios_squared ); 00071 CPPUNIT_TEST( test_average_corner_gradients_linear ); 00072 CPPUNIT_TEST( test_average_corner_gradients_rms ); 00073 CPPUNIT_TEST( test_average_corner_gradients_hms ); 00074 CPPUNIT_TEST( test_average_corner_gradients_minimum ); 00075 CPPUNIT_TEST( test_average_corner_gradients_maximum ); 00076 CPPUNIT_TEST( test_average_corner_gradients_harmonic ); 00077 CPPUNIT_TEST( test_average_corner_gradients_geometric ); 00078 CPPUNIT_TEST( test_average_corner_gradients_sum ); 00079 CPPUNIT_TEST( test_average_corner_gradients_sum_squared ); 00080 CPPUNIT_TEST( test_average_corner_gradients_standard_deviation ); 00081 CPPUNIT_TEST( test_average_corner_gradients_max_over_min ); 00082 CPPUNIT_TEST( test_average_corner_gradients_max_minus_min ); 00083 CPPUNIT_TEST( test_average_corner_gradients_sum_of_ratios_squared ); 00084 CPPUNIT_TEST( test_average_corner_hessians_linear ); 00085 CPPUNIT_TEST( test_average_corner_hessians_rms ); 00086 CPPUNIT_TEST( test_average_corner_hessians_hms ); 00087 CPPUNIT_TEST( test_average_corner_hessians_minimum ); 00088 CPPUNIT_TEST( test_average_corner_hessians_maximum ); 00089 CPPUNIT_TEST( test_average_corner_hessians_harmonic ); 00090 CPPUNIT_TEST( test_average_corner_hessians_geometric ); 00091 CPPUNIT_TEST( test_average_corner_hessians_sum ); 00092 CPPUNIT_TEST( test_average_corner_hessians_sum_squared ); 00093 CPPUNIT_TEST( test_average_corner_hessians_standard_deviation ); 00094 CPPUNIT_TEST( test_average_corner_hessians_max_over_min ); 00095 CPPUNIT_TEST( test_average_corner_hessians_max_minus_min ); 00096 CPPUNIT_TEST( test_average_corner_hessians_sum_of_ratios_squared ); 00097 CPPUNIT_TEST( test_average_corner_hessian_diagonals_linear ); 00098 CPPUNIT_TEST( test_average_corner_hessian_diagonals_rms ); 00099 CPPUNIT_TEST( test_average_corner_hessian_diagonals_hms ); 00100 CPPUNIT_TEST( test_average_corner_hessian_diagonals_minimum ); 00101 CPPUNIT_TEST( test_average_corner_hessian_diagonals_maximum ); 00102 CPPUNIT_TEST( test_average_corner_hessian_diagonals_harmonic ); 00103 CPPUNIT_TEST( test_average_corner_hessian_diagonals_geometric ); 00104 CPPUNIT_TEST( test_average_corner_hessian_diagonals_sum ); 00105 CPPUNIT_TEST( test_average_corner_hessian_diagonals_sum_squared ); 00106 CPPUNIT_TEST( test_average_corner_hessian_diagonals_standard_deviation ); 00107 CPPUNIT_TEST( test_average_corner_hessian_diagonals_max_over_min ); 00108 CPPUNIT_TEST( test_average_corner_hessian_diagonals_max_minus_min ); 00109 CPPUNIT_TEST( test_average_corner_hessian_diagonals_sum_of_ratios_squared ); 00110 CPPUNIT_TEST_SUITE_END(); 00111 00112 static const double VAL_LIST_1[5]; 00113 static const double VAL_LIST_2[8]; 00114 static const unsigned LEN_LIST_1; 00115 static const unsigned LEN_LIST_2; 00116 00117 void check_average_and_weights_fails( QualityMetric::AveragingMethod scheme ); 00118 00119 void check_average_gradients( QualityMetric::AveragingMethod scheme ); 00120 00121 void check_average_gradient_fails( QualityMetric::AveragingMethod scheme ); 00122 00123 void check_pmean_hessian_diagonals( QualityMetric::AveragingMethod scheme, 00124 double inner_power, 00125 double outer_power, 00126 bool scale ); 00127 00128 void check_hessian_diagonal_fails( QualityMetric::AveragingMethod scheme ); 00129 00130 void check_pmean_hessian( QualityMetric::AveragingMethod scheme, 00131 double inner_power, 00132 double outer_power, 00133 bool scale ); 00134 00135 void check_hessian_fails( QualityMetric::AveragingMethod scheme ); 00136 00137 void check_average_and_weights( const double* vals, 00138 unsigned n, 00139 QualityMetric::AveragingMethod method, 00140 const double* weights ); 00141 00142 public: 00143 void test_average_metrics_liner(); 00144 void test_average_metrics_rms(); 00145 void test_average_metrics_hms(); 00146 void test_average_metrics_minimum(); 00147 void test_average_metrics_maximum(); 00148 void test_average_metrics_harmonic(); 00149 void test_average_metrics_geometric(); 00150 void test_average_metrics_sum(); 00151 void test_average_metrics_sum_squared(); 00152 void test_average_metrics_standard_deviation(); 00153 void test_average_metrics_max_over_min(); 00154 void test_average_metrics_max_minus_min(); 00155 void test_average_metrics_sum_of_ratios_squared(); 00156 void test_average_and_weights_linear(); 00157 void test_average_and_weights_rms(); 00158 void test_average_and_weights_hms(); 00159 void test_average_and_weights_minimum(); 00160 void test_average_and_weights_maximum(); 00161 void test_average_and_weights_harmonic(); 00162 void test_average_and_weights_geometric(); 00163 void test_average_and_weights_sum(); 00164 void test_average_and_weights_sum_squared(); 00165 void test_average_and_weights_standard_deviation(); 00166 void test_average_and_weights_max_over_min(); 00167 void test_average_and_weights_max_minus_min(); 00168 void test_average_and_weights_sum_of_ratios_squared(); 00169 void test_average_corner_gradients_linear(); 00170 void test_average_corner_gradients_rms(); 00171 void test_average_corner_gradients_hms(); 00172 void test_average_corner_gradients_minimum(); 00173 void test_average_corner_gradients_maximum(); 00174 void test_average_corner_gradients_harmonic(); 00175 void test_average_corner_gradients_geometric(); 00176 void test_average_corner_gradients_sum(); 00177 void test_average_corner_gradients_sum_squared(); 00178 void test_average_corner_gradients_standard_deviation(); 00179 void test_average_corner_gradients_max_over_min(); 00180 void test_average_corner_gradients_max_minus_min(); 00181 void test_average_corner_gradients_sum_of_ratios_squared(); 00182 void test_average_corner_hessians_linear(); 00183 void test_average_corner_hessians_rms(); 00184 void test_average_corner_hessians_hms(); 00185 void test_average_corner_hessians_minimum(); 00186 void test_average_corner_hessians_maximum(); 00187 void test_average_corner_hessians_harmonic(); 00188 void test_average_corner_hessians_geometric(); 00189 void test_average_corner_hessians_sum(); 00190 void test_average_corner_hessians_sum_squared(); 00191 void test_average_corner_hessians_standard_deviation(); 00192 void test_average_corner_hessians_max_over_min(); 00193 void test_average_corner_hessians_max_minus_min(); 00194 void test_average_corner_hessians_sum_of_ratios_squared(); 00195 void test_average_corner_hessian_diagonals_linear(); 00196 void test_average_corner_hessian_diagonals_rms(); 00197 void test_average_corner_hessian_diagonals_hms(); 00198 void test_average_corner_hessian_diagonals_minimum(); 00199 void test_average_corner_hessian_diagonals_maximum(); 00200 void test_average_corner_hessian_diagonals_harmonic(); 00201 void test_average_corner_hessian_diagonals_geometric(); 00202 void test_average_corner_hessian_diagonals_sum(); 00203 void test_average_corner_hessian_diagonals_sum_squared(); 00204 void test_average_corner_hessian_diagonals_standard_deviation(); 00205 void test_average_corner_hessian_diagonals_max_over_min(); 00206 void test_average_corner_hessian_diagonals_max_minus_min(); 00207 void test_average_corner_hessian_diagonals_sum_of_ratios_squared(); 00208 }; 00209 00210 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AveragingQMTest, "AveragingQMTest" ); 00211 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AveragingQMTest, "Unit" ); 00212 00213 const double AveragingQMTest::VAL_LIST_1[5] = { 1, 2, -1, -2, 5 }; 00214 const double AveragingQMTest::VAL_LIST_2[8] = { 00215 M_PI, std::exp( 1.0 ), -20, 8, M_PI / 4, std::log( 2.0 ), std::sqrt( 2.0 ), -1 }; 00216 const unsigned AveragingQMTest::LEN_LIST_1 = sizeof( VAL_LIST_1 ) / sizeof( double ); 00217 const unsigned AveragingQMTest::LEN_LIST_2 = sizeof( VAL_LIST_2 ) / sizeof( double ); 00218 00219 static double pmean( const double* vals, unsigned n, double power ) 00220 { 00221 double result = 0; 00222 for( unsigned i = 0; i < n; ++i ) 00223 result += std::pow( vals[i], power ); 00224 return pow( result / n, 1.0 / power ); 00225 } 00226 00227 static double list_min( const double* vals, unsigned n ) 00228 { 00229 double result = vals[0]; 00230 for( unsigned i = 1; i < n; ++i ) 00231 if( vals[i] < result ) result = vals[i]; 00232 return result; 00233 } 00234 00235 static double list_max( const double* vals, unsigned n ) 00236 { 00237 double result = vals[0]; 00238 for( unsigned i = 1; i < n; ++i ) 00239 if( vals[i] > result ) result = vals[i]; 00240 return result; 00241 } 00242 00243 static double sum_sqr( const double* vals, unsigned n ) 00244 { 00245 double result = 0.0; 00246 for( unsigned i = 0; i < n; ++i ) 00247 result += vals[i] * vals[i]; 00248 return result; 00249 } 00250 00251 static double sum_of_ratios_squared( const double* vals, unsigned n ) 00252 { 00253 double result = 0.0; 00254 for( unsigned i = 0; i < n; ++i ) 00255 for( unsigned j = 0; j < n; ++j ) 00256 { 00257 double ratio = vals[i] / vals[j]; 00258 result += ratio * ratio; 00259 } 00260 return result / ( n * n ); 00261 } 00262 00263 static double geometric_mean( const double* vals, unsigned n ) 00264 { 00265 double result = 1.0; 00266 for( unsigned i = 0; i < n; ++i ) 00267 result *= vals[i]; 00268 return std::pow( result, 1.0 / n ); 00269 } 00270 00271 void AveragingQMTest::test_average_metrics_liner() 00272 { 00273 MsqPrintError err( std::cout ); 00274 AveragingQM aqm( QualityMetric::LINEAR ); 00275 double exp, act; 00276 00277 exp = pmean( VAL_LIST_1, LEN_LIST_1, 1 ); 00278 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00279 ASSERT_NO_ERROR( err ); 00280 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00281 00282 exp = pmean( VAL_LIST_2, LEN_LIST_2, 1 ); 00283 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00284 ASSERT_NO_ERROR( err ); 00285 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00286 } 00287 00288 void AveragingQMTest::test_average_metrics_rms() 00289 { 00290 MsqPrintError err( std::cout ); 00291 AveragingQM aqm( QualityMetric::RMS ); 00292 double exp, act; 00293 00294 exp = pmean( VAL_LIST_1, LEN_LIST_1, 2 ); 00295 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00296 ASSERT_NO_ERROR( err ); 00297 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00298 00299 exp = pmean( VAL_LIST_2, LEN_LIST_2, 2 ); 00300 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00301 ASSERT_NO_ERROR( err ); 00302 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00303 } 00304 00305 void AveragingQMTest::test_average_metrics_hms() 00306 { 00307 MsqPrintError err( std::cout ); 00308 AveragingQM aqm( QualityMetric::HMS ); 00309 double exp, act; 00310 00311 exp = pmean( VAL_LIST_1, LEN_LIST_1, -2.0 ); 00312 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00313 ASSERT_NO_ERROR( err ); 00314 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00315 00316 exp = pmean( VAL_LIST_2, LEN_LIST_2, -2.0 ); 00317 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00318 ASSERT_NO_ERROR( err ); 00319 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00320 } 00321 00322 void AveragingQMTest::test_average_metrics_minimum() 00323 { 00324 MsqPrintError err( std::cout ); 00325 AveragingQM aqm( QualityMetric::MINIMUM ); 00326 double exp, act; 00327 00328 exp = list_min( VAL_LIST_1, LEN_LIST_1 ); 00329 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00330 ASSERT_NO_ERROR( err ); 00331 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00332 00333 exp = list_min( VAL_LIST_2, LEN_LIST_2 ); 00334 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00335 ASSERT_NO_ERROR( err ); 00336 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00337 } 00338 00339 void AveragingQMTest::test_average_metrics_maximum() 00340 { 00341 MsqPrintError err( std::cout ); 00342 AveragingQM aqm( QualityMetric::MAXIMUM ); 00343 double exp, act; 00344 00345 exp = list_max( VAL_LIST_1, LEN_LIST_1 ); 00346 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00347 ASSERT_NO_ERROR( err ); 00348 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00349 00350 exp = list_max( VAL_LIST_2, LEN_LIST_2 ); 00351 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00352 ASSERT_NO_ERROR( err ); 00353 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00354 } 00355 00356 void AveragingQMTest::test_average_metrics_harmonic() 00357 { 00358 MsqPrintError err( std::cout ); 00359 AveragingQM aqm( QualityMetric::HARMONIC ); 00360 double exp, act; 00361 00362 exp = pmean( VAL_LIST_1, LEN_LIST_1, -1.0 ); 00363 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00364 ASSERT_NO_ERROR( err ); 00365 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00366 00367 exp = pmean( VAL_LIST_2, LEN_LIST_2, -1.0 ); 00368 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00369 ASSERT_NO_ERROR( err ); 00370 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00371 } 00372 00373 void AveragingQMTest::test_average_metrics_geometric() 00374 { 00375 MsqPrintError err( std::cout ); 00376 AveragingQM aqm( QualityMetric::GEOMETRIC ); 00377 double exp, act; 00378 00379 exp = geometric_mean( VAL_LIST_1, LEN_LIST_1 ); 00380 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00381 ASSERT_NO_ERROR( err ); 00382 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00383 00384 exp = geometric_mean( VAL_LIST_2, LEN_LIST_2 ); 00385 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00386 ASSERT_NO_ERROR( err ); 00387 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00388 } 00389 00390 void AveragingQMTest::test_average_metrics_sum() 00391 { 00392 MsqPrintError err( std::cout ); 00393 AveragingQM aqm( QualityMetric::SUM ); 00394 double exp, act; 00395 unsigned i; 00396 00397 for( exp = 0.0, i = 0; i < LEN_LIST_1; exp += VAL_LIST_1[i++] ) 00398 ; 00399 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00400 ASSERT_NO_ERROR( err ); 00401 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00402 00403 for( exp = 0.0, i = 0; i < LEN_LIST_2; exp += VAL_LIST_2[i++] ) 00404 ; 00405 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00406 ASSERT_NO_ERROR( err ); 00407 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00408 } 00409 00410 void AveragingQMTest::test_average_metrics_sum_squared() 00411 { 00412 MsqPrintError err( std::cout ); 00413 AveragingQM aqm( QualityMetric::SUM_SQUARED ); 00414 double exp, act; 00415 00416 exp = sum_sqr( VAL_LIST_1, LEN_LIST_1 ); 00417 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00418 ASSERT_NO_ERROR( err ); 00419 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00420 00421 exp = sum_sqr( VAL_LIST_2, LEN_LIST_2 ); 00422 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00423 ASSERT_NO_ERROR( err ); 00424 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00425 } 00426 00427 void AveragingQMTest::test_average_metrics_standard_deviation() 00428 { 00429 MsqPrintError err( std::cout ); 00430 AveragingQM aqm( QualityMetric::STANDARD_DEVIATION ); 00431 double exp, act, tmp; 00432 00433 tmp = pmean( VAL_LIST_1, LEN_LIST_1, 1.0 ); 00434 exp = sum_sqr( VAL_LIST_1, LEN_LIST_1 ); 00435 exp = exp / LEN_LIST_1 - tmp * tmp; 00436 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00437 ASSERT_NO_ERROR( err ); 00438 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00439 00440 tmp = pmean( VAL_LIST_2, LEN_LIST_2, 1.0 ); 00441 exp = sum_sqr( VAL_LIST_2, LEN_LIST_2 ); 00442 exp = exp / LEN_LIST_2 - tmp * tmp; 00443 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00444 ASSERT_NO_ERROR( err ); 00445 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00446 } 00447 00448 void AveragingQMTest::test_average_metrics_max_over_min() 00449 { 00450 MsqPrintError err( std::cout ); 00451 AveragingQM aqm( QualityMetric::MAX_OVER_MIN ); 00452 double exp, act; 00453 00454 exp = list_max( VAL_LIST_1, LEN_LIST_1 ) / list_min( VAL_LIST_1, LEN_LIST_1 ); 00455 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00456 ASSERT_NO_ERROR( err ); 00457 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00458 00459 exp = list_max( VAL_LIST_2, LEN_LIST_2 ) / list_min( VAL_LIST_2, LEN_LIST_2 ); 00460 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00461 ASSERT_NO_ERROR( err ); 00462 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00463 } 00464 00465 void AveragingQMTest::test_average_metrics_max_minus_min() 00466 { 00467 MsqPrintError err( std::cout ); 00468 AveragingQM aqm( QualityMetric::MAX_MINUS_MIN ); 00469 double exp, act; 00470 00471 exp = list_max( VAL_LIST_1, LEN_LIST_1 ) - list_min( VAL_LIST_1, LEN_LIST_1 ); 00472 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00473 ASSERT_NO_ERROR( err ); 00474 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00475 00476 exp = list_max( VAL_LIST_2, LEN_LIST_2 ) - list_min( VAL_LIST_2, LEN_LIST_2 ); 00477 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00478 ASSERT_NO_ERROR( err ); 00479 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00480 } 00481 00482 void AveragingQMTest::test_average_metrics_sum_of_ratios_squared() 00483 { 00484 MsqPrintError err( std::cout ); 00485 AveragingQM aqm( QualityMetric::SUM_OF_RATIOS_SQUARED ); 00486 double exp, act; 00487 00488 exp = sum_of_ratios_squared( VAL_LIST_1, LEN_LIST_1 ); 00489 act = aqm.average_metrics( VAL_LIST_1, LEN_LIST_1, err ); 00490 ASSERT_NO_ERROR( err ); 00491 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00492 00493 exp = sum_of_ratios_squared( VAL_LIST_2, LEN_LIST_2 ); 00494 act = aqm.average_metrics( VAL_LIST_2, LEN_LIST_2, err ); 00495 ASSERT_NO_ERROR( err ); 00496 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp, act, 1e-8 ); 00497 } 00498 00499 void AveragingQMTest::check_average_and_weights( const double* vals, 00500 unsigned n, 00501 QualityMetric::AveragingMethod method, 00502 const double* weights ) 00503 { 00504 MsqPrintError err( std::cout ); 00505 AveragingQM aqm( method ); 00506 00507 CPPUNIT_ASSERT( n > 0 ); 00508 std::vector< double > working( n ); 00509 std::copy( vals, vals + n, working.begin() ); 00510 00511 double avg1, avg2; 00512 avg1 = aqm.average_metrics( vals, n, err ); 00513 ASSERT_NO_ERROR( err ); 00514 avg2 = aqm.average_metric_and_weights( arrptr( working ), n, err ); 00515 ASSERT_NO_ERROR( err ); 00516 00517 CPPUNIT_ASSERT_DOUBLES_EQUAL( avg1, avg2, 1e-6 ); 00518 for( unsigned i = 0; i < n; ++i ) 00519 CPPUNIT_ASSERT_DOUBLES_EQUAL( weights[i], working[i], 1e-6 ); 00520 } 00521 00522 void AveragingQMTest::test_average_and_weights_linear() 00523 { 00524 std::vector< double > weights1( LEN_LIST_1, 1.0 / LEN_LIST_1 ), weights2( LEN_LIST_2, 1.0 / LEN_LIST_2 ); 00525 check_average_and_weights( VAL_LIST_1, LEN_LIST_1, QualityMetric::LINEAR, arrptr( weights1 ) ); 00526 check_average_and_weights( VAL_LIST_2, LEN_LIST_2, QualityMetric::LINEAR, arrptr( weights2 ) ); 00527 } 00528 00529 void AveragingQMTest::test_average_and_weights_rms() 00530 { 00531 std::vector< double > weights1( LEN_LIST_1 ), weights2( LEN_LIST_2 ); 00532 unsigned i; 00533 double rms; 00534 00535 rms = pmean( VAL_LIST_1, LEN_LIST_1, 2.0 ); 00536 for( i = 0; i < LEN_LIST_1; ++i ) 00537 weights1[i] = VAL_LIST_1[i] / ( LEN_LIST_1 * rms ); 00538 check_average_and_weights( VAL_LIST_1, LEN_LIST_1, QualityMetric::RMS, arrptr( weights1 ) ); 00539 00540 rms = pmean( VAL_LIST_2, LEN_LIST_2, 2.0 ); 00541 for( i = 0; i < LEN_LIST_2; ++i ) 00542 weights2[i] = VAL_LIST_2[i] / ( LEN_LIST_2 * rms ); 00543 check_average_and_weights( VAL_LIST_2, LEN_LIST_2, QualityMetric::RMS, arrptr( weights2 ) ); 00544 } 00545 00546 void AveragingQMTest::test_average_and_weights_hms() 00547 { 00548 std::vector< double > weights1( LEN_LIST_1 ), weights2( LEN_LIST_2 ); 00549 unsigned i; 00550 double hms, tmp; 00551 00552 hms = pmean( VAL_LIST_1, LEN_LIST_1, -2.0 ); 00553 for( i = 0; i < LEN_LIST_1; ++i ) 00554 { 00555 tmp = hms / VAL_LIST_1[i]; 00556 weights1[i] = tmp * tmp * tmp / LEN_LIST_1; 00557 } 00558 check_average_and_weights( VAL_LIST_1, LEN_LIST_1, QualityMetric::HMS, arrptr( weights1 ) ); 00559 00560 hms = pmean( VAL_LIST_2, LEN_LIST_2, -2.0 ); 00561 for( i = 0; i < LEN_LIST_2; ++i ) 00562 { 00563 tmp = hms / VAL_LIST_2[i]; 00564 weights2[i] = tmp * tmp * tmp / LEN_LIST_2; 00565 } 00566 check_average_and_weights( VAL_LIST_2, LEN_LIST_2, QualityMetric::HMS, arrptr( weights2 ) ); 00567 } 00568 00569 void AveragingQMTest::test_average_and_weights_minimum() 00570 { 00571 std::vector< double > weights1( LEN_LIST_1, 0.0 ), weights2( LEN_LIST_2, 0.0 ); 00572 const double* ptr; 00573 00574 ptr = std::min_element( VAL_LIST_1, VAL_LIST_1 + LEN_LIST_1 ); 00575 weights1[ptr - VAL_LIST_1] = 1.0; 00576 check_average_and_weights( VAL_LIST_1, LEN_LIST_1, QualityMetric::MINIMUM, arrptr( weights1 ) ); 00577 00578 ptr = std::min_element( VAL_LIST_2, VAL_LIST_2 + LEN_LIST_2 ); 00579 weights2[ptr - VAL_LIST_2] = 1.0; 00580 check_average_and_weights( VAL_LIST_2, LEN_LIST_2, QualityMetric::MINIMUM, arrptr( weights2 ) ); 00581 } 00582 00583 void AveragingQMTest::test_average_and_weights_maximum() 00584 { 00585 std::vector< double > weights1( LEN_LIST_1, 0.0 ), weights2( LEN_LIST_2, 0.0 ); 00586 const double* ptr; 00587 00588 ptr = std::max_element( VAL_LIST_1, VAL_LIST_1 + LEN_LIST_1 ); 00589 weights1[ptr - VAL_LIST_1] = 1.0; 00590 check_average_and_weights( VAL_LIST_1, LEN_LIST_1, QualityMetric::MAXIMUM, arrptr( weights1 ) ); 00591 00592 ptr = std::max_element( VAL_LIST_2, VAL_LIST_2 + LEN_LIST_2 ); 00593 weights2[ptr - VAL_LIST_2] = 1.0; 00594 check_average_and_weights( VAL_LIST_2, LEN_LIST_2, QualityMetric::MAXIMUM, arrptr( weights2 ) ); 00595 } 00596 00597 void AveragingQMTest::test_average_and_weights_harmonic() 00598 { 00599 std::vector< double > weights1( LEN_LIST_1 ), weights2( LEN_LIST_2 ); 00600 unsigned i; 00601 double h, tmp; 00602 00603 h = pmean( VAL_LIST_1, LEN_LIST_1, -1.0 ); 00604 for( i = 0; i < LEN_LIST_1; ++i ) 00605 { 00606 tmp = h / VAL_LIST_1[i]; 00607 weights1[i] = tmp * tmp / LEN_LIST_1; 00608 } 00609 check_average_and_weights( VAL_LIST_1, LEN_LIST_1, QualityMetric::HARMONIC, arrptr( weights1 ) ); 00610 00611 h = pmean( VAL_LIST_2, LEN_LIST_2, -1.0 ); 00612 for( i = 0; i < LEN_LIST_2; ++i ) 00613 { 00614 tmp = h / VAL_LIST_2[i]; 00615 weights2[i] = tmp * tmp / LEN_LIST_2; 00616 } 00617 check_average_and_weights( VAL_LIST_2, LEN_LIST_2, QualityMetric::HARMONIC, arrptr( weights2 ) ); 00618 } 00619 00620 void AveragingQMTest::test_average_and_weights_geometric() 00621 { 00622 std::vector< double > weights1( LEN_LIST_1 ), weights2( LEN_LIST_2 ); 00623 unsigned i; 00624 double g; 00625 00626 g = geometric_mean( VAL_LIST_1, LEN_LIST_1 ); 00627 for( i = 0; i < LEN_LIST_1; ++i ) 00628 { 00629 weights1[i] = g / VAL_LIST_1[i] / LEN_LIST_1; 00630 } 00631 check_average_and_weights( VAL_LIST_1, LEN_LIST_1, QualityMetric::GEOMETRIC, arrptr( weights1 ) ); 00632 00633 g = geometric_mean( VAL_LIST_2, LEN_LIST_2 ); 00634 for( i = 0; i < LEN_LIST_2; ++i ) 00635 { 00636 weights2[i] = g / VAL_LIST_2[i] / LEN_LIST_2; 00637 } 00638 check_average_and_weights( VAL_LIST_2, LEN_LIST_2, QualityMetric::GEOMETRIC, arrptr( weights2 ) ); 00639 } 00640 00641 void AveragingQMTest::test_average_and_weights_sum() 00642 { 00643 std::vector< double > weights1( LEN_LIST_1, 1.0 ), weights2( LEN_LIST_2, 1.0 ); 00644 check_average_and_weights( VAL_LIST_1, LEN_LIST_1, QualityMetric::SUM, arrptr( weights1 ) ); 00645 check_average_and_weights( VAL_LIST_2, LEN_LIST_2, QualityMetric::SUM, arrptr( weights2 ) ); 00646 } 00647 00648 void AveragingQMTest::test_average_and_weights_sum_squared() 00649 { 00650 std::vector< double > weights1( LEN_LIST_1 ), weights2( LEN_LIST_2 ); 00651 unsigned i; 00652 00653 for( i = 0; i < LEN_LIST_1; ++i ) 00654 weights1[i] = 2 * VAL_LIST_1[i]; 00655 check_average_and_weights( VAL_LIST_1, LEN_LIST_1, QualityMetric::SUM_SQUARED, arrptr( weights1 ) ); 00656 00657 for( i = 0; i < LEN_LIST_2; ++i ) 00658 weights2[i] = 2 * VAL_LIST_2[i]; 00659 check_average_and_weights( VAL_LIST_2, LEN_LIST_2, QualityMetric::SUM_SQUARED, arrptr( weights2 ) ); 00660 } 00661 00662 void AveragingQMTest::check_average_and_weights_fails( QualityMetric::AveragingMethod scheme ) 00663 { 00664 MsqError err; 00665 AveragingQM aqm( scheme ); 00666 double w[] = { 1.0, 2.0 }; 00667 aqm.average_metric_and_weights( w, 2, err ); 00668 CPPUNIT_ASSERT( err ); 00669 } 00670 00671 void AveragingQMTest::test_average_and_weights_standard_deviation() 00672 { 00673 check_average_and_weights_fails( QualityMetric::STANDARD_DEVIATION ); 00674 } 00675 00676 void AveragingQMTest::test_average_and_weights_max_over_min() 00677 { 00678 check_average_and_weights_fails( QualityMetric::MAX_OVER_MIN ); 00679 } 00680 00681 void AveragingQMTest::test_average_and_weights_max_minus_min() 00682 { 00683 check_average_and_weights_fails( QualityMetric::MAX_MINUS_MIN ); 00684 } 00685 00686 void AveragingQMTest::test_average_and_weights_sum_of_ratios_squared() 00687 { 00688 check_average_and_weights_fails( QualityMetric::SUM_OF_RATIOS_SQUARED ); 00689 } 00690 00691 void AveragingQMTest::check_average_gradients( QualityMetric::AveragingMethod scheme ) 00692 { 00693 double vals1[] = { 1, -2, -1, 0.5 }; 00694 double vals2[] = { 1, -2, -1, 0.5 }; 00695 Vector3D grads[12], vtxgrads[4]; 00696 for( unsigned i = 0; i < 12; ++i ) 00697 grads[i] = Vector3D( (double)i ); 00698 00699 uint32_t fixed = 0x2; // mark second vertex as fixed 00700 Vector3D exp; 00701 MsqError err; 00702 AveragingQM aqm( scheme ); 00703 00704 double a1 = aqm.average_metric_and_weights( vals1, 4, err ); 00705 ASSERT_NO_ERROR( err ); 00706 00707 double a2 = aqm.average_corner_gradients( QUADRILATERAL, fixed, 4, vals2, grads, vtxgrads, err ); 00708 ASSERT_NO_ERROR( err ); 00709 00710 CPPUNIT_ASSERT_DOUBLES_EQUAL( a1, a2, 1e-8 ); 00711 00712 exp = vals1[0] * grads[0] + vals1[1] * grads[5] + vals1[3] * grads[10]; 00713 CPPUNIT_ASSERT_VECTORS_EQUAL( exp, vtxgrads[0], 1e-6 ); 00714 00715 exp = vals1[1] * grads[4] + vals1[2] * grads[6] + vals1[3] * grads[11]; 00716 CPPUNIT_ASSERT_VECTORS_EQUAL( exp, vtxgrads[2], 1e-6 ); 00717 00718 exp = vals1[0] * grads[2] + vals1[2] * grads[7] + vals1[3] * grads[9]; 00719 CPPUNIT_ASSERT_VECTORS_EQUAL( exp, vtxgrads[3], 1e-6 ); 00720 } 00721 00722 void AveragingQMTest::test_average_corner_gradients_linear() 00723 { 00724 check_average_gradients( QualityMetric::LINEAR ); 00725 } 00726 00727 void AveragingQMTest::test_average_corner_gradients_rms() 00728 { 00729 check_average_gradients( QualityMetric::RMS ); 00730 } 00731 00732 void AveragingQMTest::test_average_corner_gradients_hms() 00733 { 00734 check_average_gradients( QualityMetric::HMS ); 00735 } 00736 00737 void AveragingQMTest::test_average_corner_gradients_minimum() 00738 { 00739 check_average_gradients( QualityMetric::MINIMUM ); 00740 } 00741 00742 void AveragingQMTest::test_average_corner_gradients_maximum() 00743 { 00744 check_average_gradients( QualityMetric::MAXIMUM ); 00745 } 00746 00747 void AveragingQMTest::test_average_corner_gradients_harmonic() 00748 { 00749 check_average_gradients( QualityMetric::HARMONIC ); 00750 } 00751 00752 void AveragingQMTest::test_average_corner_gradients_geometric() 00753 { 00754 check_average_gradients( QualityMetric::GEOMETRIC ); 00755 } 00756 00757 void AveragingQMTest::test_average_corner_gradients_sum() 00758 { 00759 check_average_gradients( QualityMetric::SUM ); 00760 } 00761 00762 void AveragingQMTest::test_average_corner_gradients_sum_squared() 00763 { 00764 check_average_gradients( QualityMetric::SUM_SQUARED ); 00765 } 00766 00767 void AveragingQMTest::check_average_gradient_fails( QualityMetric::AveragingMethod scheme ) 00768 { 00769 double vals[] = { 1, 2, -1, 0.5 }; 00770 Vector3D grads[12], vtxgrads[4]; 00771 for( unsigned i = 0; i < 12; ++i ) 00772 grads[i] = Vector3D( (double)i ); 00773 00774 MsqError err; 00775 AveragingQM aqm( scheme ); 00776 00777 aqm.average_corner_gradients( QUADRILATERAL, 0, 4, vals, grads, vtxgrads, err ); 00778 CPPUNIT_ASSERT( err ); 00779 } 00780 00781 void AveragingQMTest::test_average_corner_gradients_standard_deviation() 00782 { 00783 check_average_gradient_fails( QualityMetric::STANDARD_DEVIATION ); 00784 } 00785 00786 void AveragingQMTest::test_average_corner_gradients_max_over_min() 00787 { 00788 check_average_gradient_fails( QualityMetric::MAX_OVER_MIN ); 00789 } 00790 00791 void AveragingQMTest::test_average_corner_gradients_max_minus_min() 00792 { 00793 check_average_gradient_fails( QualityMetric::MAX_MINUS_MIN ); 00794 } 00795 00796 void AveragingQMTest::test_average_corner_gradients_sum_of_ratios_squared() 00797 { 00798 check_average_gradient_fails( QualityMetric::SUM_OF_RATIOS_SQUARED ); 00799 } 00800 00801 static double pmean_of_triangle_corner_hessians( double inner_power, 00802 double outer_power, 00803 const double* v, 00804 const Vector3D* cg, 00805 const Matrix3D* ch, 00806 Vector3D* tg, 00807 Matrix3D* th, 00808 bool scale ) 00809 { 00810 Matrix3D op; 00811 double gf[3], hf[3]; 00812 double nm, m = 0; 00813 double den = scale ? 3.0 : 1.0; 00814 for( unsigned i = 0; i < 3; ++i ) 00815 { 00816 nm = pow( v[i], inner_power ); 00817 m += nm; 00818 00819 gf[i] = inner_power * nm / v[i] / den; 00820 hf[i] = ( inner_power - 1 ) * gf[i] / v[i]; 00821 } 00822 00823 nm = m / den; 00824 00825 tg[0] = gf[0] * cg[0] + gf[1] * cg[5] + gf[2] * cg[7]; 00826 tg[1] = gf[0] * cg[1] + gf[1] * cg[3] + gf[2] * cg[8]; 00827 tg[2] = gf[0] * cg[2] + gf[1] * cg[4] + gf[2] * cg[6]; 00828 00829 th[0] = hf[0] * op.outer_product( cg[0], cg[0] ) + gf[0] * ch[0] + hf[1] * op.outer_product( cg[5], cg[5] ) + 00830 gf[1] * ch[11] + hf[2] * op.outer_product( cg[7], cg[7] ) + gf[2] * ch[15]; 00831 th[3] = hf[0] * op.outer_product( cg[1], cg[1] ) + gf[0] * ch[3] + hf[1] * op.outer_product( cg[3], cg[3] ) + 00832 gf[1] * ch[6] + hf[2] * op.outer_product( cg[8], cg[8] ) + gf[2] * ch[17]; 00833 th[5] = hf[0] * op.outer_product( cg[2], cg[2] ) + gf[0] * ch[5] + hf[1] * op.outer_product( cg[4], cg[4] ) + 00834 gf[1] * ch[9] + hf[2] * op.outer_product( cg[6], cg[6] ) + gf[2] * ch[12]; 00835 th[1] = hf[0] * op.outer_product( cg[0], cg[1] ) + gf[0] * ch[1] + hf[1] * op.outer_product( cg[5], cg[3] ) + 00836 gf[1] * transpose( ch[8] ) + hf[2] * op.outer_product( cg[7], cg[8] ) + gf[2] * ch[16]; 00837 th[2] = hf[0] * op.outer_product( cg[0], cg[2] ) + gf[0] * ch[2] + hf[1] * op.outer_product( cg[5], cg[4] ) + 00838 gf[1] * transpose( ch[10] ) + hf[2] * op.outer_product( cg[7], cg[6] ) + gf[2] * transpose( ch[13] ); 00839 th[4] = hf[0] * op.outer_product( cg[1], cg[2] ) + gf[0] * ch[4] + hf[1] * op.outer_product( cg[3], cg[4] ) + 00840 gf[1] * ch[7] + hf[2] * op.outer_product( cg[8], cg[6] ) + gf[2] * transpose( ch[14] ); 00841 00842 m = pow( nm, outer_power ); 00843 double g = m * outer_power / nm; 00844 double h = ( outer_power - 1.0 ) * g / nm; 00845 for( unsigned r = 0; r < 3; ++r ) 00846 { 00847 for( unsigned c = r; c < 3; ++c ) 00848 { 00849 *th = g * *th + h * op.outer_product( tg[r], tg[c] ); 00850 ++th; 00851 } 00852 tg[r] *= g; 00853 } 00854 00855 return m; 00856 } 00857 00858 void AveragingQMTest::check_pmean_hessian_diagonals( QualityMetric::AveragingMethod scheme, 00859 double inner_power, 00860 double outer_power, 00861 bool scale ) 00862 { 00863 MsqPrintError err( std::cout ); 00864 AveragingQM aqm( scheme ); 00865 uint32_t fixed = 0; // mark no vertices as fixed 00866 00867 // define corner values, gradients and Hessians for a triangle 00868 double vals[] = { 1, 2, 0.5 }; 00869 const Vector3D grads[9] = { Vector3D( 0, 1, 1 ), Vector3D( 0, 2, 2 ), Vector3D( 0, 3, 3 ), 00870 Vector3D( 0, 4, 4 ), Vector3D( 0, 5, 5 ), Vector3D( 0, 6, 6 ), 00871 Vector3D( 0, 7, 7 ), Vector3D( 0, 8, 8 ), Vector3D( 0, 9, 9 ) }; 00872 Matrix3D hesss[18] = { Matrix3D( 1.0 ), Matrix3D( 2.0 ), Matrix3D( -1. ), Matrix3D( 0.5 ), Matrix3D( 6.0 ), 00873 Matrix3D( 1.1 ), Matrix3D( 1.2 ), Matrix3D( 0.3 ), Matrix3D( 0.0 ), Matrix3D( 22. ), 00874 Matrix3D( -2. ), Matrix3D( 4.3 ), Matrix3D( 0.8 ), Matrix3D( 1, 7 ), Matrix3D( -.2 ), 00875 Matrix3D( 0.5 ), Matrix3D( 7.0 ), Matrix3D( 1.5 ) }; 00876 // change some values so we catch transpositional errors 00877 for( unsigned i = 0; i < sizeof( hesss ) / sizeof( hesss[0] ); ++i ) 00878 hesss[i][2][2] = 0.0; 00879 00880 // Calculate expected values 00881 Vector3D aqm_grad[3], exp_grad[3]; 00882 Matrix3D exp_hess[6]; 00883 double aqm_avg, exp_avg; 00884 exp_avg = 00885 pmean_of_triangle_corner_hessians( inner_power, outer_power, vals, grads, hesss, exp_grad, exp_hess, scale ); 00886 00887 // Test calculation of diagonal from full corner hessian data. 00888 SymMatrix3D aqm_hess[3] = { 1, 2, 3 }; 00889 aqm_avg = aqm.average_corner_hessian_diagonals( TRIANGLE, fixed, 3, vals, grads, hesss, aqm_grad, aqm_hess, err ); 00890 ASSERT_NO_ERROR( err ); 00891 00892 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp_avg, aqm_avg, 1e-6 ); 00893 00894 CPPUNIT_ASSERT_VECTORS_EQUAL( exp_grad[0], aqm_grad[0], 1e-6 ); 00895 CPPUNIT_ASSERT_VECTORS_EQUAL( exp_grad[1], aqm_grad[1], 1e-6 ); 00896 CPPUNIT_ASSERT_VECTORS_EQUAL( exp_grad[2], aqm_grad[2], 1e-6 ); 00897 00898 CPPUNIT_ASSERT_MATRICES_EQUAL( exp_hess[0], Matrix3D( aqm_hess[0] ), 1e-6 ); 00899 CPPUNIT_ASSERT_MATRICES_EQUAL( exp_hess[3], Matrix3D( aqm_hess[1] ), 1e-6 ); 00900 CPPUNIT_ASSERT_MATRICES_EQUAL( exp_hess[5], Matrix3D( aqm_hess[2] ), 1e-6 ); 00901 00902 // Test calculation of diagonal from diagonal corner hessian data. 00903 SymMatrix3D diags[9] = { hesss[0].upper(), hesss[3].upper(), hesss[5].upper(), 00904 hesss[6].upper(), hesss[9].upper(), hesss[11].upper(), 00905 hesss[12].upper(), hesss[15].upper(), hesss[17].upper() }; 00906 aqm_avg = aqm.average_corner_hessian_diagonals( TRIANGLE, fixed, 3, vals, grads, diags, aqm_grad, aqm_hess, err ); 00907 ASSERT_NO_ERROR( err ); 00908 00909 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp_avg, aqm_avg, 1e-6 ); 00910 00911 CPPUNIT_ASSERT_VECTORS_EQUAL( exp_grad[0], aqm_grad[0], 1e-6 ); 00912 CPPUNIT_ASSERT_VECTORS_EQUAL( exp_grad[1], aqm_grad[1], 1e-6 ); 00913 CPPUNIT_ASSERT_VECTORS_EQUAL( exp_grad[2], aqm_grad[2], 1e-6 ); 00914 00915 CPPUNIT_ASSERT_MATRICES_EQUAL( exp_hess[0], Matrix3D( aqm_hess[0] ), 1e-6 ); 00916 CPPUNIT_ASSERT_MATRICES_EQUAL( exp_hess[3], Matrix3D( aqm_hess[1] ), 1e-6 ); 00917 CPPUNIT_ASSERT_MATRICES_EQUAL( exp_hess[5], Matrix3D( aqm_hess[2] ), 1e-6 ); 00918 } 00919 00920 void AveragingQMTest::check_hessian_diagonal_fails( QualityMetric::AveragingMethod scheme ) 00921 { 00922 // define corner values, gradients and Hessians for a triangle 00923 double vals[] = { 1, 2, 0.5 }; 00924 const Vector3D grads[9] = { Vector3D( 1.0 ), Vector3D( 2.0 ), Vector3D( 3.0 ), Vector3D( 4.0 ), Vector3D( 5.0 ), 00925 Vector3D( 6.0 ), Vector3D( 7.0 ), Vector3D( 8.0 ), Vector3D( 9.0 ) }; 00926 const Matrix3D hesss[18] = { Matrix3D( 1.0 ), Matrix3D( 2.0 ), Matrix3D( -1. ), Matrix3D( 0.5 ), Matrix3D( 6.0 ), 00927 Matrix3D( 1.1 ), Matrix3D( 1.2 ), Matrix3D( 0.3 ), Matrix3D( 0.0 ), Matrix3D( 22. ), 00928 Matrix3D( -2. ), Matrix3D( 4.3 ), Matrix3D( 0.8 ), Matrix3D( 1, 7 ), Matrix3D( -.2 ), 00929 Matrix3D( 0.5 ), Matrix3D( 7.0 ), Matrix3D( 1.5 ) }; 00930 00931 Vector3D vtx_grad[3]; 00932 SymMatrix3D vtx_hess[6]; 00933 MsqError err; 00934 AveragingQM aqm( scheme ); 00935 uint32_t fixed = 0x4; // mark third vertex as fixed 00936 00937 aqm.average_corner_hessian_diagonals( TRIANGLE, fixed, 3, vals, grads, hesss, vtx_grad, vtx_hess, err ); 00938 CPPUNIT_ASSERT( err ); 00939 00940 const SymMatrix3D diags[9] = { SymMatrix3D( 1.0 ), SymMatrix3D( 0.5 ), SymMatrix3D( 1.0 ), 00941 SymMatrix3D( 1.2 ), SymMatrix3D( 22. ), SymMatrix3D( 4.3 ), 00942 SymMatrix3D( 0.8 ), SymMatrix3D( 0.5 ), SymMatrix3D( 1.5 ) }; 00943 00944 aqm.average_corner_hessian_diagonals( TRIANGLE, fixed, 3, vals, grads, diags, vtx_grad, vtx_hess, err ); 00945 CPPUNIT_ASSERT( err ); 00946 } 00947 00948 void AveragingQMTest::test_average_corner_hessian_diagonals_linear() 00949 { 00950 check_pmean_hessian_diagonals( QualityMetric::LINEAR, 1, 1, true ); 00951 } 00952 00953 void AveragingQMTest::test_average_corner_hessian_diagonals_rms() 00954 { 00955 check_pmean_hessian_diagonals( QualityMetric::RMS, 2, 0.5, true ); 00956 } 00957 00958 void AveragingQMTest::test_average_corner_hessian_diagonals_hms() 00959 { 00960 check_pmean_hessian_diagonals( QualityMetric::HMS, -2, -0.5, true ); 00961 } 00962 00963 void AveragingQMTest::test_average_corner_hessian_diagonals_minimum() 00964 { 00965 check_hessian_diagonal_fails( QualityMetric::MINIMUM ); 00966 } 00967 00968 void AveragingQMTest::test_average_corner_hessian_diagonals_maximum() 00969 { 00970 check_hessian_diagonal_fails( QualityMetric::MAXIMUM ); 00971 } 00972 00973 void AveragingQMTest::test_average_corner_hessian_diagonals_harmonic() 00974 { 00975 check_pmean_hessian_diagonals( QualityMetric::HARMONIC, -1, -1, true ); 00976 } 00977 00978 void AveragingQMTest::test_average_corner_hessian_diagonals_geometric() 00979 { 00980 check_hessian_diagonal_fails( QualityMetric::GEOMETRIC ); 00981 } 00982 00983 void AveragingQMTest::test_average_corner_hessian_diagonals_sum() 00984 { 00985 check_pmean_hessian_diagonals( QualityMetric::SUM, 1, 1, false ); 00986 } 00987 00988 void AveragingQMTest::test_average_corner_hessian_diagonals_sum_squared() 00989 { 00990 check_pmean_hessian_diagonals( QualityMetric::SUM_SQUARED, 2, 1, false ); 00991 } 00992 00993 void AveragingQMTest::test_average_corner_hessian_diagonals_standard_deviation() 00994 { 00995 check_hessian_diagonal_fails( QualityMetric::STANDARD_DEVIATION ); 00996 } 00997 00998 void AveragingQMTest::test_average_corner_hessian_diagonals_max_over_min() 00999 { 01000 check_hessian_diagonal_fails( QualityMetric::MAX_OVER_MIN ); 01001 } 01002 01003 void AveragingQMTest::test_average_corner_hessian_diagonals_max_minus_min() 01004 { 01005 check_hessian_diagonal_fails( QualityMetric::MAX_MINUS_MIN ); 01006 } 01007 01008 void AveragingQMTest::test_average_corner_hessian_diagonals_sum_of_ratios_squared() 01009 { 01010 check_hessian_diagonal_fails( QualityMetric::SUM_OF_RATIOS_SQUARED ); 01011 } 01012 01013 void AveragingQMTest::check_pmean_hessian( QualityMetric::AveragingMethod scheme, 01014 double inner_power, 01015 double outer_power, 01016 bool scale ) 01017 { 01018 // define corner values, gradients and Hessians for a triangle 01019 double vals[] = { 1, 2, 0.5 }; 01020 const Vector3D grads[9] = { Vector3D( 0, 1, 1 ), Vector3D( 0, 2, 2 ), Vector3D( 0, 3, 3 ), 01021 Vector3D( 0, 4, 4 ), Vector3D( 0, 5, 5 ), Vector3D( 0, 6, 6 ), 01022 Vector3D( 0, 7, 7 ), Vector3D( 0, 8, 8 ), Vector3D( 0, 9, 9 ) }; 01023 Matrix3D hesss[18] = { Matrix3D( 1.0 ), Matrix3D( 2.0 ), Matrix3D( -1. ), Matrix3D( 0.5 ), Matrix3D( 6.0 ), 01024 Matrix3D( 1.1 ), Matrix3D( 1.2 ), Matrix3D( 0.3 ), Matrix3D( 0.0 ), Matrix3D( 22. ), 01025 Matrix3D( -2. ), Matrix3D( 4.3 ), Matrix3D( 0.8 ), Matrix3D( 1, 7 ), Matrix3D( -.2 ), 01026 Matrix3D( 0.5 ), Matrix3D( 7.0 ), Matrix3D( 1.5 ) }; 01027 // change some values so we catch transpositional errors 01028 for( unsigned i = 0; i < sizeof( hesss ) / sizeof( hesss[0] ); ++i ) 01029 hesss[i][2][2] = 0.0; 01030 01031 Vector3D aqm_grad[3], exp_grad[3]; 01032 Matrix3D aqm_hess[6], exp_hess[6]; 01033 ; 01034 MsqPrintError err( std::cout ); 01035 AveragingQM aqm( scheme ); 01036 uint32_t fixed = 0x4; // mark third vertex as fixed 01037 double aqm_avg, exp_avg; 01038 01039 exp_avg = 01040 pmean_of_triangle_corner_hessians( inner_power, outer_power, vals, grads, hesss, exp_grad, exp_hess, scale ); 01041 01042 aqm_avg = aqm.average_corner_hessians( TRIANGLE, fixed, 3, vals, grads, hesss, aqm_grad, aqm_hess, err ); 01043 ASSERT_NO_ERROR( err ); 01044 01045 CPPUNIT_ASSERT_DOUBLES_EQUAL( exp_avg, aqm_avg, 1e-6 ); 01046 01047 // only check gradient terms for free vertices 01048 CPPUNIT_ASSERT_VECTORS_EQUAL( exp_grad[0], aqm_grad[0], 1e-6 ); 01049 CPPUNIT_ASSERT_VECTORS_EQUAL( exp_grad[1], aqm_grad[1], 1e-6 ); 01050 01051 // only check Hessian terms for free vertices 01052 CPPUNIT_ASSERT_MATRICES_EQUAL( exp_hess[0], aqm_hess[0], 1e-6 ); 01053 CPPUNIT_ASSERT_MATRICES_EQUAL( exp_hess[1], aqm_hess[1], 1e-6 ); 01054 CPPUNIT_ASSERT_MATRICES_EQUAL( exp_hess[3], aqm_hess[3], 1e-6 ); 01055 } 01056 01057 void AveragingQMTest::check_hessian_fails( QualityMetric::AveragingMethod scheme ) 01058 { 01059 // define corner values, gradients and Hessians for a triangle 01060 double vals[] = { 1, 2, 0.5 }; 01061 const Vector3D grads[9] = { Vector3D( 1.0 ), Vector3D( 2.0 ), Vector3D( 3.0 ), Vector3D( 4.0 ), Vector3D( 5.0 ), 01062 Vector3D( 6.0 ), Vector3D( 7.0 ), Vector3D( 8.0 ), Vector3D( 9.0 ) }; 01063 const Matrix3D hesss[18] = { Matrix3D( 1.0 ), Matrix3D( 2.0 ), Matrix3D( -1. ), Matrix3D( 0.5 ), Matrix3D( 6.0 ), 01064 Matrix3D( 1.1 ), Matrix3D( 1.2 ), Matrix3D( 0.3 ), Matrix3D( 0.0 ), Matrix3D( 22. ), 01065 Matrix3D( -2. ), Matrix3D( 4.3 ), Matrix3D( 0.8 ), Matrix3D( 1, 7 ), Matrix3D( -.2 ), 01066 Matrix3D( 0.5 ), Matrix3D( 7.0 ), Matrix3D( 1.5 ) }; 01067 01068 Vector3D vtx_grad[3]; 01069 Matrix3D vtx_hess[6]; 01070 MsqError err; 01071 AveragingQM aqm( scheme ); 01072 uint32_t fixed = 0x4; // mark third vertex as fixed 01073 01074 aqm.average_corner_hessians( TRIANGLE, fixed, 3, vals, grads, hesss, vtx_grad, vtx_hess, err ); 01075 CPPUNIT_ASSERT( err ); 01076 } 01077 01078 void AveragingQMTest::test_average_corner_hessians_linear() 01079 { 01080 check_pmean_hessian( QualityMetric::LINEAR, 1, 1, true ); 01081 } 01082 01083 void AveragingQMTest::test_average_corner_hessians_rms() 01084 { 01085 check_pmean_hessian( QualityMetric::RMS, 2, 0.5, true ); 01086 } 01087 01088 void AveragingQMTest::test_average_corner_hessians_hms() 01089 { 01090 check_pmean_hessian( QualityMetric::HMS, -2, -0.5, true ); 01091 } 01092 01093 void AveragingQMTest::test_average_corner_hessians_minimum() 01094 { 01095 check_hessian_fails( QualityMetric::MINIMUM ); 01096 } 01097 01098 void AveragingQMTest::test_average_corner_hessians_maximum() 01099 { 01100 check_hessian_fails( QualityMetric::MAXIMUM ); 01101 } 01102 01103 void AveragingQMTest::test_average_corner_hessians_harmonic() 01104 { 01105 check_pmean_hessian( QualityMetric::HARMONIC, -1, -1, true ); 01106 } 01107 01108 void AveragingQMTest::test_average_corner_hessians_geometric() 01109 { 01110 check_hessian_fails( QualityMetric::GEOMETRIC ); 01111 } 01112 01113 void AveragingQMTest::test_average_corner_hessians_sum() 01114 { 01115 check_pmean_hessian( QualityMetric::SUM, 1, 1, false ); 01116 } 01117 01118 void AveragingQMTest::test_average_corner_hessians_sum_squared() 01119 { 01120 check_pmean_hessian( QualityMetric::SUM_SQUARED, 2, 1, false ); 01121 } 01122 01123 void AveragingQMTest::test_average_corner_hessians_standard_deviation() 01124 { 01125 check_hessian_fails( QualityMetric::STANDARD_DEVIATION ); 01126 } 01127 01128 void AveragingQMTest::test_average_corner_hessians_max_over_min() 01129 { 01130 check_hessian_fails( QualityMetric::MAX_OVER_MIN ); 01131 } 01132 01133 void AveragingQMTest::test_average_corner_hessians_max_minus_min() 01134 { 01135 check_hessian_fails( QualityMetric::MAX_MINUS_MIN ); 01136 } 01137 01138 void AveragingQMTest::test_average_corner_hessians_sum_of_ratios_squared() 01139 { 01140 check_hessian_fails( QualityMetric::SUM_OF_RATIOS_SQUARED ); 01141 }