Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
#include "moab/verdict.h"
#include "verdict_defines.hpp"
#include "V_GaussIntegration.hpp"
#include "VerdictVector.hpp"
#include <memory.h>
#include <cstddef>
Go to the source code of this file.
Defines | |
#define | VERDICT_EXPORTS |
Functions | |
static int | v_tri_get_weight (double &m11, double &m21, double &m12, double &m22) |
C_FUNC_DEF void | v_set_tri_size (double size) |
Sets average size (area) of tri, needed for v_tri_relative_size(...) | |
C_FUNC_DEF void | v_set_tri_normal_func (ComputeNormal func) |
Sets fuction pointer to calculate tri normal wrt surface. | |
C_FUNC_DEF double | v_tri_edge_ratio (int, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_aspect_ratio (int, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_radius_ratio (int, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_aspect_frobenius (int, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_area (int, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_minimum_angle (int, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_maximum_angle (int, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_condition (int, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_scaled_jacobian (int, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_shape (int num_nodes, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_relative_size_squared (int, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_shape_and_size (int num_nodes, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF double | v_tri_distortion (int num_nodes, double coordinates[][3]) |
Calculates tri metric. | |
C_FUNC_DEF void | v_tri_quality (int num_nodes, double coordinates[][3], unsigned int metrics_request_flag, TriMetricVals *metric_vals) |
Calculates quality metrics for triangle elements. | |
Variables | |
static double | verdict_tri_size = 0 |
static ComputeNormal | compute_normal = NULL |
#define VERDICT_EXPORTS |
Definition at line 23 of file V_TriMetric.cpp.
C_FUNC_DEF void v_set_tri_normal_func | ( | ComputeNormal | func | ) |
Sets fuction pointer to calculate tri normal wrt surface.
Definition at line 63 of file V_TriMetric.cpp.
References compute_normal.
{ compute_normal = func; }
C_FUNC_DEF void v_set_tri_size | ( | double | size | ) |
Sets average size (area) of tri, needed for v_tri_relative_size(...)
sets the average area of a tri
Definition at line 58 of file V_TriMetric.cpp.
References size, and verdict_tri_size.
Referenced by moab::VerdictWrapper::set_size().
{ verdict_tri_size = size; }
C_FUNC_DEF double v_tri_area | ( | int | , |
double | coordinates[][3] | ||
) |
Calculates tri metric.
The area of a tri
0.5 * jacobian at a node
Definition at line 278 of file V_TriMetric.cpp.
References VerdictVector::length(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), v_quad_jacobian(), and v_quad_quality().
{ // two vectors for two sides VerdictVector side1( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], coordinates[1][2] - coordinates[0][2] ); VerdictVector side3( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1], coordinates[2][2] - coordinates[0][2] ); // the cross product of the two vectors representing two sides of the // triangle VerdictVector tmp = side1 * side3; // return the magnitude of the vector divided by two double area = 0.5 * tmp.length(); if( area > 0 ) return (double)VERDICT_MIN( area, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( area, -VERDICT_DBL_MAX ); }
C_FUNC_DEF double v_tri_aspect_frobenius | ( | int | , |
double | coordinates[][3] | ||
) |
Calculates tri metric.
the Frobenius aspect of a tri
srms^2/(2 * sqrt(3.0) * area) where srms^2 is sum of the lengths squared
NB (P. Pebay 01/14/07): this method was called "aspect ratio" in earlier incarnations of VERDICT
Definition at line 246 of file V_TriMetric.cpp.
References VerdictVector::length_squared(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
{ static const double two_times_root_of_3 = 2 * sqrt( 3.0 ); // three vectors for each side VerdictVector side1( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], coordinates[1][2] - coordinates[0][2] ); VerdictVector side2( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1], coordinates[2][2] - coordinates[1][2] ); VerdictVector side3( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1], coordinates[0][2] - coordinates[2][2] ); // sum the lengths squared of each side double srms = ( side1.length_squared() + side2.length_squared() + side3.length_squared() ); // find two times the area of the triangle by cross product double areaX2 = ( ( side1 * ( -side3 ) ).length() ); if( areaX2 == 0.0 ) return (double)VERDICT_DBL_MAX; double aspect = (double)( srms / ( two_times_root_of_3 * ( areaX2 ) ) ); if( aspect > 0 ) return (double)VERDICT_MIN( aspect, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( aspect, -VERDICT_DBL_MAX ); }
C_FUNC_DEF double v_tri_aspect_ratio | ( | int | , |
double | coordinates[][3] | ||
) |
Calculates tri metric.
the aspect ratio of a triangle
NB (P. Pebay 01/14/07): Hmax / ( 2.0 * sqrt(3.0) * IR) where Hmax is the maximum edge length and IR is the inradius
note that previous incarnations of verdict used "v_tri_aspect_ratio" to denote what is now called "v_tri_aspect_frobenius"
Definition at line 160 of file V_TriMetric.cpp.
References VerdictVector::length(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
{ static const double normal_coeff = sqrt( 3. ) / 6.; // three vectors for each side VerdictVector a( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], coordinates[1][2] - coordinates[0][2] ); VerdictVector b( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1], coordinates[2][2] - coordinates[1][2] ); VerdictVector c( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1], coordinates[0][2] - coordinates[2][2] ); double a1 = a.length(); double b1 = b.length(); double c1 = c.length(); double hm = a1 > b1 ? a1 : b1; hm = hm > c1 ? hm : c1; VerdictVector ab = a * b; double denominator = ab.length(); if( denominator < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX; else { double aspect_ratio; aspect_ratio = normal_coeff * hm * ( a1 + b1 + c1 ) / denominator; if( aspect_ratio > 0 ) return (double)VERDICT_MIN( aspect_ratio, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( aspect_ratio, -VERDICT_DBL_MAX ); } }
C_FUNC_DEF double v_tri_condition | ( | int | , |
double | coordinates[][3] | ||
) |
Calculates tri metric.
The condition of a tri
Condition number of the jacobian matrix at any corner
Definition at line 421 of file V_TriMetric.cpp.
References compute_normal, VerdictVector::length(), VERDICT_DBL_MAX, VERDICT_MIN, VerdictVector::x(), VerdictVector::y(), and VerdictVector::z().
Referenced by moab::VerdictWrapper::quality_measure(), v_quad_condition(), and v_tri_shape().
{ static const double rt3 = sqrt( 3.0 ); VerdictVector v1( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], coordinates[1][2] - coordinates[0][2] ); VerdictVector v2( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1], coordinates[2][2] - coordinates[0][2] ); VerdictVector tri_normal = v1 * v2; double areax2 = tri_normal.length(); if( areax2 == 0.0 ) return (double)VERDICT_DBL_MAX; double condition = (double)( ( ( v1 % v1 ) + ( v2 % v2 ) - ( v1 % v2 ) ) / ( areax2 * rt3 ) ); // check for inverted if we have access to the normal if( compute_normal ) { // center of tri double point[3], surf_normal[3]; point[0] = ( coordinates[0][0] + coordinates[1][0] + coordinates[2][0] ) / 3; point[1] = ( coordinates[0][1] + coordinates[1][1] + coordinates[2][1] ) / 3; point[2] = ( coordinates[0][2] + coordinates[1][2] + coordinates[2][2] ) / 3; // dot product compute_normal( point, surf_normal ); if( ( tri_normal.x() * surf_normal[0] + tri_normal.y() * surf_normal[1] + tri_normal.z() * surf_normal[2] ) < 0 ) return (double)VERDICT_DBL_MAX; } return (double)VERDICT_MIN( condition, VERDICT_DBL_MAX ); }
C_FUNC_DEF double v_tri_distortion | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
The distortion of a tri
TODO: make a short definition of the distortion and comment below
Definition at line 588 of file V_TriMetric.cpp.
References GaussIntegration::calculate_derivative_at_nodes_2d_tri(), GaussIntegration::calculate_shape_function_2d_tri(), dot_product(), GaussIntegration::get_shape_func(), GaussIntegration::initialize(), VerdictVector::length(), maxNumberNodes, maxTotalNumberGaussPoints, VerdictVector::normalize(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tri_quality().
{ double distortion; int total_number_of_gauss_points = 0; VerdictVector aa, bb, cc, normal_at_point, xin; double element_area = 0.; aa.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], coordinates[1][2] - coordinates[0][2] ); bb.set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1], coordinates[2][2] - coordinates[0][2] ); VerdictVector tri_normal = aa * bb; int number_of_gauss_points = 0; if( num_nodes == 3 ) { distortion = 1.0; return (double)distortion; } else if( num_nodes == 6 ) { total_number_of_gauss_points = 6; number_of_gauss_points = 6; } distortion = VERDICT_DBL_MAX; double shape_function[maxTotalNumberGaussPoints][maxNumberNodes]; double dndy1[maxTotalNumberGaussPoints][maxNumberNodes]; double dndy2[maxTotalNumberGaussPoints][maxNumberNodes]; double weight[maxTotalNumberGaussPoints]; // create an object of GaussIntegration int number_dims = 2; int is_tri = 1; GaussIntegration::initialize( number_of_gauss_points, num_nodes, number_dims, is_tri ); GaussIntegration::calculate_shape_function_2d_tri(); GaussIntegration::get_shape_func( shape_function[0], dndy1[0], dndy2[0], weight ); // calculate element area int ife, ja; for( ife = 0; ife < total_number_of_gauss_points; ife++ ) { aa.set( 0.0, 0.0, 0.0 ); bb.set( 0.0, 0.0, 0.0 ); for( ja = 0; ja < num_nodes; ja++ ) { xin.set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] ); aa += dndy1[ife][ja] * xin; bb += dndy2[ife][ja] * xin; } normal_at_point = aa * bb; double jacobian = normal_at_point.length(); element_area += weight[ife] * jacobian; } element_area *= 0.8660254; double dndy1_at_node[maxNumberNodes][maxNumberNodes]; double dndy2_at_node[maxNumberNodes][maxNumberNodes]; GaussIntegration::calculate_derivative_at_nodes_2d_tri( dndy1_at_node, dndy2_at_node ); VerdictVector normal_at_nodes[7]; // evaluate normal at nodes and distortion values at nodes int jai = 0; for( ja = 0; ja < num_nodes; ja++ ) { aa.set( 0.0, 0.0, 0.0 ); bb.set( 0.0, 0.0, 0.0 ); for( jai = 0; jai < num_nodes; jai++ ) { xin.set( coordinates[jai][0], coordinates[jai][1], coordinates[jai][2] ); aa += dndy1_at_node[ja][jai] * xin; bb += dndy2_at_node[ja][jai] * xin; } normal_at_nodes[ja] = aa * bb; normal_at_nodes[ja].normalize(); } // determine if element is flat bool flat_element = true; double dot_product; for( ja = 0; ja < num_nodes; ja++ ) { dot_product = normal_at_nodes[0] % normal_at_nodes[ja]; if( fabs( dot_product ) < 0.99 ) { flat_element = false; break; } } // take into consideration of the thickness of the element double thickness, thickness_gauss; double distrt; // get_tri_thickness(tri, element_area, thickness ); thickness = 0.001 * sqrt( element_area ); // set thickness gauss point location double zl = 0.5773502691896; if( flat_element ) zl = 0.0; int no_gauss_pts_z = ( flat_element ) ? 1 : 2; double thickness_z; // loop on integration points int igz; for( ife = 0; ife < total_number_of_gauss_points; ife++ ) { // loop on the thickness direction gauss points for( igz = 0; igz < no_gauss_pts_z; igz++ ) { zl = -zl; thickness_z = zl * thickness / 2.0; aa.set( 0.0, 0.0, 0.0 ); bb.set( 0.0, 0.0, 0.0 ); cc.set( 0.0, 0.0, 0.0 ); for( ja = 0; ja < num_nodes; ja++ ) { xin.set( coordinates[jai][0], coordinates[jai][1], coordinates[jai][2] ); xin += thickness_z * normal_at_nodes[ja]; aa += dndy1[ife][ja] * xin; bb += dndy2[ife][ja] * xin; thickness_gauss = shape_function[ife][ja] * thickness / 2.0; cc += thickness_gauss * normal_at_nodes[ja]; } normal_at_point = aa * bb; distrt = cc % normal_at_point; if( distrt < distortion ) distortion = distrt; } } // loop through nodal points for( ja = 0; ja < num_nodes; ja++ ) { for( igz = 0; igz < no_gauss_pts_z; igz++ ) { zl = -zl; thickness_z = zl * thickness / 2.0; aa.set( 0.0, 0.0, 0.0 ); bb.set( 0.0, 0.0, 0.0 ); cc.set( 0.0, 0.0, 0.0 ); for( jai = 0; jai < num_nodes; jai++ ) { xin.set( coordinates[jai][0], coordinates[jai][1], coordinates[jai][2] ); xin += thickness_z * normal_at_nodes[ja]; aa += dndy1_at_node[ja][jai] * xin; bb += dndy2_at_node[ja][jai] * xin; if( jai == ja ) thickness_gauss = thickness / 2.0; else thickness_gauss = 0.; cc += thickness_gauss * normal_at_nodes[jai]; } } normal_at_point = aa * bb; double sign_jacobian = ( tri_normal % normal_at_point ) > 0 ? 1. : -1.; distrt = sign_jacobian * ( cc % normal_at_point ); if( distrt < distortion ) distortion = distrt; } if( element_area * thickness != 0 ) distortion *= 1. / ( element_area * thickness ); else distortion *= 1.; if( distortion > 0 ) return (double)VERDICT_MIN( distortion, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( distortion, -VERDICT_DBL_MAX ); }
C_FUNC_DEF double v_tri_edge_ratio | ( | int | , |
double | coordinates[][3] | ||
) |
Calculates tri metric.
the edge ratio of a triangle
NB (P. Pebay 01/14/07): Hmax / Hmin where Hmax and Hmin are respectively the maximum and the minimum edge lengths
Definition at line 76 of file V_TriMetric.cpp.
References VerdictVector::length_squared(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tri_quality().
{ // three vectors for each side VerdictVector a( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], coordinates[1][2] - coordinates[0][2] ); VerdictVector b( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1], coordinates[2][2] - coordinates[1][2] ); VerdictVector c( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1], coordinates[0][2] - coordinates[2][2] ); double a2 = a.length_squared(); double b2 = b.length_squared(); double c2 = c.length_squared(); double m2, M2; if( a2 < b2 ) { if( b2 < c2 ) { m2 = a2; M2 = c2; } else // b2 <= a2 { if( a2 < c2 ) { m2 = a2; M2 = b2; } else // c2 <= a2 { m2 = c2; M2 = b2; } } } else // b2 <= a2 { if( a2 < c2 ) { m2 = b2; M2 = c2; } else // c2 <= a2 { if( b2 < c2 ) { m2 = b2; M2 = a2; } else // c2 <= b2 { m2 = c2; M2 = a2; } } } if( m2 < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX; else { double edge_ratio; edge_ratio = sqrt( M2 / m2 ); if( edge_ratio > 0 ) return (double)VERDICT_MIN( edge_ratio, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( edge_ratio, -VERDICT_DBL_MAX ); } }
static int v_tri_get_weight | ( | double & | m11, |
double & | m21, | ||
double & | m12, | ||
double & | m22 | ||
) | [static] |
get weights based on the average area of a set of tris
Definition at line 40 of file V_TriMetric.cpp.
References verdict_tri_size.
Referenced by v_tri_quality(), and v_tri_relative_size_squared().
{ static const double rootOf3 = sqrt( 3.0 ); m11 = 1; m21 = 0; m12 = 0.5; m22 = 0.5 * rootOf3; double scale = sqrt( 2.0 * verdict_tri_size / ( m11 * m22 - m21 * m12 ) ); m11 *= scale; m21 *= scale; m12 *= scale; m22 *= scale; return 1; }
C_FUNC_DEF double v_tri_maximum_angle | ( | int | , |
double | coordinates[][3] | ||
) |
Calculates tri metric.
The maximum angle of a tri
The maximum angle of a tri is the maximum angle between two adjacents sides out of all three corners of the triangle.
Definition at line 361 of file V_TriMetric.cpp.
References VerdictVector::interior_angle(), VerdictVector::length_squared(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), v_quad_maximum_angle(), and v_quad_quality().
{ // vectors for all the sides VerdictVector sides[4]; sides[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], coordinates[1][2] - coordinates[0][2] ); sides[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1], coordinates[2][2] - coordinates[1][2] ); sides[2].set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1], coordinates[2][2] - coordinates[0][2] ); // in case we need to find the interior angle // between sides 0 and 1 sides[3] = -sides[1]; // calculate the lengths squared of the sides double sides_lengths[3]; sides_lengths[0] = sides[0].length_squared(); sides_lengths[1] = sides[1].length_squared(); sides_lengths[2] = sides[2].length_squared(); if( sides_lengths[0] == 0.0 || sides_lengths[1] == 0.0 || sides_lengths[2] == 0.0 ) { return 0.0; } // using the law of sines, we know that the maximum // angle is opposite of the longest side // find the longest side int short_side = 0; if( sides_lengths[1] > sides_lengths[0] ) short_side = 1; if( sides_lengths[2] > sides_lengths[short_side] ) short_side = 2; // from the longest side, calculate the angle of the // opposite angle double max_angle; if( short_side == 0 ) { max_angle = sides[2].interior_angle( sides[1] ); } else if( short_side == 1 ) { max_angle = sides[0].interior_angle( sides[2] ); } else { max_angle = sides[0].interior_angle( sides[3] ); } if( max_angle > 0 ) return (double)VERDICT_MIN( max_angle, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( max_angle, -VERDICT_DBL_MAX ); }
C_FUNC_DEF double v_tri_minimum_angle | ( | int | , |
double | coordinates[][3] | ||
) |
Calculates tri metric.
The minimum angle of a tri
The minimum angle of a tri is the minimum angle between two adjacents sides out of all three corners of the triangle.
Definition at line 303 of file V_TriMetric.cpp.
References VerdictVector::interior_angle(), VerdictVector::length_squared(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), v_quad_minimum_angle(), and v_quad_quality().
{ // vectors for all the sides VerdictVector sides[4]; sides[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], coordinates[1][2] - coordinates[0][2] ); sides[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1], coordinates[2][2] - coordinates[1][2] ); sides[2].set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1], coordinates[2][2] - coordinates[0][2] ); // in case we need to find the interior angle // between sides 0 and 1 sides[3] = -sides[1]; // calculate the lengths squared of the sides double sides_lengths[3]; sides_lengths[0] = sides[0].length_squared(); sides_lengths[1] = sides[1].length_squared(); sides_lengths[2] = sides[2].length_squared(); if( sides_lengths[0] == 0.0 || sides_lengths[1] == 0.0 || sides_lengths[2] == 0.0 ) return 0.0; // using the law of sines, we know that the minimum // angle is opposite of the shortest side // find the shortest side int short_side = 0; if( sides_lengths[1] < sides_lengths[0] ) short_side = 1; if( sides_lengths[2] < sides_lengths[short_side] ) short_side = 2; // from the shortest side, calculate the angle of the // opposite angle double min_angle; if( short_side == 0 ) { min_angle = sides[2].interior_angle( sides[1] ); } else if( short_side == 1 ) { min_angle = sides[0].interior_angle( sides[2] ); } else { min_angle = sides[0].interior_angle( sides[3] ); } if( min_angle > 0 ) return (double)VERDICT_MIN( min_angle, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( min_angle, -VERDICT_DBL_MAX ); }
C_FUNC_DEF void v_tri_quality | ( | int | num_nodes, |
double | coordinates[][3], | ||
unsigned int | metrics_request_flag, | ||
TriMetricVals * | metric_vals | ||
) |
Calculates quality metrics for triangle elements.
tri_quality for calculating multiple tri metrics at once
using this method is generally faster than using the individual method multiple times.
Definition at line 777 of file V_TriMetric.cpp.
References TriMetricVals::area, TriMetricVals::aspect_frobenius, TriMetricVals::aspect_ratio, compute_normal, TriMetricVals::condition, determinant(), TriMetricVals::distortion, TriMetricVals::edge_ratio, interior_angle(), length(), VerdictVector::length(), TriMetricVals::maximum_angle, TriMetricVals::minimum_angle, TriMetricVals::radius_ratio, TriMetricVals::relative_size_squared, TriMetricVals::scaled_jacobian, VerdictVector::set(), TriMetricVals::shape, TriMetricVals::shape_and_size, size, V_TRI_AREA, V_TRI_ASPECT_FROBENIUS, V_TRI_CONDITION, V_TRI_DISTORTION, v_tri_distortion(), V_TRI_EDGE_RATIO, v_tri_edge_ratio(), v_tri_get_weight(), V_TRI_MAXIMUM_ANGLE, V_TRI_MINIMUM_ANGLE, V_TRI_RADIUS_RATIO, v_tri_radius_ratio(), V_TRI_RELATIVE_SIZE_SQUARED, V_TRI_SCALED_JACOBIAN, V_TRI_SHAPE, V_TRI_SHAPE_AND_SIZE, VERDICT_DBL_MAX, VERDICT_MAX, VERDICT_MIN, VerdictVector::x(), VerdictVector::y(), and VerdictVector::z().
Referenced by moab::VerdictWrapper::all_quality_measures().
{ memset( metric_vals, 0, sizeof( TriMetricVals ) ); // for starts, lets set up some basic and common information /* node numbers and side numbers used below 2 ++ / \ 2 / \ 1 / \ / \ 0 ---------+ 1 0 */ // vectors for each side VerdictVector sides[3]; sides[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], coordinates[1][2] - coordinates[0][2] ); sides[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1], coordinates[2][2] - coordinates[1][2] ); sides[2].set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1], coordinates[2][2] - coordinates[0][2] ); VerdictVector tri_normal = sides[0] * sides[2]; // if we have access to normal information, check to see if the // element is inverted. If we don't have the normal information // that we need for this, assume the element is not inverted. // This flag will be used for condition number, jacobian, shape, // and size and shape. bool is_inverted = false; if( compute_normal ) { // center of tri double point[3], surf_normal[3]; point[0] = ( coordinates[0][0] + coordinates[1][0] + coordinates[2][0] ) / 3; point[1] = ( coordinates[0][1] + coordinates[1][1] + coordinates[2][1] ) / 3; point[2] = ( coordinates[0][2] + coordinates[1][2] + coordinates[2][2] ) / 3; // dot product compute_normal( point, surf_normal ); if( ( tri_normal.x() * surf_normal[0] + tri_normal.y() * surf_normal[1] + tri_normal.z() * surf_normal[2] ) < 0 ) is_inverted = true; } // lengths squared of each side double sides_lengths_squared[3]; sides_lengths_squared[0] = sides[0].length_squared(); sides_lengths_squared[1] = sides[1].length_squared(); sides_lengths_squared[2] = sides[2].length_squared(); // if we are doing angle calcuations if( metrics_request_flag & ( V_TRI_MINIMUM_ANGLE | V_TRI_MAXIMUM_ANGLE ) ) { // which is short and long side int short_side = 0, long_side = 0; if( sides_lengths_squared[1] < sides_lengths_squared[0] ) short_side = 1; if( sides_lengths_squared[2] < sides_lengths_squared[short_side] ) short_side = 2; if( sides_lengths_squared[1] > sides_lengths_squared[0] ) long_side = 1; if( sides_lengths_squared[2] > sides_lengths_squared[long_side] ) long_side = 2; // calculate the minimum angle of the tri if( metrics_request_flag & V_TRI_MINIMUM_ANGLE ) { if( sides_lengths_squared[0] == 0.0 || sides_lengths_squared[1] == 0.0 || sides_lengths_squared[2] == 0.0 ) { metric_vals->minimum_angle = 0.0; } else if( short_side == 0 ) metric_vals->minimum_angle = (double)sides[2].interior_angle( sides[1] ); else if( short_side == 1 ) metric_vals->minimum_angle = (double)sides[0].interior_angle( sides[2] ); else metric_vals->minimum_angle = (double)sides[0].interior_angle( -sides[1] ); } // calculate the maximum angle of the tri if( metrics_request_flag & V_TRI_MAXIMUM_ANGLE ) { if( sides_lengths_squared[0] == 0.0 || sides_lengths_squared[1] == 0.0 || sides_lengths_squared[2] == 0.0 ) { metric_vals->maximum_angle = 0.0; } else if( long_side == 0 ) metric_vals->maximum_angle = (double)sides[2].interior_angle( sides[1] ); else if( long_side == 1 ) metric_vals->maximum_angle = (double)sides[0].interior_angle( sides[2] ); else metric_vals->maximum_angle = (double)sides[0].interior_angle( -sides[1] ); } } // calculate the area of the tri // the following metrics depend on area if( metrics_request_flag & ( V_TRI_AREA | V_TRI_SCALED_JACOBIAN | V_TRI_SHAPE | V_TRI_RELATIVE_SIZE_SQUARED | V_TRI_SHAPE_AND_SIZE ) ) { metric_vals->area = (double)( ( sides[0] * sides[2] ).length() * 0.5 ); } // calculate the aspect ratio if( metrics_request_flag & V_TRI_ASPECT_FROBENIUS ) { // sum the lengths squared double srms = sides_lengths_squared[0] + sides_lengths_squared[1] + sides_lengths_squared[2]; // calculate once and reuse static const double twoTimesRootOf3 = 2 * sqrt( 3.0 ); double div = ( twoTimesRootOf3 * ( ( sides[0] * sides[2] ).length() ) ); if( div == 0.0 ) metric_vals->aspect_frobenius = (double)VERDICT_DBL_MAX; else metric_vals->aspect_frobenius = (double)( srms / div ); } // calculate the scaled jacobian if( metrics_request_flag & V_TRI_SCALED_JACOBIAN ) { // calculate once and reuse static const double twoOverRootOf3 = 2 / sqrt( 3.0 ); // use the area from above double tmp = tri_normal.length() * twoOverRootOf3; // now scale it by the lengths of the sides double min_scaled_jac = VERDICT_DBL_MAX; double temp_scaled_jac; for( int i = 0; i < 3; i++ ) { if( sides_lengths_squared[i % 3] == 0.0 || sides_lengths_squared[( i + 2 ) % 3] == 0.0 ) temp_scaled_jac = 0.0; else temp_scaled_jac = tmp / sqrt( sides_lengths_squared[i % 3] ) / sqrt( sides_lengths_squared[( i + 2 ) % 3] ); if( temp_scaled_jac < min_scaled_jac ) min_scaled_jac = temp_scaled_jac; } // multiply by -1 if the normals are in opposite directions if( is_inverted ) { min_scaled_jac *= -1; } metric_vals->scaled_jacobian = (double)min_scaled_jac; } // calculate the condition number if( metrics_request_flag & V_TRI_CONDITION ) { // calculate once and reuse static const double rootOf3 = sqrt( 3.0 ); // if it is inverted, the condition number is considered to be infinity. if( is_inverted ) { metric_vals->condition = VERDICT_DBL_MAX; } else { double area2x = ( sides[0] * sides[2] ).length(); if( area2x == 0.0 ) metric_vals->condition = (double)( VERDICT_DBL_MAX ); else metric_vals->condition = (double)( ( sides[0] % sides[0] + sides[2] % sides[2] - sides[0] % sides[2] ) / ( area2x * rootOf3 ) ); } } // calculate the shape if( metrics_request_flag & V_TRI_SHAPE || metrics_request_flag & V_TRI_SHAPE_AND_SIZE ) { // if element is inverted, shape is zero. We don't need to // calculate anything. if( is_inverted ) { metric_vals->shape = 0.0; } else { // otherwise, we calculate the shape // calculate once and reuse static const double rootOf3 = sqrt( 3.0 ); // reuse area from before double area2x = metric_vals->area * 2; // dot products double dots[3] = { sides[0] % sides[0], sides[2] % sides[2], sides[0] % sides[2] }; // add the dots double sum_dots = dots[0] + dots[1] - dots[2]; // then the finale if( sum_dots == 0.0 ) metric_vals->shape = 0.0; else metric_vals->shape = (double)( rootOf3 * area2x / sum_dots ); } } // calculate relative size squared if( metrics_request_flag & V_TRI_RELATIVE_SIZE_SQUARED || metrics_request_flag & V_TRI_SHAPE_AND_SIZE ) { // get weights double w11, w21, w12, w22; v_tri_get_weight( w11, w21, w12, w22 ); // get the determinant double detw = determinant( w11, w21, w12, w22 ); // use the area from above and divide with the determinant if( metric_vals->area == 0.0 || detw == 0.0 ) metric_vals->relative_size_squared = 0.0; else { double size = metric_vals->area * 2.0 / detw; // square the size size *= size; // value ranges between 0 to 1 metric_vals->relative_size_squared = (double)VERDICT_MIN( size, 1.0 / size ); } } // calculate shape and size if( metrics_request_flag & V_TRI_SHAPE_AND_SIZE ) { metric_vals->shape_and_size = metric_vals->relative_size_squared * metric_vals->shape; } // calculate distortion if( metrics_request_flag & V_TRI_DISTORTION ) metric_vals->distortion = v_tri_distortion( num_nodes, coordinates ); // take care of any over-flow problems if( metric_vals->aspect_frobenius > 0 ) metric_vals->aspect_frobenius = (double)VERDICT_MIN( metric_vals->aspect_frobenius, VERDICT_DBL_MAX ); else metric_vals->aspect_frobenius = (double)VERDICT_MAX( metric_vals->aspect_frobenius, -VERDICT_DBL_MAX ); if( metric_vals->area > 0 ) metric_vals->area = (double)VERDICT_MIN( metric_vals->area, VERDICT_DBL_MAX ); else metric_vals->area = (double)VERDICT_MAX( metric_vals->area, -VERDICT_DBL_MAX ); if( metric_vals->minimum_angle > 0 ) metric_vals->minimum_angle = (double)VERDICT_MIN( metric_vals->minimum_angle, VERDICT_DBL_MAX ); else metric_vals->minimum_angle = (double)VERDICT_MAX( metric_vals->minimum_angle, -VERDICT_DBL_MAX ); if( metric_vals->maximum_angle > 0 ) metric_vals->maximum_angle = (double)VERDICT_MIN( metric_vals->maximum_angle, VERDICT_DBL_MAX ); else metric_vals->maximum_angle = (double)VERDICT_MAX( metric_vals->maximum_angle, -VERDICT_DBL_MAX ); if( metric_vals->condition > 0 ) metric_vals->condition = (double)VERDICT_MIN( metric_vals->condition, VERDICT_DBL_MAX ); else metric_vals->condition = (double)VERDICT_MAX( metric_vals->condition, -VERDICT_DBL_MAX ); if( metric_vals->shape > 0 ) metric_vals->shape = (double)VERDICT_MIN( metric_vals->shape, VERDICT_DBL_MAX ); else metric_vals->shape = (double)VERDICT_MAX( metric_vals->shape, -VERDICT_DBL_MAX ); if( metric_vals->scaled_jacobian > 0 ) metric_vals->scaled_jacobian = (double)VERDICT_MIN( metric_vals->scaled_jacobian, VERDICT_DBL_MAX ); else metric_vals->scaled_jacobian = (double)VERDICT_MAX( metric_vals->scaled_jacobian, -VERDICT_DBL_MAX ); if( metric_vals->relative_size_squared > 0 ) metric_vals->relative_size_squared = (double)VERDICT_MIN( metric_vals->relative_size_squared, VERDICT_DBL_MAX ); else metric_vals->relative_size_squared = (double)VERDICT_MAX( metric_vals->relative_size_squared, -VERDICT_DBL_MAX ); if( metric_vals->shape_and_size > 0 ) metric_vals->shape_and_size = (double)VERDICT_MIN( metric_vals->shape_and_size, VERDICT_DBL_MAX ); else metric_vals->shape_and_size = (double)VERDICT_MAX( metric_vals->shape_and_size, -VERDICT_DBL_MAX ); if( metric_vals->distortion > 0 ) metric_vals->distortion = (double)VERDICT_MIN( metric_vals->distortion, VERDICT_DBL_MAX ); else metric_vals->distortion = (double)VERDICT_MAX( metric_vals->distortion, -VERDICT_DBL_MAX ); if( metrics_request_flag & V_TRI_EDGE_RATIO ) { metric_vals->edge_ratio = v_tri_edge_ratio( 3, coordinates ); } if( metrics_request_flag & V_TRI_RADIUS_RATIO ) { metric_vals->radius_ratio = v_tri_radius_ratio( 3, coordinates ); } if( metrics_request_flag & V_TRI_ASPECT_FROBENIUS ) // there is no V_TRI_ASPECT_RATIO ! { metric_vals->aspect_ratio = v_tri_radius_ratio( 3, coordinates ); } }
C_FUNC_DEF double v_tri_radius_ratio | ( | int | , |
double | coordinates[][3] | ||
) |
Calculates tri metric.
the radius ratio of a triangle
NB (P. Pebay 01/13/07): CR / (3.0*IR) where CR is the circumradius and IR is the inradius
this quality metric is also known to VERDICT, for tetrahedral elements only, a the "aspect beta"
Definition at line 206 of file V_TriMetric.cpp.
References VerdictVector::length_squared(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tri_quality().
{ // three vectors for each side VerdictVector a( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], coordinates[1][2] - coordinates[0][2] ); VerdictVector b( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1], coordinates[2][2] - coordinates[1][2] ); VerdictVector c( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1], coordinates[0][2] - coordinates[2][2] ); double a2 = a.length_squared(); double b2 = b.length_squared(); double c2 = c.length_squared(); VerdictVector ab = a * b; double denominator = ab.length_squared(); if( denominator < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX; double radius_ratio; radius_ratio = .25 * a2 * b2 * c2 * ( a2 + b2 + c2 ) / denominator; if( radius_ratio > 0 ) return (double)VERDICT_MIN( radius_ratio, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( radius_ratio, -VERDICT_DBL_MAX ); }
C_FUNC_DEF double v_tri_relative_size_squared | ( | int | , |
double | coordinates[][3] | ||
) |
Calculates tri metric.
The relative size of a tri
Min(J,1/J) where J is the determinant of the weighted jacobian matrix.
Definition at line 534 of file V_TriMetric.cpp.
References determinant(), VerdictVector::length(), VerdictVector::set(), size, v_tri_get_weight(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tri_shape_and_size().
{ double w11, w21, w12, w22; VerdictVector xxi, xet, tri_normal; v_tri_get_weight( w11, w21, w12, w22 ); double detw = determinant( w11, w21, w12, w22 ); if( detw == 0.0 ) return 0.0; xxi.set( coordinates[0][0] - coordinates[1][0], coordinates[0][1] - coordinates[1][1], coordinates[0][2] - coordinates[1][2] ); xet.set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1], coordinates[0][2] - coordinates[2][2] ); tri_normal = xxi * xet; double deta = tri_normal.length(); if( deta == 0.0 || detw == 0.0 ) return 0.0; double size = pow( deta / detw, 2 ); double rel_size = VERDICT_MIN( size, 1.0 / size ); if( rel_size > 0 ) return (double)VERDICT_MIN( rel_size, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( rel_size, -VERDICT_DBL_MAX ); }
C_FUNC_DEF double v_tri_scaled_jacobian | ( | int | , |
double | coordinates[][3] | ||
) |
Calculates tri metric.
The scaled jacobian of a tri
minimum of the jacobian divided by the lengths of 2 edge vectors
Definition at line 461 of file V_TriMetric.cpp.
References compute_normal, moab::cross(), moab::GeomUtil::first(), length(), VerdictVector::length(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, VERDICT_MIN, VerdictVector::x(), VerdictVector::y(), and VerdictVector::z().
Referenced by moab::VerdictWrapper::quality_measure(), v_quad_quality(), and v_quad_scaled_jacobian().
{ static const double detw = 2. / sqrt( 3.0 ); VerdictVector first, second; double jacobian; VerdictVector edge[3]; edge[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], coordinates[1][2] - coordinates[0][2] ); edge[1].set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1], coordinates[2][2] - coordinates[0][2] ); edge[2].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1], coordinates[2][2] - coordinates[1][2] ); first = edge[1] - edge[0]; second = edge[2] - edge[0]; VerdictVector cross = first * second; jacobian = cross.length(); double max_edge_length_product; max_edge_length_product = VERDICT_MAX( edge[0].length() * edge[1].length(), VERDICT_MAX( edge[1].length() * edge[2].length(), edge[0].length() * edge[2].length() ) ); if( max_edge_length_product < VERDICT_DBL_MIN ) return (double)0.0; jacobian *= detw; jacobian /= max_edge_length_product; if( compute_normal ) { // center of tri double point[3], surf_normal[3]; point[0] = ( coordinates[0][0] + coordinates[1][0] + coordinates[2][0] ) / 3; point[1] = ( coordinates[0][1] + coordinates[1][1] + coordinates[2][1] ) / 3; point[2] = ( coordinates[0][2] + coordinates[1][2] + coordinates[2][2] ) / 3; // dot product compute_normal( point, surf_normal ); if( ( cross.x() * surf_normal[0] + cross.y() * surf_normal[1] + cross.z() * surf_normal[2] ) < 0 ) jacobian *= -1; } if( jacobian > 0 ) return (double)VERDICT_MIN( jacobian, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( jacobian, -VERDICT_DBL_MAX ); }
C_FUNC_DEF double v_tri_shape | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
The shape of a tri
2 / condition number of weighted jacobian matrix
Definition at line 515 of file V_TriMetric.cpp.
References v_tri_condition(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tri_shape_and_size().
{ double condition = v_tri_condition( num_nodes, coordinates ); double shape; if( condition <= VERDICT_DBL_MIN ) shape = VERDICT_DBL_MAX; else shape = ( 1 / condition ); if( shape > 0 ) return (double)VERDICT_MIN( shape, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( shape, -VERDICT_DBL_MAX ); }
C_FUNC_DEF double v_tri_shape_and_size | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
The shape and size of a tri
Product of the Shape and Relative Size
Definition at line 570 of file V_TriMetric.cpp.
References size, v_tri_relative_size_squared(), v_tri_shape(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
{ double size, shape; size = v_tri_relative_size_squared( num_nodes, coordinates ); shape = v_tri_shape( num_nodes, coordinates ); double shape_and_size = size * shape; if( shape_and_size > 0 ) return (double)VERDICT_MIN( shape_and_size, VERDICT_DBL_MAX ); return (double)VERDICT_MAX( shape_and_size, -VERDICT_DBL_MAX ); }
ComputeNormal compute_normal = NULL [static] |
Definition at line 34 of file V_TriMetric.cpp.
Referenced by v_set_tri_normal_func(), v_tri_condition(), v_tri_quality(), and v_tri_scaled_jacobian().
double verdict_tri_size = 0 [static] |
Definition at line 33 of file V_TriMetric.cpp.
Referenced by v_set_tri_size(), and v_tri_get_weight().