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

Averaging functionality for use in quality metrics. More...

#include <AveragingQM.hpp>

+ Inheritance diagram for MBMesquite::AveragingQM:

Public Member Functions

MESQUITE_EXPORT AveragingQM (QualityMetric::AveragingMethod method)
virtual ~AveragingQM ()
MESQUITE_EXPORT void set_averaging_method (QualityMetric::AveragingMethod method)
MESQUITE_EXPORT void set_averaging_method (QualityMetric::AveragingMethod method, MsqError &)
MESQUITE_EXPORT
QualityMetric::AveragingMethod 
get_averaging_method () const
bool analytical_average_gradient ()
bool analytical_average_hessian ()
double average_metrics (const double metric_values[], int num_values, MsqError &err)
double average_metric_and_weights (double metric_values[], int num_metric_values, MsqError &err)
double average_corner_gradients (EntityTopology element_type, uint32_t fixed_vertices, unsigned num_corners, double corner_values[], const Vector3D corner_grads[], Vector3D vertex_grads[], MsqError &err)
 Average metric values and gradients for per-corner evaluation.
double average_corner_hessian_diagonals (EntityTopology element_type, uint32_t fixed_vertices, unsigned num_corners, const double corner_values[], const Vector3D corner_grads[], const Matrix3D corner_hessians[], Vector3D vertex_grads[], SymMatrix3D vertex_hessians[], MsqError &err)
 Average metric values, gradients, and Hessian diagonal blocks for per-corner evaluation.
double average_corner_hessian_diagonals (EntityTopology element_type, uint32_t fixed_vertices, unsigned num_corners, const double corner_values[], const Vector3D corner_grads[], const SymMatrix3D corner_hess_diag[], Vector3D vertex_grads[], SymMatrix3D vertex_hessians[], MsqError &err)
 Average metric values, gradients, and Hessian diagonal blocks for per-corner evaluation.
double average_corner_hessians (EntityTopology element_type, uint32_t fixed_vertices, unsigned num_corners, const double corner_values[], const Vector3D corner_grads[], const Matrix3D corner_hessians[], Vector3D vertex_grads[], Matrix3D vertex_hessians[], MsqError &err)
 Average metric values, gradients, and Hessians for per-corner evaluation.

Private Attributes

QualityMetric::AveragingMethod avgMethod

Detailed Description

Averaging functionality for use in quality metrics.

Definition at line 55 of file AveragingQM.hpp.


Constructor & Destructor Documentation

virtual MBMesquite::AveragingQM::~AveragingQM ( ) [inline, virtual]

Definition at line 60 of file AveragingQM.hpp.

{}

Member Function Documentation

Return true if the requested averaging scheme is supported for analytical calculation of gradients.

Definition at line 80 of file AveragingQM.hpp.

References avgMethod, and MBMesquite::QualityMetric::LAST_WITH_GRADIENT.

Referenced by MBMesquite::IdealWeightMeanRatio::evaluate_with_gradient(), and MBMesquite::IdealWeightInverseMeanRatio::evaluate_with_gradient().

double MBMesquite::AveragingQM::average_corner_gradients ( EntityTopology  element_type,
uint32_t  fixed_vertices,
unsigned  num_corners,
double  corner_values[],
const Vector3D  corner_grads[],
Vector3D  vertex_grads[],
MsqError err 
)

Average metric values and gradients for per-corner evaluation.

Parameters:
element_typeThe element type
num_cornersThe number of corners (e.g. pass 4 for a pyramid if the metric couldn't be evaluated for the apex)
corner_valuesAn array of metric values, one per element corner
corner_gradsThe corner gradients, 4 for each corner
vertex_gradsOutput. Gradient at each vertex.
Returns:
average metric value for element

Definition at line 49 of file AveragingQM.cpp.

References average_metric_and_weights(), corners, dim, and MSQ_ERRZERO.

Referenced by AveragingQMTest::check_average_gradient_fails(), AveragingQMTest::check_average_gradients(), MBMesquite::IdealWeightMeanRatio::evaluate_with_gradient(), and MBMesquite::IdealWeightInverseMeanRatio::evaluate_with_gradient().

{
    const unsigned num_vertex = TopologyInfo::corners( type );
    const unsigned dim        = TopologyInfo::dimension( type );
    const unsigned per_vertex = dim + 1;

    unsigned i, j, num_adj;
    const unsigned *adj_idx, *rev_idx;

    // NOTE: This function changes the corner_values array such that
    //       it contains the gradient coefficients.
    double avg = average_metric_and_weights( corner_values, num_corner, err );
    MSQ_ERRZERO( err );

    for( i = 0; i < num_vertex; ++i )
    {
        if( fixed_vertices & ( 1 << i ) )  // skip fixed vertices
            continue;

        adj_idx = TopologyInfo::adjacent_vertices( type, i, num_adj );
        rev_idx = TopologyInfo::reverse_vertex_adjacency_offsets( type, i, num_adj );
        if( i < num_corner )  // not all vertices are corners (e.g. pyramid)
            vertex_grads[i] = corner_values[i] * corner_grads[per_vertex * i];
        else
            vertex_grads[i] = 0;
        for( j = 0; j < num_adj; ++j )
        {
            const unsigned v = adj_idx[j], c = rev_idx[j] + 1;
            if( v >= num_corner )  // if less corners than vertices (e.g. pyramid apex)
                continue;
            vertex_grads[i] += corner_values[v] * corner_grads[per_vertex * v + c];
        }
    }

    return avg;
}
double MBMesquite::AveragingQM::average_corner_hessian_diagonals ( EntityTopology  element_type,
uint32_t  fixed_vertices,
unsigned  num_corners,
const double  corner_values[],
const Vector3D  corner_grads[],
const Matrix3D  corner_hessians[],
Vector3D  vertex_grads[],
SymMatrix3D  vertex_hessians[],
MsqError err 
)

Average metric values, gradients, and Hessian diagonal blocks for per-corner evaluation.

Parameters:
element_typeThe element type
num_cornersThe number of corners (e.g. pass 4 for a pyramid if the metric couldn't be evaluated for the apex)
corner_valuesAn array of metric values, one per element corner
corner_gradsThe corner gradients, 4 for each corner
corner_hessiansThe hessians, 10 for each corner
vertex_gradsOutput. Gradient at each vertex.
vertex_hessiansOutput. Hessian diagonal block for each vertex.
Returns:
average metric value for element

Definition at line 332 of file AveragingQM.cpp.

References MBMesquite::average_corner_diagonals(), and avgMethod.

Referenced by AveragingQMTest::check_hessian_diagonal_fails(), AveragingQMTest::check_pmean_hessian_diagonals(), MBMesquite::IdealWeightMeanRatio::evaluate_with_Hessian_diagonal(), and MBMesquite::IdealWeightInverseMeanRatio::evaluate_with_Hessian_diagonal().

{
    return average_corner_diagonals( element_type, avgMethod, num_corners, corner_values, corner_grads,
                                     CornerHessDiagIterator( corner_hessians, element_type ), vertex_grads,
                                     vertex_hessians, err );
}
double MBMesquite::AveragingQM::average_corner_hessian_diagonals ( EntityTopology  element_type,
uint32_t  fixed_vertices,
unsigned  num_corners,
const double  corner_values[],
const Vector3D  corner_grads[],
const SymMatrix3D  corner_hess_diag[],
Vector3D  vertex_grads[],
SymMatrix3D  vertex_hessians[],
MsqError err 
)

Average metric values, gradients, and Hessian diagonal blocks for per-corner evaluation.

Parameters:
element_typeThe element type
num_cornersThe number of corners (e.g. pass 4 for a pyramid if the metric couldn't be evaluated for the apex)
corner_valuesAn array of metric values, one per element corner
corner_gradsThe corner gradients, 4 for each corner
corner_hess_diagThe diagonal blocks of the Hessian: 4 for each corner.
vertex_gradsOutput. Gradient at each vertex.
vertex_hessiansOutput. Hessian diagonal block for each vertex.
Returns:
average metric value for element

Definition at line 342 of file AveragingQM.cpp.

References MBMesquite::average_corner_diagonals(), and avgMethod.

{
    return average_corner_diagonals( element_type, avgMethod, num_corners, corner_values, corner_grads,
                                     corner_hess_diag, vertex_grads, vertex_hessians, err );
}
double MBMesquite::AveragingQM::average_corner_hessians ( EntityTopology  element_type,
uint32_t  fixed_vertices,
unsigned  num_corners,
const double  corner_values[],
const Vector3D  corner_grads[],
const Matrix3D  corner_hessians[],
Vector3D  vertex_grads[],
Matrix3D  vertex_hessians[],
MsqError err 
)

Average metric values, gradients, and Hessians for per-corner evaluation.

Parameters:
element_typeThe element type
num_cornersThe number of corners (e.g. pass 4 for a pyramid if the metric couldn't be evaluated for the apex)
corner_valuesAn array of metric values, one per element corner
corner_gradsThe corner gradients, 4 for each corner
corner_hessiansThe hessians, 10 for each corner
vertex_gradsOutput. Gradient at each vertex.
vertex_hessiansOutput. Hessians. Length must be (n*(n+1))/2, where n is the number of vertices in the element.
Returns:
average metric value for element

Definition at line 514 of file AveragingQM.cpp.

References avgMethod, corners, MBMesquite::QualityMetric::HARMONIC, MBMesquite::QualityMetric::HMS, MBMesquite::inv(), MBMesquite::MsqError::INVALID_STATE, MBMesquite::QualityMetric::LINEAR, MSQ_SETERR, MBMesquite::pmean_corner_hessians(), MBMesquite::QualityMetric::RMS, MBMesquite::QualityMetric::SUM, MBMesquite::sum_corner_hessians(), MBMesquite::sum_sqr_corner_hessians(), and MBMesquite::QualityMetric::SUM_SQUARED.

Referenced by AveragingQMTest::check_hessian_fails(), AveragingQMTest::check_pmean_hessian(), MBMesquite::IdealWeightMeanRatio::evaluate_with_Hessian(), and MBMesquite::IdealWeightInverseMeanRatio::evaluate_with_Hessian().

{
    unsigned i;
    double avg, inv;

    // Zero gradients and Hessians
    const unsigned num_vertex = TopologyInfo::corners( type );
    for( i = 0; i < num_vertex; ++i )
        vertex_grads[i].set( 0.0 );
    const unsigned num_hess = num_vertex * ( num_vertex + 1 ) / 2;
    for( i = 0; i < num_hess; ++i )
        vertex_hessians[i].zero();

    switch( avgMethod )
    {
        case QualityMetric::SUM:
            avg = sum_corner_hessians( type, num_corner, corner_values, corner_grads, corner_hessians, vertex_grads,
                                       vertex_hessians );
            break;

        case QualityMetric::LINEAR:
            avg = sum_corner_hessians( type, num_corner, corner_values, corner_grads, corner_hessians, vertex_grads,
                                       vertex_hessians );
            inv = 1.0 / num_corner;
            avg *= inv;
            for( i = 0; i < num_vertex; ++i )
                vertex_grads[i] *= inv;
            for( i = 0; i < num_hess; ++i )
                vertex_hessians[i] *= inv;
            break;

        case QualityMetric::SUM_SQUARED:
            avg = sum_sqr_corner_hessians( type, num_corner, corner_values, corner_grads, corner_hessians, vertex_grads,
                                           vertex_hessians );
            break;

        case QualityMetric::RMS:
            avg = pmean_corner_hessians( type, num_corner, corner_values, corner_grads, corner_hessians, vertex_grads,
                                         vertex_hessians, 2.0 );
            break;

        case QualityMetric::HARMONIC:
            avg = pmean_corner_hessians( type, num_corner, corner_values, corner_grads, corner_hessians, vertex_grads,
                                         vertex_hessians, -1.0 );
            break;

        case QualityMetric::HMS:
            avg = pmean_corner_hessians( type, num_corner, corner_values, corner_grads, corner_hessians, vertex_grads,
                                         vertex_hessians, -2.0 );
            break;

        default:
            MSQ_SETERR( err )( "averaging method not available.", MsqError::INVALID_STATE );
            return 0.0;
    }

    return avg;
}
double MBMesquite::AveragingQM::average_metric_and_weights ( double  metric_values[],
int  num_metric_values,
MsqError err 
)

Given a list of metric values, calculate the average metric valude according to the current avgMethod and write into the passed metric_values array the the value weight/count to use when averaging gradient vectors for the metric.

Parameters:
metric_values: As input, a set of quality metric values to average. As output, the fraction of the corresponding gradient vector that contributes to the average gradient.
num_metric_valuesThe number of values in the passed array.

Definition at line 576 of file AveragingQM.cpp.

References avgMethod, MBMesquite::QualityMetric::GEOMETRIC, MBMesquite::QualityMetric::HARMONIC, MBMesquite::QualityMetric::HMS, MBMesquite::MsqError::INVALID_STATE, MBMesquite::QualityMetric::LINEAR, MBMesquite::QualityMetric::MAXIMUM, MBMesquite::QualityMetric::MINIMUM, MSQ_DBGOUT, MBMesquite::MSQ_MIN, MSQ_SETERR, MBMesquite::QualityMetric::RMS, MBMesquite::QualityMetric::SUM, and MBMesquite::QualityMetric::SUM_SQUARED.

Referenced by average_corner_gradients(), AveragingQMTest::check_average_and_weights(), AveragingQMTest::check_average_and_weights_fails(), and AveragingQMTest::check_average_gradients().

{
    static bool min_max_warning = false;
    double avg                  = 0.0;
    int i, tmp_count;
    double f;

    switch( avgMethod )
    {

        case QualityMetric::MINIMUM:
            if( !min_max_warning )
            {
                MSQ_DBGOUT( 1 ) << "Minimum and maximum not continuously differentiable.\n"
                                   "Element of subdifferential will be returned.\n";
                min_max_warning = true;
            }

            avg = metrics[0];
            for( i = 1; i < count; ++i )
                if( metrics[i] < avg ) avg = metrics[i];

            tmp_count = 0;
            for( i = 0; i < count; ++i )
            {
                if( metrics[i] - avg <= MSQ_MIN )
                {
                    metrics[i] = 1.0;
                    ++tmp_count;
                }
                else
                {
                    metrics[i] = 0.0;
                }
            }

            f = 1.0 / tmp_count;
            for( i = 0; i < count; ++i )
                metrics[i] *= f;

            break;

        case QualityMetric::MAXIMUM:
            if( !min_max_warning )
            {
                MSQ_DBGOUT( 1 ) << "Minimum and maximum not continuously differentiable.\n"
                                   "Element of subdifferential will be returned.\n";
                min_max_warning = true;
            }

            avg = metrics[0];
            for( i = 1; i < count; ++i )
                if( metrics[i] > avg ) avg = metrics[i];

            tmp_count = 0;
            for( i = 0; i < count; ++i )
            {
                if( avg - metrics[i] <= MSQ_MIN )
                {
                    metrics[i] = 1.0;
                    ++tmp_count;
                }
                else
                {
                    metrics[i] = 0.0;
                }
            }

            f = 1.0 / tmp_count;
            for( i = 0; i < count; ++i )
                metrics[i] *= f;

            break;

        case QualityMetric::SUM:
            for( i = 0; i < count; ++i )
            {
                avg += metrics[i];
                metrics[i] = 1.0;
            }

            break;

        case QualityMetric::SUM_SQUARED:
            for( i = 0; i < count; ++i )
            {
                avg += ( metrics[i] * metrics[i] );
                metrics[i] *= 2;
            }

            break;

        case QualityMetric::LINEAR:
            f = 1.0 / count;
            for( i = 0; i < count; ++i )
            {
                avg += metrics[i];
                metrics[i] = f;
            }
            avg *= f;

            break;

        case QualityMetric::GEOMETRIC:
            avg = 1.0;
            for( i = 0; i < count; ++i )
                avg *= metrics[i];
            avg = pow( avg, 1.0 / count );

            f = avg / count;
            for( i = 0; i < count; ++i )
                metrics[i] = f / metrics[i];

            break;

        case QualityMetric::RMS:
            for( i = 0; i < count; ++i )
                avg += metrics[i] * metrics[i];
            avg = sqrt( avg / count );

            f = 1. / ( avg * count );
            for( i = 0; i < count; ++i )
                metrics[i] *= f;

            break;

        case QualityMetric::HARMONIC:
            for( i = 0; i < count; ++i )
                avg += 1.0 / metrics[i];
            avg = count / avg;

            for( i = 0; i < count; ++i )
                metrics[i] = ( avg * avg ) / ( count * metrics[i] * metrics[i] );

            break;

        case QualityMetric::HMS:
            for( i = 0; i < count; ++i )
                avg += 1. / ( metrics[i] * metrics[i] );
            avg = sqrt( count / avg );

            f = avg * avg * avg / count;
            for( i = 0; i < count; ++i )
                metrics[i] = f / ( metrics[i] * metrics[i] * metrics[i] );

            break;

        default:
            MSQ_SETERR( err )( "averaging method not available.", MsqError::INVALID_STATE );
    }

    return avg;
}
double MBMesquite::AveragingQM::average_metrics ( const double  metric_values[],
int  num_values,
MsqError err 
)

average_metrics takes an array of length num_values and averages the contents using averaging method data member avgMethod .

average_metrics takes an array of length num_value and averages the contents using averaging method 'method'.

Definition at line 734 of file AveragingQM.cpp.

References avgMethod, MBMesquite::QualityMetric::GEOMETRIC, MBMesquite::QualityMetric::HARMONIC, MBMesquite::QualityMetric::HMS, MBMesquite::QualityMetric::LINEAR, MBMesquite::QualityMetric::MAX_MINUS_MIN, MBMesquite::QualityMetric::MAX_OVER_MIN, MBMesquite::QualityMetric::MAXIMUM, MBMesquite::QualityMetric::MINIMUM, MBMesquite::MSQ_MAX_CAP, MBMesquite::MSQ_MIN, MSQ_SETERR, NOT_IMPLEMENTED, MBMesquite::QualityMetric::RMS, MBMesquite::QualityMetric::STANDARD_DEVIATION, MBMesquite::QualityMetric::SUM, MBMesquite::QualityMetric::SUM_OF_RATIOS_SQUARED, and MBMesquite::QualityMetric::SUM_SQUARED.

Referenced by AveragingQMTest::check_average_and_weights(), MBMesquite::VertexConditionNumberQualityMetric::evaluate(), MBMesquite::LocalSizeQualityMetric::evaluate(), MBMesquite::ConditionNumberQualityMetric::evaluate(), MBMesquite::IdealWeightMeanRatio::evaluate(), MBMesquite::UntangleBetaQualityMetric::evaluate(), MBMesquite::IdealWeightInverseMeanRatio::evaluate(), MBMesquite::EdgeLengthQualityMetric::evaluate_common(), MBMesquite::EdgeLengthRangeQualityMetric::evaluate_common(), AveragingQMTest::test_average_metrics_geometric(), AveragingQMTest::test_average_metrics_harmonic(), AveragingQMTest::test_average_metrics_hms(), AveragingQMTest::test_average_metrics_liner(), AveragingQMTest::test_average_metrics_max_minus_min(), AveragingQMTest::test_average_metrics_max_over_min(), AveragingQMTest::test_average_metrics_maximum(), AveragingQMTest::test_average_metrics_minimum(), AveragingQMTest::test_average_metrics_rms(), AveragingQMTest::test_average_metrics_standard_deviation(), AveragingQMTest::test_average_metrics_sum(), AveragingQMTest::test_average_metrics_sum_of_ratios_squared(), and AveragingQMTest::test_average_metrics_sum_squared().

{
    // MSQ_MAX needs to be made global?
    // double MSQ_MAX=1e10;
    double total_value = 0.0;
    double temp_value  = 0.0;
    int i              = 0;
    int j              = 0;
    // if no values, return zero
    if( num_values <= 0 ) { return 0.0; }

    switch( avgMethod )
    {
        case QualityMetric::GEOMETRIC:
            total_value = 1.0;
            for( i = 0; i < num_values; ++i )
            {
                total_value *= ( metric_values[i] );
            }
            total_value = pow( total_value, 1.0 / num_values );
            break;

        case QualityMetric::HARMONIC:
            // ensure no divide by zero, return zero
            for( i = 0; i < num_values; ++i )
            {
                if( metric_values[i] < MSQ_MIN )
                {
                    if( metric_values[i] > MSQ_MIN ) { return 0.0; }
                }
                total_value += ( 1 / metric_values[i] );
            }
            // ensure no divide by zero, return MSQ_MAX_CAP
            if( total_value < MSQ_MIN )
            {
                if( total_value > MSQ_MIN ) { return MSQ_MAX_CAP; }
            }
            total_value = num_values / total_value;
            break;

        case QualityMetric::LINEAR:
            for( i = 0; i < num_values; ++i )
            {
                total_value += metric_values[i];
            }
            total_value /= (double)num_values;
            break;

        case QualityMetric::MAXIMUM:
            total_value = metric_values[0];
            for( i = 1; i < num_values; ++i )
            {
                if( metric_values[i] > total_value ) { total_value = metric_values[i]; }
            }
            break;

        case QualityMetric::MINIMUM:
            total_value = metric_values[0];
            for( i = 1; i < num_values; ++i )
            {
                if( metric_values[i] < total_value ) { total_value = metric_values[i]; }
            }
            break;

        case QualityMetric::RMS:
            for( i = 0; i < num_values; ++i )
            {
                total_value += ( metric_values[i] * metric_values[i] );
            }
            total_value /= (double)num_values;
            total_value = sqrt( total_value );
            break;

        case QualityMetric::HMS:
            // ensure no divide by zero, return zero
            for( i = 0; i < num_values; ++i )
            {
                if( metric_values[i] * metric_values[i] < MSQ_MIN ) { return 0.0; }
                total_value += ( 1.0 / ( metric_values[i] * metric_values[i] ) );
            }

            // ensure no divide by zero, return MSQ_MAX_CAP
            if( total_value < MSQ_MIN ) { return MSQ_MAX_CAP; }
            total_value = sqrt( num_values / total_value );
            break;

        case QualityMetric::STANDARD_DEVIATION:
            total_value = 0;
            temp_value  = 0;
            for( i = 0; i < num_values; ++i )
            {
                temp_value += metric_values[i];
                total_value += ( metric_values[i] * metric_values[i] );
            }
            temp_value /= (double)num_values;
            temp_value *= temp_value;
            total_value /= (double)num_values;
            total_value = total_value - temp_value;
            break;

        case QualityMetric::SUM:
            for( i = 0; i < num_values; ++i )
            {
                total_value += metric_values[i];
            }
            break;

        case QualityMetric::SUM_SQUARED:
            for( i = 0; i < num_values; ++i )
            {
                total_value += ( metric_values[i] * metric_values[i] );
            }
            break;

        case QualityMetric::MAX_MINUS_MIN:
            // total_value used to store the maximum
            // temp_value used to store the minimum
            temp_value = MSQ_MAX_CAP;
            for( i = 0; i < num_values; ++i )
            {
                if( metric_values[i] < temp_value ) { temp_value = metric_values[i]; }
                if( metric_values[i] > total_value ) { total_value = metric_values[i]; }
            }

            total_value -= temp_value;
            break;

        case QualityMetric::MAX_OVER_MIN:
            // total_value used to store the maximum
            // temp_value used to store the minimum
            temp_value = MSQ_MAX_CAP;
            for( i = 0; i < num_values; ++i )
            {
                if( metric_values[i] < temp_value ) { temp_value = metric_values[i]; }
                if( metric_values[i] > total_value ) { total_value = metric_values[i]; }
            }

            // ensure no divide by zero, return MSQ_MAX_CAP
            if( fabs( temp_value ) < MSQ_MIN ) { return MSQ_MAX_CAP; }
            total_value /= temp_value;
            break;

        case QualityMetric::SUM_OF_RATIOS_SQUARED:
            for( j = 0; j < num_values; ++j )
            {
                // ensure no divide by zero, return MSQ_MAX_CAP
                if( fabs( metric_values[j] ) < MSQ_MIN ) { return MSQ_MAX_CAP; }
                for( i = 0; i < num_values; ++i )
                {
                    total_value +=
                        ( ( metric_values[i] / metric_values[j] ) * ( metric_values[i] / metric_values[j] ) );
                }
            }
            total_value /= (double)( num_values * num_values );
            break;

        default:
            // Return error saying Averaging Method mode not implemented
            MSQ_SETERR( err )
            ( "Requested Averaging Method Not Implemented", MsqError::NOT_IMPLEMENTED );
            return 0;
    }
    return total_value;
}

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