MOAB: Mesh Oriented datABase  (version 5.2.1)
MBMesquite::TerminationCriterion Class Reference

The TerminationCriterion class contains functionality to terminate the VertexMover's optimization. More...

#include <TerminationCriterion.hpp>

+ Collaboration diagram for MBMesquite::TerminationCriterion:

Public Types

enum  InnerOuterType { TYPE_UNKNOWN, TYPE_INNER, TYPE_OUTER }
enum  TimeStepFileType { NOTYPE = 0, VTK, GNUPLOT }

Public Member Functions

MESQUITE_EXPORT void add_absolute_gradient_L2_norm (double value)
MESQUITE_EXPORT void add_absolute_gradient_inf_norm (double value)
MESQUITE_EXPORT void add_relative_gradient_L2_norm (double value)
MESQUITE_EXPORT void add_relative_gradient_inf_norm (double value)
MESQUITE_EXPORT void add_absolute_quality_improvement (double value)
MESQUITE_EXPORT void add_relative_quality_improvement (double value)
MESQUITE_EXPORT void add_absolute_vertex_movement (double value)
MESQUITE_EXPORT void add_relative_vertex_movement (double value)
MESQUITE_EXPORT void add_absolute_vertex_movement_edge_length (double value)
MESQUITE_EXPORT void add_absolute_successive_improvement (double value)
MESQUITE_EXPORT void add_relative_successive_improvement (double value)
MESQUITE_EXPORT void add_cpu_time (double seconds)
MESQUITE_EXPORT void add_iteration_limit (unsigned int max_iterations)
 Terminates when the number of iterations exceeds a given integer.
MESQUITE_EXPORT void add_bounded_vertex_movement (double value)
MESQUITE_EXPORT void add_untangled_mesh ()
MESQUITE_EXPORT void remove_all_criteria ()
MESQUITE_EXPORT void cull_on_absolute_quality_improvement (double limit)
MESQUITE_EXPORT void cull_on_relative_quality_improvement (double limit)
MESQUITE_EXPORT void cull_on_absolute_vertex_movement (double limit)
MESQUITE_EXPORT void cull_on_relative_vertex_movement (double limit)
MESQUITE_EXPORT void cull_on_absolute_successive_improvement (double limit)
MESQUITE_EXPORT void cull_on_absolute_vertex_movement_edge_length (double value)
MESQUITE_EXPORT void cull_on_relative_successive_improvement (double limit)
MESQUITE_EXPORT void cull_for_global_patch (bool val=true)
MESQUITE_EXPORT void cull_untangled_mesh ()
MESQUITE_EXPORT void remove_culling ()
MESQUITE_EXPORT TerminationCriterion (std::string name="", InnerOuterType innerOuterType=TYPE_UNKNOWN)
 Constructor which does not take any arguements.
MESQUITE_EXPORT ~TerminationCriterion ()
 Destructor.
MESQUITE_EXPORT double get_current_function_value ()
 This function returns the current function value.
MESQUITE_EXPORT void set_debug_output_level (int i)
MESQUITE_EXPORT void write_mesh_steps (const char *filename, TimeStepFileType type=VTK)
 Write mesh improvement animation.
MESQUITE_EXPORT void write_iterations (const char *filename, MsqError &err)
MESQUITE_EXPORT int get_iteration_count () const
void reset_outer (Mesh *ms, MeshDomain *dm, OFEvaluator &of, const Settings *settings, MsqError &err)
 Clear any data accumulated during an outer iteration.
void reset_inner (PatchData &pd, OFEvaluator &of, MsqError &err)
 Clear any data accumulated during an inner iteration.
void reset_patch (PatchData &pd, MsqError &err)
 Shared inner and outer initialization during inner loop.
void accumulate_inner (PatchData &pd, OFEvaluator &eval, MsqError &err)
 Accumulate data during inner iteration.
void accumulate_inner (PatchData &pd, double of_value, Vector3D *of_grads, MsqError &err)
 Accumulate data during inner iteration.
void accumulate_patch (PatchData &pd, MsqError &err)
void accumulate_outer (Mesh *ms, MeshDomain *dm, OFEvaluator &eval, const Settings *settings, MsqError &err)
MESQUITE_EXPORT bool terminate ()
 Check if termination criterion has been met.
MESQUITE_EXPORT bool criterion_is_set ()
 Check if at least one termination criterion is set.
bool cull_vertices (PatchData &pd, OFEvaluator &obj_ptr, MsqError &err)
 Function which determines whether this patch should be 'culled'.
bool cull_vertices_global (PatchData &global_patch, Mesh *mesh, MeshDomain *domain, const Settings *settings, OFEvaluator &of_eval, MsqError &err)
 experimental, first cut at culling for global patches - not finished
void cleanup (Mesh *ms, MeshDomain *domain, MsqError &err)
 Cleans up after the TerminationCriterion is finished.
void initialize_queue (MeshDomainAssoc *mesh_and_domain, const Settings *settings, MsqError &err)

Protected Member Functions

void write_timestep (PatchData &pd, const Vector3D *gradient, MsqError &err)
std::string par_string ()

Static Protected Member Functions

static size_t count_inverted (PatchData &pd, MsqError &err)

Private Attributes

long unsigned int terminationCriterionFlag
 Bit flag of termination crit.
long unsigned int cullingMethodFlag
double cullingEps
bool cullingGlobalPatch
double initialOFValue
double previousOFValue
double currentOFValue
double lowerOFBound
std::vector< Vector3DmGrad
double initialGradL2NormSquared
double currentGradL2NormSquared
double gradL2NormAbsoluteEpsSquared
double gradL2NormRelativeEpsSquared
double initialGradInfNorm
double currentGradInfNorm
double gradInfNormAbsoluteEps
double gradInfNormRelativeEps
double qualityImprovementAbsoluteEps
double qualityImprovementRelativeEps
int iterationBound
int iterationCounter
Timer mTimer
double timeBound
PatchDataVerticesMementoinitialVerticesMemento
PatchDataVerticesMementopreviousVerticesMemento
double vertexMovementAbsoluteEps
double vertexMovementRelativeEps
double vertexMovementAvgBeta
 input beta value used to calculate vertexMovementAbsoluteAvg
double vertexMovementAbsoluteAvgEdge
double maxSquaredInitialMovement
double maxSquaredMovement
double successiveImprovementsAbsoluteEps
double successiveImprovementsRelativeEps
double boundedVertexMovementEps
int vertexMovementExceedsBound
size_t globalInvertedCount
 number of inverted elements in entire mesh
size_t patchInvertedCount
 number of inverted elements in previously tested patch
int debugLevel
std::ofstream plotFile
 Plot data.
std::string timeStepFileName
 Base name for timestep files.
TimeStepFileType timeStepFileType
std::string moniker
InnerOuterType innerOuterType

Friends

class VertexMover

Detailed Description

The TerminationCriterion class contains functionality to terminate the VertexMover's optimization.

The Termination Criterion class has three roles. It is used to terminate the optimization on a single patch; it is used to terminate the iterations over all patches in the mesh; and it is used to cull vertices from the optimization processes. Thus, for each optimization, two TerminationCriterion objects are used. The class contains five important member functions used in the VertexMover: initialize(), reset(), terminate(), cull_vertices(), and cleanup(). These functions are each explained in detail below. In general, the only one of these functions called directly from a concrete VertexMover is terminate() which allows the concrete VertexMover to determine when to stop producing new iterates on a given patch. All other functionality is handled from the base VertexMover base class.

There are several different types of termination criteria available. Multiple criteria types can be set on a given Termination Criterion object, and when this occurs, the optimization process will terminate whenever any of the criteria have been satisfied.

The following is a brief description of how TerminationCriterion is used within Mesquite. Functions called during QualityImprovement can be divided into three groups: reset_* - Initialize data for an iteration accumulate_* - Update TC for changed data during iteration terminate - Check if the termination criterion has been met. There are three different forms of the reset_* and accumulate_* functions which are called on the inner, outer, or both TerminationCriterion classes: _outer - Called on outer termination criterion. _inner - Called on inner termination criterion. _patch - Called on outer termination criterion for each patch and on inner termination criterion for each inner iteration.

If implementing a new TerminationCriterion, the following rules should be followed. If the value must be calculated on a global patch for the outer TC, then: o The functionality should be added to *_inner (yes, INNER) o The *_outer methods should be updated to call the *_inner with a global patch when your TC is requested. o The internal data for any such TC should be initialized in the reset_inner method. If the value for the outer criterion can be calculated from each local patch when iterating over the mesh with local patches, then: o The functionality should be added to *_patch o Any state values pertaining to the entire iteration must be initialized in reset_inner(..) and cleared in terminate() o Any patch-specific data should be initialized in reset_patch o Care should be taken that terminate() does not check uninitialized data if called before the first call to accumulate_patch()

Definition at line 121 of file TerminationCriterion.hpp.


Member Enumeration Documentation

Enumerator:
TYPE_UNKNOWN 
TYPE_INNER 
TYPE_OUTER 

Definition at line 254 of file TerminationCriterion.hpp.

Enumerator:
NOTYPE 
VTK 
GNUPLOT 

Definition at line 282 of file TerminationCriterion.hpp.

    {
        NOTYPE = 0,
        VTK,
        GNUPLOT
    };

Constructor & Destructor Documentation

MBMesquite::TerminationCriterion::TerminationCriterion ( std::string  name = "",
InnerOuterType  pinnerOuterType = TYPE_UNKNOWN 
)

Constructor which does not take any arguements.

Constructor initializes all of the data members which are not necessarily automatically initialized in their constructors.

Definition at line 145 of file TerminationCriterion.cpp.

References boundedVertexMovementEps, cullingEps, cullingGlobalPatch, cullingMethodFlag, currentOFValue, globalInvertedCount, gradInfNormAbsoluteEps, gradInfNormRelativeEps, gradL2NormAbsoluteEpsSquared, gradL2NormRelativeEpsSquared, initialGradInfNorm, initialGradL2NormSquared, initialOFValue, iterationBound, iterationCounter, lowerOFBound, MBMesquite::NONE, patchInvertedCount, previousOFValue, qualityImprovementAbsoluteEps, qualityImprovementRelativeEps, successiveImprovementsAbsoluteEps, successiveImprovementsRelativeEps, terminationCriterionFlag, timeBound, vertexMovementAbsoluteAvgEdge, vertexMovementAbsoluteEps, vertexMovementAvgBeta, and vertexMovementRelativeEps.


Member Function Documentation

Accumulate data during inner iteration.

Definition at line 543 of file TerminationCriterion.cpp.

References MBMesquite::arrptr(), b, MBMesquite::OFEvaluator::evaluate(), MBMesquite::GRAD_FLAGS, MBMesquite::MsqError::INVALID_MESH, mGrad, MSQ_CHKERR, MSQ_ERRRTN, MSQ_SETERR, MBMesquite::PatchData::num_free_vertices(), MBMesquite::OF_FLAGS, and terminationCriterionFlag.

Referenced by accumulate_outer(), MBMesquite::NonGradient::evaluate(), MBMesquite::QuasiNewton::optimize_vertex_positions(), MBMesquite::TrustRegion::optimize_vertex_positions(), MBMesquite::ConjugateGradient::optimize_vertex_positions(), MBMesquite::SteepestDescent::optimize_vertex_positions(), MBMesquite::FeasibleNewton::optimize_vertex_positions(), TerminationCriterionTest::test_absolute_vertex_movement_edge_length(), TerminationCriterionTest::test_cpu_time_common(), TerminationCriterionTest::test_gradient_common(), TerminationCriterionTest::test_number_of_iterates_inner(), TerminationCriterionTest::test_quality_common(), TerminationCriterionTest::test_untangled_mesh(), TerminationCriterionTest::test_vertex_bound(), and TerminationCriterionTest::test_vertex_movement_common().

{
    double of_value = 0;

    if( terminationCriterionFlag & GRAD_FLAGS )
    {
        mGrad.resize( pd.num_free_vertices() );
        bool b = of_eval.evaluate( pd, of_value, mGrad, err );MSQ_ERRRTN( err );
        if( !b )
        {
            MSQ_SETERR( err )
            ( "Initial patch is invalid for gradient compuation.", MsqError::INVALID_MESH );
            return;
        }
    }
    else if( terminationCriterionFlag & OF_FLAGS )
    {
        bool b = of_eval.evaluate( pd, of_value, err );MSQ_ERRRTN( err );
        if( !b )
        {
            MSQ_SETERR( err )
            ( "Invalid patch passed to TerminationCriterion.", MsqError::INVALID_MESH );
            return;
        }
    }

    accumulate_inner( pd, of_value, mGrad.empty() ? 0 : arrptr( mGrad ), err );MSQ_CHKERR( err );
}
void MBMesquite::TerminationCriterion::accumulate_inner ( PatchData pd,
double  of_value,
Vector3D of_grads,
MsqError err 
)

Accumulate data during inner iteration.

Definition at line 572 of file TerminationCriterion.cpp.

References currentGradInfNorm, currentGradL2NormSquared, currentOFValue, debugLevel, MBMesquite::PatchData::get_max_vertex_movement_squared(), globalInvertedCount, MBMesquite::GRADIENT_INF_NORM_ABSOLUTE, MBMesquite::GRADIENT_INF_NORM_RELATIVE, MBMesquite::GRADIENT_L2_NORM_ABSOLUTE, MBMesquite::GRADIENT_L2_NORM_RELATIVE, initialVerticesMemento, iterationCounter, MBMesquite::length_squared(), MBMesquite::Linf(), maxSquaredInitialMovement, maxSquaredMovement, MSQ_DBGOUT_P0_ONLY, MSQ_ERRRTN, mTimer, MBMesquite::PatchData::num_free_vertices(), MBMesquite::OF_FLAGS, par_string(), plotFile, previousOFValue, RPM, MBMesquite::Timer::since_birth(), terminationCriterionFlag, timeStepFileType, MBMesquite::VERTEX_MOVEMENT_RELATIVE, and write_timestep().

{
    // if terminating on the norm of the gradient
    // currentGradL2NormSquared = HUGE_VAL;
    if( terminationCriterionFlag & ( GRADIENT_L2_NORM_ABSOLUTE | GRADIENT_L2_NORM_RELATIVE ) )
    {
        currentGradL2NormSquared = length_squared( grad_array, pd.num_free_vertices() );  // get the L2 norm
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o Info -- gradient L2 norm: "
                                         << " " << RPM( std::sqrt( currentGradL2NormSquared ) ) << std::endl;
    }
    // currentGradInfNorm = 10e6;
    if( terminationCriterionFlag & ( GRADIENT_INF_NORM_ABSOLUTE | GRADIENT_INF_NORM_RELATIVE ) )
    {
        currentGradInfNorm = Linf( grad_array, pd.num_free_vertices() );  // get the Linf norm
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o Info -- gradient Inf norm: "
                                         << " " << RPM( currentGradInfNorm ) << std::endl;
    }

    if( terminationCriterionFlag & VERTEX_MOVEMENT_RELATIVE )
    {
        maxSquaredInitialMovement = pd.get_max_vertex_movement_squared( initialVerticesMemento, err );MSQ_ERRRTN( err );
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o Info -- max initial vertex movement: "
                                         << " " << RPM( maxSquaredInitialMovement ) << std::endl;
    }

    previousOFValue = currentOFValue;
    currentOFValue  = of_value;
    if( terminationCriterionFlag & OF_FLAGS )
    {
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o Info -- OF Value: "
                                         << " " << RPM( of_value ) << " iterationCounter= " << iterationCounter
                                         << std::endl;
    }
    else if( grad_array )
    {
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o OF Value: "
                                         << " " << RPM( of_value ) << " iterationCounter= "
                                         << iterationCounter
                                         //<< " terminationCriterionFlag= " <<
                                         // terminationCriterionFlag << " OF_FLAGS = " << OF_FLAGS
                                         << std::endl;
    }

    ++iterationCounter;
    if( timeStepFileType ) write_timestep( pd, grad_array, err );

    if( plotFile.is_open() )
        plotFile << iterationCounter << '\t' << mTimer.since_birth() << '\t' << of_value << '\t'
                 << std::sqrt( currentGradL2NormSquared ) << '\t' << currentGradInfNorm << '\t'
                 << ( maxSquaredMovement > 0.0 ? std::sqrt( maxSquaredMovement ) : 0.0 ) << '\t' << globalInvertedCount
                 << std::endl;
}
void MBMesquite::TerminationCriterion::accumulate_outer ( Mesh ms,
MeshDomain dm,
OFEvaluator eval,
const Settings settings,
MsqError err 
)

Common code for both inner and outer termination criteria during inner iteration.

Definition at line 642 of file TerminationCriterion.cpp.

References MBMesquite::BOUNDED_VERTEX_MOVEMENT, boundedVertexMovementEps, count_inverted(), cullingMethodFlag, MBMesquite::PatchData::get_max_vertex_movement_squared(), MBMesquite::PatchData::get_vertex_array(), globalInvertedCount, maxSquaredMovement, MBMesquite::MOVEMENT_FLAGS, MSQ_ERRRTN, MBMesquite::PatchData::num_free_vertices(), patchInvertedCount, previousVerticesMemento, MBMesquite::PatchData::recreate_vertices_memento(), terminationCriterionFlag, MBMesquite::UNTANGLED_MESH, and vertexMovementExceedsBound.

Referenced by MBMesquite::VertexMover::loop_over_mesh(), MBMesquite::QuasiNewton::optimize_vertex_positions(), MBMesquite::TrustRegion::optimize_vertex_positions(), MBMesquite::ConjugateGradient::optimize_vertex_positions(), MBMesquite::SteepestDescent::optimize_vertex_positions(), MBMesquite::FeasibleNewton::optimize_vertex_positions(), TerminationCriterionTest::test_absolute_vertex_movement_edge_length(), TerminationCriterionTest::test_cpu_time_common(), TerminationCriterionTest::test_gradient_common(), TerminationCriterionTest::test_number_of_iterates_inner(), TerminationCriterionTest::test_number_of_iterates_outer(), TerminationCriterionTest::test_quality_common(), TerminationCriterionTest::test_untangled_mesh(), TerminationCriterionTest::test_vertex_bound(), and TerminationCriterionTest::test_vertex_movement_common().

{
    if( terminationCriterionFlag & MOVEMENT_FLAGS )
    {
        double patch_max_dist = pd.get_max_vertex_movement_squared( previousVerticesMemento, err );
        if( patch_max_dist > maxSquaredMovement ) maxSquaredMovement = patch_max_dist;
        pd.recreate_vertices_memento( previousVerticesMemento, err );MSQ_ERRRTN( err );
    }

    // if terminating on bounded vertex movement (a bounding box for the mesh)
    if( terminationCriterionFlag & BOUNDED_VERTEX_MOVEMENT )
    {
        const MsqVertex* vert = pd.get_vertex_array( err );
        int num_vert          = pd.num_free_vertices();
        int i                 = 0;
        // for each vertex
        for( i = 0; i < num_vert; ++i )
        {
            // if any of the coordinates are greater than eps
            if( ( vert[i][0] > boundedVertexMovementEps ) || ( vert[i][1] > boundedVertexMovementEps ) ||
                ( vert[i][2] > boundedVertexMovementEps ) )
            { ++vertexMovementExceedsBound; }
        }
    }

    if( ( terminationCriterionFlag | cullingMethodFlag ) & UNTANGLED_MESH )
    {
        size_t new_count = count_inverted( pd, err );
        // be careful here because size_t is unsigned
        globalInvertedCount += new_count;
        globalInvertedCount -= patchInvertedCount;
        patchInvertedCount = new_count;
        // if (innerOuterType==TYPE_OUTER)
        //  MSQ_DBGOUT_P0_ONLY(debugLevel) << par_string() << "  o Num Patch Inverted: " << " " <<
        //  patchInvertedCount << " globalInvertedCount= " << globalInvertedCount << std::endl;

        MSQ_ERRRTN( err );
    }
}

checks the gradient \(\nabla f \) of objective function \(f : I\!\!R^{3N} \rightarrow I\!\!R \) against a double \(d\) and stops when \( \max_{i=1}^{3N} \nabla f_i < d \)

Definition at line 197 of file TerminationCriterion.cpp.

References eps, MBMesquite::GRADIENT_INF_NORM_ABSOLUTE, gradInfNormAbsoluteEps, and terminationCriterionFlag.

Referenced by TerminationCriterionTest::test_gradient_common().

Calculates a constant \( \delta = \beta \times (a - \sigma) \) and terminates when the maximum vertex movement of an iteration is less than delta.

\( \beta \) is the passed value, \( a \) is the average edge length of the initial mesh and \( \sigma \) is the standard deviation of the edge lengths of the initial mesh. The initial mesh values are (re)calcualted for each time the instruction queue is run.

Parameters:
value\( beta \). Must be in range (0,1), exclusive.

Definition at line 234 of file TerminationCriterion.cpp.

References beta, terminationCriterionFlag, MBMesquite::VERTEX_MOVEMENT_ABS_EDGE_LENGTH, and vertexMovementAvgBeta.

Referenced by MBMesquite::ShapeImprover::run_wrapper(), MBMesquite::DeformingDomainWrapper::run_wrapper(), and TerminationCriterionTest::test_absolute_vertex_movement_edge_length().

Terminates when any vertex leaves the bounding box, defined by the given value, d. That is, when the absolute value of a single coordinate of vertex's position exceeds d.

Definition at line 271 of file TerminationCriterion.cpp.

References MBMesquite::BOUNDED_VERTEX_MOVEMENT, boundedVertexMovementEps, eps, and terminationCriterionFlag.

Referenced by TerminationCriterionTest::test_vertex_bound().

void MBMesquite::TerminationCriterion::add_iteration_limit ( unsigned int  max_iterations)

Terminates when the number of iterations exceeds a given integer.

Definition at line 265 of file TerminationCriterion.cpp.

References iterationBound, MBMesquite::NUMBER_OF_ITERATES, and terminationCriterionFlag.

Referenced by BCDTest::compare_bcd(), MBMesquite::ConjugateGradient::ConjugateGradient(), create_instruction_queue(), do_smoother(), MBMesquite::VertexMover::loop_over_mesh(), main(), MBMesquite::NonGradient::NonGradient(), MBMesquite::QualityImprover::QualityImprover(), run(), run_global_smoother(), run_local_smoother(), run_local_smoother2(), run_smoother(), run_solution_mesh_optimizer(), run_test(), MBMesquite::PaverMinEdgeLengthWrapper::run_wrapper(), MBMesquite::SizeAdaptShapeWrapper::run_wrapper(), MBMesquite::ViscousCFDTetShapeWrapper::run_wrapper(), MBMesquite::ShapeImprovementWrapper::run_wrapper(), ParShapeImprover::ParShapeImprovementWrapper::run_wrapper(), MBMesquite::DeformingDomainWrapper::run_wrapper(), smooth_mesh(), smooth_mixed_mesh(), TerminationCriterionTest::test_abs_vtx_movement_culling(), SphericalGeometryTest::test_cg_mesh_cond_sphere(), SphericalGeometryTest::test_lapl_geo_sphere(), VertexCullingRegressionTest::test_laplacian_smoothing_with_cull(), TerminationCriterionTest::test_number_of_iterates_inner(), TerminationCriterionTest::test_number_of_iterates_outer(), PlanarGeometryTest::test_plane_quad_tangled(), PlanarGeometryTest::test_plane_tri_tangled(), PlanarGeometryTest::test_plane_tri_xz(), and SphericalGeometryTest::test_smart_lapl_sphere().

terminates on the j_th iteration when \(\max_{i=1 \cdots 3N}\nabla f_{i,j}<d \max_{i=1 \cdots 3N}\nabla f_{i,0}\) That is, terminates when the norm of the gradient is small than some scaling factor times the norm of the original gradient. (Using the infinity norm.)

Definition at line 209 of file TerminationCriterion.cpp.

References eps, MBMesquite::GRADIENT_INF_NORM_RELATIVE, gradInfNormRelativeEps, and terminationCriterionFlag.

Referenced by TerminationCriterionTest::test_gradient_common().

terminates on the j_th iteration when \(\sqrt{\sum_{i=1}^{3N}\nabla f_{i,j}^2}<d\sqrt{\sum_{i=1}^{3N}\nabla f_{i,0}^2}\) That is, terminates when the norm of the gradient is smaller than the specified fraction of the initial norm of the gradient.

Definition at line 203 of file TerminationCriterion.cpp.

References eps, MBMesquite::GRADIENT_L2_NORM_RELATIVE, gradL2NormRelativeEpsSquared, and terminationCriterionFlag.

Referenced by TerminationCriterionTest::test_gradient_common().

Terminates when the objective function value is smaller than the given scalar value times the original objective function value.

Definition at line 221 of file TerminationCriterion.cpp.

References eps, MBMesquite::QUALITY_IMPROVEMENT_RELATIVE, qualityImprovementRelativeEps, and terminationCriterionFlag.

Referenced by main(), smooth_mixed_mesh(), and TerminationCriterionTest::test_quality_common().

Terminates when the decrease in the objective function value since the previous iteration is below the given value times the decrease in the objective function value since the beginning of this optimization process.

Definition at line 253 of file TerminationCriterion.cpp.

References eps, MBMesquite::SUCCESSIVE_IMPROVEMENTS_RELATIVE, successiveImprovementsRelativeEps, and terminationCriterionFlag.

Referenced by MBMesquite::ShapeImprovementWrapper::run_wrapper(), and TerminationCriterionTest::test_quality_common().

Terminates when a the maximum distance moved by any vertex during the previous iteration is below the given value times the maximum distance moved by any vertex over the entire course of the optimization.

Definition at line 240 of file TerminationCriterion.cpp.

References eps, terminationCriterionFlag, MBMesquite::VERTEX_MOVEMENT_RELATIVE, and vertexMovementRelativeEps.

Referenced by TerminationCriterionTest::test_vertex_movement_common().

{
    terminationCriterionFlag |= VERTEX_MOVEMENT_RELATIVE;
    // we actually compare squared movement to squared epsilon
    vertexMovementRelativeEps = ( eps * eps );
}

Terminates when the mesh is detected to be untangled. Uses the same approach as QualityAssessor, checks the tau values at all the sample points.

Definition at line 277 of file TerminationCriterion.cpp.

References terminationCriterionFlag, and MBMesquite::UNTANGLED_MESH.

Referenced by TerminationCriterionTest::test_untangled_mesh().

void MBMesquite::TerminationCriterion::cleanup ( Mesh ms,
MeshDomain domain,
MsqError err 
)

Cleans up after the TerminationCriterion is finished.

Currently this only deletes the memento of the vertex positions and the mGrad vector if neccessary. When culling, we remove the soft fixed flags from all of the vertices.

Definition at line 1093 of file TerminationCriterion.cpp.

References initialVerticesMemento, and previousVerticesMemento.

Referenced by MBMesquite::VertexMover::loop_over_mesh().

size_t MBMesquite::TerminationCriterion::count_inverted ( PatchData pd,
MsqError err 
) [static, protected]

Definition at line 1075 of file TerminationCriterion.cpp.

References MBMesquite::MsqMeshEntity::check_element_orientation(), MBMesquite::PatchData::element_by_index(), and MBMesquite::PatchData::num_elements().

Referenced by accumulate_patch(), reset_inner(), and reset_patch().

{
    size_t num_elem = pd.num_elements();
    size_t count    = 0;
    int inverted, samples;
    for( size_t i = 0; i < num_elem; i++ )
    {
        pd.element_by_index( i ).check_element_orientation( pd, inverted, samples, err );
        if( inverted ) ++count;
    }
    return count;
}

Check if at least one termination criterion is set.

Definition at line 876 of file TerminationCriterion.cpp.

References terminationCriterionFlag.

Referenced by MBMesquite::VertexMover::loop_over_mesh().

{
    if( !terminationCriterionFlag )
        return false;
    else
        return true;
}

Cull for a global patch - sets soft fixed flags for vertices that touch elements that are culled by above flags.

Definition at line 332 of file TerminationCriterion.cpp.

References cullingGlobalPatch.

{
    cullingGlobalPatch = val;
}

Cull when the objective function value is smaller than the given scalar value.

Definition at line 287 of file TerminationCriterion.cpp.

References cullingEps, cullingMethodFlag, and MBMesquite::QUALITY_IMPROVEMENT_ABSOLUTE.

Cull when the decrease in the objective function value since the previous iteration is below the given value.

Definition at line 312 of file TerminationCriterion.cpp.

References cullingEps, cullingMethodFlag, and MBMesquite::SUCCESSIVE_IMPROVEMENTS_ABSOLUTE.

Cull when a the maximum distance moved by any vertex during the previous iteration is below the given value.

Definition at line 297 of file TerminationCriterion.cpp.

References cullingEps, cullingMethodFlag, and MBMesquite::VERTEX_MOVEMENT_ABSOLUTE.

Referenced by TerminationCriterionTest::test_abs_vtx_movement_culling(), and VertexCullingRegressionTest::test_laplacian_smoothing_with_cull().

Calculates a constant \( \delta = \beta \times (a - \sigma) \) and culls when the vertex movement is less than delta.

\( \beta \) is the passed value, \( a \) is the average edge length of the initial mesh and \( \sigma \) is the standard deviation of the edge lengths of the initial mesh. The initial mesh values are (re)calcualted for each time the instruction queue is run.

Parameters:
value\( beta \). Must be in range (0,1), exclusive.

Definition at line 307 of file TerminationCriterion.cpp.

References cullingMethodFlag, MBMesquite::VERTEX_MOVEMENT_ABS_EDGE_LENGTH, and vertexMovementAvgBeta.

Referenced by MBMesquite::LaplaceWrapper::run_wrapper(), and MBMesquite::DeformingDomainWrapper::run_wrapper().

Cull when the objective function value is smaller than the given scalar value times the original objective function value.

Definition at line 292 of file TerminationCriterion.cpp.

References cullingEps, cullingMethodFlag, and MBMesquite::QUALITY_IMPROVEMENT_RELATIVE.

Cull when the decrease in the objective function value since the previous iteration is below the given value times the decrease in the objective function value since the beginning of this optimization process.

Definition at line 317 of file TerminationCriterion.cpp.

References cullingEps, cullingMethodFlag, and MBMesquite::SUCCESSIVE_IMPROVEMENTS_RELATIVE.

Cull when a the maximum distance moved by any vertex during the previous iteration is below the given value times the maximum distance moved by any vertex over the entire course of the optimization.

Definition at line 302 of file TerminationCriterion.cpp.

References cullingEps, cullingMethodFlag, and MBMesquite::VERTEX_MOVEMENT_RELATIVE.

Cull when the mesh is detected to be untangled. Uses the same approach as QualityAssessor, checks the tau values at all the sample points.

Definition at line 322 of file TerminationCriterion.cpp.

References cullingMethodFlag, and MBMesquite::UNTANGLED_MESH.

Function which determines whether this patch should be 'culled'.

This function checks the culling method criterion supplied to the object by the user. If the user does not supply a culling method criterion, the default criterion is NONE, and in that case, no culling is performed. If the culling method criterion is satisfied, the interior vertices of the given patch are flagged as soft_fixed. Otherwise, the soft_fixed flag is removed from each of the vertices in the patch (interior and boundary vertices). Also, if the criterion was satisfied, then the function returns true. Otherwise, the function returns false.

Definition at line 893 of file TerminationCriterion.cpp.

References b, cullingEps, cullingMethodFlag, currentOFValue, MBMesquite::OFEvaluator::evaluate(), MBMesquite::PatchData::get_max_vertex_movement_squared(), initialOFValue, initialVerticesMemento, MBMesquite::MsqError::INVALID_MESH, lowerOFBound, MSQ_CHKERR, MSQ_ERRZERO, MSQ_SETERR, MBMesquite::NONE, NOT_IMPLEMENTED, patchInvertedCount, previousVerticesMemento, MBMesquite::QUALITY_IMPROVEMENT_ABSOLUTE, MBMesquite::QUALITY_IMPROVEMENT_RELATIVE, MBMesquite::PatchData::set_all_vertices_soft_free(), MBMesquite::PatchData::set_free_vertices_soft_fixed(), MBMesquite::UNTANGLED_MESH, MBMesquite::VERTEX_MOVEMENT_ABS_EDGE_LENGTH, MBMesquite::VERTEX_MOVEMENT_ABSOLUTE, and MBMesquite::VERTEX_MOVEMENT_RELATIVE.

Referenced by cull_vertices_global(), and MBMesquite::VertexMover::loop_over_mesh().

{
    // PRINT_INFO("CULLING_METHOD FLAG = %i",cullingMethodFlag);

    // cull_bool will be changed to true if the criterion is satisfied
    bool b, cull_bool = false;
    double prev_m, init_m;
    switch( cullingMethodFlag )
    {
            // if no culling is requested, always return false
        case NONE:
            return cull_bool;
            // if culling on quality improvement absolute
        case QUALITY_IMPROVEMENT_ABSOLUTE:
            // get objective function value
            b = of_eval.evaluate( pd, currentOFValue, err );
            if( MSQ_CHKERR( err ) ) return false;
            if( !b )
            {
                MSQ_SETERR( err )( MsqError::INVALID_MESH );
                return false;
            }
            // if the improvement was enough, cull
            if( currentOFValue <= cullingEps ) { cull_bool = true; }
            // PRINT_INFO("\ncurrentOFValue = %f, bool = %i\n",currentOFValue,cull_bool);

            break;
            // if culing on quality improvement relative
        case QUALITY_IMPROVEMENT_RELATIVE:
            // get objective function value
            b = of_eval.evaluate( pd, currentOFValue, err );
            if( MSQ_CHKERR( err ) ) return false;
            if( !b )
            {
                MSQ_SETERR( err )( MsqError::INVALID_MESH );
                return false;
            }
            // if the improvement was enough, cull
            if( ( currentOFValue - lowerOFBound ) <= ( cullingEps * ( initialOFValue - lowerOFBound ) ) )
            { cull_bool = true; }
            break;
            // if culling on vertex movement absolute
        case VERTEX_MOVEMENT_ABSOLUTE:
        case VERTEX_MOVEMENT_ABS_EDGE_LENGTH:
            // if movement was enough, cull
            prev_m = pd.get_max_vertex_movement_squared( previousVerticesMemento, err );
            MSQ_ERRZERO( err );
            if( prev_m <= cullingEps * cullingEps ) { cull_bool = true; }

            break;
            // if culling on vertex movement relative
        case VERTEX_MOVEMENT_RELATIVE:
            // if movement was small enough, cull
            prev_m = pd.get_max_vertex_movement_squared( previousVerticesMemento, err );
            MSQ_ERRZERO( err );
            init_m = pd.get_max_vertex_movement_squared( initialVerticesMemento, err );
            MSQ_ERRZERO( err );
            if( prev_m <= ( cullingEps * cullingEps * init_m ) ) { cull_bool = true; }
            break;
        case UNTANGLED_MESH:
            if( !patchInvertedCount ) cull_bool = true;
            break;
        default:
            MSQ_SETERR( err )
            ( "Requested culling method not yet implemented.", MsqError::NOT_IMPLEMENTED );
            return false;
    };
    // Now actually have patch data cull vertices
    if( cull_bool )
    {
        pd.set_free_vertices_soft_fixed( err );
        MSQ_ERRZERO( err );
    }
    else
    {
        pd.set_all_vertices_soft_free( err );
        MSQ_ERRZERO( err );
    }
    return cull_bool;
}
bool MBMesquite::TerminationCriterion::cull_vertices_global ( PatchData global_patch,
Mesh mesh,
MeshDomain domain,
const Settings settings,
OFEvaluator of_eval,
MsqError err 
)

experimental, first cut at culling for global patches - not finished

This function is activated when cullingGlobalPatch is true. It supplies cull_vertices with a single vertex-based patch at a time. If the patch satisfies the culling criterion, it's free vertices are then soft-fixed.

Definition at line 978 of file TerminationCriterion.cpp.

References MBMesquite::PatchData::attach_settings(), cull_vertices(), cullingGlobalPatch, MBMesquite::Mesh::elements_get_attached_vertices(), MBMesquite::Mesh::get_all_vertices(), MBMesquite::PatchData::get_vertex_array(), MBMesquite::PatchData::get_vertex_handles_array(), ie, MBMesquite::MsqVertex::is_free_vertex(), MBMesquite::MsqVertex::MSQ_CULLED, MBMesquite::PatchData::num_nodes(), MBMesquite::PatchData::set_domain(), MBMesquite::MsqVertex::set_flags(), MBMesquite::PatchData::set_mesh(), MBMesquite::PatchData::set_mesh_entities(), MBMesquite::PatchData::set_vertex_culled(), MBMesquite::Mesh::vertex_get_byte(), and MBMesquite::Mesh::vertices_get_attached_elements().

Referenced by MBMesquite::VertexMover::loop_over_mesh().

{
    if( !cullingGlobalPatch ) return false;

    // PRINT_INFO("CULLING_METHOD FLAG = %i",cullingMethodFlag);

    // cull_bool will be changed to true if the criterion is satisfied
    bool cull_bool = false;

    std::vector< Mesh::VertexHandle > mesh_vertices;
    // std::vector<Mesh::VertexHandle> patch_vertices;
    // std::vector<Mesh::ElementHandle> patch_elements;
    // std::vector<Mesh::VertexHandle> fixed_vertices;
    // std::vector<Mesh::VertexHandle> free_vertices;

    // FIXME, verify global_patch is a global patch... how, is this right?
    mesh->get_all_vertices( mesh_vertices, err );
    size_t mesh_num_nodes         = mesh_vertices.size();
    size_t global_patch_num_nodes = global_patch.num_nodes();
    if( 0 )
        std::cout << "tmp srk mesh_num_nodes= " << mesh_num_nodes
                  << " global_patch_num_nodes= " << global_patch_num_nodes << std::endl;
    if( mesh_num_nodes != global_patch_num_nodes )
    {
        std::cout << "tmp srk cull_vertices_global found non global patch" << std::endl;
        exit( 123 );
        return false;
    }
    PatchData patch;
    patch.set_mesh( (Mesh*)mesh );
    patch.set_domain( domain );
    patch.attach_settings( settings );

    // const MsqVertex* global_patch_vertex_array = global_patch.get_vertex_array( err );
    Mesh::VertexHandle* global_patch_vertex_handles = global_patch.get_vertex_handles_array();

    int num_culled = 0;
    for( unsigned iv = 0; iv < global_patch_num_nodes; iv++ )
    {
        // form a patch for this vertex; if it is culled, set it to be soft fixed
        Mesh::VertexHandle vert = global_patch_vertex_handles[iv];
        std::vector< Mesh::ElementHandle > elements;
        std::vector< size_t > offsets;
        mesh->vertices_get_attached_elements( &vert, 1, elements, offsets, err );

        std::set< Mesh::VertexHandle > patch_free_vertices_set;

        for( unsigned ie = 0; ie < elements.size(); ie++ )
        {
            std::vector< Mesh::VertexHandle > vert_handles;
            std::vector< size_t > v_offsets;
            mesh->elements_get_attached_vertices( &elements[ie], 1, vert_handles, v_offsets, err );
            for( unsigned jv = 0; jv < vert_handles.size(); jv++ )
            {
                unsigned char bt;
                mesh->vertex_get_byte( vert_handles[jv], &bt, err );
                MsqVertex v;
                v.set_flags( bt );
                if( v.is_free_vertex() ) patch_free_vertices_set.insert( vert_handles[jv] );
            }
        }

        std::vector< Mesh::VertexHandle > patch_free_vertices_vector( patch_free_vertices_set.begin(),
                                                                      patch_free_vertices_set.end() );
        // std::vector<unsigned char> byte_vector(patch_vertices_vector.size());
        // mesh->vertices_get_byte(&vert_handles[0], &byte_vector[0], vert_handles.size(), err);

        patch.set_mesh_entities( elements, patch_free_vertices_vector, err );
        if( cull_vertices( patch, of_eval, err ) )
        {
            // std::cout << "tmp srk cull_vertices_global found culled patch" << std::endl;
            Mesh::VertexHandle* patch_vertex_handles = patch.get_vertex_handles_array();
            const MsqVertex* patch_vertex_array      = patch.get_vertex_array( err );
            for( unsigned jv = 0; jv < patch.num_nodes(); jv++ )
            {
                if( patch_vertex_handles[jv] == global_patch_vertex_handles[iv] )
                {
                    if( patch_vertex_array[jv].is_flag_set( MsqVertex::MSQ_CULLED ) )
                    {
                        global_patch.set_vertex_culled( iv );
                        ++num_culled;
                        cull_bool = true;
                        // std::cout << "tmp srk cull_vertices_global found culled vertex" <<
                        // std::endl;
                    }
                }
            }
        }
    }
    if( 0 )
        std::cout << "tmp srk cull_vertices_global found " << num_culled << " culled vertices out of "
                  << global_patch_num_nodes << std::endl;

    return cull_bool;
}

This function returns the current function value.

Todo:
Michael: this function is not reliable. It needs to be more robust. How do we know whether currentOFValue got updated or not? We may want to make sure that all the criteria get checked.

Definition at line 272 of file TerminationCriterion.hpp.

References currentOFValue.

    {
        return currentOFValue;
    }
std::string MBMesquite::TerminationCriterion::par_string ( ) [protected]

Definition at line 180 of file TerminationCriterion.cpp.

References MBMesquite::get_parallel_rank(), MBMesquite::get_parallel_size(), and moniker.

Referenced by accumulate_inner(), reset_inner(), and terminate().

{
    if( get_parallel_size() )
    {
        std::ostringstream str;
        str << "P[" << get_parallel_rank() << "] " + moniker + " ";
        return str.str();
    }
    return moniker + " ";
}

Clear any data accumulated during an inner iteration.

Reset function using using a PatchData object. This function is called for the inner-stopping criterion directly from the loop over mesh function in VertexMover. For outer criterion, it is called from the reset function which takes a MeshSet object. This function prepares the object to be used by setting the initial values of some of the data members. As examples, if needed, it resets the cpu timer to zero, the iteration counter to zero, and the initial and previous objective function values to the current objective function value for this patch. The return value for this function is similar to that of terminate(). The function returns false if the checked criteria have not been satisfied, and true if they have been. reset() only checks the GRADIENT_INF_NORM_ABSOLUTE, GRADIENT_L2_NORM_ABSOLUTE, and the QUALITY_IMPROVEMENT_ABSOLUTE criteria. Checking these criteria allows the QualityImprover to skip the entire optimization if the initial mesh satisfies the appropriate conditions.

Definition at line 377 of file TerminationCriterion.cpp.

References MBMesquite::arrptr(), b, MBMesquite::MsqError::clear(), count_inverted(), MBMesquite::CPU_TIME, MBMesquite::PatchData::create_vertices_memento(), cullingMethodFlag, currentGradInfNorm, currentGradL2NormSquared, currentOFValue, debugLevel, MBMesquite::OFEvaluator::evaluate(), globalInvertedCount, MBMesquite::GRAD_FLAGS, MBMesquite::GRADIENT_INF_NORM_ABSOLUTE, MBMesquite::GRADIENT_INF_NORM_RELATIVE, MBMesquite::GRADIENT_L2_NORM_ABSOLUTE, MBMesquite::GRADIENT_L2_NORM_RELATIVE, MBMesquite::OFEvaluator::have_objective_function(), initialGradInfNorm, initialGradL2NormSquared, initialOFValue, initialVerticesMemento, MBMesquite::MsqError::INVALID_STATE, iterationCounter, MBMesquite::length_squared(), MBMesquite::Linf(), maxSquaredInitialMovement, maxSquaredMovement, mGrad, MSQ_DBGOUT_P0_ONLY, MSQ_ERRRTN, MSQ_SETERR, mTimer, MBMesquite::PatchData::num_free_vertices(), MBMesquite::OF_FLAGS, par_string(), patchInvertedCount, plotFile, previousOFValue, MBMesquite::PatchData::recreate_vertices_memento(), MBMesquite::Timer::reset(), RPM, MBMesquite::Timer::since_birth(), terminationCriterionFlag, timeStepFileType, MBMesquite::UNTANGLED_MESH, MBMesquite::VERTEX_MOVEMENT_RELATIVE, vertexMovementExceedsBound, and write_timestep().

Referenced by MBMesquite::VertexMover::loop_over_mesh(), reset_outer(), TerminationCriterionTest::test_absolute_vertex_movement_edge_length(), TerminationCriterionTest::test_cpu_time_common(), TerminationCriterionTest::test_gradient_common(), TerminationCriterionTest::test_number_of_iterates_inner(), TerminationCriterionTest::test_quality_common(), TerminationCriterionTest::test_untangled_mesh(), TerminationCriterionTest::test_vertex_bound(), and TerminationCriterionTest::test_vertex_movement_common().

{
    const unsigned long totalFlag = terminationCriterionFlag | cullingMethodFlag;

    // clear flag for BOUNDED_VERTEX_MOVEMENT
    vertexMovementExceedsBound = 0;

    // Use -1 to denote that this isn't initialized yet.
    // As all valid values must be >= 0.0, a negative
    // value indicates that it is uninitialized and is
    // always less than any valid value.
    maxSquaredMovement = -1;

    // Clear the iteration count.
    iterationCounter = 0;

    // reset the inner timer if needed
    if( totalFlag & CPU_TIME ) { mTimer.reset(); }

    // GRADIENT
    currentGradInfNorm = initialGradInfNorm = 0.0;
    currentGradL2NormSquared = initialGradL2NormSquared = 0.0;
    if( totalFlag & GRAD_FLAGS )
    {
        if( !obj_eval.have_objective_function() )
        {
            MSQ_SETERR( err )
            ( "Error termination criteria set which uses objective "
              "functions, but no objective function is available.",
              MsqError::INVALID_STATE );
            return;
        }
        int num_vertices = pd.num_free_vertices();
        mGrad.resize( num_vertices );

        // get gradient and make sure it is valid
        bool b = obj_eval.evaluate( pd, currentOFValue, mGrad, err );MSQ_ERRRTN( err );
        if( !b )
        {
            MSQ_SETERR( err )
            ( "Initial patch is invalid for gradient computation.", MsqError::INVALID_STATE );
            return;
        }

        // get the gradient norms
        if( totalFlag & ( GRADIENT_INF_NORM_ABSOLUTE | GRADIENT_INF_NORM_RELATIVE ) )
        {
            currentGradInfNorm = initialGradInfNorm = Linf( mGrad );
            MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o Initial gradient Inf norm: "
                                             << " " << RPM( initialGradInfNorm ) << std::endl;
        }

        if( totalFlag & ( GRADIENT_L2_NORM_ABSOLUTE | GRADIENT_L2_NORM_RELATIVE ) )
        {
            currentGradL2NormSquared = initialGradL2NormSquared = length_squared( mGrad );
            MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o Initial gradient L2 norm: "
                                             << " " << RPM( std::sqrt( initialGradL2NormSquared ) ) << std::endl;
        }

        // the OFvalue comes for free, so save it
        previousOFValue = currentOFValue;
        initialOFValue  = currentOFValue;
    }
    // find the initial objective function value if needed and not already
    // computed.  If we needed the gradient, we have the OF value for free.
    // Also, if possible, get initial OF value if writing plot file.  Solvers
    // often supply the OF value for subsequent iterations so by calculating
    // the initial value we can generate OF value plots.
    else if( ( totalFlag & OF_FLAGS ) ||
             ( plotFile.is_open() && pd.num_free_vertices() && obj_eval.have_objective_function() ) )
    {
        // ensure the obj_ptr is not null
        if( !obj_eval.have_objective_function() )
        {
            MSQ_SETERR( err )
            ( "Error termination criteria set which uses objective "
              "functions, but no objective function is available.",
              MsqError::INVALID_STATE );
            return;
        }

        bool b = obj_eval.evaluate( pd, currentOFValue, err );MSQ_ERRRTN( err );
        if( !b )
        {
            MSQ_SETERR( err )
            ( "Initial patch is invalid for evaluation.", MsqError::INVALID_STATE );
            return;
        }
        // std::cout<<"\nReseting initial of value = "<<initialOFValue;
        previousOFValue = currentOFValue;
        initialOFValue  = currentOFValue;
    }

    if( totalFlag & ( GRAD_FLAGS | OF_FLAGS ) )
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o Initial OF value: "
                                         << " " << RPM( initialOFValue ) << std::endl;

    // Store current vertex locations now, because we'll
    // need them later to compare the current movement with.
    if( totalFlag & VERTEX_MOVEMENT_RELATIVE )
    {
        if( initialVerticesMemento ) { pd.recreate_vertices_memento( initialVerticesMemento, err ); }
        else
        {
            initialVerticesMemento = pd.create_vertices_memento( err );
        }
        MSQ_ERRRTN( err );
        maxSquaredInitialMovement = DBL_MAX;
    }
    else
    {
        maxSquaredInitialMovement = 0;
    }

    if( terminationCriterionFlag & UNTANGLED_MESH )
    {
        globalInvertedCount = count_inverted( pd, err );
        // if (innerOuterType==TYPE_OUTER) MSQ_DBGOUT_P0_ONLY(debugLevel) << par_string() << "  o
        // Num Inverted: " << " " << globalInvertedCount << std::endl;
        patchInvertedCount = 0;MSQ_ERRRTN( err );
    }

    if( timeStepFileType )
    {
        // If didn't already calculate gradient abive, calculate it now.
        if( !( totalFlag & GRAD_FLAGS ) )
        {
            mGrad.resize( pd.num_free_vertices() );
            obj_eval.evaluate( pd, currentOFValue, mGrad, err );
            err.clear();
        }
        write_timestep( pd, mGrad.empty() ? 0 : arrptr( mGrad ), err );
    }

    if( plotFile.is_open() )
    {
        // two newlines so GNU plot knows that we are starting a new data set
        plotFile << std::endl << std::endl;
        // write column headings as comment in data file
        plotFile << "#Iter\tCPU\tObjFunc\tGradL2\tGradInf\tMovement\tInverted" << std::endl;
        // write initial values
        plotFile << 0 << '\t' << mTimer.since_birth() << '\t' << initialOFValue << '\t'
                 << std::sqrt( currentGradL2NormSquared ) << '\t' << currentGradInfNorm << '\t' << 0.0 << '\t'
                 << globalInvertedCount << std::endl;
    }
}
void MBMesquite::TerminationCriterion::reset_outer ( Mesh mesh,
MeshDomain domain,
OFEvaluator obj_eval,
const Settings settings,
MsqError err 
)

Clear any data accumulated during an outer iteration.

This version of reset is called using a MeshSet, which implies it is only called when this criterion is used as the 'outer' termination criterion.

Definition at line 341 of file TerminationCriterion.cpp.

References MBMesquite::PatchData::attach_settings(), cullingMethodFlag, MBMesquite::PatchData::fill_global_patch(), MBMesquite::GRAD_FLAGS, MSQ_ERRRTN, MBMesquite::OF_FLAGS, reset_inner(), MBMesquite::PatchData::set_domain(), MBMesquite::PatchData::set_mesh(), terminationCriterionFlag, timeStepFileType, MBMesquite::UNTANGLED_MESH, and MBMesquite::VERTEX_MOVEMENT_RELATIVE.

Referenced by MBMesquite::VertexMover::loop_over_mesh(), TerminationCriterionTest::test_cpu_time_common(), and TerminationCriterionTest::test_number_of_iterates_outer().

{
    const unsigned long totalFlag = terminationCriterionFlag | cullingMethodFlag;
    PatchData global_patch;
    if( settings ) global_patch.attach_settings( settings );

    // if we need to fill out the global patch data object.
    if( ( totalFlag & ( GRAD_FLAGS | OF_FLAGS | VERTEX_MOVEMENT_RELATIVE | UNTANGLED_MESH ) ) || timeStepFileType )
    {
        global_patch.set_mesh( mesh );
        global_patch.set_domain( domain );
        global_patch.fill_global_patch( err );MSQ_ERRRTN( err );
    }

    // now call the other reset
    reset_inner( global_patch, obj_eval, err );MSQ_ERRRTN( err );
}

Check if termination criterion has been met.

This function evaluates the needed information and then evaluates the termination criteria. If any of the selected criteria are satisfied, the function returns true. Otherwise, the function returns false.

Definition at line 686 of file TerminationCriterion.cpp.

References MBMesquite::BOUNDED_VERTEX_MOVEMENT, MBMesquite::CPU_TIME, currentGradInfNorm, currentGradL2NormSquared, currentOFValue, debugLevel, MBMesquite::get_parallel_rank(), globalInvertedCount, GNUPLOT, MBMesquite::GRADIENT_INF_NORM_ABSOLUTE, MBMesquite::GRADIENT_INF_NORM_RELATIVE, MBMesquite::GRADIENT_L2_NORM_ABSOLUTE, MBMesquite::GRADIENT_L2_NORM_RELATIVE, gradInfNormAbsoluteEps, gradInfNormRelativeEps, gradL2NormAbsoluteEpsSquared, gradL2NormRelativeEpsSquared, initialGradInfNorm, initialGradL2NormSquared, initialOFValue, innerOuterType, MBMesquite::MsqInterrupt::interrupt(), iterationBound, iterationCounter, lowerOFBound, maxSquaredInitialMovement, maxSquaredMovement, moniker, MBMesquite::MOVEMENT_FLAGS, MSQ_DBG, MSQ_DBGOUT, MSQ_DBGOUT_P0_ONLY, mTimer, MBMesquite::NUMBER_OF_ITERATES, par_string(), previousOFValue, MBMesquite::QUALITY_IMPROVEMENT_ABSOLUTE, MBMesquite::QUALITY_IMPROVEMENT_RELATIVE, qualityImprovementAbsoluteEps, qualityImprovementRelativeEps, RPM, MBMesquite::Timer::since_birth(), MBMesquite::SUCCESSIVE_IMPROVEMENTS_ABSOLUTE, MBMesquite::SUCCESSIVE_IMPROVEMENTS_RELATIVE, successiveImprovementsAbsoluteEps, successiveImprovementsRelativeEps, terminationCriterionFlag, timeBound, timeStepFileName, timeStepFileType, TYPE_OUTER, MBMesquite::UNTANGLED_MESH, MBMesquite::VERTEX_MOVEMENT_ABS_EDGE_LENGTH, MBMesquite::VERTEX_MOVEMENT_ABSOLUTE, MBMesquite::VERTEX_MOVEMENT_RELATIVE, vertexMovementAbsoluteAvgEdge, vertexMovementAbsoluteEps, vertexMovementExceedsBound, vertexMovementRelativeEps, and MBMesquite::MeshWriter::write_gnuplot_overlay().

Referenced by MBMesquite::VertexMover::loop_over_mesh(), MBMesquite::QuasiNewton::optimize_vertex_positions(), MBMesquite::TrustRegion::optimize_vertex_positions(), MBMesquite::ConjugateGradient::optimize_vertex_positions(), MBMesquite::SteepestDescent::optimize_vertex_positions(), MBMesquite::FeasibleNewton::optimize_vertex_positions(), MBMesquite::NonGradient::optimize_vertex_positions(), TerminationCriterionTest::test_absolute_vertex_movement_edge_length(), TerminationCriterionTest::test_cpu_time_common(), TerminationCriterionTest::test_gradient_common(), TerminationCriterionTest::test_number_of_iterates_inner(), TerminationCriterionTest::test_number_of_iterates_outer(), TerminationCriterionTest::test_quality_common(), TerminationCriterionTest::test_untangled_mesh(), TerminationCriterionTest::test_vertex_bound(), and TerminationCriterionTest::test_vertex_movement_common().

{
    bool return_flag = false;
    // std::cout<<"\nInside terminate(pd,of,err):  flag = "<<terminationCriterionFlag << std::endl;
    int type = 0;

    // First check for an interrupt signal
    if( MsqInterrupt::interrupt() )
    {
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- INTERRUPTED"
                                         << " " << std::endl;
        return true;
    }

    // if terminating on numbering of inner iterations
    if( NUMBER_OF_ITERATES & terminationCriterionFlag && iterationCounter >= iterationBound )
    {
        return_flag = true;
        type        = 1;
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- Reached "
                                         << " " << iterationBound << " iterations." << std::endl;
    }

    if( CPU_TIME & terminationCriterionFlag && mTimer.since_birth() >= timeBound )
    {
        return_flag = true;
        type        = 2;
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- Exceeded CPU time. "
                                         << " " << std::endl;
    }

    if( MOVEMENT_FLAGS & terminationCriterionFlag && maxSquaredMovement >= 0.0 )
    {
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o Info -- Maximum vertex movement: "
                                         << " " << RPM( sqrt( maxSquaredMovement ) ) << std::endl;

        if( VERTEX_MOVEMENT_ABSOLUTE & terminationCriterionFlag && maxSquaredMovement <= vertexMovementAbsoluteEps )
        {
            MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- VERTEX_MOVEMENT_ABSOLUTE: "
                                             << " " << RPM( sqrt( maxSquaredMovement ) ) << std::endl;
            return_flag = true;
            type        = 3;
        }

        if( VERTEX_MOVEMENT_RELATIVE & terminationCriterionFlag &&
            maxSquaredMovement <= vertexMovementRelativeEps * maxSquaredInitialMovement )
        {
            MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- VERTEX_MOVEMENT_RELATIVE: "
                                             << " " << RPM( sqrt( maxSquaredMovement ) ) << std::endl;
            return_flag = true;
            type        = 4;
        }

        if( VERTEX_MOVEMENT_ABS_EDGE_LENGTH & terminationCriterionFlag )
        {
            assert( vertexMovementAbsoluteAvgEdge > -1e-12 );  // make sure value actually got calculated
            if( maxSquaredMovement <= vertexMovementAbsoluteAvgEdge )
            {
                MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- VERTEX_MOVEMENT_ABS_EDGE_LENGTH: "
                                                 << " " << RPM( sqrt( maxSquaredMovement ) ) << std::endl;
                return_flag = true;
                type        = 5;
            }
        }
    }

    if( GRADIENT_L2_NORM_ABSOLUTE & terminationCriterionFlag &&
        currentGradL2NormSquared <= gradL2NormAbsoluteEpsSquared )
    {
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- GRADIENT_L2_NORM_ABSOLUTE: "
                                         << " " << RPM( currentGradL2NormSquared ) << std::endl;
        return_flag = true;
        type        = 6;
    }

    if( GRADIENT_INF_NORM_ABSOLUTE & terminationCriterionFlag && currentGradInfNorm <= gradInfNormAbsoluteEps )
    {
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- GRADIENT_INF_NORM_ABSOLUTE: "
                                         << " " << RPM( currentGradInfNorm ) << std::endl;
        return_flag = true;
        type        = 7;
    }

    if( GRADIENT_L2_NORM_RELATIVE & terminationCriterionFlag &&
        currentGradL2NormSquared <= ( gradL2NormRelativeEpsSquared * initialGradL2NormSquared ) )
    {
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- GRADIENT_L2_NORM_RELATIVE: "
                                         << " " << RPM( currentGradL2NormSquared ) << std::endl;
        return_flag = true;
        type        = 8;
    }

    if( GRADIENT_INF_NORM_RELATIVE & terminationCriterionFlag &&
        currentGradInfNorm <= ( gradInfNormRelativeEps * initialGradInfNorm ) )
    {
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- GRADIENT_INF_NORM_RELATIVE: "
                                         << " " << RPM( currentGradInfNorm ) << std::endl;
        return_flag = true;
        type        = 9;
    }
    // Quality Improvement and Successive Improvements are below.
    // The relative forms are only valid after the first iteration.
    if( ( QUALITY_IMPROVEMENT_ABSOLUTE & terminationCriterionFlag ) && currentOFValue <= qualityImprovementAbsoluteEps )
    {
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- QUALITY_IMPROVEMENT_ABSOLUTE: "
                                         << " " << RPM( currentOFValue ) << std::endl;
        return_flag = true;
        type        = 10;
    }

    // only valid if an iteration has occurred, see above.
    if( iterationCounter > 0 )
    {
        if( SUCCESSIVE_IMPROVEMENTS_ABSOLUTE & terminationCriterionFlag &&
            ( previousOFValue - currentOFValue ) <= successiveImprovementsAbsoluteEps )
        {
            MSQ_DBGOUT_P0_ONLY( debugLevel )
                << par_string() << "  o TermCrit -- SUCCESSIVE_IMPROVEMENTS_ABSOLUTE: previousOFValue= "
                << " " << previousOFValue << " currentOFValue= " << RPM( currentOFValue )
                << " successiveImprovementsAbsoluteEps= " << successiveImprovementsAbsoluteEps << std::endl;
            return_flag = true;
            type        = 11;
        }
        if( QUALITY_IMPROVEMENT_RELATIVE & terminationCriterionFlag &&
            ( currentOFValue - lowerOFBound ) <= qualityImprovementRelativeEps * ( initialOFValue - lowerOFBound ) )
        {
            MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- QUALITY_IMPROVEMENT_RELATIVE: "
                                             << " " << std::endl;
            return_flag = true;
            type        = 12;
        }
        if( SUCCESSIVE_IMPROVEMENTS_RELATIVE & terminationCriterionFlag &&
            ( previousOFValue - currentOFValue ) <=
                successiveImprovementsRelativeEps * ( initialOFValue - currentOFValue ) )
        {
            MSQ_DBGOUT_P0_ONLY( debugLevel )
                << par_string() << "  o TermCrit -- SUCCESSIVE_IMPROVEMENTS_RELATIVE: previousOFValue= "
                << " " << previousOFValue << " currentOFValue= " << RPM( currentOFValue )
                << " successiveImprovementsRelativeEps= " << successiveImprovementsRelativeEps << std::endl;
            return_flag = true;
            type        = 13;
        }
    }

    if( BOUNDED_VERTEX_MOVEMENT & terminationCriterionFlag && vertexMovementExceedsBound )
    {
        return_flag = true;
        type        = 14;
        MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- "
                                         << " " << vertexMovementExceedsBound << " vertices out of bounds."
                                         << std::endl;
    }

    if( UNTANGLED_MESH & terminationCriterionFlag )
    {
        if( innerOuterType == TYPE_OUTER )
        {
            // MSQ_DBGOUT_P0_ONLY(debugLevel)
            MSQ_DBGOUT( debugLevel ) << par_string() << "  o Num Inverted: "
                                     << " " << globalInvertedCount << std::endl;
        }
        if( !globalInvertedCount )
        {
            MSQ_DBGOUT_P0_ONLY( debugLevel ) << par_string() << "  o TermCrit -- UNTANGLED_MESH: "
                                             << " " << std::endl;
            return_flag = true;
            type        = 15;
        }
    }

    // clear this value at the end of each iteration
    vertexMovementExceedsBound = 0;
    maxSquaredMovement         = -1.0;

    if( timeStepFileType == GNUPLOT && return_flag )
    {
        MsqError err;
        MeshWriter::write_gnuplot_overlay( iterationCounter, timeStepFileName.c_str(), err );
    }

    if( 0 && return_flag && MSQ_DBG( 2 ) )
        std::cout << "P[" << get_parallel_rank() << "] tmp TerminationCriterion::terminate: " << moniker
                  << " return_flag= " << return_flag << " type= " << type
                  << " terminationCriterionFlag= " << terminationCriterionFlag << " debugLevel= " << debugLevel
                  << std::endl;

    // if none of the criteria were satisfied
    return return_flag;
}
void MBMesquite::TerminationCriterion::write_iterations ( const char *  filename,
MsqError err 
)

Definition at line 1116 of file TerminationCriterion.cpp.

References MBMesquite::MsqError::FILE_ACCESS, filename, MSQ_SETERR, and plotFile.

Referenced by run().

{
    if( filename )
    {
        plotFile.open( filename, std::ios::trunc );
        if( !plotFile ) MSQ_SETERR( err )
        ( MsqError::FILE_ACCESS, "Failed to open plot data file: '%s'", filename );
    }
    else
    {
        plotFile.close();
    }
}
MESQUITE_EXPORT void MBMesquite::TerminationCriterion::write_mesh_steps ( const char *  filename,
TimeStepFileType  type = VTK 
) [inline]

Write mesh improvement animation.

Write mesh at each iteration such that the sequence of mesh files can be used to produce an animation of the mesh through the quality improvement process.

Files can be written either as VTK timesteps for viewing in a tool such as Paraview or as GNU plot data files and a GNU plot script which, in combination with recent versions of GNU plot, can be used to produce an animated GIF image.

Writing of mesh steps can be disabled by calling this function with type == NOTYPE and filename ==NULL.

Definition at line 301 of file TerminationCriterion.hpp.

References filename, timeStepFileName, and timeStepFileType.

Referenced by main().

void MBMesquite::TerminationCriterion::write_timestep ( PatchData pd,
const Vector3D gradient,
MsqError err 
) [protected]

Definition at line 1101 of file TerminationCriterion.cpp.

References MBMesquite::PatchData::get_mesh(), GNUPLOT, MBMesquite::gradient(), iterationCounter, timeStepFileName, timeStepFileType, VTK, write_gnuplot(), and write_vtk.

Referenced by accumulate_inner(), and reset_inner().

{
    std::ostringstream str;
    if( timeStepFileType == VTK )
    {
        str << timeStepFileName << '_' << iterationCounter << ".vtk";
        MeshWriter::write_vtk( pd, str.str().c_str(), err, gradient );
    }
    else if( timeStepFileType == GNUPLOT )
    {
        str << timeStepFileName << '.' << iterationCounter;
        MeshWriter::write_gnuplot( pd.get_mesh(), str.str().c_str(), err );
    }
}

Friends And Related Function Documentation

friend class VertexMover [friend]

Definition at line 360 of file TerminationCriterion.hpp.


Member Data Documentation

enable culling of pieces of a global patch

Definition at line 376 of file TerminationCriterion.hpp.

Referenced by cull_for_global_patch(), cull_vertices_global(), and TerminationCriterion().

Definition at line 385 of file TerminationCriterion.hpp.

Referenced by accumulate_inner(), and reset_inner().

Definition at line 435 of file TerminationCriterion.hpp.

Referenced by par_string(), and terminate().

number of inverted elements in previously tested patch

Definition at line 425 of file TerminationCriterion.hpp.

Referenced by accumulate_patch(), cull_vertices(), MBMesquite::VertexMover::loop_over_mesh(), reset_inner(), reset_patch(), and TerminationCriterion().

Plot data.

Definition at line 430 of file TerminationCriterion.hpp.

Referenced by accumulate_inner(), reset_inner(), and write_iterations().

Base name for timestep files.

Definition at line 433 of file TerminationCriterion.hpp.

Referenced by terminate(), write_mesh_steps(), and write_timestep().

calculated constant for VERTEX_MOVEMENT_ABS_EDGE_LENGTH

Definition at line 411 of file TerminationCriterion.hpp.

Referenced by initialize_queue(), terminate(), and TerminationCriterion().

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