MOAB: Mesh Oriented datABase  (version 5.4.1)
AveragingQMTest.cpp
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     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 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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines