MOAB: Mesh Oriented datABase  (version 5.4.1)
TerminationCriterionTest Class Reference
+ Inheritance diagram for TerminationCriterionTest:
+ Collaboration diagram for TerminationCriterionTest:

Public Member Functions

 TerminationCriterionTest ()
void test_number_of_iterates_inner ()
void test_number_of_iterates_outer ()
void test_cpu_time_inner ()
void test_cpu_time_outer ()
void test_absolute_vertex_movement ()
void test_relative_vertex_movement ()
void test_absolute_vertex_movement_edge_length ()
void test_gradient_L2_norm_absolute ()
void test_gradient_Linf_norm_absolute ()
void test_gradient_L2_norm_relative ()
void test_gradient_Linf_norm_relative ()
void test_quality_improvement_absolute ()
void test_quality_improvement_relative ()
void test_successive_improvements_absolute ()
void test_successive_improvements_relative ()
void test_vertex_bound ()
void test_untangled_mesh ()
void test_abs_vtx_movement_culling ()

Private Member Functions

 CPPUNIT_TEST_SUITE (TerminationCriterionTest)
 CPPUNIT_TEST (test_number_of_iterates_inner)
 CPPUNIT_TEST (test_number_of_iterates_outer)
 CPPUNIT_TEST (test_cpu_time_inner)
 CPPUNIT_TEST (test_cpu_time_outer)
 CPPUNIT_TEST (test_absolute_vertex_movement)
 CPPUNIT_TEST (test_relative_vertex_movement)
 CPPUNIT_TEST (test_absolute_vertex_movement_edge_length)
 CPPUNIT_TEST (test_gradient_L2_norm_absolute)
 CPPUNIT_TEST (test_gradient_Linf_norm_absolute)
 CPPUNIT_TEST (test_gradient_L2_norm_relative)
 CPPUNIT_TEST (test_gradient_Linf_norm_relative)
 CPPUNIT_TEST (test_quality_improvement_absolute)
 CPPUNIT_TEST (test_quality_improvement_relative)
 CPPUNIT_TEST (test_successive_improvements_absolute)
 CPPUNIT_TEST (test_successive_improvements_relative)
 CPPUNIT_TEST (test_vertex_bound)
 CPPUNIT_TEST (test_untangled_mesh)
 CPPUNIT_TEST (test_abs_vtx_movement_culling)
 CPPUNIT_TEST_SUITE_END ()
void test_gradient_common (bool absolute, bool L2)
void test_quality_common (bool absolute, bool successive)
void test_vertex_movement_common (bool absolute)
void test_cpu_time_common (bool inner)

Private Attributes

DummyOF objFunc
OFEvaluator ofEval

Detailed Description

Definition at line 97 of file TerminationCriterionTest.cpp.


Constructor & Destructor Documentation


Member Function Documentation

Definition at line 786 of file TerminationCriterionTest.cpp.

References MBMesquite::TerminationCriterion::add_absolute_vertex_movement(), MBMesquite::TerminationCriterion::add_iteration_limit(), ASSERT_NO_ERROR, conn, CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::TerminationCriterion::cull_on_absolute_vertex_movement(), fixed, MBMesquite::ArrayMesh::get_all_vertices(), MBMesquite::inner(), mesh, TCTFauxOptimizer::num_passes(), MBMesquite::outer(), MBMesquite::QUADRILATERAL, MBMesquite::IQInterface::run_instructions(), MBMesquite::QualityImprover::set_inner_termination_criterion(), MBMesquite::InstructionQueue::set_master_quality_improver(), MBMesquite::QualityImprover::set_outer_termination_criterion(), TCTFauxOptimizer::should_have_terminated(), MBMesquite::ArrayMesh::vertices_set_byte(), and MBMesquite::PlanarDomain::XY.

{
    /* define a quad mesh like the following
      16--17--18--19--20--21--22--23
       |   |   |   |   |   |   |   |   Y
       8---9--10--11--12--13--14--15   ^
       |   |   |   |   |   |   |   |   |
       0---1---2---3---4---5---6---7   +-->X
    */

    const int nvtx = 24;
    int fixed[nvtx];
    double coords[3 * nvtx];
    for( int i = 0; i < nvtx; ++i )
    {
        coords[3 * i]     = i / 8;
        coords[3 * i + 1] = i % 8;
        coords[3 * i + 2] = 0;
        fixed[i]          = i < 9 || i > 14;
    }

    const int nquad = 14;
    unsigned long conn[4 * nquad];
    for( int i = 0; i < nquad; ++i )
    {
        int row         = i / 7;
        int idx         = i % 7;
        int n0          = 8 * row + idx;
        conn[4 * i]     = n0;
        conn[4 * i + 1] = n0 + 1;
        conn[4 * i + 2] = n0 + 9;
        conn[4 * i + 3] = n0 + 8;
    }

    const double tol = 0.05;
    PlanarDomain zplane( PlanarDomain::XY, 0.0 );
    ArrayMesh mesh( 3, nvtx, coords, fixed, nquad, QUADRILATERAL, conn );

    // fill vertex byte with garbage to make sure that quality improver
    // is initializing correctly.
    MsqError err;
    std::vector< unsigned char > junk( nvtx, 255 );
    std::vector< Mesh::VertexHandle > vertices;
    mesh.get_all_vertices( vertices, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT_EQUAL( junk.size(), vertices.size() );
    mesh.vertices_set_byte( &vertices[0], &junk[0], vertices.size(), err );
    ASSERT_NO_ERROR( err );

    // Define optimizer
    TCTFauxOptimizer smoother( 2 * tol );
    TerminationCriterion outer, inner;
    outer.add_absolute_vertex_movement( tol );
    inner.cull_on_absolute_vertex_movement( tol );
    inner.add_iteration_limit( 1 );
    smoother.set_inner_termination_criterion( &inner );
    smoother.set_outer_termination_criterion( &outer );

    // No run the "optimizer"
    InstructionQueue q;
    q.set_master_quality_improver( &smoother, err );
    MeshDomainAssoc mesh_and_domain = MeshDomainAssoc( &mesh, &zplane );
    q.run_instructions( &mesh_and_domain, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( smoother.should_have_terminated() );
    CPPUNIT_ASSERT( smoother.num_passes() > 1 );
}

Definition at line 371 of file TerminationCriterionTest.cpp.

References MBMesquite::TerminationCriterion::accumulate_inner(), MBMesquite::TerminationCriterion::accumulate_patch(), MBMesquite::TerminationCriterion::add_absolute_vertex_movement_edge_length(), ASSERT_NO_ERROR, MBMesquite::SimpleStats::average(), beta, conn, CPPUNIT_ASSERT, MBMesquite::MeshUtil::edge_length_distribution(), MBMesquite::PatchData::fill_global_patch(), fixed, MBMesquite::TerminationCriterion::initialize_queue(), mesh, MBMesquite::PatchData::move_vertex(), MBMesquite::PatchData::num_free_vertices(), MBMesquite::TerminationCriterion::reset_inner(), MBMesquite::TerminationCriterion::reset_patch(), MBMesquite::PatchData::set_mesh(), MBMesquite::SimpleStats::standard_deviation(), MBMesquite::TerminationCriterion::terminate(), and MBMesquite::TETRAHEDRON.

{
    MsqPrintError err( std::cout );

    // define two-tet mesh where tets share a face
    double coords[]            = { 0, -5, 0, 0, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1 };
    const unsigned long conn[] = { 4, 3, 2, 0, 2, 3, 4, 1 };
    int fixed[5]               = { 0 };
    ArrayMesh mesh( 3, 5, coords, fixed, 2, TETRAHEDRON, conn );

    // calculate beta
    const double LIMIT = 1e-4;  // desired absolute limit
    MeshUtil tool( &mesh );
    SimpleStats len;
    tool.edge_length_distribution( len, err );
    ASSERT_NO_ERROR( err );
    const double beta = LIMIT / ( len.average() - len.standard_deviation() );

    // initialize termination criterion
    TerminationCriterion tc;
    tc.add_absolute_vertex_movement_edge_length( beta );
    MeshDomainAssoc mesh_and_domain2 = MeshDomainAssoc( &mesh, 0 );
    tc.initialize_queue( &mesh_and_domain2, 0, err );
    ASSERT_NO_ERROR( err );

    // get a patch data
    PatchData pd;
    pd.set_mesh( &mesh );
    pd.fill_global_patch( err );
    ASSERT_NO_ERROR( err );

    // test termination criteiorn
    tc.reset_inner( pd, ofEval, err );
    ASSERT_NO_ERROR( err );
    tc.reset_patch( pd, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( !tc.terminate() );

    const double FIRST_STEP = 10.0;
    // move a vertex by 10 units and check that it did not meet criterion
    pd.move_vertex( Vector3D( FIRST_STEP, 0, 0 ), 0, err );
    ASSERT_NO_ERROR( err );
    tc.accumulate_inner( pd, 0.0, 0, err );
    ASSERT_NO_ERROR( err );
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( !tc.terminate() );

    double test_limit = LIMIT;

    int idx = 0;
    for( double step = FIRST_STEP; step > test_limit; step *= 0.09 )
    {
        idx = ( idx + 1 ) % pd.num_free_vertices();
        pd.move_vertex( Vector3D( step, 0, 0 ), idx, err );
        ASSERT_NO_ERROR( err );

        tc.accumulate_inner( pd, 0.0, 0, err );
        ASSERT_NO_ERROR( err );
        tc.accumulate_patch( pd, err );
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT( !tc.terminate() );
    }

    idx = ( idx + 1 ) % pd.num_free_vertices();
    pd.move_vertex( Vector3D( 0.5 * test_limit, 0, 0 ), idx, err );
    ASSERT_NO_ERROR( err );

    tc.accumulate_inner( pd, 0.0, 0, err );
    ASSERT_NO_ERROR( err );
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( tc.terminate() );
}

Definition at line 143 of file TerminationCriterionTest.cpp.

    {
        test_cpu_time_common( true );
    }

Definition at line 147 of file TerminationCriterionTest.cpp.

    {
        test_cpu_time_common( false );
    }
void TerminationCriterionTest::test_gradient_common ( bool  absolute,
bool  L2 
) [private]

Definition at line 455 of file TerminationCriterionTest.cpp.

References MBMesquite::TerminationCriterion::accumulate_inner(), MBMesquite::TerminationCriterion::accumulate_patch(), MBMesquite::TerminationCriterion::add_absolute_gradient_inf_norm(), MBMesquite::TerminationCriterion::add_absolute_gradient_L2_norm(), MBMesquite::TerminationCriterion::add_relative_gradient_inf_norm(), MBMesquite::TerminationCriterion::add_relative_gradient_L2_norm(), MBMesquite::arrptr(), ASSERT_NO_ERROR, CPPUNIT_ASSERT, MBMesquite::create_twelve_hex_patch(), MBMesquite::grad(), lenfunc(), maxfunc(), MBMesquite::PatchData::num_free_vertices(), MBMesquite::TerminationCriterion::reset_inner(), MBMesquite::TerminationCriterion::reset_patch(), MBMesquite::TerminationCriterion::terminate(), and value().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    create_twelve_hex_patch( pd, err );
    ASSERT_NO_ERROR( err );

    const double LIMIT = 1e-4;
    TerminationCriterion tc;
    if( absolute )
    {
        if( L2 )
            tc.add_absolute_gradient_L2_norm( LIMIT );
        else
            tc.add_absolute_gradient_inf_norm( LIMIT );
    }
    else
    {
        if( L2 )
            tc.add_relative_gradient_L2_norm( LIMIT );
        else
            tc.add_relative_gradient_inf_norm( LIMIT );
    }

    double ( *func_ptr )( const Vector3D*, int ) = L2 ? &lenfunc : &maxfunc;

    double junk, value = 1;
    objFunc.mGrad = Vector3D( value, value, value );
    tc.reset_inner( pd, ofEval, err );
    ASSERT_NO_ERROR( err );
    tc.reset_patch( pd, err );
    ASSERT_NO_ERROR( err );

    std::vector< Vector3D > grad;
    ofEval.evaluate( pd, junk, grad, err );
    ASSERT_NO_ERROR( err );

    double limit = LIMIT;
    if( !absolute ) limit *= func_ptr( arrptr( grad ), pd.num_free_vertices() );

    while( func_ptr( arrptr( grad ), pd.num_free_vertices() ) > limit )
    {
        CPPUNIT_ASSERT( !tc.terminate() );

        value *= 0.1;
        objFunc.mGrad = Vector3D( value, value, value );
        ofEval.evaluate( pd, junk, grad, err );
        ASSERT_NO_ERROR( err );

        tc.accumulate_inner( pd, 0.0, arrptr( grad ), err );
        ASSERT_NO_ERROR( err );
        tc.accumulate_patch( pd, err );
        ASSERT_NO_ERROR( err );
    }

    CPPUNIT_ASSERT( tc.terminate() );
}
void TerminationCriterionTest::test_quality_common ( bool  absolute,
bool  successive 
) [private]

Definition at line 530 of file TerminationCriterionTest.cpp.

References MBMesquite::TerminationCriterion::accumulate_inner(), MBMesquite::TerminationCriterion::accumulate_patch(), MBMesquite::TerminationCriterion::add_absolute_quality_improvement(), MBMesquite::TerminationCriterion::add_absolute_successive_improvement(), MBMesquite::TerminationCriterion::add_relative_quality_improvement(), MBMesquite::TerminationCriterion::add_relative_successive_improvement(), ASSERT_NO_ERROR, CPPUNIT_ASSERT, limit_absolute_quality(), limit_absolute_sucessive(), limit_relative_quality(), limit_relative_sucessive(), MBMesquite::TerminationCriterion::reset_inner(), MBMesquite::TerminationCriterion::reset_patch(), and MBMesquite::TerminationCriterion::terminate().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    ASSERT_NO_ERROR( err );

    const double LIMIT = 1e-4;
    TerminationCriterion tc;
    bool ( *func_ptr )( double, double, double, double );
    if( absolute )
    {
        if( successive )
        {
            tc.add_absolute_successive_improvement( LIMIT );
            func_ptr = &limit_absolute_sucessive;
        }
        else
        {
            tc.add_absolute_quality_improvement( LIMIT );
            func_ptr = &limit_absolute_quality;
        }
    }
    else
    {
        if( successive )
        {
            tc.add_relative_successive_improvement( LIMIT );
            func_ptr = &limit_relative_sucessive;
        }
        else
        {
            tc.add_relative_quality_improvement( LIMIT );
            func_ptr = &limit_relative_quality;
        }
    }

    const double INIT_VALUE = 10.0;
    objFunc.mValue          = INIT_VALUE;
    tc.reset_inner( pd, ofEval, err );
    ASSERT_NO_ERROR( err );
    tc.reset_patch( pd, err );
    ASSERT_NO_ERROR( err );
    double prev = HUGE_VAL;

    while( !func_ptr( INIT_VALUE, prev, objFunc.mValue, LIMIT ) )
    {
        CPPUNIT_ASSERT( !tc.terminate() );

        prev = objFunc.mValue;
        objFunc.mValue *= 0.1;
        tc.accumulate_inner( pd, objFunc.mValue, 0, err );
        ASSERT_NO_ERROR( err );
        tc.accumulate_patch( pd, err );
        ASSERT_NO_ERROR( err );
    }

    CPPUNIT_ASSERT( tc.terminate() );
}

Definition at line 626 of file TerminationCriterionTest.cpp.

References MBMesquite::TerminationCriterion::accumulate_inner(), MBMesquite::TerminationCriterion::accumulate_patch(), MBMesquite::TerminationCriterion::add_untangled_mesh(), ASSERT_NO_ERROR, MBMesquite::MsqMeshEntity::check_element_orientation(), CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, MBMesquite::create_twelve_hex_patch(), MBMesquite::PatchData::element_by_index(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), MBMesquite::PatchData::move_vertex(), MBMesquite::TerminationCriterion::reset_inner(), MBMesquite::TerminationCriterion::reset_patch(), MBMesquite::PatchData::set_vertex_coordinates(), MBMesquite::TerminationCriterion::terminate(), and MBMesquite::PatchData::vertex_by_index().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    create_twelve_hex_patch( pd, err );
    ASSERT_NO_ERROR( err );

    // get two opposite vertices in first hexahedral element
    int vtx1                 = pd.element_by_index( 0 ).get_vertex_index_array()[0];
    int vtx2                 = pd.element_by_index( 0 ).get_vertex_index_array()[7];
    Vector3D saved_coords    = pd.vertex_by_index( vtx2 );
    Vector3D opposite_coords = pd.vertex_by_index( vtx1 );

    // invert the element
    pd.move_vertex( 2 * ( opposite_coords - saved_coords ), vtx2, err );
    ASSERT_NO_ERROR( err );
    int inverted, samples;
    pd.element_by_index( 0 ).check_element_orientation( pd, inverted, samples, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( inverted > 0 );

    // check initial termination criterion
    TerminationCriterion tc;
    tc.add_untangled_mesh();
    tc.reset_inner( pd, ofEval, err );
    ASSERT_NO_ERROR( err );
    tc.reset_patch( pd, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( !tc.terminate() );

    // fix the element
    pd.set_vertex_coordinates( saved_coords, vtx2, err );
    ASSERT_NO_ERROR( err );
    pd.element_by_index( 0 ).check_element_orientation( pd, inverted, samples, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT_EQUAL( 0, inverted );

    // check that TC recognized untangled mesh
    tc.accumulate_inner( pd, 0.0, 0, err );
    ASSERT_NO_ERROR( err );
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( tc.terminate() );
}

Definition at line 590 of file TerminationCriterionTest.cpp.

References MBMesquite::TerminationCriterion::accumulate_inner(), MBMesquite::TerminationCriterion::accumulate_patch(), MBMesquite::TerminationCriterion::add_bounded_vertex_movement(), ASSERT_NO_ERROR, CPPUNIT_ASSERT, MBMesquite::create_twelve_hex_patch(), MBMesquite::PatchData::num_free_vertices(), MBMesquite::PatchData::num_nodes(), MBMesquite::TerminationCriterion::reset_inner(), MBMesquite::TerminationCriterion::reset_patch(), MBMesquite::PatchData::set_vertex_coordinates(), MBMesquite::TerminationCriterion::terminate(), and MBMesquite::PatchData::vertex_by_index().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    create_twelve_hex_patch( pd, err );
    ASSERT_NO_ERROR( err );

    // get bounding dimension for patch
    double maxcoord = 0.0;
    for( size_t i = 0; i < pd.num_nodes(); ++i )
        for( int d = 0; d < 3; ++d )
            if( fabs( pd.vertex_by_index( i )[d] ) > maxcoord ) maxcoord = fabs( pd.vertex_by_index( i )[d] );
    // add a little bit for rounding error
    maxcoord += 1e-5;

    TerminationCriterion tc;
    tc.add_bounded_vertex_movement( maxcoord );
    tc.reset_inner( pd, ofEval, err );
    ASSERT_NO_ERROR( err );
    tc.reset_patch( pd, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( !tc.terminate() );

    int idx      = pd.num_free_vertices() - 1;
    Vector3D pos = pd.vertex_by_index( idx );
    pos[0]       = 2 * maxcoord;
    pd.set_vertex_coordinates( pos, idx, err );
    ASSERT_NO_ERROR( err );
    tc.accumulate_inner( pd, 0.0, 0, err );
    ASSERT_NO_ERROR( err );
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( tc.terminate() );
}
void TerminationCriterionTest::test_vertex_movement_common ( bool  absolute) [private]

Definition at line 313 of file TerminationCriterionTest.cpp.

References MBMesquite::TerminationCriterion::accumulate_inner(), MBMesquite::TerminationCriterion::accumulate_patch(), MBMesquite::TerminationCriterion::add_absolute_vertex_movement(), MBMesquite::TerminationCriterion::add_relative_vertex_movement(), ASSERT_NO_ERROR, CPPUNIT_ASSERT, MBMesquite::create_twelve_hex_patch(), MBMesquite::PatchData::move_vertex(), MBMesquite::PatchData::num_free_vertices(), MBMesquite::TerminationCriterion::reset_inner(), MBMesquite::TerminationCriterion::reset_patch(), and MBMesquite::TerminationCriterion::terminate().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    create_twelve_hex_patch( pd, err );
    ASSERT_NO_ERROR( err );

    const double LIMIT = 1e-4;
    TerminationCriterion tc;
    if( absolute )
        tc.add_absolute_vertex_movement( LIMIT );
    else
        tc.add_relative_vertex_movement( LIMIT );

    tc.reset_inner( pd, ofEval, err );
    ASSERT_NO_ERROR( err );
    tc.reset_patch( pd, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( !tc.terminate() );

    const double FIRST_STEP = 10.0;
    // move a vertex by 10 units and check that it did not meet criterion
    pd.move_vertex( Vector3D( FIRST_STEP, 0, 0 ), 0, err );
    ASSERT_NO_ERROR( err );
    tc.accumulate_inner( pd, 0.0, 0, err );
    ASSERT_NO_ERROR( err );
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( !tc.terminate() );

    double test_limit = LIMIT;
    if( !absolute ) test_limit *= FIRST_STEP;

    int idx = 0;
    for( double step = FIRST_STEP; step > test_limit; step *= 0.09 )
    {
        idx = ( idx + 1 ) % pd.num_free_vertices();
        pd.move_vertex( Vector3D( step, 0, 0 ), idx, err );
        ASSERT_NO_ERROR( err );

        tc.accumulate_inner( pd, 0.0, 0, err );
        ASSERT_NO_ERROR( err );
        tc.accumulate_patch( pd, err );
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT( !tc.terminate() );
    }

    idx = ( idx + 1 ) % pd.num_free_vertices();
    pd.move_vertex( Vector3D( 0.5 * test_limit, 0, 0 ), idx, err );
    ASSERT_NO_ERROR( err );

    tc.accumulate_inner( pd, 0.0, 0, err );
    ASSERT_NO_ERROR( err );
    tc.accumulate_patch( pd, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( tc.terminate() );
}

Member Data Documentation

List of all members.


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