MOAB: Mesh Oriented datABase  (version 5.2.1)
QualityMetricTester Class Reference

#include <QualityMetricTester.hpp>

+ Collaboration diagram for QualityMetricTester:

Classes

class  PatchXform

Public Types

enum  ElemTypeGroup {
  SIMPLICIES, NON_MIXED_FE, TWO_D, TWO_D_FE,
  THREE_D, THREE_D_FE, THREE_D_NON_MIXED_FE, THREE_D_FE_EXCEPT_SEPTAHEDRON,
  ALL_FE_EXCEPT_SEPTAHEDRON, ALL_FE, ALL
}

Public Member Functions

void get_ideal_tris (PatchData &pd, bool unit_area)
void get_ideal_quads (PatchData &pd)
void get_ideal_hexes (PatchData &pd)
void get_ideal_element (EntityTopology type, bool unit_area, PatchData &pd, bool first_vertex_fixed=false)
void get_ideal_element (EntityTopology type, bool unit_area, PatchData &pd, int free_vertex_index)
void get_nonideal_element (EntityTopology type, PatchData &pd, bool first_vertex_fixed=false)
void get_nonideal_element (EntityTopology type, PatchData &pd, int free_vertex_index)
void get_degenerate_element (EntityTopology type, PatchData &pd)
void get_zero_element (EntityTopology type, PatchData &pd)
void get_inverted_element (EntityTopology type, PatchData &pd)
 QualityMetricTester (ElemTypeGroup group, const Settings *set=0)
 QualityMetricTester (const EntityTopology *supported_elem_types, size_t supported_elem_types_len, const Settings *set=0)
void ideal_pyramid_base_equals_height (bool flag)
void test_supported_element_types (QualityMetric *qm)
void test_measures_quality (QualityMetric *qm)
void test_measures_vertex_quality (QualityMetric *qm)
void test_domain_deviation_quality (QualityMetric *qm)
void test_gradient_reflects_quality (QualityMetric *qm)
void test_vertex_gradient_reflects_quality (QualityMetric *qm)
void test_domain_deviation_gradient (QualityMetric *qm)
void test_evaluate_unit_element (QualityMetric *qm, EntityTopology type, double value)
void test_evaluate_unit_edge_element (QualityMetric *qm, EntityTopology type, double value)
void test_evaluate_unit_tris_about_vertex (QualityMetric *qm, double expected_val)
void test_evaluate_unit_quads_about_vertex (QualityMetric *qm, double expected_val)
void test_evaluate_unit_hexes_about_vertex (QualityMetric *qm, double expected_val)
void test_evaluate_unit_edge_tris_about_vertex (QualityMetric *qm, double expected_val)
void test_evaluate_inverted_element (QualityMetric *qm, bool should_succeed)
void test_evaluate_degenerate_element (QualityMetric *qm, bool should_succeed)
void test_evaluate_zero_element (QualityMetric *qm, bool should_succeed)
void test_get_element_evaluations (QualityMetric *qm)
void test_get_vertex_evaluations (QualityMetric *qm)
void test_get_sample_evaluations (QualityMetric *qm)
void test_get_edge_evaluations (EdgeQM *qm)
void test_get_in_element_evaluations (ElemSampleQM *qm)
void test_get_indices_fixed (QualityMetric *qm)
void test_get_element_indices (QualityMetric *qm)
void test_get_vertex_indices (QualityMetric *qm)
void test_get_edge_indices (EdgeQM *qm)
void test_get_sample_indices (QualityMetric *qm)
void compare_eval_and_eval_with_indices (QualityMetric *qm)
void compare_eval_and_eval_with_indices (QualityMetric *qm, PatchData &pd)
void compare_eval_with_indices_and_eval_with_gradient (QualityMetric *qm)
void compare_eval_with_indices_and_eval_with_gradient (QualityMetric *qm, PatchData &pd)
void compare_eval_with_indices_and_eval_with_hessian (QualityMetric *qm)
void compare_eval_with_indices_and_eval_with_hessian (QualityMetric *qm, PatchData &pd)
void compare_eval_with_indices_and_eval_with_diagonal (QualityMetric *qm)
void compare_eval_with_indices_and_eval_with_diagonal (QualityMetric *qm, PatchData &pd)
void compare_eval_with_grad_and_eval_with_hessian (QualityMetric *qm)
void compare_eval_with_grad_and_eval_with_hessian (QualityMetric *qm, PatchData &pd)
void compare_eval_with_grad_and_eval_with_diagonal (QualityMetric *qm)
void compare_eval_with_grad_and_eval_with_diagonal (QualityMetric *qm, PatchData &pd)
void compare_eval_with_diag_and_eval_with_hessian (QualityMetric *qm)
void compare_eval_with_diag_and_eval_with_hessian (QualityMetric *qm, PatchData &pd)
void compare_analytical_and_numerical_gradients (QualityMetric *qm)
void compare_analytical_and_numerical_gradients (QualityMetric *qm, PatchData &pd)
void compare_analytical_and_numerical_hessians (QualityMetric *qm)
void compare_analytical_and_numerical_hessians (QualityMetric *qm, PatchData &pd)
void compare_analytical_and_numerical_diagonals (QualityMetric *qm)
void compare_analytical_and_numerical_diagonals (QualityMetric *qm, PatchData &pd)
void test_gradient_with_fixed_vertex (QualityMetric *qm, const Settings *settings=0)
void test_gradient_with_fixed_vertex (EntityTopology type, QualityMetric *qm, const Settings *settings=0)
void test_hessian_with_fixed_vertex (QualityMetric *qm, const Settings *settings=0)
void test_hessian_with_fixed_vertex (EntityTopology type, QualityMetric *qm, const Settings *settings=0)
void test_diagonal_with_fixed_vertex (QualityMetric *qm, const Settings *settings=0)
void test_diagonal_with_fixed_vertex (EntityTopology type, QualityMetric *qm, const Settings *settings=0)
void test_ideal_element_zero_gradient (QualityMetric *qm, bool unit_area)
void test_ideal_element_zero_vertex_gradient (QualityMetric *qm, bool unit_area)
void test_ideal_element_positive_definite_Hessian (QualityMetric *qm, bool unit_area)
void test_symmetric_Hessian_diagonal_blocks (QualityMetric *qm)
void test_location_invariant (QualityMetric *qm, bool untangler=false)
void test_scale_invariant (QualityMetric *qm, bool untangler=false)
void test_orient_invariant (QualityMetric *qm, bool untangler=false)
void test_grad_location_invariant (QualityMetric *qm, bool untangler=false)
void test_grad_orient_invariant (QualityMetric *qm, bool untangler=false)
void test_hessian_location_invariant (QualityMetric *qm, bool untangler=false)
void test_measures_size (QualityMetric *qm, bool unit_area)
void test_measures_in_plane_orientation (QualityMetric *qm)
void test_measures_out_of_plane_orientation (QualityMetric *qm)
void test_transform_invariant (QualityMetric *qm, PatchXform &transform, bool untangler)
void test_grad_transform_invariant (QualityMetric *qm, PatchXform &transform, bool untangler)
void test_hessian_transform_invariant (QualityMetric *qm, PatchXform &transform, bool untangler)
void test_measures_transform (QualityMetric *qm, PatchXform &transform, bool unit_area)

Private Member Functions

bool type_is_supported (EntityTopology type)
void test_type_is_supported (EntityTopology type, QualityMetric *qm)
void test_type_is_not_supported (EntityTopology type, QualityMetric *qm)

Private Attributes

bool degenHexPyramid
 See: ideal_pyramid_base_equals_height()
std::vector< EntityTopologytypes
const SettingsmSettings
PlanarDomain geomPlane

Detailed Description

Definition at line 45 of file QualityMetricTester.hpp.


Member Enumeration Documentation

Enumerator:
SIMPLICIES 
NON_MIXED_FE 
TWO_D 
TWO_D_FE 
THREE_D 
THREE_D_FE 
THREE_D_NON_MIXED_FE 
THREE_D_FE_EXCEPT_SEPTAHEDRON 
ALL_FE_EXCEPT_SEPTAHEDRON 
ALL_FE 
ALL 

Definition at line 59 of file QualityMetricTester.hpp.

    {
        SIMPLICIES,                     // triangle and tetrahedron
        NON_MIXED_FE,                   // tri, quad, tet, hex
        TWO_D,                          // tri, quad, polygon
        TWO_D_FE,                       // tri, quad
        THREE_D,                        // tet, hex, pyr, wedge, septahedron, polyhedron
        THREE_D_FE,                     // tet, hex, pyr, wedge, septahedron
        THREE_D_NON_MIXED_FE,           // tet, hex,
        THREE_D_FE_EXCEPT_SEPTAHEDRON,  // tet, hex, pyr, wedge
        ALL_FE_EXCEPT_SEPTAHEDRON,      // tri, quad, tet, hex, pyr, wedge
        ALL_FE,                         // everything except polygon and polyhedron
        ALL
    };  // everything (including polyhedron)

Constructor & Destructor Documentation

Definition at line 91 of file QualityMetricTester.cpp.

    : degenHexPyramid( false ), types( types_in_group( group ) ), mSettings( settings ),
      geomPlane( Vector3D( 0, 0, 1 ), Vector3D( 0, 0, 0 ) )
{
}
QualityMetricTester::QualityMetricTester ( const EntityTopology supported_elem_types,
size_t  supported_elem_types_len,
const Settings set = 0 
)

Definition at line 83 of file QualityMetricTester.cpp.

References types.

    : degenHexPyramid( false ), types( len ), mSettings( settings ),
      geomPlane( Vector3D( 0, 0, 1 ), Vector3D( 0, 0, 0 ) )
{
    std::copy( supported_elem_types, supported_elem_types + len, types.begin() );
}

Member Function Documentation

compare analytical and numerical Hessian diagonal results

Definition at line 1422 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, get_nonideal_element(), mSettings, and types.

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    MsqError err;

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_nonideal_element( types[i], pd, true );
        compare_analytical_and_numerical_diagonals( qm, pd );
    }
}

Definition at line 1379 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_MATRICES_EQUAL, MBMesquite::QualityMetric::evaluate_with_Hessian_diagonal(), MBMesquite::QualityMetric::get_evaluations(), and MSQ_CHKERR.

{
    MsqPrintError err( std::cout );
    std::vector< size_t > handles, indices1, indices2;
    std::vector< Vector3D > grad1, grad2;
    std::vector< Matrix3D > Hess1;
    std::vector< SymMatrix3D > Hess2;
    double qm_val1, qm_val2;
    bool rval;

    qm->get_evaluations( pd, handles, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles.empty() );
    for( size_t j = 0; j < handles.size(); ++j )
    {
        rval = qm->QualityMetric::evaluate_with_Hessian( pd, handles[j], qm_val1, indices1, grad1, Hess1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        rval = qm->evaluate_with_Hessian_diagonal( pd, handles[j], qm_val2, indices2, grad2, Hess2, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );

        CPPUNIT_ASSERT_DOUBLES_EQUAL( qm_val1, qm_val2, 1e-6 );
        CPPUNIT_ASSERT_EQUAL( indices1.size(), indices2.size() );
        CPPUNIT_ASSERT( !indices1.empty() );
        CPPUNIT_ASSERT_EQUAL( indices1.size() * ( indices1.size() + 1 ) / 2, Hess1.size() );
        CPPUNIT_ASSERT_EQUAL( indices2.size(), Hess2.size() );

        size_t h = 0;
        std::vector< size_t >::iterator it;
        for( unsigned r = 0; r < indices1.size(); ++r )
        {
            it = std::find( indices2.begin(), indices2.end(), indices1[r] );
            CPPUNIT_ASSERT( it != indices2.end() );
            unsigned r2 = it - indices2.begin();
            // if (!utest_mat_equal(Hess1[h],Hess2[r2],0.001))
            //  assert(false);
            CPPUNIT_ASSERT_MATRICES_EQUAL( Hess1[h], Hess2[r2], 0.001 );
            h += indices1.size() - r;
        }
    }
}

compare analytical and numerical gradient results

Definition at line 1300 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, get_nonideal_element(), mSettings, and types.

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_nonideal_element( types[i], pd, true );
        compare_analytical_and_numerical_gradients( qm, pd );
    }
}

Definition at line 1263 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::get_evaluations(), and MSQ_CHKERR.

{
    MsqPrintError err( std::cout );
    std::vector< size_t > handles, indices1, indices2;
    std::vector< Vector3D > grad1, grad2;
    double qm_val1, qm_val2;
    bool rval;

    qm->get_evaluations( pd, handles, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles.empty() );
    for( size_t j = 0; j < handles.size(); ++j )
    {
        rval = qm->QualityMetric::evaluate_with_gradient( pd, handles[j], qm_val1, indices1, grad1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        rval = qm->evaluate_with_gradient( pd, handles[j], qm_val2, indices2, grad2, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );

        CPPUNIT_ASSERT_DOUBLES_EQUAL( qm_val1, qm_val2, 1e-6 );
        CPPUNIT_ASSERT_EQUAL( indices1.size(), indices2.size() );
        CPPUNIT_ASSERT( !indices1.empty() );

        std::vector< size_t >::iterator it1, it2;
        for( it1 = indices1.begin(); it1 != indices1.end(); ++it1 )
        {
            it2 = std::find( indices2.begin(), indices2.end(), *it1 );
            CPPUNIT_ASSERT( it2 != indices2.end() );

            size_t idx1 = it1 - indices1.begin();
            size_t idx2 = it2 - indices2.begin();
            CPPUNIT_ASSERT_VECTORS_EQUAL( grad1[idx1], grad2[idx2], 0.01 );
        }
    }
}

compare analytical and numerical Hessian results

Definition at line 1366 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, get_nonideal_element(), mSettings, and types.

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_nonideal_element( types[i], pd, true );
        compare_analytical_and_numerical_hessians( qm, pd );
    }
}

Definition at line 1313 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_MATRICES_EQUAL, MBMesquite::QualityMetric::evaluate_with_Hessian(), MBMesquite::QualityMetric::get_evaluations(), and MSQ_CHKERR.

{
    MsqPrintError err( std::cout );
    std::vector< size_t > handles, indices1, indices2;
    std::vector< Vector3D > grad1, grad2;
    std::vector< Matrix3D > Hess1, Hess2;
    double qm_val1, qm_val2;
    bool rval;

    qm->get_evaluations( pd, handles, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles.empty() );
    for( size_t j = 0; j < handles.size(); ++j )
    {
        rval = qm->QualityMetric::evaluate_with_Hessian( pd, handles[j], qm_val1, indices1, grad1, Hess1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        rval = qm->evaluate_with_Hessian( pd, handles[j], qm_val2, indices2, grad2, Hess2, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );

        CPPUNIT_ASSERT_DOUBLES_EQUAL( qm_val1, qm_val2, 1e-6 );
        CPPUNIT_ASSERT_EQUAL( indices1.size(), indices2.size() );
        CPPUNIT_ASSERT( !indices1.empty() );

        std::vector< size_t >::iterator it;
        unsigned h = 0;
        for( unsigned r = 0; r < indices1.size(); ++r )
        {
            it = std::find( indices2.begin(), indices2.end(), indices1[r] );
            CPPUNIT_ASSERT( it != indices2.end() );
            unsigned r2 = it - indices2.begin();

            for( unsigned c = r; c < indices1.size(); ++c, ++h )
            {
                it = std::find( indices2.begin(), indices2.end(), indices1[c] );
                CPPUNIT_ASSERT( it != indices2.end() );
                unsigned c2 = it - indices2.begin();

                unsigned h2;
                if( r2 <= c2 )
                    h2 = indices2.size() * r - r * ( r + 1 ) / 2 + c;
                else
                    h2 = indices2.size() * c - c * ( c + 1 ) / 2 + r;

                // if (!utest_mat_equal(Hess1[h],Hess2[h2],0.001))
                //  assert(false);
                CPPUNIT_ASSERT_MATRICES_EQUAL( Hess1[h], Hess2[h2], 0.001 );
            }
        }
    }
}

compare results of evaluate() and evaluate_with_indices() methods

Definition at line 953 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, MBMesquite::QualityMetric::evaluate(), MBMesquite::QualityMetric::evaluate_with_indices(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), mSettings, MSQ_CHKERR, and types.

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices;
    double qm_val1, qm_val2;
    bool rval;

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_ideal_element( types[i], false, pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );
        for( size_t j = 0; j < handles.size(); ++j )
        {
            rval = qm->evaluate( pd, handles[j], qm_val1, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            rval = qm->evaluate_with_indices( pd, handles[j], qm_val2, indices, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );

            CPPUNIT_ASSERT_DOUBLES_EQUAL( qm_val1, qm_val2, 1e-6 );
        }
    }
}

compare results of evaluate_with_Hessian_diagonal() and evaluate_with_Hessian() methods

Definition at line 1250 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, get_nonideal_element(), mSettings, and types.

Referenced by TQualityMetricTest::test_inverse_mean_ratio_hess_diag().

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_nonideal_element( types[i], pd, true );
        compare_eval_with_diag_and_eval_with_hessian( qm, pd );
    }
}

Definition at line 1208 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_MATRICES_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::QualityMetric::evaluate_with_Hessian(), MBMesquite::QualityMetric::evaluate_with_Hessian_diagonal(), MBMesquite::QualityMetric::get_evaluations(), and MSQ_CHKERR.

{
    MsqPrintError err( std::cout );
    std::vector< size_t > handles, indices1, indices2;
    std::vector< Vector3D > grad1, grad2;
    std::vector< SymMatrix3D > hess1;
    std::vector< Matrix3D > hess2;
    double qm_val1, qm_val2;
    bool rval;

    qm->get_evaluations( pd, handles, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles.empty() );
    for( size_t j = 0; j < handles.size(); ++j )
    {
        rval = qm->evaluate_with_Hessian_diagonal( pd, handles[j], qm_val1, indices1, grad1, hess1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        rval = qm->evaluate_with_Hessian( pd, handles[j], qm_val2, indices2, grad2, hess2, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );

        CPPUNIT_ASSERT_DOUBLES_EQUAL( qm_val1, qm_val2, 1e-6 );

        CPPUNIT_ASSERT_EQUAL( indices1.size(), indices2.size() );
        CPPUNIT_ASSERT_EQUAL( grad1.size(), grad2.size() );
        CPPUNIT_ASSERT_EQUAL( hess2.size(), hess1.size() * ( hess1.size() + 1 ) / 2 );
        unsigned h2step                             = indices2.size();
        std::vector< Matrix3D >::const_iterator h2i = hess2.begin();

        for( size_t k = 0; k < indices2.size(); ++k )
        {
            std::vector< size_t >::iterator it = std::find( indices1.begin(), indices1.end(), indices2[k] );
            CPPUNIT_ASSERT( it != indices1.end() );
            size_t m = it - indices1.begin();
            CPPUNIT_ASSERT_VECTORS_EQUAL( grad1[m], grad2[k], 5e-5 );
            CPPUNIT_ASSERT_MATRICES_EQUAL( Matrix3D( hess1[m] ), *h2i, 5e-5 );
            h2i += h2step--;
        }
    }
}

compare results of evaluate_with_gradient() and evaluate_with_Hessian_diagonal() methods

Definition at line 1195 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, get_nonideal_element(), mSettings, and types.

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_nonideal_element( types[i], pd, true );
        compare_eval_with_grad_and_eval_with_diagonal( qm, pd );
    }
}

Definition at line 1161 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::evaluate_with_Hessian_diagonal(), MBMesquite::QualityMetric::get_evaluations(), and MSQ_CHKERR.

{
    MsqPrintError err( std::cout );
    std::vector< size_t > handles, indices1, indices2;
    std::vector< Vector3D > grad1, grad2;
    std::vector< SymMatrix3D > Hess;
    double qm_val1, qm_val2;
    bool rval;

    qm->get_evaluations( pd, handles, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles.empty() );
    for( size_t j = 0; j < handles.size(); ++j )
    {
        rval = qm->evaluate_with_gradient( pd, handles[j], qm_val1, indices1, grad1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        rval = qm->evaluate_with_Hessian_diagonal( pd, handles[j], qm_val2, indices2, grad2, Hess, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );

        CPPUNIT_ASSERT_DOUBLES_EQUAL( qm_val1, qm_val2, 1e-6 );
        CPPUNIT_ASSERT_EQUAL( indices1.size(), indices2.size() );

        for( size_t k = 0; k < indices1.size(); ++k )
        {
            std::vector< size_t >::iterator it = std::find( indices2.begin(), indices2.end(), indices1[k] );
            CPPUNIT_ASSERT( it != indices2.end() );
            size_t m = it - indices2.begin();
            CPPUNIT_ASSERT_VECTORS_EQUAL( grad1[k], grad2[m], 1e-6 );
        }
    }
}

compare results of evaluate_with_gradient() and evaluate_with_Hessian() methods

Definition at line 1148 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, get_nonideal_element(), mSettings, and types.

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_nonideal_element( types[i], pd, true );
        compare_eval_with_grad_and_eval_with_hessian( qm, pd );
    }
}

Definition at line 1114 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::evaluate_with_Hessian(), MBMesquite::QualityMetric::get_evaluations(), and MSQ_CHKERR.

{
    MsqPrintError err( std::cout );
    std::vector< size_t > handles, indices1, indices2;
    std::vector< Vector3D > grad1, grad2;
    std::vector< Matrix3D > Hess;
    double qm_val1, qm_val2;
    bool rval;

    qm->get_evaluations( pd, handles, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles.empty() );
    for( size_t j = 0; j < handles.size(); ++j )
    {
        rval = qm->evaluate_with_gradient( pd, handles[j], qm_val1, indices1, grad1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        rval = qm->evaluate_with_Hessian( pd, handles[j], qm_val2, indices2, grad2, Hess, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );

        CPPUNIT_ASSERT_DOUBLES_EQUAL( qm_val1, qm_val2, 1e-6 );
        CPPUNIT_ASSERT_EQUAL( indices1.size(), indices2.size() );

        for( size_t k = 0; k < indices1.size(); ++k )
        {
            std::vector< size_t >::iterator it = std::find( indices2.begin(), indices2.end(), indices1[k] );
            CPPUNIT_ASSERT( it != indices2.end() );
            size_t m = it - indices2.begin();
            CPPUNIT_ASSERT_VECTORS_EQUAL( grad1[k], grad2[m], 1e-6 );
        }
    }
}

compare results of evaluate_with_indices() and evaluate_with_Hessian_diagonal() methods

Definition at line 1101 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, get_nonideal_element(), mSettings, and types.

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_nonideal_element( types[i], pd, true );
        compare_eval_with_indices_and_eval_with_diagonal( qm, pd );
    }
}

Definition at line 1070 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::evaluate_with_Hessian_diagonal(), MBMesquite::QualityMetric::evaluate_with_indices(), MBMesquite::QualityMetric::get_evaluations(), MBMesquite::grad(), and MSQ_CHKERR.

{
    MsqPrintError err( std::cout );
    std::vector< size_t > handles, indices1, indices2;
    std::vector< Vector3D > grad;
    std::vector< SymMatrix3D > Hess;
    double qm_val1, qm_val2;
    bool rval;

    qm->get_evaluations( pd, handles, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles.empty() );
    for( size_t j = 0; j < handles.size(); ++j )
    {
        rval = qm->evaluate_with_indices( pd, handles[j], qm_val1, indices1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        rval = qm->evaluate_with_Hessian_diagonal( pd, handles[j], qm_val2, indices2, grad, Hess, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );

        CPPUNIT_ASSERT_DOUBLES_EQUAL( qm_val1, qm_val2, 1e-6 );
        CPPUNIT_ASSERT_EQUAL( indices1.size(), indices2.size() );

        std::sort( indices1.begin(), indices1.end() );
        std::sort( indices2.begin(), indices2.end() );
        CPPUNIT_ASSERT( indices1 == indices2 );
        CPPUNIT_ASSERT( !indices1.empty() );
    }
}

compare results of evaluate_with_indices() and evaluate_with_gradient() methods

Definition at line 1013 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, get_ideal_element(), mSettings, and types.

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_ideal_element( types[i], false, pd, true );
        compare_eval_with_indices_and_eval_with_gradient( qm, pd );
    }
}

Definition at line 983 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::evaluate_with_indices(), MBMesquite::QualityMetric::get_evaluations(), MBMesquite::grad(), and MSQ_CHKERR.

{
    MsqPrintError err( std::cout );
    std::vector< size_t > handles, indices1, indices2;
    std::vector< Vector3D > grad;
    double qm_val1, qm_val2;
    bool rval;

    qm->get_evaluations( pd, handles, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles.empty() );
    for( size_t j = 0; j < handles.size(); ++j )
    {
        rval = qm->evaluate_with_indices( pd, handles[j], qm_val1, indices1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        rval = qm->evaluate_with_gradient( pd, handles[j], qm_val2, indices2, grad, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );

        CPPUNIT_ASSERT_DOUBLES_EQUAL( qm_val1, qm_val2, 1e-6 );
        CPPUNIT_ASSERT_EQUAL( indices1.size(), indices2.size() );

        std::sort( indices1.begin(), indices1.end() );
        std::sort( indices2.begin(), indices2.end() );
        CPPUNIT_ASSERT( indices1 == indices2 );
        CPPUNIT_ASSERT( !indices1.empty() );
    }
}

compare results of evaluate_with_indices() and evaluate_with_Hessian() methods

Definition at line 1057 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, get_nonideal_element(), mSettings, and types.

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_nonideal_element( types[i], pd, true );
        compare_eval_with_indices_and_eval_with_hessian( qm, pd );
    }
}

Definition at line 1026 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::evaluate_with_Hessian(), MBMesquite::QualityMetric::evaluate_with_indices(), MBMesquite::QualityMetric::get_evaluations(), MBMesquite::grad(), and MSQ_CHKERR.

{
    MsqPrintError err( std::cout );
    std::vector< size_t > handles, indices1, indices2;
    std::vector< Vector3D > grad;
    std::vector< Matrix3D > Hess;
    double qm_val1, qm_val2;
    bool rval;

    qm->get_evaluations( pd, handles, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles.empty() );
    for( size_t j = 0; j < handles.size(); ++j )
    {
        rval = qm->evaluate_with_indices( pd, handles[j], qm_val1, indices1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        rval = qm->evaluate_with_Hessian( pd, handles[j], qm_val2, indices2, grad, Hess, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );

        CPPUNIT_ASSERT_DOUBLES_EQUAL( qm_val1, qm_val2, 1e-6 );
        CPPUNIT_ASSERT_EQUAL( indices1.size(), indices2.size() );

        std::sort( indices1.begin(), indices1.end() );
        std::sort( indices2.begin(), indices2.end() );
        CPPUNIT_ASSERT( indices1 == indices2 );
        CPPUNIT_ASSERT( !indices1.empty() );
    }
}

Collapse first and second vertices of an ideal element

Definition at line 242 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::element_by_index(), get_ideal_element(), MBMesquite::PatchData::get_vertex_array(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), and MBMesquite::PatchData::set_vertex_coordinates().

Referenced by test_evaluate_degenerate_element().

{
    MsqError err;
    get_ideal_element( type, false, pd );
    const size_t* verts     = pd.element_by_index( 0 ).get_vertex_index_array();
    const MsqVertex* coords = pd.get_vertex_array( err );
    pd.set_vertex_coordinates( coords[verts[1]], verts[0], err );
}
void QualityMetricTester::get_ideal_element ( EntityTopology  type,
bool  unit_area,
PatchData pd,
int  free_vertex_index 
)

Definition at line 181 of file QualityMetricTester.cpp.

References MBMesquite::arrptr(), conn, corners, CPPUNIT_ASSERT, degenHexPyramid, MBMesquite::PatchData::fill(), fixed, geomPlane, MSQ_CHKERR, n, MBMesquite::PatchData::set_domain(), MBMesquite::unit_edge_element(), and MBMesquite::unit_element().

{
    if( TopologyInfo::dimension( type ) == 2 ) pd.set_domain( &geomPlane );

    const size_t n = TopologyInfo::corners( type );
    const Vector3D* coords =
        unit_area ? unit_element( type, degenHexPyramid ) : unit_edge_element( type, degenHexPyramid );
    CPPUNIT_ASSERT( coords != 0 );

    CPPUNIT_ASSERT( sizeof( double ) * 3 == sizeof( Vector3D ) );
    const double* elem_verts = reinterpret_cast< const double* >( coords );

    bool* fixed = new bool[n];
    std::vector< size_t > conn( n );
    for( size_t i = 0; i < n; ++i )
    {
        conn[i]  = i;
        fixed[i] = ( free_vertex_index >= 0 );
    }
    if( free_vertex_index == -2 )
        fixed[0] = true;
    else if( free_vertex_index >= 0 )
        fixed[free_vertex_index] = false;

    MsqPrintError err( std::cout );
    pd.fill( n, elem_verts, 1, type, arrptr( conn ), fixed, err );
    delete[] fixed;
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
}

Definition at line 154 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, MBMesquite::PatchData::fill(), fixed, MBMesquite::HEXAHEDRON, and MSQ_CHKERR.

Referenced by test_evaluate_unit_hexes_about_vertex(), test_get_element_evaluations(), test_get_sample_evaluations(), test_get_vertex_evaluations(), test_ideal_element_zero_vertex_gradient(), test_measures_vertex_quality(), and test_vertex_gradient_reflects_quality().

{
    static const double ideal_hex_verts[] = { 0.0,  0.0,  0.0,  -1.0, 0.0,  0.0,  -1.0, -1.0, 0.0,  0.0,  -1.0, 0.0,
                                              1.0,  -1.0, 0.0,  1.0,  0.0,  0.0,  1.0,  1.0,  0.0,  0.0,  1.0,  0.0,
                                              -1.0, 1.0,  0.0,  0.0,  0.0,  -1.0, -1.0, 0.0,  -1.0, -1.0, -1.0, -1.0,
                                              0.0,  -1.0, -1.0, 1.0,  -1.0, -1.0, 1.0,  0.0,  -1.0, 1.0,  1.0,  -1.0,
                                              0.0,  1.0,  -1.0, -1.0, 1.0,  -1.0, 0.0,  0.0,  1.0,  -1.0, 0.0,  1.0,
                                              -1.0, -1.0, 1.0,  0.0,  -1.0, 1.0,  1.0,  -1.0, 1.0,  1.0,  0.0,  1.0,
                                              1.0,  1.0,  1.0,  0.0,  1.0,  1.0,  -1.0, 1.0,  1.0 };
    static const size_t ideal_hex_elems[] = { 9, 10, 11, 12, 0,  1,  2,  3,  9, 12, 13, 14, 0,  3,  4,  5,
                                              9, 14, 15, 16, 0,  5,  6,  7,  9, 16, 17, 10, 0,  7,  8,  1,
                                              0, 1,  2,  3,  18, 19, 20, 21, 0, 3,  4,  5,  18, 21, 22, 23,
                                              0, 5,  6,  7,  18, 23, 24, 25, 0, 7,  8,  1,  18, 25, 26, 19 };
    bool fixed[27];
    fixed[0] = false;
    for( size_t f = 1; f < 27; ++f )
        fixed[f] = true;

    MsqPrintError err( std::cout );
    pd.fill( 27, ideal_hex_verts, 8, HEXAHEDRON, ideal_hex_elems, fixed, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
}

Definition at line 128 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, MBMesquite::PatchData::fill(), fixed, geomPlane, MSQ_CHKERR, MBMesquite::QUADRILATERAL, and MBMesquite::PatchData::set_domain().

Referenced by test_domain_deviation_gradient(), test_domain_deviation_quality(), test_evaluate_unit_quads_about_vertex(), test_get_element_evaluations(), test_get_sample_evaluations(), test_get_vertex_evaluations(), test_ideal_element_zero_vertex_gradient(), test_measures_vertex_quality(), and test_vertex_gradient_reflects_quality().

{
    //            7
    //   8 +------+------+ 6
    //     |      |      |
    //     |      |      |
    //     |      |0     |
    //   1 +------+------+ 5
    //     |      |      |
    //     |      |      |
    //     |      |      |
    //   2 +------+------+ 4
    //            3
    static const double ideal_quad_verts[] = { 0.0, 0.0,  0.0, -1.0, 0.0,  0.0, -1.0, -1.0, 0.0,
                                               0.0, -1.0, 0.0, 1.0,  -1.0, 0.0, 1.0,  0.0,  0.0,
                                               1.0, 1.0,  0.0, 0.0,  1.0,  0.0, -1.0, 1.0,  0.0 };
    static const size_t ideal_quad_elems[] = { 0, 1, 2, 3, 0, 3, 4, 5, 0, 5, 6, 7, 0, 7, 8, 1 };
    const bool fixed[]                     = { false, true, true, true, true, true, true, true, true };

    pd.set_domain( &geomPlane );

    MsqPrintError err( std::cout );
    pd.fill( 9, ideal_quad_verts, 4, QUADRILATERAL, ideal_quad_elems, fixed, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
}
void QualityMetricTester::get_ideal_tris ( PatchData pd,
bool  unit_area 
)

Definition at line 97 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, MBMesquite::PatchData::fill(), fixed, geomPlane, MSQ_CHKERR, MBMesquite::MSQ_SQRT_THREE_DIV_TWO, MBMesquite::PatchData::set_domain(), and MBMesquite::TRIANGLE.

Referenced by test_domain_deviation_gradient(), test_domain_deviation_quality(), test_evaluate_unit_edge_tris_about_vertex(), test_evaluate_unit_tris_about_vertex(), test_get_element_evaluations(), test_get_sample_evaluations(), test_get_vertex_evaluations(), test_ideal_element_zero_vertex_gradient(), test_measures_vertex_quality(), and test_vertex_gradient_reflects_quality().

{
    //      6 ------- 5     .
    //       /\     /\      .
    //      /  \   /  \     .
    //     /    \ /    \    .
    //  1 <------X------> 4 .
    //     \    /0\    /    .
    //      \  /   \  /     .
    //       \/     \/      .
    //      2 ------- 3     .
    static const double y3         = MSQ_SQRT_THREE_DIV_TWO;
    double ideal_tri_verts[]       = { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -0.5, -y3,  0.0, 0.5, -y3,
                                 0.0, 1.0, 0.0, 0.0,  0.5, y3,  0.0,  -0.5, y3,  0.0 };
    const size_t ideal_tri_elems[] = { 0, 1, 2, 0, 2, 3, 0, 4, 5, 0, 4, 5, 0, 5, 6, 0, 6, 1 };
    const bool fixed[]             = { false, true, true, true, true, true, true };

    if( unit_area )
    {
        const double unit_tri_scale = 2.0 / std::sqrt( 6.0 );
        for( size_t i = 0; i < sizeof( ideal_tri_verts ) / sizeof( double ); ++i )
            ideal_tri_verts[i] *= unit_tri_scale;
    }

    pd.set_domain( &geomPlane );

    MsqPrintError err( std::cout );
    pd.fill( 7, ideal_tri_verts, 6, TRIANGLE, ideal_tri_elems, fixed, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
}

Create inverted elements. For tri and tet elements, reflect one vertex about the opposite side. For all other elements, introduce a concave vertex in one of the quadrilateral faces.

Definition at line 304 of file QualityMetricTester.cpp.

References MBMesquite::MsqMeshEntity::check_element_orientation(), CPPUNIT_ASSERT, MBMesquite::PatchData::domain_set(), MBMesquite::PatchData::element_by_index(), get_ideal_element(), MBMesquite::PatchData::get_vertex_array(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), MBMesquite::HEXAHEDRON, MBMesquite::PRISM, MBMesquite::PYRAMID, MBMesquite::QUADRILATERAL, MBMesquite::PatchData::set_vertex_coordinates(), moab::sum(), MBMesquite::TETRAHEDRON, and MBMesquite::TRIANGLE.

Referenced by test_evaluate_inverted_element(), test_grad_transform_invariant(), test_hessian_transform_invariant(), and test_transform_invariant().

{
    MsqError err;
    get_ideal_element( type, false, pd );
    MsqMeshEntity& elem     = pd.element_by_index( 0 );
    const size_t* verts     = elem.get_vertex_index_array();
    const MsqVertex* coords = pd.get_vertex_array( err );
    unsigned i;
    Vector3D sum( 0, 0, 0 );

    //  switch (type) {
    //    case TRIANGLE:
    //      coords[verts[2]] = coords[verts[0]] + coords[verts[1]] - coords[verts[2]];
    //      break;
    //    case QUADRILATERAL:
    //    case PYRAMID:
    //    case HEXAHEDRON:
    //      coords[verts[2]] += 0.75 * (coords[verts[0]] - coords[verts[2]]);
    //      break;
    //    case TETRAHEDRON:
    //      for (i = 0; i < 3; ++i)
    //        sum += coords[verts[i]];
    //      coords[verts[3]] += 0.5*sum - 1.5*coords[verts[3]];
    //      break;
    //    case PRISM:
    //      coords[verts[4]] += 0.75 * (coords[verts[0]] - coords[verts[4]]);
    //      break;
    //    default:
    //      CPPUNIT_ASSERT(false);
    //      break;
    //  }
    if( type == TRIANGLE )
        pd.set_vertex_coordinates( coords[verts[0]] + coords[verts[1]] - coords[verts[2]], verts[2], err );
    else if( type == QUADRILATERAL || type == PYRAMID || type == HEXAHEDRON )
        pd.set_vertex_coordinates( 0.75 * ( coords[verts[0]] - coords[verts[2]] ), verts[2], err );
    else if( type == TETRAHEDRON )
    {
        for( i = 0; i < 3; ++i )
            sum += coords[verts[i]];
        pd.set_vertex_coordinates( 0.5 * sum - 1.5 * coords[verts[3]], verts[3], err );
    }
    else if( type == PRISM )
        pd.set_vertex_coordinates( 0.75 * ( coords[verts[0]] - coords[verts[4]] ), verts[4], err );
    else
        CPPUNIT_ASSERT( false );

    if( TopologyInfo::dimension( type ) == 3 || pd.domain_set() )
    {
        int inverted, total;
        elem.check_element_orientation( pd, inverted, total, err );
        CPPUNIT_ASSERT( !err );
        CPPUNIT_ASSERT( total );
    }
}
void QualityMetricTester::get_nonideal_element ( EntityTopology  type,
PatchData pd,
int  free_vtx_type 
)

Begin with an ideal element, and move the first vertex one half of the distnace to the centroid

Definition at line 218 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::element_by_index(), get_ideal_element(), MBMesquite::PatchData::get_vertex_array(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), n, MBMesquite::PatchData::set_vertex_coordinates(), moab::sum(), and MBMesquite::MsqMeshEntity::vertex_count().

{
    MsqError err;
    get_ideal_element( type, false, pd, free_vtx_type );
    const size_t* verts     = pd.element_by_index( 0 ).get_vertex_index_array();
    const MsqVertex* coords = pd.get_vertex_array( err );
    size_t n                = pd.element_by_index( 0 ).vertex_count();

    Vector3D sum( 0, 0, 0 );
    for( unsigned i = 0; i < n; ++i )
        sum += coords[verts[i]];

    sum /= n;
    sum += coords[verts[0]];
    sum *= 0.5;
    pd.set_vertex_coordinates( sum, verts[0], err );
}

Create element with zero area/volume For quads and hexes, the results are also inverted elements.

Definition at line 254 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, MBMesquite::PatchData::element_by_index(), get_ideal_element(), MBMesquite::PatchData::get_vertex_array(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), MBMesquite::HEXAHEDRON, MBMesquite::PRISM, MBMesquite::PYRAMID, MBMesquite::QUADRILATERAL, MBMesquite::PatchData::set_vertex_coordinates(), moab::sum(), MBMesquite::TETRAHEDRON, and MBMesquite::TRIANGLE.

Referenced by test_evaluate_zero_element().

{
    MsqError err;
    get_ideal_element( type, false, pd );
    MsqMeshEntity& elem     = pd.element_by_index( 0 );
    const size_t* verts     = elem.get_vertex_index_array();
    const MsqVertex* coords = pd.get_vertex_array( err );
    unsigned i;
    Vector3D sum( 0, 0, 0 );

    switch( type )
    {
        case TRIANGLE:
            pd.set_vertex_coordinates( 0.5 * ( coords[verts[0]] + coords[verts[1]] ), verts[2], err );
            break;
        case QUADRILATERAL:
            pd.set_vertex_coordinates( coords[verts[0]], verts[1], err );
            pd.set_vertex_coordinates( coords[verts[3]], verts[2], err );
            break;
        case TETRAHEDRON:
            for( i = 0; i < 3; ++i )
                sum += coords[verts[i]];
            pd.set_vertex_coordinates( sum / 3.0, verts[3], err );
            break;
        case PYRAMID:
            for( i = 0; i < 4; ++i )
                sum += coords[verts[i]];
            pd.set_vertex_coordinates( 0.25 * sum, verts[4], err );
            break;
        case PRISM:
            pd.set_vertex_coordinates( 0.5 * ( coords[verts[0]] + coords[verts[1]] ), verts[2], err );
            pd.set_vertex_coordinates( 0.5 * ( coords[verts[3]] + coords[verts[4]] ), verts[5], err );
            break;
        case HEXAHEDRON:
            pd.set_vertex_coordinates( coords[verts[0]], verts[4], err );
            pd.set_vertex_coordinates( coords[verts[1]], verts[5], err );
            pd.set_vertex_coordinates( coords[verts[2]], verts[6], err );
            pd.set_vertex_coordinates( coords[verts[3]], verts[7], err );
            break;
        default:
            CPPUNIT_ASSERT( false );
            break;
    }
}

Ideal pyramids should be considerd to have a heigth equal to the length of a side, rather than the default which is equilateral triangle faces.

Definition at line 83 of file QualityMetricTester.hpp.

    {
        degenHexPyramid = flag;
    }

compare Hessian diagonal w/ no fixed vertices to Hessian for element with all but one vertex fixed.

Definition at line 2468 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, and types.

{
    CPPUNIT_ASSERT( !types.empty() );
    for( unsigned i = 0; i < types.size(); ++i )
        test_diagonal_with_fixed_vertex( types[i], qm, settings );
}

Definition at line 2587 of file QualityMetricTester.cpp.

References ASSERT_NO_ERROR, MBMesquite::PatchData::attach_settings(), conn, corners, CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_MATRICES_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::PatchData::element_by_index(), MBMesquite::QualityMetric::evaluate_with_Hessian_diagonal(), MBMesquite::QualityMetric::get_evaluations(), get_nonideal_element(), MBMesquite::MsqMeshEntity::get_vertex_indices(), MBMesquite::grad(), MBMesquite::hess(), mSettings, and n.

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( settings )
        pd.attach_settings( settings );
    else if( mSettings )
        pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices, indices_fixed, conn;
    std::vector< Vector3D > grad, grad_fixed;
    std::vector< SymMatrix3D > hess, hess_fixed;
    double val, val_fixed;
    bool rval;
    const int n = TopologyInfo::corners( type );

    get_nonideal_element( type, pd );
    pd.element_by_index( 0 ).get_vertex_indices( conn );

    qm->get_evaluations( pd, handles, false, err );
    ASSERT_NO_ERROR( err );
    // For sample-based metrics, it is difficult to set up such that
    // both surface and volume elements have only one sample point.
    // Make things easier by skipping element types with no sample points.
    if( handles.empty() ) return;
    CPPUNIT_ASSERT_EQUAL_MESSAGE( "test only valid for element-based metrics", (size_t)1, handles.size() );
    size_t h = handles[0];

    rval = qm->evaluate_with_Hessian_diagonal( pd, h, val, indices, grad, hess, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( rval );
    CPPUNIT_ASSERT_EQUAL( (size_t)n, indices.size() );
    CPPUNIT_ASSERT_EQUAL( (size_t)n, grad.size() );
    CPPUNIT_ASSERT_EQUAL( (size_t)n, hess.size() );

    for( int i = 0; i < n; ++i )
    {
        get_nonideal_element( type, pd, i );

        qm->get_evaluations( pd, handles, false, err );
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT_EQUAL_MESSAGE( "test only valid for element-based metrics", (size_t)1, handles.size() );
        h = handles[0];

        rval = qm->evaluate_with_Hessian_diagonal( pd, h, val_fixed, indices_fixed, grad_fixed, hess_fixed, err );
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT( rval );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, indices_fixed.size() );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, grad_fixed.size() );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, hess_fixed.size() );

        const size_t j = conn[i];
        CPPUNIT_ASSERT_DOUBLES_EQUAL( val, val_fixed, 1e-5 );
        CPPUNIT_ASSERT_VECTORS_EQUAL( grad[j], grad_fixed.front(), 1e-5 );
        CPPUNIT_ASSERT_MATRICES_EQUAL( hess[j], hess_fixed.front(), 1e-4 );
    }
}

Test gradient reflects deviation from domain

Definition at line 1997 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_quads(), get_ideal_tris(), MBMesquite::QualityMetric::get_negate_flag(), MBMesquite::grad(), MBMesquite::PatchData::move_vertex(), mSettings, MSQ_CHKERR, MBMesquite::QUADRILATERAL, MBMesquite::TRIANGLE, and type_is_supported().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices;
    std::vector< Vector3D > grad;
    size_t i;
    double qmval;
    bool rval;

    CPPUNIT_ASSERT( type_is_supported( TRIANGLE ) || type_is_supported( QUADRILATERAL ) );

    if( type_is_supported( TRIANGLE ) )
    {
        // get a patch
        get_ideal_tris( pd, false );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );
        // move the free vertex out of the plane
        pd.move_vertex( Vector3D( 0, 0, 0.2 ), 0, err );
        // find an evaluation that depends on the free vertex
        for( i = 0; i < handles.size(); ++i )
        {
            rval = qm->evaluate_with_gradient( pd, handles[i], qmval, indices, grad, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            if( !grad.empty() ) break;
        }
        CPPUNIT_ASSERT_EQUAL( (size_t)1, indices.size() );   // one free vertex in patch
        CPPUNIT_ASSERT_EQUAL( (size_t)0, indices.front() );  // one free vertex in patch
        CPPUNIT_ASSERT_EQUAL( (size_t)1, grad.size() );

        Vector3D v = qm->get_negate_flag() * Vector3D( 0, 0, 1 );
        CPPUNIT_ASSERT( v % grad[0] > DBL_EPSILON );
    }

    if( type_is_supported( QUADRILATERAL ) )
    {
        // get a patch
        get_ideal_quads( pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );
        // move the free vertex out of the plane
        pd.move_vertex( Vector3D( 0, 0, 0.2 ), 0, err );
        // find an evaluation that depends on the free vertex
        for( i = 0; i < handles.size(); ++i )
        {
            rval = qm->evaluate_with_gradient( pd, handles[i], qmval, indices, grad, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            if( !grad.empty() ) break;
        }
        CPPUNIT_ASSERT_EQUAL( (size_t)1, indices.size() );   // one free vertex in patch
        CPPUNIT_ASSERT_EQUAL( (size_t)0, indices.front() );  // one free vertex in patch
        CPPUNIT_ASSERT_EQUAL( (size_t)1, grad.size() );

        Vector3D v = qm->get_negate_flag() * Vector3D( 0, 0, 1 );
        CPPUNIT_ASSERT( v % grad[0] > DBL_EPSILON );
    }
}

Test measures deviation from domain

Definition at line 1910 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::evaluate(), MBMesquite::QualityMetric::evaluate_with_indices(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_quads(), get_ideal_tris(), MBMesquite::QualityMetric::get_negate_flag(), mSettings, MSQ_CHKERR, MBMesquite::PatchData::num_nodes(), MBMesquite::QUADRILATERAL, MBMesquite::PatchData::set_vertex_coordinates(), MBMesquite::TRIANGLE, type_is_supported(), and MBMesquite::PatchData::vertex_by_index().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices;
    size_t i;
    double qmval1, qmval2;
    bool rval;
    bool decreasing = false;
    if( qm->get_negate_flag() != 1 )
    {
        CPPUNIT_ASSERT_EQUAL( qm->get_negate_flag(), -1 );
        decreasing = true;
    }

    CPPUNIT_ASSERT( type_is_supported( TRIANGLE ) || type_is_supported( QUADRILATERAL ) );

    if( type_is_supported( TRIANGLE ) )
    {
        // get a patch
        get_ideal_tris( pd, false );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );
        // find an evaluation that depends on the free vertex
        for( i = 0; i < handles.size(); ++i )
        {
            rval = qm->evaluate_with_indices( pd, handles[i], qmval1, indices, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            if( !indices.empty() ) break;
        }
        CPPUNIT_ASSERT_EQUAL( (size_t)1, indices.size() );   // one free vertex in patch
        CPPUNIT_ASSERT_EQUAL( (size_t)0, indices.front() );  // one free vertex in patch
        const size_t handle = handles[i];
        // rotate patch about origin such that elements are no longer in the plane
        const Matrix3D rot( M_PI / 4.0, Vector3D( 1, 1, 0 ) );
        for( i = 0; i < pd.num_nodes(); ++i )
            pd.set_vertex_coordinates( rot * pd.vertex_by_index( i ), i, err );
        // evaluate for rotated patch
        rval = qm->evaluate( pd, handle, qmval2, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        // check quality
        if( decreasing ) { CPPUNIT_ASSERT( qmval1 > qmval2 ); }
        else
        {
            CPPUNIT_ASSERT( qmval1 < qmval2 );
        }
    }

    if( type_is_supported( QUADRILATERAL ) )
    {
        // get a patch
        get_ideal_quads( pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );
        // find an evaluation that depends on the free vertex
        for( i = 0; i < handles.size(); ++i )
        {
            rval = qm->evaluate_with_indices( pd, handles[i], qmval1, indices, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            if( !indices.empty() ) break;
        }
        CPPUNIT_ASSERT_EQUAL( (size_t)1, indices.size() );   // one free vertex in patch
        CPPUNIT_ASSERT_EQUAL( (size_t)0, indices.front() );  // one free vertex in patch
        const size_t handle = handles[i];
        // rotate patch about origin such that elements are no longer in the plane
        const Matrix3D rot( M_PI / 3.0, Vector3D( 1, 0, 0 ) );
        for( i = 0; i < pd.num_nodes(); ++i )
            pd.set_vertex_coordinates( rot * pd.vertex_by_index( i ), i, err );
        // evaluate for rotated patch
        rval = qm->evaluate( pd, handle, qmval2, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        // check quality
        if( decreasing ) { CPPUNIT_ASSERT( qmval1 > qmval2 ); }
        else
        {
            CPPUNIT_ASSERT( qmval1 < qmval2 );
        }
    }
}
void QualityMetricTester::test_evaluate_degenerate_element ( QualityMetric qm,
bool  should_succeed 
)

Test that evaluation of the metric for degenerate element does not pass back an error condition, and that the returned boolean feasible value is the specified value

Definition at line 1840 of file QualityMetricTester.cpp.

References get_degenerate_element(), mSettings, test_bad_element(), and types.

void QualityMetricTester::test_evaluate_inverted_element ( QualityMetric qm,
bool  should_succeed 
)

Test that evaluation of the metric for an inverted element does not pass back an error condition, and that the returned boolean feasible value is the specified value

Definition at line 1836 of file QualityMetricTester.cpp.

References get_inverted_element(), mSettings, test_bad_element(), and types.

Test evaluation of a single ideal element with unit edge length

Definition at line 468 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), get_ideal_element(), mSettings, and test_evaluate().

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    get_ideal_element( type, false, pd );
    test_evaluate( pd, qm, value );
}

Test evaluation of metric over patch with one free vertex surrounded by 6 ideal unit-edge-length tris

Definition at line 500 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), get_ideal_tris(), mSettings, and test_evaluate().

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    get_ideal_tris( pd, false );
    test_evaluate( pd, qm, value );
}

Test evaluation of a single ideal element with unit area/volume

Definition at line 460 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), get_ideal_element(), mSettings, and test_evaluate().

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    get_ideal_element( type, true, pd );
    test_evaluate( pd, qm, value );
}

Test evaluation of metric over patch with one free vertex surrounded by 8 unit-volume hexes

Definition at line 492 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), get_ideal_hexes(), mSettings, and test_evaluate().

Test evaluation of metric over patch with one free vertex surrounded by 4 unit-area quads

Definition at line 484 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), get_ideal_quads(), mSettings, and test_evaluate().

Test evaluation of metric over patch with one free vertex surrounded by 6 ideal unit-area tris

Definition at line 476 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), get_ideal_tris(), mSettings, and test_evaluate().

{
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    get_ideal_tris( pd, true );
    test_evaluate( pd, qm, value );
}
void QualityMetricTester::test_evaluate_zero_element ( QualityMetric qm,
bool  should_succeed 
)

Test that evaluation of the metric for zero area/volume element does not pass back an error condition, and that the returned boolean feasible value is the specified value

Definition at line 1844 of file QualityMetricTester.cpp.

References get_zero_element(), mSettings, test_bad_element(), and types.

Test method to get samples in an element in the EdgeQM base class

Definition at line 659 of file QualityMetricTester.cpp.

References ASSERT_NO_ERROR, MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, edges, MBMesquite::EdgeQM::get_evaluations(), get_ideal_element(), mSettings, and types.

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles;

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_ideal_element( types[i], true, pd );
        handles.clear();
        qm->get_evaluations( pd, handles, false, err );
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT_EQUAL( TopologyInfo::edges( types[i] ), (unsigned)handles.size() );
    }
}

Definition at line 845 of file QualityMetricTester.cpp.

References ASSERT_NO_ERROR, MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, edges, MBMesquite::EdgeQM::evaluate_with_indices(), MBMesquite::EdgeQM::get_evaluations(), get_ideal_element(), MBMesquite::EdgeQM::get_metric_type(), mSettings, MBMesquite::PatchData::num_free_vertices(), and types.

{
    MsqPrintError err( std::cout );
    PatchData pd, pd2;
    if( mSettings )
    {
        pd.attach_settings( mSettings );
        pd2.attach_settings( mSettings );
    }
    std::vector< size_t > handles, indices, indices2, verts;
    std::vector< size_t >::iterator it;
    double qm_val;

    CPPUNIT_ASSERT( qm->get_metric_type() == QualityMetric::VERTEX_BASED );
    CPPUNIT_ASSERT( !types.empty() );

    for( size_t i = 0; i < types.size(); ++i )
    {
        // construct patch w/ no free vertices
        get_ideal_element( types[i], false, pd, false );

        qm->get_evaluations( pd, handles, false, err );
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT_EQUAL( (size_t)TopologyInfo::edges( types[i] ), handles.size() );

        for( size_t j = 0; j < handles.size(); ++j )
        {
            // evaluate metric
            qm->evaluate_with_indices( pd, handles[j], qm_val, indices, err );
            ASSERT_NO_ERROR( err );
            // evaluation at each edge should depend on at least the two end vertices
            CPPUNIT_ASSERT( indices.size() >= (size_t)2 );
        }
    }

    for( size_t i = 0; i < types.size(); ++i )
    {
        // construct patch w/ one free vertex
        get_ideal_element( types[i], false, pd, true );
        const size_t fixed_vertex = pd.num_free_vertices();

        qm->get_evaluations( pd, handles, false, err );
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT_EQUAL( (size_t)TopologyInfo::edges( types[i] ), handles.size() );

        for( size_t j = 0; j < handles.size(); ++j )
        {
            // evaluate metric
            qm->evaluate_with_indices( pd, handles[j], qm_val, indices, err );
            ASSERT_NO_ERROR( err );
            // evaluation at each edge should depend on at least the two end vertices
            CPPUNIT_ASSERT( !indices.empty() );

            // indices should never contain the index of a fixed vertex
            it = std::find( indices.begin(), indices.end(), fixed_vertex );
            CPPUNIT_ASSERT( it == indices.end() );
        }
    }
}

Test get_evaluatinos() method for element-based metric

Definition at line 508 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::get_evaluations(), get_ideal_hexes(), get_ideal_quads(), get_ideal_tris(), MBMesquite::HEXAHEDRON, mSettings, MSQ_CHKERR, MBMesquite::PatchData::num_elements(), MBMesquite::QUADRILATERAL, MBMesquite::TRIANGLE, and type_is_supported().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    unsigned count = 0;
    std::vector< size_t > handles;

    if( type_is_supported( HEXAHEDRON ) )
    {
        get_ideal_hexes( pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT_EQUAL( pd.num_elements(), handles.size() );
        std::sort( handles.begin(), handles.end() );
        handles.erase( std::unique( handles.begin(), handles.end() ), handles.end() );
        CPPUNIT_ASSERT_EQUAL( pd.num_elements(), handles.size() );
        ++count;
    }

    if( type_is_supported( QUADRILATERAL ) )
    {
        get_ideal_quads( pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT_EQUAL( pd.num_elements(), handles.size() );
        std::sort( handles.begin(), handles.end() );
        handles.erase( std::unique( handles.begin(), handles.end() ), handles.end() );
        CPPUNIT_ASSERT_EQUAL( pd.num_elements(), handles.size() );
        ++count;
    }

    if( type_is_supported( TRIANGLE ) )
    {
        get_ideal_tris( pd, false );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT_EQUAL( pd.num_elements(), handles.size() );
        std::sort( handles.begin(), handles.end() );
        handles.erase( std::unique( handles.begin(), handles.end() ), handles.end() );
        CPPUNIT_ASSERT_EQUAL( pd.num_elements(), handles.size() );
        ++count;
    }

    CPPUNIT_ASSERT( count > 0 );
}

Test indices from evaluate_with_indices() method

Definition at line 767 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::PatchData::element_by_index(), MBMesquite::QualityMetric::evaluate_with_indices(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), MBMesquite::QualityMetric::get_metric_type(), MBMesquite::MsqMeshEntity::get_vertex_indices(), mSettings, MSQ_CHKERR, MBMesquite::PatchData::num_free_vertices(), and types.

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices, verts;
    double qm_val;

    CPPUNIT_ASSERT( qm->get_metric_type() == QualityMetric::ELEMENT_BASED );
    CPPUNIT_ASSERT( !types.empty() );

    for( size_t i = 0; i < types.size(); ++i )
    {
        // construct patch w/ one fixed vertex
        get_ideal_element( types[i], false, pd, true );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, handles.size() );
        // get vertex list
        verts.clear();
        pd.element_by_index( 0 ).get_vertex_indices( verts );
        // remove fixed vertex
        for( size_t j = 0; j < verts.size(); ++j )
            if( verts[j] >= pd.num_free_vertices() )
            {
                verts.erase( verts.begin() + j );
                break;
            }
        // evaluate metric
        qm->evaluate_with_indices( pd, handles[0], qm_val, indices, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        // index list should match vertex list (element metric
        // should depend on all free vertices in element).
        CPPUNIT_ASSERT_EQUAL( verts.size(), indices.size() );
        std::sort( verts.begin(), verts.end() );
        std::sort( indices.begin(), indices.end() );
        CPPUNIT_ASSERT( verts == indices );
    }
}

Test method to get samples in an element in the ElemSampleQM base class

Definition at line 677 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, MBMesquite::ElemSampleQM::get_element_evaluations(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), mSettings, MSQ_CHKERR, MBMesquite::PatchData::num_elements(), and types.

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles1, handles2;

    CPPUNIT_ASSERT( !types.empty() );

    get_ideal_element( types[0], false, pd );
    CPPUNIT_ASSERT( pd.num_elements() == 1 );
    qm->get_evaluations( pd, handles1, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles1.empty() );
    qm->get_element_evaluations( pd, 0, handles2, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles2.empty() );
    std::sort( handles1.begin(), handles1.end() );
    std::sort( handles2.begin(), handles2.end() );
    CPPUNIT_ASSERT( handles1 == handles2 );

    get_ideal_element( types.back(), false, pd );
    CPPUNIT_ASSERT( pd.num_elements() == 1 );
    qm->get_evaluations( pd, handles1, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles1.empty() );
    qm->get_element_evaluations( pd, 0, handles2, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles2.empty() );
    std::sort( handles1.begin(), handles1.end() );
    std::sort( handles2.begin(), handles2.end() );
    CPPUNIT_ASSERT( handles1 == handles2 );
}

Test that evaluate_with_indices returns indices only for free vertices

Definition at line 711 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), corners, CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, MBMesquite::PatchData::element_by_index(), MBMesquite::QualityMetric::evaluate_with_indices(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), MBMesquite::QualityMetric::get_metric_type(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), mSettings, MSQ_CHKERR, MBMesquite::PatchData::num_free_vertices(), and types.

{
    MsqPrintError err( std::cout );
    PatchData pd1, pd2;
    if( mSettings )
    {
        pd1.attach_settings( mSettings );
        pd2.attach_settings( mSettings );
    }
    std::vector< size_t > handles1, handles2, indices1, indices2;
    double qm_val1, qm_val2;

    CPPUNIT_ASSERT( !types.empty() );
    // get element with no fixed vertices
    get_ideal_element( types.back(), false, pd1, false );
    qm->get_evaluations( pd1, handles1, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles1.empty() );
    // call evaluate with indices
    size_t handle = handles1.back();
    qm->evaluate_with_indices( pd1, handle, qm_val1, indices1, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !indices1.empty() );
    // get element with one fixed vertex
    get_ideal_element( types.back(), false, pd2, true );
    qm->get_evaluations( pd2, handles2, false, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !handles2.empty() );
    // If vertex-based metric, need to find corresponding handle
    // in second patch.  The vertex order changed as a result of
    // one of the vertices beging fixed in the second patch.
    if( qm->get_metric_type() == QualityMetric::VERTEX_BASED )
    {
        handle              = handles1.back();
        const size_t* conn1 = pd1.element_by_index( 0 ).get_vertex_index_array();
        const size_t* conn2 = pd2.element_by_index( 0 ).get_vertex_index_array();
        const size_t len    = TopologyInfo::corners( types.back() );
        const size_t* ptr   = std::find( conn1, conn1 + len, handle );
        handle              = conn2[ptr - conn1];
    }
    // call evaluate with indices
    qm->evaluate_with_indices( pd2, handle, qm_val2, indices2, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( !indices2.empty() );
    // make sure we got the same QM value
    // (shoudn't be affected by fixed/non-fixed)
    CPPUNIT_ASSERT_DOUBLES_EQUAL( qm_val1, qm_val2, 1e-6 );
    // should have gotten back one less index (for element-based metrics)
    if( handles1.size() == 1 ) { CPPUNIT_ASSERT_EQUAL( indices1.size(), indices2.size() + 1 ); }
    // indices2 shouldn't contain any fixed vertices
    std::sort( indices2.begin(), indices2.end() );
    CPPUNIT_ASSERT( indices2.back() < pd2.num_free_vertices() );
    // indices2 shouldn/t contain any duplicates
    CPPUNIT_ASSERT( std::unique( indices2.begin(), indices2.end() ) == indices2.end() );
}

Test get_evaluatinos() method for sample-based metric

Definition at line 593 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::get_evaluations(), get_ideal_hexes(), get_ideal_quads(), get_ideal_tris(), MBMesquite::PatchData::get_samples(), MBMesquite::HEXAHEDRON, mSettings, MSQ_CHKERR, MBMesquite::PatchData::num_elements(), MBMesquite::NodeSet::num_nodes(), MBMesquite::QUADRILATERAL, MBMesquite::TRIANGLE, and type_is_supported().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    unsigned count = 0;
    std::vector< size_t > handles;

    if( type_is_supported( HEXAHEDRON ) )
    {
        get_ideal_hexes( pd );
        size_t expected_evals = 0;
        for( size_t i = 0; i < pd.num_elements(); ++i )
            expected_evals += pd.get_samples( i ).num_nodes();

        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT_EQUAL( expected_evals, handles.size() );

        std::sort( handles.begin(), handles.end() );
        handles.erase( std::unique( handles.begin(), handles.end() ), handles.end() );
        CPPUNIT_ASSERT_EQUAL( expected_evals, handles.size() );

        ++count;
    }

    if( type_is_supported( TRIANGLE ) )
    {
        get_ideal_tris( pd, false );
        size_t expected_evals = 0;
        for( size_t i = 0; i < pd.num_elements(); ++i )
            expected_evals += pd.get_samples( i ).num_nodes();

        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT_EQUAL( expected_evals, handles.size() );

        std::sort( handles.begin(), handles.end() );
        handles.erase( std::unique( handles.begin(), handles.end() ), handles.end() );
        CPPUNIT_ASSERT_EQUAL( expected_evals, handles.size() );

        ++count;
    }

    if( type_is_supported( QUADRILATERAL ) )
    {
        get_ideal_quads( pd );
        size_t expected_evals = 0;
        for( size_t i = 0; i < pd.num_elements(); ++i )
            expected_evals += pd.get_samples( i ).num_nodes();

        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT_EQUAL( expected_evals, handles.size() );

        std::sort( handles.begin(), handles.end() );
        handles.erase( std::unique( handles.begin(), handles.end() ), handles.end() );
        CPPUNIT_ASSERT_EQUAL( expected_evals, handles.size() );

        ++count;
    }

    CPPUNIT_ASSERT( count > 0 );
}

Test indices from evaluate_with_indices() method

Definition at line 905 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::PatchData::element_by_index(), MBMesquite::QualityMetric::evaluate_with_indices(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), MBMesquite::QualityMetric::get_metric_type(), MBMesquite::PatchData::get_samples(), MBMesquite::MsqMeshEntity::get_vertex_indices(), mSettings, MSQ_CHKERR, MBMesquite::PatchData::num_free_vertices(), MBMesquite::NodeSet::num_nodes(), and types.

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices, verts;
    double qm_val;

    CPPUNIT_ASSERT( qm->get_metric_type() == QualityMetric::ELEMENT_BASED );
    CPPUNIT_ASSERT( !types.empty() );

    for( size_t i = 0; i < types.size(); ++i )
    {
        // get evaluation locations
        get_ideal_element( types[i], false, pd, true );
        const size_t count = pd.get_samples( 0 ).num_nodes();
        CPPUNIT_ASSERT( count > 0 );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        // should have one evaluation for each sample point
        CPPUNIT_ASSERT_EQUAL( count, handles.size() );
        // get vertex list
        verts.clear();
        pd.element_by_index( 0 ).get_vertex_indices( verts );
        // remove fixed vertex
        for( size_t j = 0; j < verts.size(); ++j )
            if( verts[j] >= pd.num_free_vertices() )
            {
                verts.erase( verts.begin() + j );
                break;
            }
        // evaluate metric
        qm->evaluate_with_indices( pd, handles[0], qm_val, indices, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        // only one fixed vertex, and presumably every possible evaluation
        // depends on more than one vertex, so should be at least one
        // other, non-fixed, vertex.
        CPPUNIT_ASSERT( indices.size() > 0 );
        // make sure no duplicates
        std::sort( indices.begin(), indices.end() );
        CPPUNIT_ASSERT( std::unique( indices.begin(), indices.end() ) == indices.end() );
        // check that all indices are in vertex list
        CPPUNIT_ASSERT( indices.size() <= verts.size() );
        for( std::vector< size_t >::iterator j = indices.begin(); j != indices.end(); ++j )
            CPPUNIT_ASSERT( std::find( verts.begin(), verts.end(), *j ) != verts.end() );
    }
}

Test get_evaluatinos() method for vertex-based metric

Definition at line 555 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::get_evaluations(), get_ideal_hexes(), get_ideal_quads(), get_ideal_tris(), MBMesquite::HEXAHEDRON, mSettings, MSQ_CHKERR, MBMesquite::QUADRILATERAL, MBMesquite::TRIANGLE, and type_is_supported().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    unsigned count = 0;
    std::vector< size_t > handles;

    if( type_is_supported( HEXAHEDRON ) )
    {
        get_ideal_hexes( pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, handles.size() );
        ++count;
    }

    if( type_is_supported( TRIANGLE ) )
    {
        get_ideal_tris( pd, false );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, handles.size() );
        ++count;
    }

    if( type_is_supported( QUADRILATERAL ) )
    {
        get_ideal_quads( pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, handles.size() );
        ++count;
    }

    CPPUNIT_ASSERT( count > 0 );
}

Test indices from evaluate_with_indices() method, assuming quality at a vertex depends only on edge-connected vertices.

Definition at line 807 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::evaluate_with_indices(), MBMesquite::PatchData::get_adjacent_vertex_indices(), get_ideal_element(), MBMesquite::QualityMetric::get_metric_type(), mSettings, MSQ_CHKERR, MBMesquite::PatchData::num_free_vertices(), and types.

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > indices, verts;
    double qm_val;

    CPPUNIT_ASSERT( qm->get_metric_type() == QualityMetric::VERTEX_BASED );
    CPPUNIT_ASSERT( !types.empty() );

    for( size_t i = 0; i < types.size(); ++i )
    {
        // construct patch w/ one fixed vertex
        get_ideal_element( types[i], false, pd, true );
        // get adjacent vertices
        verts.clear();
        pd.get_adjacent_vertex_indices( 0, verts, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        // remove fixed vertex
        for( size_t j = 0; j < verts.size(); ++j )
            if( verts[j] >= pd.num_free_vertices() )
            {
                verts.erase( verts.begin() + j );
                break;
            }
        verts.push_back( 0 );
        // evaluate metric
        qm->evaluate_with_indices( pd, 0, qm_val, indices, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        // vertex metric should depend on all adjacent free vertices
        CPPUNIT_ASSERT_EQUAL( verts.size(), indices.size() );
        std::sort( verts.begin(), verts.end() );
        std::sort( indices.begin(), indices.end() );
        CPPUNIT_ASSERT( verts == indices );
    }
}
void QualityMetricTester::test_grad_location_invariant ( QualityMetric qm,
bool  untangler = false 
)

test that gradient values don't change with element translation

Definition at line 1720 of file QualityMetricTester.cpp.

References test_grad_transform_invariant().

{
    PatchTranslate xform( Vector3D( 1, 1, -1 ) );
    test_grad_transform_invariant( qm, xform, untangle );
}
void QualityMetricTester::test_grad_orient_invariant ( QualityMetric qm,
bool  untangler = false 
)

test that gradient values rotate with element rotation

Definition at line 1732 of file QualityMetricTester.cpp.

References test_grad_transform_invariant().

{
    // rotate 45 degrees about x-axis
    const double f = std::sqrt( 2.0 ) / 2;
    Matrix3D rotation( 1, 0, 0, 0, f, f, 0, -f, f );
    PatchRotate xform( rotation );
    test_grad_transform_invariant( qm, xform, untangle );
}

Definition at line 1589 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::get_evaluations(), get_inverted_element(), get_nonideal_element(), mSettings, MSQ_CHKERR, size, types, QualityMetricTester::PatchXform::xform(), and QualityMetricTester::PatchXform::xform_grad().

Referenced by test_grad_location_invariant(), and test_grad_orient_invariant().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices2;
    std::vector< Vector3D > grad2;
    double qmval;
    bool rval;
    PlanarDomain dom( Vector3D( 0, 0, 1 ), Vector3D( 0, 0, 0 ) );
    size_t i, j, k;

    CPPUNIT_ASSERT( !types.empty() );
    for( i = 0; i < types.size(); ++i )
    {
        if( untangle )
            get_inverted_element( types[i], pd );
        else
            get_nonideal_element( types[i], pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );

        // get value(s) for orignal patch
        std::vector< std::vector< Vector3D > > grad1( handles.size() );
        std::vector< std::vector< size_t > > indices1( handles.size() );
        for( j = 0; j < handles.size(); ++j )
        {
            rval = qm->evaluate_with_gradient( pd, handles[j], qmval, indices1[j], grad1[j], err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            CPPUNIT_ASSERT( !grad1[j].empty() );
        }

        // transform patch
        xform.xform( pd, &dom );

        // compare values
        for( j = 0; j < handles.size(); ++j )
        {
            rval = qm->evaluate_with_gradient( pd, handles[j], qmval, indices2, grad2, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );

            CPPUNIT_ASSERT_EQUAL( indices1[j].size(), indices2.size() );
            CPPUNIT_ASSERT_EQUAL( grad1[j].size(), grad2.size() );
            CPPUNIT_ASSERT( indices1[j] == indices2 );

            xform.xform_grad( grad1[j] );
            for( k = 0; k < grad2.size(); ++k )
                CPPUNIT_ASSERT_VECTORS_EQUAL( grad1[j][k], grad2[k], 1e-3 );
        }
    }
}

Test that metric value increases (or decreases if negate_flag is -1) as the quality of an element worsens. Compares gradient values for ideal element with unit edge length to the value for the same element with one corner vertex moved 1/2 of the distance towards the element centroid. This test is applicable only for element-based metrics.

Definition at line 2061 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::PatchData::element_by_index(), MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), MBMesquite::QualityMetric::get_negate_flag(), MBMesquite::PatchData::get_vertex_array(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), MBMesquite::grad(), mSettings, MSQ_CHKERR, n, MBMesquite::PatchData::set_vertex_coordinates(), moab::sum(), types, and MBMesquite::MsqMeshEntity::vertex_count().

Referenced by TQualityMetricTest::test_inverse_mean_ratio_grad().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices;
    std::vector< Vector3D > grad;
    double qmval;
    bool rval;
    bool decreasing = false;
    if( qm->get_negate_flag() != 1 )
    {
        CPPUNIT_ASSERT_EQUAL( qm->get_negate_flag(), -1 );
        decreasing = true;
    }

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        // get a patch
        get_ideal_element( types[i], false, pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );
        // make element non-ideal
        const size_t* verts     = pd.element_by_index( 0 ).get_vertex_index_array();
        const MsqVertex* coords = pd.get_vertex_array( err );
        size_t n                = pd.element_by_index( 0 ).vertex_count();
        Vector3D sum( 0, 0, 0 );
        for( unsigned j = 0; j < n; ++j )
            sum += coords[verts[j]];
        const Vector3D init_pos = coords[verts[0]];
        const Vector3D new_pos  = 0.5 * coords[verts[0]] + sum / ( 2 * n );
        pd.set_vertex_coordinates( new_pos, verts[0], err );
        // evaluate for non-ideal element
        rval = qm->evaluate_with_gradient( pd, handles[0], qmval, indices, grad, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        // find gradient for vertex 0
        std::vector< size_t >::iterator it = std::find( indices.begin(), indices.end(), verts[0] );
        CPPUNIT_ASSERT( it != indices.end() );
        Vector3D g = grad[it - indices.begin()];
        // check gradient direction
        Vector3D v     = init_pos - coords[verts[0]];
        double dotprod = v % g;
        if( decreasing )
            CPPUNIT_ASSERT( dotprod > 1e-6 );
        else
            CPPUNIT_ASSERT( dotprod < -1e-6 );
    }
}

compare gradient w/ no fixed vertices to gradient for element with all but one vertex fixed.

Definition at line 2454 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, and types.

Referenced by TQualityMetricTest::test_inverse_mean_ratio_grad().

{
    CPPUNIT_ASSERT( !types.empty() );
    for( unsigned i = 0; i < types.size(); ++i )
        test_gradient_with_fixed_vertex( types[i], qm, settings );
}

Definition at line 2475 of file QualityMetricTester.cpp.

References ASSERT_NO_ERROR, MBMesquite::PatchData::attach_settings(), conn, corners, CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::PatchData::element_by_index(), MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::get_evaluations(), get_nonideal_element(), MBMesquite::MsqMeshEntity::get_vertex_indices(), MBMesquite::grad(), mSettings, and n.

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( settings )
        pd.attach_settings( settings );
    else if( mSettings )
        pd.attach_settings( mSettings );

    std::vector< size_t > handles, indices, indices_fixed, conn;
    std::vector< Vector3D > grad, grad_fixed;
    double val, val_fixed;
    bool rval;
    const int n = TopologyInfo::corners( type );

    get_nonideal_element( type, pd );
    pd.element_by_index( 0 ).get_vertex_indices( conn );

    qm->get_evaluations( pd, handles, false, err );
    ASSERT_NO_ERROR( err );
    // For sample-based metrics, it is difficult to set up such that
    // both surface and volume elements have only one sample point.
    // Make things easier by skipping element types with no sample points.
    if( handles.empty() ) return;
    CPPUNIT_ASSERT_EQUAL_MESSAGE( "test only valid for element-based metrics", (size_t)1, handles.size() );
    size_t h = handles[0];

    rval = qm->evaluate_with_gradient( pd, h, val, indices, grad, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( rval );
    CPPUNIT_ASSERT_EQUAL( (size_t)n, indices.size() );
    CPPUNIT_ASSERT_EQUAL( (size_t)n, grad.size() );

    for( int i = 0; i < n; ++i )
    {
        get_nonideal_element( type, pd, i );

        qm->get_evaluations( pd, handles, false, err );
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT_EQUAL_MESSAGE( "test only valid for element-based metrics", (size_t)1, handles.size() );
        h = handles[0];

        rval = qm->evaluate_with_gradient( pd, h, val_fixed, indices_fixed, grad_fixed, err );
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT( rval );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, indices_fixed.size() );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, grad_fixed.size() );

        CPPUNIT_ASSERT_DOUBLES_EQUAL( val, val_fixed, 1e-5 );
        CPPUNIT_ASSERT_VECTORS_EQUAL( grad[conn[i]], grad_fixed.front(), 1e-5 );
    }
}
void QualityMetricTester::test_hessian_location_invariant ( QualityMetric qm,
bool  untangler = false 
)

test that Hessian values don't change with element translation

Definition at line 1726 of file QualityMetricTester.cpp.

References test_hessian_transform_invariant().

{
    PatchTranslate xform( Vector3D( 1, 1, -1 ) );
    test_hessian_transform_invariant( qm, xform, untangle );
}

Definition at line 1645 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_MATRICES_EQUAL, MBMesquite::QualityMetric::evaluate_with_Hessian(), MBMesquite::QualityMetric::get_evaluations(), get_inverted_element(), get_nonideal_element(), mSettings, MSQ_CHKERR, size, types, and QualityMetricTester::PatchXform::xform().

Referenced by test_hessian_location_invariant().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices2;
    std::vector< Vector3D > grad1, grad2;
    std::vector< Matrix3D > hess2;
    double qmval;
    bool rval;
    PlanarDomain dom( Vector3D( 0, 0, 1 ), Vector3D( 0, 0, 0 ) );
    size_t i, j, k;

    CPPUNIT_ASSERT( !types.empty() );
    for( i = 0; i < types.size(); ++i )
    {
        if( untangle )
            get_inverted_element( types[i], pd );
        else
            get_nonideal_element( types[i], pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );

        std::vector< std::vector< size_t > > indices1( handles.size() );
        std::vector< std::vector< Matrix3D > > hess1( handles.size() );
        for( j = 0; j < handles.size(); ++j )
        {
            rval = qm->evaluate_with_Hessian( pd, handles[j], qmval, indices1[j], grad1, hess1[j], err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            CPPUNIT_ASSERT( !hess1[j].empty() );
        }

        xform.xform( pd, &dom );

        for( j = 0; j < handles.size(); ++j )
        {
            rval = qm->evaluate_with_Hessian( pd, handles[j], qmval, indices2, grad2, hess2, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );

            CPPUNIT_ASSERT_EQUAL( indices1[j].size(), indices2.size() );
            CPPUNIT_ASSERT_EQUAL( hess1[j].size(), hess2.size() );
            CPPUNIT_ASSERT( indices1[j] == indices2 );

            for( k = 0; k < hess2.size(); ++k )
                CPPUNIT_ASSERT_MATRICES_EQUAL( hess1[j][k], hess2[k], 1e-3 );
        }
    }
}

compare Hessian w/ no fixed vertices to Hessian for element with all but one vertex fixed.

Definition at line 2461 of file QualityMetricTester.cpp.

References CPPUNIT_ASSERT, and types.

Referenced by TQualityMetricTest::test_inverse_mean_ratio_hess().

{
    CPPUNIT_ASSERT( !types.empty() );
    for( unsigned i = 0; i < types.size(); ++i )
        test_hessian_with_fixed_vertex( types[i], qm, settings );
}

Definition at line 2529 of file QualityMetricTester.cpp.

References ASSERT_NO_ERROR, MBMesquite::PatchData::attach_settings(), conn, corners, CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_MATRICES_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::PatchData::element_by_index(), MBMesquite::QualityMetric::evaluate_with_Hessian(), MBMesquite::QualityMetric::get_evaluations(), get_nonideal_element(), MBMesquite::MsqMeshEntity::get_vertex_indices(), MBMesquite::grad(), MBMesquite::hess(), mSettings, and n.

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( settings )
        pd.attach_settings( settings );
    else if( mSettings )
        pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices, indices_fixed, conn;
    std::vector< Vector3D > grad, grad_fixed;
    std::vector< Matrix3D > hess, hess_fixed;
    double val, val_fixed;
    bool rval;
    const int n = TopologyInfo::corners( type );

    get_nonideal_element( type, pd );
    pd.element_by_index( 0 ).get_vertex_indices( conn );

    qm->get_evaluations( pd, handles, false, err );
    ASSERT_NO_ERROR( err );
    // For sample-based metrics, it is difficult to set up such that
    // both surface and volume elements have only one sample point.
    // Make things easier by skipping element types with no sample points.
    if( handles.empty() ) return;
    CPPUNIT_ASSERT_EQUAL_MESSAGE( "test only valid for element-based metrics", (size_t)1, handles.size() );
    size_t h = handles[0];

    rval = qm->evaluate_with_Hessian( pd, h, val, indices, grad, hess, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( rval );
    CPPUNIT_ASSERT_EQUAL( (size_t)n, indices.size() );
    CPPUNIT_ASSERT_EQUAL( (size_t)n, grad.size() );
    CPPUNIT_ASSERT_EQUAL( ( size_t )( n * ( n + 1 ) / 2 ), hess.size() );

    for( int i = 0; i < n; ++i )
    {
        get_nonideal_element( type, pd, i );

        qm->get_evaluations( pd, handles, false, err );
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT_EQUAL_MESSAGE( "test only valid for element-based metrics", (size_t)1, handles.size() );
        h = handles[0];

        rval = qm->evaluate_with_Hessian( pd, h, val_fixed, indices_fixed, grad_fixed, hess_fixed, err );
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT( rval );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, indices_fixed.size() );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, grad_fixed.size() );
        CPPUNIT_ASSERT_EQUAL( (size_t)1, hess_fixed.size() );

        const size_t j = conn[i];
        CPPUNIT_ASSERT_DOUBLES_EQUAL( val, val_fixed, 1e-5 );
        CPPUNIT_ASSERT_VECTORS_EQUAL( grad[j], grad_fixed.front(), 1e-5 );
        CPPUNIT_ASSERT_MATRICES_EQUAL( hess[n * j - j * ( j - 1 ) / 2], hess_fixed.front(), 1e-4 );
    }
}

Test that Hessian is positive-definite for ideal elements

Definition at line 2369 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::evaluate_with_Hessian(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), MBMesquite::QualityMetric::get_negate_flag(), MBMesquite::grad(), mSettings, MSQ_CHKERR, n, and types.

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices;
    std::vector< Vector3D > grad;
    std::vector< Matrix3D > Hess;
    double qmval;
    bool rval;

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        // get a patch
        get_ideal_element( types[i], unit_area, pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );
        for( size_t j = 0; j < handles.size(); ++j )
        {
            // evaluate
            rval = qm->evaluate_with_Hessian( pd, handles[j], qmval, indices, grad, Hess, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            const size_t n = indices.size();
            CPPUNIT_ASSERT_EQUAL( n, grad.size() );
            CPPUNIT_ASSERT_EQUAL( n * ( n + 1 ) / 2, Hess.size() );
            // if necessary, adjust Hessian for negate_flag();
            if( qm->get_negate_flag() == -1 )
                for( size_t k = 0; k < Hess.size(); ++k )
                    Hess[k] *= -1.0;
            // check that all diagonal blocks are positive definite
            size_t h_idx = 0;
            for( size_t k = 0; k < n; h_idx += ( n - k ), ++k )
            {
                CPPUNIT_ASSERT( Hess[h_idx].positive_definite() );
            }
            // check that the entire Hessian is positive definite
            // CPPUNIT_ASSERT( positive_definite( arrptr(Hess), n ) );
        }  // for(j < handles.size())
    }      // for(i < types.size())
}

Test that gradient values are zero for an ideal element. If 'unit_area' is true, then ideal elements have unit measure, otherwise they have unit edge lengths. This test is applicable only to element-based metrics.

Definition at line 2228 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), MBMesquite::grad(), mSettings, MSQ_CHKERR, and types.

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices;
    std::vector< Vector3D > grad;
    double qmval;
    bool rval;

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        // get a patch
        get_ideal_element( types[i], unit_area, pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );
        for( size_t j = 0; j < handles.size(); ++j )
        {
            // evaluate
            rval = qm->evaluate_with_gradient( pd, handles[j], qmval, indices, grad, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            CPPUNIT_ASSERT_EQUAL( indices.size(), grad.size() );
            // check that all gradients are zero
            for( size_t k = 0; k < grad.size(); ++k )
            {
                CPPUNIT_ASSERT_VECTORS_EQUAL( Vector3D( 0, 0, 0 ), grad[k], 1e-4 );
            }  // for(k < grad.size())
        }      // for(j < handles.size())
    }          // for(i < types.size())
}

Test that gradient values are zero at the shared vertex in a patch of containing ideal elements. If 'unit_area' is true, then ideal elements have unit measure, otherwise they have unit edge lengths. Test is done only for TRIANGLE, QUADRILATERAL, and HEXAHEDRON element types.

Definition at line 2262 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_hexes(), get_ideal_quads(), get_ideal_tris(), MBMesquite::grad(), MBMesquite::HEXAHEDRON, mSettings, MSQ_CHKERR, MBMesquite::QUADRILATERAL, MBMesquite::TRIANGLE, and type_is_supported().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices;
    std::vector< Vector3D > grad;
    double qmval;
    bool rval;

    unsigned count = 0;
    for( size_t i = 0; i < 3; ++i )
    {
        // get a patch
        switch( i )
        {
            case 0:
                if( !type_is_supported( TRIANGLE ) ) continue;
                get_ideal_tris( pd, unit_area );
                break;
            case 1:
                if( !type_is_supported( QUADRILATERAL ) ) continue;
                get_ideal_quads( pd );
                break;
            case 2:
                if( !type_is_supported( HEXAHEDRON ) ) continue;
                get_ideal_hexes( pd );
                break;
        }

        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );
        for( size_t j = 0; j < handles.size(); ++j )
        {
            // evaluate
            rval = qm->evaluate_with_gradient( pd, handles[j], qmval, indices, grad, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            CPPUNIT_ASSERT_EQUAL( indices.size(), grad.size() );
            if( grad.empty() ) continue;
            ++count;
            CPPUNIT_ASSERT_EQUAL( (size_t)1, grad.size() );  // only 1 free vertex in patch
                                                             // check that all gradients are zero
            CPPUNIT_ASSERT_VECTORS_EQUAL( Vector3D( 0, 0, 0 ), grad[0], 1e-4 );
        }  // for(j < handles.size())
    }      // for(i < 3)
           // make sure we tested something
    CPPUNIT_ASSERT( count > 0 );
}
void QualityMetricTester::test_location_invariant ( QualityMetric qm,
bool  untangler = false 
)

test that metric value is consistent for element translation

Definition at line 1698 of file QualityMetricTester.cpp.

References test_transform_invariant().

{
    PatchTranslate xform( Vector3D( 1, 1, -1 ) );
    test_transform_invariant( qm, xform, untangle );
}

test that metric value increases as element orientation changes from ideal

Definition at line 1788 of file QualityMetricTester.cpp.

References test_measures_transform().

{
    // rotate 45 degrees about z-axis
    const double f = std::sqrt( 2.0 ) / 2;
    Matrix3D rotation( f, -f, 0, f, f, 0, 0, 0, 1 );
    PatchRotate xform( rotation );
    test_measures_transform( qm, xform, false );
}

test that metric value increases as element orientation changes from ideal

Definition at line 1797 of file QualityMetricTester.cpp.

References test_measures_transform().

{
    // rotate 45 degrees about z-axis
    const double f = std::sqrt( 2.0 ) / 2;
    Matrix3D rotation( 1, 0, 0, 0, f, f, 0, -f, f );
    PatchRotate xform( rotation );
    test_measures_transform( qm, xform, false );
}

Test that metric value increases (or decreases if negate_flag is -1) as the quality of an element worsens. Compares metric values for ideal element with unit edge length to the value for the same element with one corner vertex moved 1/2 of the distance towards the element centroid. This test is applicable only for element-based metrics.

Definition at line 1849 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::PatchData::element_by_index(), MBMesquite::QualityMetric::evaluate(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), MBMesquite::QualityMetric::get_negate_flag(), MBMesquite::PatchData::get_vertex_array(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), mSettings, MSQ_CHKERR, n, MBMesquite::PatchData::set_vertex_coordinates(), types, and MBMesquite::MsqMeshEntity::vertex_count().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles;
    double qmval1, qmval2;
    bool rval;
    bool decreasing = false;
    if( qm->get_negate_flag() != 1 )
    {
        CPPUNIT_ASSERT_EQUAL( qm->get_negate_flag(), -1 );
        decreasing = true;
    }

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        // get a patch
        get_ideal_element( types[i], false, pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );
        // evaluate for ideal element
        rval = qm->evaluate( pd, handles[0], qmval1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        // calculate element centroid
        const size_t* verts     = pd.element_by_index( 0 ).get_vertex_index_array();
        const MsqVertex* coords = pd.get_vertex_array( err );
        size_t n                = pd.element_by_index( 0 ).vertex_count();
        Vector3D cent( 0, 0, 0 );
        Vector3D coords0 = coords[verts[0]];
        for( unsigned j = 0; j < n; ++j )
            cent += coords[verts[j]];
        cent /= n;
        // evaluate for non-ideal element (decreased area)
        pd.set_vertex_coordinates( 0.5 * ( cent + coords0 ), verts[0], err );
        rval = qm->evaluate( pd, handles[0], qmval2, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        // check values
        if( decreasing ) { CPPUNIT_ASSERT( qmval2 < qmval1 ); }
        else
        {
            CPPUNIT_ASSERT( qmval2 > qmval1 );
        }
        // evaluate for non-ideal element (increased area)
        pd.set_vertex_coordinates( 3 * coords0 - 2 * cent, verts[0], err );
        rval = qm->evaluate( pd, handles[0], qmval2, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        // check values
        if( decreasing ) { CPPUNIT_ASSERT( qmval2 < qmval1 ); }
        else
        {
            CPPUNIT_ASSERT( qmval2 > qmval1 );
        }
    }
}
void QualityMetricTester::test_measures_size ( QualityMetric qm,
bool  unit_area 
)

test that metric inceases (decreases) as size deviates from ideal

Definition at line 1781 of file QualityMetricTester.cpp.

References test_measures_transform().

{
    PatchScale s1( 0.5 ), s2( 2.0 );
    test_measures_transform( qm, s1, unit_area );
    test_measures_transform( qm, s2, unit_area );
}

Definition at line 1741 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::evaluate(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), MBMesquite::QualityMetric::get_negate_flag(), mSettings, MSQ_CHKERR, types, and QualityMetricTester::PatchXform::xform().

Referenced by test_measures_in_plane_orientation(), test_measures_out_of_plane_orientation(), and test_measures_size().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles;
    double qmval1, qmval2;
    bool rval;
    PlanarDomain dom( Vector3D( 0, 0, 1 ), Vector3D( 0, 0, 0 ) );
    bool decreasing = false;
    if( qm->get_negate_flag() != 1 )
    {
        CPPUNIT_ASSERT_EQUAL( qm->get_negate_flag(), -1 );
        decreasing = true;
    }

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        get_ideal_element( types[i], unit_area, pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );

        rval = qm->evaluate( pd, handles[0], qmval1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );

        xform.xform( pd, &dom );
        rval = qm->evaluate( pd, handles[0], qmval2, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        if( decreasing )
            CPPUNIT_ASSERT( qmval2 < qmval1 );
        else
            CPPUNIT_ASSERT( qmval2 > qmval1 );
    }
}

Test that metric value increases (or decreases if negate_flag is -1) as the quality of the element worsen. Compares metric values for ideal elements with unit edge length to the value for the same elements with the shared vertex moved 1/2 of the length of one of the adjacent edges. This test is done only for TRIANGLE, QUADRILATERAL, and HEXAHEDRAL element types.

Definition at line 2113 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::evaluate(), get_ideal_hexes(), get_ideal_quads(), get_ideal_tris(), MBMesquite::QualityMetric::get_negate_flag(), MBMesquite::HEXAHEDRON, MBMesquite::PatchData::move_vertex(), mSettings, MSQ_CHKERR, MBMesquite::QUADRILATERAL, MBMesquite::TRIANGLE, and type_is_supported().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    double qmval1, qmval2;
    bool rval;
    bool increasing = true;
    if( qm->get_negate_flag() != 1 )
    {
        CPPUNIT_ASSERT_EQUAL( qm->get_negate_flag(), -1 );
        increasing = true;
    }

    unsigned count = 0;
    for( size_t i = 0; i < 3; ++i )
    {
        // get a patch
        switch( i )
        {
            case 0:
                if( !type_is_supported( TRIANGLE ) ) continue;
                get_ideal_tris( pd, false );
                break;
            case 1:
                if( !type_is_supported( QUADRILATERAL ) ) continue;
                get_ideal_quads( pd );
                break;
            case 2:
                if( !type_is_supported( HEXAHEDRON ) ) continue;
                get_ideal_hexes( pd );
                break;
        }
        ++count;

        // evaluate for ideal element
        rval = qm->evaluate( pd, 0, qmval1, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        // move center vertex
        pd.move_vertex( Vector3D( 0.3, 0.3, 0.3 ), 0, err );
        // evaluate for non-ideal element
        rval = qm->evaluate( pd, 0, qmval2, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        // check values
        if( increasing ) { CPPUNIT_ASSERT( qmval2 > qmval1 ); }
        else
        {
            CPPUNIT_ASSERT( qmval2 < qmval1 );
        }
    }
    // make sure we tested something
    CPPUNIT_ASSERT( count > 0 );
}
void QualityMetricTester::test_orient_invariant ( QualityMetric qm,
bool  untangler = false 
)

test that metric value is consistent for element rotation

Definition at line 1711 of file QualityMetricTester.cpp.

References test_transform_invariant().

{
    // rotate 45 degrees about x-axis
    const double f = std::sqrt( 2.0 ) / 2;
    Matrix3D rotation( 1, 0, 0, 0, f, f, 0, -f, f );
    PatchRotate xform( rotation );
    test_transform_invariant( qm, xform, untangle );
}
void QualityMetricTester::test_scale_invariant ( QualityMetric qm,
bool  untangler = false 
)

test that metric value is consistent for element scalaing

Definition at line 1704 of file QualityMetricTester.cpp.

References test_transform_invariant().

{
    PatchScale scale1( 0.5 ), scale2( 2.0 );
    test_transform_invariant( qm, scale1, untangle );
    test_transform_invariant( qm, scale2, untangle );
}

Test that metric evaluation succeeds for all supported element types and fails for all unsupported types

Definition at line 430 of file QualityMetricTester.cpp.

References MBMesquite::MIXED, MBMesquite::POLYGON, MBMesquite::POLYHEDRON, MBMesquite::SEPTAHEDRON, test_type_is_not_supported(), test_type_is_supported(), MBMesquite::TRIANGLE, and type_is_supported().

{
    for( int i = TRIANGLE; i < MIXED; ++i )
    {
        if( i == POLYGON || i == POLYHEDRON || i == SEPTAHEDRON )
            continue;
        else if( type_is_supported( (EntityTopology)i ) )
            test_type_is_supported( (EntityTopology)i, qm );
        else
            test_type_is_not_supported( (EntityTopology)i, qm );
    }
}

Test that diagonal bocks of Hessian are symetrical

Test that diagonal bocks of Hessian are symmetric

Definition at line 2414 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::evaluate_with_Hessian(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), MBMesquite::grad(), mSettings, MSQ_CHKERR, n, and types.

Referenced by TQualityMetricTest::test_inverse_mean_ratio_hess().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles, indices;
    std::vector< Vector3D > grad;
    std::vector< Matrix3D > Hess;
    double qmval;
    bool rval;

    CPPUNIT_ASSERT( !types.empty() );
    for( size_t i = 0; i < types.size(); ++i )
    {
        // get a patch
        get_ideal_element( types[i], false, pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );
        for( size_t j = 0; j < handles.size(); ++j )
        {
            // evaluate
            rval = qm->evaluate_with_Hessian( pd, handles[j], qmval, indices, grad, Hess, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            const size_t n = indices.size();
            CPPUNIT_ASSERT_EQUAL( n, grad.size() );
            CPPUNIT_ASSERT_EQUAL( n * ( n + 1 ) / 2, Hess.size() );
            // check that diagonal Hessian blocks are symmetric
            size_t h_idx = 0;
            for( size_t k = 0; k < n; h_idx += ( n - k ), ++k )
            {
                CPPUNIT_ASSERT_DOUBLES_EQUAL( Hess[h_idx][0][1], Hess[h_idx][1][0], 5e-3 );
                CPPUNIT_ASSERT_DOUBLES_EQUAL( Hess[h_idx][0][2], Hess[h_idx][2][0], 5e-3 );
                CPPUNIT_ASSERT_DOUBLES_EQUAL( Hess[h_idx][1][2], Hess[h_idx][2][1], 5e-3 );
            }  // for(k < Hess.size())
        }      // for(j < handles.size())
    }          // for(i < types.size())
}

Definition at line 1545 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, MBMesquite::QualityMetric::evaluate(), MBMesquite::QualityMetric::get_evaluations(), get_inverted_element(), get_nonideal_element(), mSettings, MSQ_CHKERR, types, and QualityMetricTester::PatchXform::xform().

Referenced by test_location_invariant(), test_orient_invariant(), and test_scale_invariant().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > handles;
    double qmval;
    bool rval;
    PlanarDomain dom( Vector3D( 0, 0, 1 ), Vector3D( 0, 0, 0 ) );
    size_t i, j;

    CPPUNIT_ASSERT( !types.empty() );
    for( i = 0; i < types.size(); ++i )
    {
        if( untangle )
            get_inverted_element( types[i], pd );
        else
            get_nonideal_element( types[i], pd );
        qm->get_evaluations( pd, handles, false, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( !handles.empty() );

        // get value(s) for ideal element
        std::vector< double > values( handles.size() );
        for( j = 0; j < handles.size(); ++j )
        {
            rval = qm->evaluate( pd, handles[j], values[j], err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
        }

        // compare values for transformed patch
        xform.xform( pd, &dom );
        for( j = 0; j < handles.size(); ++j )
        {
            rval = qm->evaluate( pd, handles[j], qmval, err );
            CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
            CPPUNIT_ASSERT( rval );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( values[j], qmval, 1e-3 );
        }
    }
}

Definition at line 401 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::MsqError::error_code(), MBMesquite::QualityMetric::evaluate(), MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::evaluate_with_Hessian(), MBMesquite::QualityMetric::evaluate_with_indices(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), MBMesquite::grad(), MBMesquite::hess(), mSettings, and value().

Referenced by test_supported_element_types().

{
    MsqError err;
    bool rval;
    // create patch containing only elements of sepcified type
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    get_ideal_element( type, false, pd );
    // get list of evaluation locations in patch
    std::vector< size_t > handles;
    qm->get_evaluations( pd, handles, false, err );
    if( err.error_code() == MsqError::UNSUPPORTED_ELEMENT ) return;
    CPPUNIT_ASSERT( !err );
    if( handles.empty() ) return;
    // evaluate the metric at one location
    double value;
    rval = qm->evaluate( pd, handles[0], value, err );
    CPPUNIT_ASSERT_EQUAL( MsqError::UNSUPPORTED_ELEMENT, err.error_code() );
    std::vector< size_t > indices;
    rval = qm->evaluate_with_indices( pd, handles[0], value, indices, err );
    CPPUNIT_ASSERT_EQUAL( MsqError::UNSUPPORTED_ELEMENT, err.error_code() );
    std::vector< Vector3D > grad;
    rval = qm->evaluate_with_gradient( pd, handles[0], value, indices, grad, err );
    CPPUNIT_ASSERT_EQUAL( MsqError::UNSUPPORTED_ELEMENT, err.error_code() );
    std::vector< Matrix3D > hess;
    rval = qm->evaluate_with_Hessian( pd, handles[0], value, indices, grad, hess, err );
    CPPUNIT_ASSERT_EQUAL( MsqError::UNSUPPORTED_ELEMENT, err.error_code() );
}

Definition at line 359 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, MBMesquite::QualityMetric::evaluate(), MBMesquite::QualityMetric::evaluate_with_gradient(), MBMesquite::QualityMetric::evaluate_with_Hessian(), MBMesquite::QualityMetric::evaluate_with_indices(), MBMesquite::QualityMetric::get_evaluations(), get_ideal_element(), MBMesquite::grad(), MBMesquite::hess(), mSettings, MSQ_CHKERR, and value().

Referenced by test_supported_element_types().

{
    MsqPrintError err( std::cout );
    bool rval;
    // create patch containing only elements of sepcified type
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    get_ideal_element( type, false, pd );
    // get list of evaluation locations in patch
    std::vector< size_t > handles;
    qm->get_evaluations( pd, handles, false, err );
    CPPUNIT_ASSERT( !err );
    CPPUNIT_ASSERT( !handles.empty() );
    // evaluate the metric at one location
    double value = -HUGE_VAL;
    rval         = qm->evaluate( pd, handles[0], value, err );
    CPPUNIT_ASSERT( !err );
    CPPUNIT_ASSERT( rval );
    // if metric returned input value for 'value' try again
    // with a different initial value to verify that the metric
    // is setting 'value' to something.
    if( value == -HUGE_VAL )
    {
        value = 0.0;
        rval  = qm->evaluate( pd, handles[0], value, err );
        CPPUNIT_ASSERT( !err && rval );
        CPPUNIT_ASSERT( value != 0.0 );
    }
    std::vector< size_t > indices;
    rval = qm->evaluate_with_indices( pd, handles[0], value, indices, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( rval );
    std::vector< Vector3D > grad;
    rval = qm->evaluate_with_gradient( pd, handles[0], value, indices, grad, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( rval );
    std::vector< Matrix3D > hess;
    rval = qm->evaluate_with_Hessian( pd, handles[0], value, indices, grad, hess, err );
    CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
    CPPUNIT_ASSERT( rval );
}

Test that metric value increases (or decreases if negate_flag is -1) as the quality of the element worsen. Compares gradient values for ideal elements with unit edge length to the value for the same elements with the shared vertex moved 1/2 of the length of one of the adjacent edges. This test is done only for TRIANGLE, QUADRILATERAL, and HEXAHEDRAL element types.

Definition at line 2169 of file QualityMetricTester.cpp.

References MBMesquite::PatchData::attach_settings(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::QualityMetric::evaluate_with_gradient(), get_ideal_hexes(), get_ideal_quads(), get_ideal_tris(), MBMesquite::QualityMetric::get_negate_flag(), MBMesquite::grad(), MBMesquite::HEXAHEDRON, MBMesquite::PatchData::move_vertex(), mSettings, MSQ_CHKERR, MBMesquite::QUADRILATERAL, MBMesquite::TRIANGLE, and type_is_supported().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    if( mSettings ) pd.attach_settings( mSettings );
    std::vector< size_t > indices;
    std::vector< Vector3D > grad;
    double qmval;
    bool rval;
    bool increasing = true;
    if( qm->get_negate_flag() != 1 )
    {
        CPPUNIT_ASSERT_EQUAL( qm->get_negate_flag(), -1 );
        increasing = false;
    }

    unsigned count = 0;
    for( size_t i = 0; i < 3; ++i )
    {
        // get a patch
        switch( i )
        {
            case 0:
                if( !type_is_supported( TRIANGLE ) ) continue;
                get_ideal_tris( pd, false );
                break;
            case 1:
                if( !type_is_supported( QUADRILATERAL ) ) continue;
                get_ideal_quads( pd );
                break;
            case 2:
                if( !type_is_supported( HEXAHEDRON ) ) continue;
                get_ideal_hexes( pd );
                break;
        }

        // move center vertex
        pd.move_vertex( Vector3D( 0.3, 0.3, 0.3 ), 0, err );

        // evaluate for ideal non-element
        rval = qm->evaluate_with_gradient( pd, 0, qmval, indices, grad, err );
        CPPUNIT_ASSERT( !MSQ_CHKERR( err ) );
        CPPUNIT_ASSERT( rval );
        // find gradient for vertex 0
        if( indices.empty() ) continue;
        CPPUNIT_ASSERT_EQUAL( (size_t)1, indices.size() );  // only 1 free vertex
        CPPUNIT_ASSERT_EQUAL( (size_t)0, indices[0] );      // and that vertex is vertex 0
        ++count;
        Vector3D g = grad[0];
        // check gradient direction
        if( increasing )
            CPPUNIT_ASSERT( g[2] > 1e-6 );
        else
            CPPUNIT_ASSERT( g[2] < -1e-6 );
    }
    // make sure we tested something
    CPPUNIT_ASSERT( count > 0 );
}

Member Data Documentation

Definition at line 305 of file QualityMetricTester.hpp.

Referenced by compare_analytical_and_numerical_diagonals(), compare_analytical_and_numerical_gradients(), compare_analytical_and_numerical_hessians(), compare_eval_and_eval_with_indices(), compare_eval_with_diag_and_eval_with_hessian(), compare_eval_with_grad_and_eval_with_diagonal(), compare_eval_with_grad_and_eval_with_hessian(), compare_eval_with_indices_and_eval_with_diagonal(), compare_eval_with_indices_and_eval_with_gradient(), compare_eval_with_indices_and_eval_with_hessian(), test_diagonal_with_fixed_vertex(), test_domain_deviation_gradient(), test_domain_deviation_quality(), test_evaluate_degenerate_element(), test_evaluate_inverted_element(), test_evaluate_unit_edge_element(), test_evaluate_unit_edge_tris_about_vertex(), test_evaluate_unit_element(), test_evaluate_unit_hexes_about_vertex(), test_evaluate_unit_quads_about_vertex(), test_evaluate_unit_tris_about_vertex(), test_evaluate_zero_element(), test_get_edge_evaluations(), test_get_edge_indices(), test_get_element_evaluations(), test_get_element_indices(), test_get_in_element_evaluations(), test_get_indices_fixed(), test_get_sample_evaluations(), test_get_sample_indices(), test_get_vertex_evaluations(), test_get_vertex_indices(), test_grad_transform_invariant(), test_gradient_reflects_quality(), test_gradient_with_fixed_vertex(), test_hessian_transform_invariant(), test_hessian_with_fixed_vertex(), test_ideal_element_positive_definite_Hessian(), test_ideal_element_zero_gradient(), test_ideal_element_zero_vertex_gradient(), test_measures_quality(), test_measures_transform(), test_measures_vertex_quality(), test_symmetric_Hessian_diagonal_blocks(), test_transform_invariant(), test_type_is_not_supported(), test_type_is_supported(), and test_vertex_gradient_reflects_quality().

List of all members.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines