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