MOAB: Mesh Oriented datABase  (version 5.3.0)
MBMesquite::IdealWeightInverseMeanRatio Class Reference

Computes the inverse mean ratio of given element. More...

#include <IdealWeightInverseMeanRatio.hpp>

+ Inheritance diagram for MBMesquite::IdealWeightInverseMeanRatio:
+ Collaboration diagram for MBMesquite::IdealWeightInverseMeanRatio:

Public Member Functions

MESQUITE_EXPORT IdealWeightInverseMeanRatio (MsqError &err, double power=1.0)
MESQUITE_EXPORT IdealWeightInverseMeanRatio ()
virtual MESQUITE_EXPORT ~IdealWeightInverseMeanRatio ()
 virtual destructor ensures use of polymorphism during destruction
virtual std::string get_name () const
virtual int get_negate_flag () const
 1 if metric should be minimized, -1 if metric should be maximized.
virtual bool evaluate (PatchData &pd, size_t handle, double &value, MsqError &err)
 Get metric value at a logical location in the patch.
virtual bool evaluate_with_gradient (PatchData &pd, size_t handle, double &value, std::vector< size_t > &indices, std::vector< Vector3D > &gradient, MsqError &err)
 Get metric value and gradient at a logical location in the patch.
virtual bool evaluate_with_Hessian_diagonal (PatchData &pd, size_t handle, double &value, std::vector< size_t > &indices, std::vector< Vector3D > &gradient, std::vector< SymMatrix3D > &Hessian, MsqError &err)
 Get metric value and gradient at a logical location in the patch.
virtual bool evaluate_with_Hessian (PatchData &pd, size_t handle, double &value, std::vector< size_t > &indices, std::vector< Vector3D > &gradient, std::vector< Matrix3D > &Hessian, MsqError &err)
 Get metric value and deravitives at a logical location in the patch.

Private Member Functions

void set_metric_power (double pow_dbl, MsqError &err)
 Sets the power value in the metric computation.

Private Attributes

Vector3D mCoords [4]
Vector3D mGradients [32]
Matrix3D mHessians [80]
double mMetrics [8]
double a2Con
Exponent b2Con
Exponent c2Con
double a3Con
Exponent b3Con
Exponent c3Con

Detailed Description

Computes the inverse mean ratio of given element.

The metric does not use the sample point functionality or the compute_weighted_jacobian. It evaluates the metric at the element vertices, and uses the isotropic ideal element. Optionally, the metric computation can be raised to the 'pow_dbl' power. This does not necessarily raise the metric value to the 'pow_dbl' power but instead raises each local metric. For example, if the corner inverse mean ratios of a quadraliteral element were m1,m2,m3, and m4 and we set pow_dbl=2 and used linear averaging, the metric value would then be m = .25(m1*m1 + m2*m2 + m3*m3 + m4*m4). The metric does require a feasible region, and the metric needs to be minimized if pow_dbl is greater than zero and maximized if pow_dbl is less than zero. pow_dbl being equal to zero is invalid.

Definition at line 72 of file IdealWeightInverseMeanRatio.hpp.


Constructor & Destructor Documentation

virtual destructor ensures use of polymorphism during destruction

Definition at line 79 of file IdealWeightInverseMeanRatio.hpp.

{}

Member Function Documentation

bool MBMesquite::IdealWeightInverseMeanRatio::evaluate ( PatchData pd,
size_t  handle,
double &  value,
MsqError err 
) [virtual]

Get metric value at a logical location in the patch.

Evaluate the metric at one location in the PatchData.

Parameters:
pdThe patch.
handleThe location in the patch (as passed back from get_evaluations).
valueThe output metric value.

Implements MBMesquite::QualityMetric.

Definition at line 90 of file IdealWeightInverseMeanRatio.cpp.

References a2Con, a3Con, MBMesquite::AveragingQM::average_metrics(), b2Con, b3Con, c2Con, c3Con, MBMesquite::PatchData::element_by_index(), MBMesquite::PatchData::get_domain_normal_at_element(), MBMesquite::MsqMeshEntity::get_element_type(), MBMesquite::PatchData::get_vertex_array(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), MBMesquite::HEXAHEDRON, MBMesquite::Vector3D::length(), MBMesquite::m_fcn_2e(), MBMesquite::m_fcn_2i(), MBMesquite::m_fcn_3e(), MBMesquite::m_fcn_3i(), MBMesquite::m_fcn_3p(), MBMesquite::m_fcn_3w(), mCoords, mMetrics, MSQ_ERRZERO, MSQ_SETERR, n, MBMesquite::PRISM, MBMesquite::PYRAMID, MBMesquite::QUADRILATERAL, MBMesquite::TETRAHEDRON, MBMesquite::TRIANGLE, and MBMesquite::MsqError::UNSUPPORTED_ELEMENT.

{
    const MsqMeshEntity* e = &pd.element_by_index( handle );
    EntityTopology topo    = e->get_element_type();

    const MsqVertex* vertices = pd.get_vertex_array( err );
    MSQ_ERRZERO( err );
    const size_t* v_i = e->get_vertex_index_array();

    Vector3D n;  // Surface normal for 2D objects

    // Prism and Hex element descriptions
    static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 },
                                        { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } };
    static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 },
                                        { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } };

    const Vector3D d_con( 1.0, 1.0, 1.0 );

    int i;

    m                 = 0.0;
    bool metric_valid = false;
    switch( topo )
    {
        case TRIANGLE:
            pd.get_domain_normal_at_element( e, n, err );
            MSQ_ERRZERO( err );
            n            = n / n.length();  // Need unit normal
            mCoords[0]   = vertices[v_i[0]];
            mCoords[1]   = vertices[v_i[1]];
            mCoords[2]   = vertices[v_i[2]];
            metric_valid = m_fcn_2e( m, mCoords, n, a2Con, b2Con, c2Con );
            if( !metric_valid ) return false;
            break;

        case QUADRILATERAL:
            pd.get_domain_normal_at_element( e, n, err );
            MSQ_ERRZERO( err );
            n = n / n.length();  // Need unit normal
            for( i = 0; i < 4; ++i )
            {
                mCoords[0]   = vertices[v_i[locs_hex[i][0]]];
                mCoords[1]   = vertices[v_i[locs_hex[i][1]]];
                mCoords[2]   = vertices[v_i[locs_hex[i][2]]];
                metric_valid = m_fcn_2i( mMetrics[i], mCoords, n, a2Con, b2Con, c2Con, d_con );
                if( !metric_valid ) return false;
            }
            m = average_metrics( mMetrics, 4, err );
            break;

        case TETRAHEDRON:
            mCoords[0]   = vertices[v_i[0]];
            mCoords[1]   = vertices[v_i[1]];
            mCoords[2]   = vertices[v_i[2]];
            mCoords[3]   = vertices[v_i[3]];
            metric_valid = m_fcn_3e( m, mCoords, a3Con, b3Con, c3Con );
            if( !metric_valid ) return false;
            break;

        case PYRAMID:
            for( i = 0; i < 4; ++i )
            {
                mCoords[0]   = vertices[v_i[i]];
                mCoords[1]   = vertices[v_i[( i + 1 ) % 4]];
                mCoords[2]   = vertices[v_i[( i + 3 ) % 4]];
                mCoords[3]   = vertices[v_i[4]];
                metric_valid = m_fcn_3p( mMetrics[i], mCoords, a3Con, b3Con, c3Con );
                if( !metric_valid ) return false;
            }
            m = average_metrics( mMetrics, 4, err );
            MSQ_ERRZERO( err );
            break;

        case PRISM:
            for( i = 0; i < 6; ++i )
            {
                mCoords[0]   = vertices[v_i[locs_pri[i][0]]];
                mCoords[1]   = vertices[v_i[locs_pri[i][1]]];
                mCoords[2]   = vertices[v_i[locs_pri[i][2]]];
                mCoords[3]   = vertices[v_i[locs_pri[i][3]]];
                metric_valid = m_fcn_3w( mMetrics[i], mCoords, a3Con, b3Con, c3Con );
                if( !metric_valid ) return false;
            }
            m = average_metrics( mMetrics, 6, err );
            MSQ_ERRZERO( err );
            break;

        case HEXAHEDRON:
            for( i = 0; i < 8; ++i )
            {
                mCoords[0]   = vertices[v_i[locs_hex[i][0]]];
                mCoords[1]   = vertices[v_i[locs_hex[i][1]]];
                mCoords[2]   = vertices[v_i[locs_hex[i][2]]];
                mCoords[3]   = vertices[v_i[locs_hex[i][3]]];
                metric_valid = m_fcn_3i( mMetrics[i], mCoords, a3Con, b3Con, c3Con, d_con );
                if( !metric_valid ) return false;
            }
            m = average_metrics( mMetrics, 8, err );
            MSQ_ERRZERO( err );
            break;

        default:
            MSQ_SETERR( err )
            ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightInverseMeanRatio",
              (int)topo );
            return false;
    }  // end switch over element type
    return true;
}
bool MBMesquite::IdealWeightInverseMeanRatio::evaluate_with_gradient ( PatchData pd,
size_t  handle,
double &  value,
std::vector< size_t > &  indices,
std::vector< Vector3D > &  gradient,
MsqError err 
) [virtual]

Get metric value and gradient at a logical location in the patch.

Evaluate the metric at one location in the PatchData.

Parameters:
pdThe patch.
handleThe location in the patch (as passed back from get_evaluations).
valueThe output metric value.
indicesThe free vertices that the evaluation is a function of, specified as vertex indices in the PatchData.
gradientThe gradient of the metric as a function of the coordinates of the free vertices passed back in the indices list.

Reimplemented from MBMesquite::QualityMetric.

Definition at line 201 of file IdealWeightInverseMeanRatio.cpp.

References a2Con, a3Con, MBMesquite::AveragingQM::analytical_average_gradient(), MBMesquite::arrptr(), MBMesquite::AveragingQM::average_corner_gradients(), b2Con, b3Con, c2Con, c3Con, MBMesquite::PatchData::element_by_index(), MBMesquite::QualityMetric::fixed_vertex_bitmap(), MBMesquite::g_fcn_2e(), MBMesquite::g_fcn_2i(), MBMesquite::g_fcn_3e(), MBMesquite::g_fcn_3i(), MBMesquite::g_fcn_3p(), MBMesquite::g_fcn_3w(), MBMesquite::PatchData::get_domain_normal_at_element(), MBMesquite::MsqMeshEntity::get_element_type(), MBMesquite::PatchData::get_vertex_array(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), MBMesquite::HEXAHEDRON, MBMesquite::Vector3D::length(), mCoords, mGradients, mMetrics, MSQ_DBGOUT, MSQ_ERRZERO, MSQ_SETERR, n, MBMesquite::print(), MBMesquite::PRISM, MBMesquite::PYRAMID, MBMesquite::QUADRILATERAL, MBMesquite::QualityMetric::remove_fixed_gradients(), MBMesquite::TETRAHEDRON, MBMesquite::TRIANGLE, and MBMesquite::MsqError::UNSUPPORTED_ELEMENT.

Referenced by TQualityMetricTest::regression_inverse_mean_ratio_grad().

{
    const MsqMeshEntity* e = &pd.element_by_index( handle );
    EntityTopology topo    = e->get_element_type();

    if( !analytical_average_gradient() && topo != TRIANGLE && topo != TETRAHEDRON )
    {
        static bool print = true;
        if( print )
        {
            MSQ_DBGOUT( 1 ) << "Analyical gradient not available for selected averaging scheme. "
                            << "Using (possibly much slower) numerical approximation of gradient"
                            << " of quality metric. " << std::endl;
            print = false;
        }
        return QualityMetric::evaluate_with_gradient( pd, handle, m, indices, g, err );
    }

    const MsqVertex* vertices = pd.get_vertex_array( err );
    MSQ_ERRZERO( err );
    const size_t* v_i = e->get_vertex_index_array();

    Vector3D n;  // Surface normal for 2D objects

    // Prism and Hex element descriptions
    static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 },
                                        { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } };
    static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 },
                                        { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } };

    const Vector3D d_con( 1.0, 1.0, 1.0 );

    int i;

    bool metric_valid = false;
    const uint32_t fm = fixed_vertex_bitmap( pd, e, indices );

    m = 0.0;

    switch( topo )
    {
        case TRIANGLE:
            pd.get_domain_normal_at_element( e, n, err );
            MSQ_ERRZERO( err );
            n /= n.length();  // Need unit normal
            mCoords[0] = vertices[v_i[0]];
            mCoords[1] = vertices[v_i[1]];
            mCoords[2] = vertices[v_i[2]];
            g.resize( 3 );
            if( !g_fcn_2e( m, arrptr( g ), mCoords, n, a2Con, b2Con, c2Con ) ) return false;
            break;

        case QUADRILATERAL:
            pd.get_domain_normal_at_element( e, n, err );
            MSQ_ERRZERO( err );
            n /= n.length();  // Need unit normal
            for( i = 0; i < 4; ++i )
            {
                mCoords[0] = vertices[v_i[locs_hex[i][0]]];
                mCoords[1] = vertices[v_i[locs_hex[i][1]]];
                mCoords[2] = vertices[v_i[locs_hex[i][2]]];
                if( !g_fcn_2i( mMetrics[i], mGradients + 3 * i, mCoords, n, a2Con, b2Con, c2Con, d_con ) ) return false;
            }

            g.resize( 4 );
            m = average_corner_gradients( QUADRILATERAL, fm, 4, mMetrics, mGradients, arrptr( g ), err );
            MSQ_ERRZERO( err );
            break;

        case TETRAHEDRON:
            mCoords[0] = vertices[v_i[0]];
            mCoords[1] = vertices[v_i[1]];
            mCoords[2] = vertices[v_i[2]];
            mCoords[3] = vertices[v_i[3]];
            g.resize( 4 );
            metric_valid = g_fcn_3e( m, arrptr( g ), mCoords, a3Con, b3Con, c3Con );
            if( !metric_valid ) return false;
            break;

        case PYRAMID:
            for( i = 0; i < 4; ++i )
            {
                mCoords[0]   = vertices[v_i[i]];
                mCoords[1]   = vertices[v_i[( i + 1 ) % 4]];
                mCoords[2]   = vertices[v_i[( i + 3 ) % 4]];
                mCoords[3]   = vertices[v_i[4]];
                metric_valid = g_fcn_3p( mMetrics[i], mGradients + 4 * i, mCoords, a3Con, b3Con, c3Con );
                if( !metric_valid ) return false;
            }

            g.resize( 5 );
            m = average_corner_gradients( PYRAMID, fm, 4, mMetrics, mGradients, arrptr( g ), err );
            MSQ_ERRZERO( err );
            break;

        case PRISM:
            for( i = 0; i < 6; ++i )
            {
                mCoords[0] = vertices[v_i[locs_pri[i][0]]];
                mCoords[1] = vertices[v_i[locs_pri[i][1]]];
                mCoords[2] = vertices[v_i[locs_pri[i][2]]];
                mCoords[3] = vertices[v_i[locs_pri[i][3]]];
                if( !g_fcn_3w( mMetrics[i], mGradients + 4 * i, mCoords, a3Con, b3Con, c3Con ) ) return false;
            }

            g.resize( 6 );
            m = average_corner_gradients( PRISM, fm, 6, mMetrics, mGradients, arrptr( g ), err );
            MSQ_ERRZERO( err );
            break;

        case HEXAHEDRON:
            for( i = 0; i < 8; ++i )
            {
                mCoords[0] = vertices[v_i[locs_hex[i][0]]];
                mCoords[1] = vertices[v_i[locs_hex[i][1]]];
                mCoords[2] = vertices[v_i[locs_hex[i][2]]];
                mCoords[3] = vertices[v_i[locs_hex[i][3]]];
                if( !g_fcn_3i( mMetrics[i], mGradients + 4 * i, mCoords, a3Con, b3Con, c3Con, d_con ) ) return false;
            }

            g.resize( 8 );
            m = average_corner_gradients( HEXAHEDRON, fm, 8, mMetrics, mGradients, arrptr( g ), err );
            MSQ_ERRZERO( err );
            break;

        default:
            MSQ_SETERR( err )
            ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightInverseMeanRatio",
              (int)topo );
            return false;
    }  // end switch over element type

    remove_fixed_gradients( topo, fm, g );
    return true;
}
bool MBMesquite::IdealWeightInverseMeanRatio::evaluate_with_Hessian ( PatchData pd,
size_t  handle,
double &  value,
std::vector< size_t > &  indices,
std::vector< Vector3D > &  gradient,
std::vector< Matrix3D > &  Hessian,
MsqError err 
) [virtual]

Get metric value and deravitives at a logical location in the patch.

Evaluate the metric at one location in the PatchData.

Parameters:
pdThe patch.
handleThe location in the patch (as passed back from get_evaluations).
valueThe output metric value.
indicesThe free vertices that the evaluation is a function of, specified as vertex indices in the PatchData.
gradientThe gradient of the metric as a function of the coordinates of the free vertices passed back in the indices list.
HessianThe Hessian of the metric as a function of the coordinates. The Hessian is passed back as the upper-triangular portion of the matrix in row-major order, where each Matrix3D is the portion of the Hessian with respect to the vertices at the corresponding positions in the indices list.

Reimplemented from MBMesquite::QualityMetric.

Definition at line 502 of file IdealWeightInverseMeanRatio.cpp.

References a2Con, a3Con, MBMesquite::AveragingQM::analytical_average_hessian(), MBMesquite::arrptr(), MBMesquite::AveragingQM::average_corner_hessians(), b2Con, b3Con, c2Con, c3Con, MBMesquite::PatchData::element_by_index(), MBMesquite::QualityMetric::fixed_vertex_bitmap(), MBMesquite::PatchData::get_domain_normal_at_element(), MBMesquite::MsqMeshEntity::get_element_type(), MBMesquite::PatchData::get_vertex_array(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), MBMesquite::h_fcn_2e(), MBMesquite::h_fcn_2i(), MBMesquite::h_fcn_3e(), MBMesquite::h_fcn_3i(), MBMesquite::h_fcn_3p(), MBMesquite::h_fcn_3w(), MBMesquite::HEXAHEDRON, MBMesquite::Vector3D::length(), mCoords, mGradients, mHessians, mMetrics, MSQ_DBGOUT, MSQ_ERRZERO, MSQ_SETERR, n, MBMesquite::print(), MBMesquite::PRISM, MBMesquite::PYRAMID, MBMesquite::QUADRILATERAL, MBMesquite::QualityMetric::remove_fixed_gradients(), MBMesquite::QualityMetric::remove_fixed_hessians(), MBMesquite::TETRAHEDRON, MBMesquite::TRIANGLE, and MBMesquite::MsqError::UNSUPPORTED_ELEMENT.

Referenced by TQualityMetricTest::regression_inverse_mean_ratio_hess().

{
    const MsqMeshEntity* e = &pd.element_by_index( handle );
    EntityTopology topo    = e->get_element_type();

    if( !analytical_average_hessian() && topo != TRIANGLE && topo != TETRAHEDRON )
    {
        static bool print = true;
        if( print )
        {
            MSQ_DBGOUT( 1 ) << "Analyical gradient not available for selected averaging scheme. "
                            << "Using (possibly much slower) numerical approximation of gradient"
                            << " of quality metric. " << std::endl;
            print = false;
        }
        return QualityMetric::evaluate_with_Hessian( pd, handle, m, indices, g, h, err );
    }

    const MsqVertex* vertices = pd.get_vertex_array( err );
    MSQ_ERRZERO( err );
    const size_t* v_i = e->get_vertex_index_array();

    Vector3D n;  // Surface normal for 2D objects

    // Prism and Hex element descriptions
    static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 },
                                        { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } };
    static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 },
                                        { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } };

    const Vector3D d_con( 1.0, 1.0, 1.0 );

    int i;

    bool metric_valid = false;
    const uint32_t fm = fixed_vertex_bitmap( pd, e, indices );

    m = 0.0;

    switch( topo )
    {
        case TRIANGLE:
            pd.get_domain_normal_at_element( e, n, err );
            MSQ_ERRZERO( err );
            n /= n.length();  // Need unit normal
            mCoords[0] = vertices[v_i[0]];
            mCoords[1] = vertices[v_i[1]];
            mCoords[2] = vertices[v_i[2]];
            g.resize( 3 );
            h.resize( 6 );
            if( !h_fcn_2e( m, arrptr( g ), arrptr( h ), mCoords, n, a2Con, b2Con, c2Con ) ) return false;
            break;

        case QUADRILATERAL:
            pd.get_domain_normal_at_element( e, n, err );
            MSQ_ERRZERO( err );
            n /= n.length();  // Need unit normal
            for( i = 0; i < 4; ++i )
            {
                mCoords[0] = vertices[v_i[locs_hex[i][0]]];
                mCoords[1] = vertices[v_i[locs_hex[i][1]]];
                mCoords[2] = vertices[v_i[locs_hex[i][2]]];
                if( !h_fcn_2i( mMetrics[i], mGradients + 3 * i, mHessians + 6 * i, mCoords, n, a2Con, b2Con, c2Con,
                               d_con ) )
                    return false;
            }

            g.resize( 4 );
            h.resize( 10 );
            m = average_corner_hessians( QUADRILATERAL, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ),
                                         arrptr( h ), err );
            MSQ_ERRZERO( err );
            break;

        case TETRAHEDRON:
            mCoords[0] = vertices[v_i[0]];
            mCoords[1] = vertices[v_i[1]];
            mCoords[2] = vertices[v_i[2]];
            mCoords[3] = vertices[v_i[3]];
            g.resize( 4 );
            h.resize( 10 );
            metric_valid = h_fcn_3e( m, arrptr( g ), arrptr( h ), mCoords, a3Con, b3Con, c3Con );
            if( !metric_valid ) return false;
            break;

        case PYRAMID:
            for( i = 0; i < 4; ++i )
            {
                mCoords[0] = vertices[v_i[i]];
                mCoords[1] = vertices[v_i[( i + 1 ) % 4]];
                mCoords[2] = vertices[v_i[( i + 3 ) % 4]];
                mCoords[3] = vertices[v_i[4]];
                metric_valid =
                    h_fcn_3p( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con );

                if( !metric_valid ) return false;
            }

            g.resize( 5 );
            h.resize( 15 );
            m = average_corner_hessians( PYRAMID, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ), arrptr( h ),
                                         err );
            MSQ_ERRZERO( err );
            break;

        case PRISM:
            for( i = 0; i < 6; ++i )
            {
                mCoords[0] = vertices[v_i[locs_pri[i][0]]];
                mCoords[1] = vertices[v_i[locs_pri[i][1]]];
                mCoords[2] = vertices[v_i[locs_pri[i][2]]];
                mCoords[3] = vertices[v_i[locs_pri[i][3]]];
                if( !h_fcn_3w( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con ) )
                    return false;
            }

            g.resize( 6 );
            h.resize( 21 );
            m = average_corner_hessians( PRISM, fm, 6, mMetrics, mGradients, mHessians, arrptr( g ), arrptr( h ), err );
            MSQ_ERRZERO( err );
            break;

        case HEXAHEDRON:
            for( i = 0; i < 8; ++i )
            {
                mCoords[0] = vertices[v_i[locs_hex[i][0]]];
                mCoords[1] = vertices[v_i[locs_hex[i][1]]];
                mCoords[2] = vertices[v_i[locs_hex[i][2]]];
                mCoords[3] = vertices[v_i[locs_hex[i][3]]];
                if( !h_fcn_3i( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con,
                               d_con ) )
                    return false;
            }

            g.resize( 8 );
            h.resize( 36 );
            m = average_corner_hessians( HEXAHEDRON, fm, 8, mMetrics, mGradients, mHessians, arrptr( g ), arrptr( h ),
                                         err );
            MSQ_ERRZERO( err );
            break;

        default:
            MSQ_SETERR( err )
            ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightInverseMeanRatio",
              (int)topo );
            return false;
    }  // end switch over element type

    remove_fixed_gradients( topo, fm, g );
    remove_fixed_hessians( topo, fm, h );
    return true;
}
bool MBMesquite::IdealWeightInverseMeanRatio::evaluate_with_Hessian_diagonal ( PatchData pd,
size_t  handle,
double &  value,
std::vector< size_t > &  indices,
std::vector< Vector3D > &  gradient,
std::vector< SymMatrix3D > &  Hessian_diagonal,
MsqError err 
) [virtual]

Get metric value and gradient at a logical location in the patch.

Evaluate the metric at one location in the PatchData.

Parameters:
pdThe patch.
handleThe location in the patch (as passed back from get_evaluations).
valueThe output metric value.
indicesThe free vertices that the evaluation is a function of, specified as vertex indices in the PatchData.
gradientThe gradient of the metric as a function of the coordinates of the free vertices passed back in the indices list.
Hessian_diagonalThe 3x3 blocks along the diagonal of the Hessian matrix.

Reimplemented from MBMesquite::QualityMetric.

Definition at line 339 of file IdealWeightInverseMeanRatio.cpp.

References a2Con, a3Con, MBMesquite::AveragingQM::analytical_average_hessian(), MBMesquite::arrptr(), MBMesquite::AveragingQM::average_corner_hessian_diagonals(), b2Con, b3Con, c2Con, c3Con, MBMesquite::PatchData::element_by_index(), MBMesquite::QualityMetric::fixed_vertex_bitmap(), MBMesquite::PatchData::get_domain_normal_at_element(), MBMesquite::MsqMeshEntity::get_element_type(), MBMesquite::PatchData::get_vertex_array(), MBMesquite::MsqMeshEntity::get_vertex_index_array(), MBMesquite::h_fcn_2e(), MBMesquite::h_fcn_2i(), MBMesquite::h_fcn_3e(), MBMesquite::h_fcn_3i(), MBMesquite::h_fcn_3p(), MBMesquite::h_fcn_3w(), MBMesquite::HEXAHEDRON, MBMesquite::Vector3D::length(), mCoords, mGradients, mHessians, mMetrics, MSQ_DBGOUT, MSQ_ERRZERO, MSQ_SETERR, n, MBMesquite::print(), MBMesquite::PRISM, MBMesquite::PYRAMID, MBMesquite::QUADRILATERAL, MBMesquite::QualityMetric::remove_fixed_diagonals(), MBMesquite::TETRAHEDRON, MBMesquite::TRIANGLE, MBMesquite::MsqError::UNSUPPORTED_ELEMENT, and MBMesquite::Matrix3D::upper().

{
    const MsqMeshEntity* e = &pd.element_by_index( handle );
    EntityTopology topo    = e->get_element_type();

    if( !analytical_average_hessian() && topo != TRIANGLE && topo != TETRAHEDRON )
    {
        static bool print = true;
        if( print )
        {
            MSQ_DBGOUT( 1 ) << "Analyical gradient not available for selected averaging scheme. "
                            << "Using (possibly much slower) numerical approximation of gradient"
                            << " of quality metric. " << std::endl;
            print = false;
        }
        return QualityMetric::evaluate_with_Hessian_diagonal( pd, handle, m, indices, g, h, err );
    }

    const MsqVertex* vertices = pd.get_vertex_array( err );
    MSQ_ERRZERO( err );
    const size_t* v_i = e->get_vertex_index_array();

    Vector3D n;  // Surface normal for 2D objects

    // Prism and Hex element descriptions
    static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 },
                                        { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } };
    static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 },
                                        { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } };

    const Vector3D d_con( 1.0, 1.0, 1.0 );

    int i;

    bool metric_valid = false;
    const uint32_t fm = fixed_vertex_bitmap( pd, e, indices );

    m = 0.0;

    switch( topo )
    {
        case TRIANGLE:
            pd.get_domain_normal_at_element( e, n, err );
            MSQ_ERRZERO( err );
            n /= n.length();  // Need unit normal
            mCoords[0] = vertices[v_i[0]];
            mCoords[1] = vertices[v_i[1]];
            mCoords[2] = vertices[v_i[2]];
            g.resize( 3 );
            h.resize( 3 );
            if( !h_fcn_2e( m, arrptr( g ), mHessians, mCoords, n, a2Con, b2Con, c2Con ) ) return false;
            h[0] = mHessians[0].upper();
            h[1] = mHessians[3].upper();
            h[2] = mHessians[5].upper();
            break;

        case QUADRILATERAL:
            pd.get_domain_normal_at_element( e, n, err );
            MSQ_ERRZERO( err );
            n /= n.length();  // Need unit normal
            for( i = 0; i < 4; ++i )
            {
                mCoords[0] = vertices[v_i[locs_hex[i][0]]];
                mCoords[1] = vertices[v_i[locs_hex[i][1]]];
                mCoords[2] = vertices[v_i[locs_hex[i][2]]];
                if( !h_fcn_2i( mMetrics[i], mGradients + 3 * i, mHessians + 6 * i, mCoords, n, a2Con, b2Con, c2Con,
                               d_con ) )
                    return false;
            }

            g.resize( 4 );
            h.resize( 4 );
            m = average_corner_hessian_diagonals( QUADRILATERAL, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ),
                                                  arrptr( h ), err );
            MSQ_ERRZERO( err );
            break;

        case TETRAHEDRON:
            mCoords[0] = vertices[v_i[0]];
            mCoords[1] = vertices[v_i[1]];
            mCoords[2] = vertices[v_i[2]];
            mCoords[3] = vertices[v_i[3]];
            g.resize( 4 );
            h.resize( 4 );
            metric_valid = h_fcn_3e( m, arrptr( g ), mHessians, mCoords, a3Con, b3Con, c3Con );
            if( !metric_valid ) return false;
            h[0] = mHessians[0].upper();
            h[1] = mHessians[4].upper();
            h[2] = mHessians[7].upper();
            h[3] = mHessians[9].upper();
            break;

        case PYRAMID:
            for( i = 0; i < 4; ++i )
            {
                mCoords[0] = vertices[v_i[i]];
                mCoords[1] = vertices[v_i[( i + 1 ) % 4]];
                mCoords[2] = vertices[v_i[( i + 3 ) % 4]];
                mCoords[3] = vertices[v_i[4]];
                metric_valid =
                    h_fcn_3p( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con );

                if( !metric_valid ) return false;
            }

            g.resize( 5 );
            h.resize( 5 );
            m = average_corner_hessian_diagonals( PYRAMID, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ),
                                                  arrptr( h ), err );
            MSQ_ERRZERO( err );
            break;

        case PRISM:
            for( i = 0; i < 6; ++i )
            {
                mCoords[0] = vertices[v_i[locs_pri[i][0]]];
                mCoords[1] = vertices[v_i[locs_pri[i][1]]];
                mCoords[2] = vertices[v_i[locs_pri[i][2]]];
                mCoords[3] = vertices[v_i[locs_pri[i][3]]];
                if( !h_fcn_3w( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con ) )
                    return false;
            }

            g.resize( 6 );
            h.resize( 6 );
            m = average_corner_hessian_diagonals( PRISM, fm, 6, mMetrics, mGradients, mHessians, arrptr( g ),
                                                  arrptr( h ), err );
            MSQ_ERRZERO( err );
            break;

        case HEXAHEDRON:
            for( i = 0; i < 8; ++i )
            {
                mCoords[0] = vertices[v_i[locs_hex[i][0]]];
                mCoords[1] = vertices[v_i[locs_hex[i][1]]];
                mCoords[2] = vertices[v_i[locs_hex[i][2]]];
                mCoords[3] = vertices[v_i[locs_hex[i][3]]];
                if( !h_fcn_3i( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con,
                               d_con ) )
                    return false;
            }

            g.resize( 8 );
            h.resize( 8 );
            m = average_corner_hessian_diagonals( HEXAHEDRON, fm, 8, mMetrics, mGradients, mHessians, arrptr( g ),
                                                  arrptr( h ), err );
            MSQ_ERRZERO( err );
            break;

        default:
            MSQ_SETERR( err )
            ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightInverseMeanRatio",
              (int)topo );
            return false;
    }  // end switch over element type

    remove_fixed_diagonals( topo, fm, g, h );
    return true;
}
std::string MBMesquite::IdealWeightInverseMeanRatio::get_name ( ) const [virtual]

Implements MBMesquite::QualityMetric.

Definition at line 64 of file IdealWeightInverseMeanRatio.cpp.

{
    return "Inverse Mean Ratio";
}

1 if metric should be minimized, -1 if metric should be maximized.

Implements MBMesquite::QualityMetric.

Definition at line 69 of file IdealWeightInverseMeanRatio.cpp.

References b2Con, and MBMesquite::Exponent::value().

{
    return b2Con.value() < 0 ? -1 : 1;
}
void MBMesquite::IdealWeightInverseMeanRatio::set_metric_power ( double  pow_dbl,
MsqError err 
) [private]

Sets the power value in the metric computation.

Definition at line 75 of file IdealWeightInverseMeanRatio.cpp.

References a2Con, a3Con, b2Con, b3Con, c2Con, c3Con, MBMesquite::MsqError::INVALID_ARG, MBMesquite::MSQ_MIN, and MSQ_SETERR.

Referenced by IdealWeightInverseMeanRatio().

{
    if( fabs( pow_dbl ) <= MSQ_MIN )
    {
        MSQ_SETERR( err )( MsqError::INVALID_ARG );
        return;
    }
    a2Con = pow( .5, pow_dbl );
    b2Con = pow_dbl;
    c2Con = -pow_dbl;
    a3Con = pow( 1.0 / 3.0, pow_dbl );
    b3Con = pow_dbl;
    c3Con = -2.0 * pow_dbl / 3.0;
}

Member Data Documentation

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