Header file for verdict library that calculates metrics for finite elements. Also see: Main Page. More...
Go to the source code of this file.
Classes | |
struct | HexMetricVals |
struct | EdgeMetricVals |
struct | KnifeMetricVals |
struct | QuadMetricVals |
struct | PyramidMetricVals |
struct | WedgeMetricVals |
struct | TetMetricVals |
struct | TriMetricVals |
Typedefs | |
typedef double(* | VerdictFunction) (int, double[][3]) |
typedef int(* | ComputeNormal) (double point[3], double normal[3]) |
Tri bit fields | |
#define | V_TRI_ASPECT_FROBENIUS |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_AREA |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_MINIMUM_ANGLE |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_MAXIMUM_ANGLE |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_CONDITION |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_SCALED_JACOBIAN |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_SHAPE |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_RELATIVE_SIZE_SQUARED |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_SHAPE_AND_SIZE |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_DISTORTION |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_RADIUS_RATIO |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_EDGE_RATIO |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_ALL |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_TRADITIONAL |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_DIAGNOSTIC |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_TRI_ALGEBRAIC ( V_TRI_SHAPE + V_TRI_SHAPE_AND_SIZE + V_TRI_RELATIVE_SIZE_SQUARED ) |
Calculates quality metrics for hexahedral elements. More... | |
#define | V_EDGE_LENGTH |
Calculates quality metrics for hexahedral elements. More... | |
C_FUNC_DEF void | v_hex_quality (int num_nodes, double coordinates[][3], unsigned int metrics_request_flag, struct HexMetricVals *metric_vals) |
Calculates quality metrics for hexahedral elements. More... | |
C_FUNC_DEF void | v_tet_quality (int num_nodes, double coordinates[][3], unsigned int metrics_request_flag, struct TetMetricVals *metric_vals) |
Calculates quality metrics for tetrahedral elements. More... | |
C_FUNC_DEF void | v_pyramid_quality (int num_nodes, double coordinates[][3], unsigned int metrics_request_flag, struct PyramidMetricVals *metric_vals) |
Calculates quality metrics for pyramid elements. More... | |
C_FUNC_DEF void | v_wedge_quality (int num_nodes, double coordinates[][3], unsigned int metrics_request_flag, struct WedgeMetricVals *metric_vals) |
Calculates quality metrics for wedge elements. More... | |
C_FUNC_DEF void | v_knife_quality (int num_nodes, double coordinates[][3], unsigned int metrics_request_flag, struct KnifeMetricVals *metric_vals) |
Calculates quality metrics for knife elements. More... | |
C_FUNC_DEF void | v_quad_quality (int num_nodes, double coordinates[][3], unsigned int metrics_request_flag, struct QuadMetricVals *metric_vals) |
Calculates quality metrics for quadrilateral elements. More... | |
C_FUNC_DEF void | v_tri_quality (int num_nodes, double coordinates[][3], unsigned int metrics_request_flag, struct TriMetricVals *metric_vals) |
Calculates quality metrics for triangle elements. More... | |
C_FUNC_DEF void | v_edge_quality (int num_nodes, double coordinates[][3], unsigned int metrics_request_flag, struct EdgeMetricVals *metric_vals) |
Calculates quality metrics for edge elements. More... | |
C_FUNC_DEF void | v_set_hex_size (double size) |
Sets average size (volume) of hex, needed for v_hex_relative_size(...) More... | |
C_FUNC_DEF double | v_hex_edge_ratio (int num_nodes, double coordinates[][3]) |
Calculates hex edge ratio metric. More... | |
C_FUNC_DEF double | v_hex_max_edge_ratio (int num_nodes, double coordinates[][3]) |
Calculates hex maximum of edge ratio. More... | |
C_FUNC_DEF double | v_hex_skew (int num_nodes, double coordinates[][3]) |
Calculates hex skew metric. More... | |
C_FUNC_DEF double | v_hex_taper (int num_nodes, double coordinates[][3]) |
Calculates hex taper metric. More... | |
C_FUNC_DEF double | v_hex_volume (int num_nodes, double coordinates[][3]) |
Calculates hex volume. More... | |
C_FUNC_DEF double | v_hex_stretch (int num_nodes, double coordinates[][3]) |
Calculates hex stretch metric. More... | |
C_FUNC_DEF double | v_hex_diagonal (int num_nodes, double coordinates[][3]) |
Calculates hex diagonal metric. More... | |
C_FUNC_DEF double | v_hex_dimension (int num_nodes, double coordinates[][3]) |
Calculates hex dimension metric. More... | |
C_FUNC_DEF double | v_hex_oddy (int num_nodes, double coordinates[][3]) |
Calculates hex oddy metric. More... | |
C_FUNC_DEF double | v_hex_med_aspect_frobenius (int num_nodes, double coordinates[][3]) |
Calculates hex condition metric. More... | |
C_FUNC_DEF double | v_hex_max_aspect_frobenius (int num_nodes, double coordinates[][3]) |
Calculates hex condition metric. More... | |
C_FUNC_DEF double | v_hex_condition (int num_nodes, double coordinates[][3]) |
C_FUNC_DEF double | v_hex_jacobian (int num_nodes, double coordinates[][3]) |
Calculates hex jacobian metric. More... | |
C_FUNC_DEF double | v_hex_scaled_jacobian (int num_nodes, double coordinates[][3]) |
Calculates hex scaled jacobian metric. More... | |
C_FUNC_DEF double | v_hex_shear (int num_nodes, double coordinates[][3]) |
Calculates hex shear metric. More... | |
C_FUNC_DEF double | v_hex_shape (int num_nodes, double coordinates[][3]) |
Calculates hex shape metric. More... | |
C_FUNC_DEF double | v_hex_relative_size_squared (int num_nodes, double coordinates[][3]) |
Calculates hex relative size metric. More... | |
C_FUNC_DEF double | v_hex_shape_and_size (int num_nodes, double coordinates[][3]) |
Calculates hex shape-size metric. More... | |
C_FUNC_DEF double | v_hex_shear_and_size (int num_nodes, double coordinates[][3]) |
Calculates hex shear-size metric. More... | |
C_FUNC_DEF double | v_hex_distortion (int num_nodes, double coordinates[][3]) |
Calculates hex distortion metric. More... | |
C_FUNC_DEF void | v_set_tet_size (double size) |
Sets average size (volume) of tet, needed for v_tet_relative_size(...) More... | |
C_FUNC_DEF double | v_tet_edge_ratio (int num_nodes, double coordinates[][3]) |
Calculates tet edge ratio metric. More... | |
C_FUNC_DEF double | v_tet_radius_ratio (int num_nodes, double coordinates[][3]) |
Calculates tet radius ratio metric. More... | |
C_FUNC_DEF double | v_tet_aspect_beta (int num_nodes, double coordinates[][3]) |
Calculates the radius ratio metric of a positively oriented tet. More... | |
C_FUNC_DEF double | v_tet_aspect_ratio (int num_nodes, double coordinates[][3]) |
Calculates tet aspect ratio metric. More... | |
C_FUNC_DEF double | v_tet_aspect_gamma (int num_nodes, double coordinates[][3]) |
Calculates tet aspect gamma metric. More... | |
C_FUNC_DEF double | v_tet_aspect_frobenius (int num_nodes, double coordinates[][3]) |
Calculates tet aspect frobenius metric. More... | |
C_FUNC_DEF double | v_tet_minimum_angle (int num_nodes, double coordinates[][3]) |
Calculates tet minimum dihedral angle. More... | |
C_FUNC_DEF double | v_tet_collapse_ratio (int num_nodes, double coordinates[][3]) |
Calculates tet collapse ratio metric. More... | |
C_FUNC_DEF double | v_tet_volume (int num_nodes, double coordinates[][3]) |
Calculates tet volume. More... | |
C_FUNC_DEF double | v_tet_condition (int num_nodes, double coordinates[][3]) |
Calculates tet condition metric. More... | |
C_FUNC_DEF double | v_tet_jacobian (int num_nodes, double coordinates[][3]) |
Calculates tet jacobian. More... | |
C_FUNC_DEF double | v_tet_scaled_jacobian (int num_nodes, double coordinates[][3]) |
Calculates tet scaled jacobian. More... | |
C_FUNC_DEF double | v_tet_shape (int num_nodes, double coordinates[][3]) |
Calculates tet shape metric. More... | |
C_FUNC_DEF double | v_tet_relative_size_squared (int num_nodes, double coordinates[][3]) |
Calculates tet relative size metric. More... | |
C_FUNC_DEF double | v_tet_shape_and_size (int num_nodes, double coordinates[][3]) |
Calculates tet shape-size metric. More... | |
C_FUNC_DEF double | v_tet_distortion (int num_nodes, double coordinates[][3]) |
Calculates tet distortion metric. More... | |
C_FUNC_DEF double | v_pyramid_volume (int num_nodes, double coordinates[][3]) |
Calculates pyramid volume. More... | |
C_FUNC_DEF double | v_wedge_volume (int num_nodes, double coordinates[][3]) |
Calculates wedge volume. More... | |
C_FUNC_DEF double | v_knife_volume (int num_nodes, double coordinates[][3]) |
Calculates knife volume. More... | |
C_FUNC_DEF double | v_edge_length (int num_nodes, double coordinates[][3]) |
Calculates edge length. More... | |
C_FUNC_DEF void | v_set_quad_size (double size) |
Sets average size (area) of quad, needed for v_quad_relative_size(...) More... | |
C_FUNC_DEF double | v_quad_edge_ratio (int num_nodes, double coordinates[][3]) |
Calculates quad edge ratio. More... | |
C_FUNC_DEF double | v_quad_max_edge_ratio (int num_nodes, double coordinates[][3]) |
Calculates quad maximum of edge ratio. More... | |
C_FUNC_DEF double | v_quad_aspect_ratio (int num_nodes, double coordinates[][3]) |
Calculates quad aspect ratio. More... | |
C_FUNC_DEF double | v_quad_radius_ratio (int num_nodes, double coordinates[][3]) |
Calculates quad radius ratio. More... | |
C_FUNC_DEF double | v_quad_med_aspect_frobenius (int num_nodes, double coordinates[][3]) |
Calculates quad average Frobenius aspect. More... | |
C_FUNC_DEF double | v_quad_max_aspect_frobenius (int num_nodes, double coordinates[][3]) |
Calculates quad maximum Frobenius aspect. More... | |
C_FUNC_DEF double | v_quad_skew (int num_nodes, double coordinates[][3]) |
Calculates quad skew metric. More... | |
C_FUNC_DEF double | v_quad_taper (int num_nodes, double coordinates[][3]) |
Calculates quad taper metric. More... | |
C_FUNC_DEF double | v_quad_warpage (int num_nodes, double coordinates[][3]) |
Calculates quad warpage metric. More... | |
C_FUNC_DEF double | v_quad_area (int num_nodes, double coordinates[][3]) |
Calculates quad area. More... | |
C_FUNC_DEF double | v_quad_stretch (int num_nodes, double coordinates[][3]) |
Calculates quad strech metric. More... | |
C_FUNC_DEF double | v_quad_minimum_angle (int num_nodes, double coordinates[][3]) |
Calculates quad's smallest angle. More... | |
C_FUNC_DEF double | v_quad_maximum_angle (int num_nodes, double coordinates[][3]) |
Calculates quad's largest angle. More... | |
C_FUNC_DEF double | v_quad_oddy (int num_nodes, double coordinates[][3]) |
Calculates quad oddy metric. More... | |
C_FUNC_DEF double | v_quad_condition (int num_nodes, double coordinates[][3]) |
Calculates quad condition number metric. More... | |
C_FUNC_DEF double | v_quad_jacobian (int num_nodes, double coordinates[][3]) |
Calculates quad jacobian. More... | |
C_FUNC_DEF double | v_quad_scaled_jacobian (int num_nodes, double coordinates[][3]) |
Calculates quad scaled jacobian. More... | |
C_FUNC_DEF double | v_quad_shear (int num_nodes, double coordinates[][3]) |
Calculates quad shear metric. More... | |
C_FUNC_DEF double | v_quad_shape (int num_nodes, double coordinates[][3]) |
Calculates quad shape metric. More... | |
C_FUNC_DEF double | v_quad_relative_size_squared (int num_nodes, double coordinates[][3]) |
Calculates quad relative size metric. More... | |
C_FUNC_DEF double | v_quad_shape_and_size (int num_nodes, double coordinates[][3]) |
Calculates quad shape-size metric. More... | |
C_FUNC_DEF double | v_quad_shear_and_size (int num_nodes, double coordinates[][3]) |
Calculates quad shear-size metric. More... | |
C_FUNC_DEF double | v_quad_distortion (int num_nodes, double coordinates[][3]) |
Calculates quad distortion metric. More... | |
C_FUNC_DEF void | v_set_tri_size (double size) |
Sets average size (area) of tri, needed for v_tri_relative_size(...) More... | |
C_FUNC_DEF void | v_set_tri_normal_func (ComputeNormal func) |
Sets fuction pointer to calculate tri normal wrt surface. More... | |
C_FUNC_DEF double | v_tri_edge_ratio (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_aspect_ratio (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_radius_ratio (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_aspect_frobenius (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_area (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_minimum_angle (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_maximum_angle (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_condition (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_scaled_jacobian (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_relative_size_squared (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_shape (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_shape_and_size (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
C_FUNC_DEF double | v_tri_distortion (int num_nodes, double coordinates[][3]) |
Calculates tri metric. More... | |
Header file for verdict library that calculates metrics for finite elements. Also see: Main Page.
verdict.h is the header file for applications/libraries to include to compute quality metrics.
This file is part of VERDICT
Definition in file verdict.h.
#define V_EDGE_LENGTH |
#define V_HEX_ROBINSON ( V_HEX_SKEW + V_HEX_TAPER ) |
#define V_QUAD_ROBINSON ( V_QUAD_MAX_EDGE_RATIO + V_QUAD_SKEW + V_QUAD_TAPER ) |
#define V_TET_ALGEBRAIC ( V_TET_SHAPE + V_TET_RELATIVE_SIZE_SQUARED + V_TET_SHAPE_AND_SIZE ) |
#define V_TRI_ALGEBRAIC ( V_TRI_SHAPE + V_TRI_SHAPE_AND_SIZE + V_TRI_RELATIVE_SIZE_SQUARED ) |
#define V_TRI_ALL |
#define V_TRI_AREA |
#define V_TRI_ASPECT_FROBENIUS |
#define V_TRI_CONDITION |
#define V_TRI_DIAGNOSTIC |
#define V_TRI_DISTORTION |
#define V_TRI_EDGE_RATIO |
#define V_TRI_MAXIMUM_ANGLE |
#define V_TRI_MINIMUM_ANGLE |
#define V_TRI_RADIUS_RATIO |
#define V_TRI_RELATIVE_SIZE_SQUARED |
#define V_TRI_SCALED_JACOBIAN |
#define V_TRI_SHAPE |
#define V_TRI_SHAPE_AND_SIZE |
#define V_TRI_TRADITIONAL |
typedef int( * ComputeNormal) (double point[3], double normal[3]) |
C_FUNC_DEF double v_edge_length | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates edge length.
length of and edge length is calculated by taking the distance between the end nodes
Definition at line 32 of file V_EdgeMetric.cpp.
33 {
34
35 double x = coordinates[1][0] - coordinates[0][0];
36 double y = coordinates[1][1] - coordinates[0][1];
37 double z = coordinates[1][2] - coordinates[0][2];
38 return (double)( sqrt( x * x + y * y + z * z ) );
39 }
Referenced by moab::VerdictWrapper::all_quality_measures(), edge_quality(), and moab::VerdictWrapper::quality_measure().
C_FUNC_DEF void v_edge_quality | ( | int | num_nodes, |
double | coordinates[][3], | ||
unsigned int | metrics_request_flag, | ||
struct EdgeMetricVals * | metric_vals | ||
) |
Calculates quality metrics for edge elements.
C_FUNC_DEF double v_hex_condition | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
The maximum Frobenius condition of a hex, a.k.a. condition NB (P. Pebay 01/25/07): this method is maintained for backwards compatibility only. It will become deprecated at some point.
Definition at line 1371 of file V_HexMetric.cpp.
1372 {
1373
1374 return v_hex_max_aspect_frobenius( 8, coordinates );
1375 }
References v_hex_max_aspect_frobenius().
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_hex_diagonal | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex diagonal metric.
Minimum diagonal length / maximum diagonal length. Reference — Unknown
diagonal ratio of a hex
Minimum diagonal length / maximum diagonal length
Definition at line 771 of file V_HexMetric.cpp.
772 {
773
774 double min_diag = diag_length( 0, coordinates );
775 double max_diag = diag_length( 1, coordinates );
776
777 double diagonal = safe_ratio( min_diag, max_diag );
778
779 if( diagonal > 0 ) return (double)VERDICT_MIN( diagonal, VERDICT_DBL_MAX );
780 return (double)VERDICT_MAX( diagonal, -VERDICT_DBL_MAX );
781 }
References diag_length(), safe_ratio(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_hex_quality().
C_FUNC_DEF double v_hex_dimension | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex dimension metric.
Pronto-specific characteristic length for stable time step calculation.
Char_length = Volume / 2 grad Volume. Reference — L.M. Taylor, and D.P. Flanagan, Pronto3D - A Three Dimensional Transient Solid Dynamics Program, SAND87-1912, Sandia National Laboratories, 1989.
dimension of a hex
Pronto-specific characteristic length for stable time step calculation. Char_length = Volume / 2 grad Volume
Definition at line 791 of file V_HexMetric.cpp.
792 {
793
794 double gradop[9][4];
795
796 double x1 = coordinates[0][0];
797 double x2 = coordinates[1][0];
798 double x3 = coordinates[2][0];
799 double x4 = coordinates[3][0];
800 double x5 = coordinates[4][0];
801 double x6 = coordinates[5][0];
802 double x7 = coordinates[6][0];
803 double x8 = coordinates[7][0];
804
805 double y1 = coordinates[0][1];
806 double y2 = coordinates[1][1];
807 double y3 = coordinates[2][1];
808 double y4 = coordinates[3][1];
809 double y5 = coordinates[4][1];
810 double y6 = coordinates[5][1];
811 double y7 = coordinates[6][1];
812 double y8 = coordinates[7][1];
813
814 double z1 = coordinates[0][2];
815 double z2 = coordinates[1][2];
816 double z3 = coordinates[2][2];
817 double z4 = coordinates[3][2];
818 double z5 = coordinates[4][2];
819 double z6 = coordinates[5][2];
820 double z7 = coordinates[6][2];
821 double z8 = coordinates[7][2];
822
823 double z24 = z2 - z4;
824 double z52 = z5 - z2;
825 double z45 = z4 - z5;
826 gradop[1][1] =
827 ( y2 * ( z6 - z3 - z45 ) + y3 * z24 + y4 * ( z3 - z8 - z52 ) + y5 * ( z8 - z6 - z24 ) + y6 * z52 + y8 * z45 ) /
828 12.0;
829
830 double z31 = z3 - z1;
831 double z63 = z6 - z3;
832 double z16 = z1 - z6;
833 gradop[2][1] =
834 ( y3 * ( z7 - z4 - z16 ) + y4 * z31 + y1 * ( z4 - z5 - z63 ) + y6 * ( z5 - z7 - z31 ) + y7 * z63 + y5 * z16 ) /
835 12.0;
836
837 double z42 = z4 - z2;
838 double z74 = z7 - z4;
839 double z27 = z2 - z7;
840 gradop[3][1] =
841 ( y4 * ( z8 - z1 - z27 ) + y1 * z42 + y2 * ( z1 - z6 - z74 ) + y7 * ( z6 - z8 - z42 ) + y8 * z74 + y6 * z27 ) /
842 12.0;
843
844 double z13 = z1 - z3;
845 double z81 = z8 - z1;
846 double z38 = z3 - z8;
847 gradop[4][1] =
848 ( y1 * ( z5 - z2 - z38 ) + y2 * z13 + y3 * ( z2 - z7 - z81 ) + y8 * ( z7 - z5 - z13 ) + y5 * z81 + y7 * z38 ) /
849 12.0;
850
851 double z86 = z8 - z6;
852 double z18 = z1 - z8;
853 double z61 = z6 - z1;
854 gradop[5][1] =
855 ( y8 * ( z4 - z7 - z61 ) + y7 * z86 + y6 * ( z7 - z2 - z18 ) + y1 * ( z2 - z4 - z86 ) + y4 * z18 + y2 * z61 ) /
856 12.0;
857
858 double z57 = z5 - z7;
859 double z25 = z2 - z5;
860 double z72 = z7 - z2;
861 gradop[6][1] =
862 ( y5 * ( z1 - z8 - z72 ) + y8 * z57 + y7 * ( z8 - z3 - z25 ) + y2 * ( z3 - z1 - z57 ) + y1 * z25 + y3 * z72 ) /
863 12.0;
864
865 double z68 = z6 - z8;
866 double z36 = z3 - z6;
867 double z83 = z8 - z3;
868 gradop[7][1] =
869 ( y6 * ( z2 - z5 - z83 ) + y5 * z68 + y8 * ( z5 - z4 - z36 ) + y3 * ( z4 - z2 - z68 ) + y2 * z36 + y4 * z83 ) /
870 12.0;
871
872 double z75 = z7 - z5;
873 double z47 = z4 - z7;
874 double z54 = z5 - z4;
875 gradop[8][1] =
876 ( y7 * ( z3 - z6 - z54 ) + y6 * z75 + y5 * ( z6 - z1 - z47 ) + y4 * ( z1 - z3 - z75 ) + y3 * z47 + y1 * z54 ) /
877 12.0;
878
879 double x24 = x2 - x4;
880 double x52 = x5 - x2;
881 double x45 = x4 - x5;
882 gradop[1][2] =
883 ( z2 * ( x6 - x3 - x45 ) + z3 * x24 + z4 * ( x3 - x8 - x52 ) + z5 * ( x8 - x6 - x24 ) + z6 * x52 + z8 * x45 ) /
884 12.0;
885
886 double x31 = x3 - x1;
887 double x63 = x6 - x3;
888 double x16 = x1 - x6;
889 gradop[2][2] =
890 ( z3 * ( x7 - x4 - x16 ) + z4 * x31 + z1 * ( x4 - x5 - x63 ) + z6 * ( x5 - x7 - x31 ) + z7 * x63 + z5 * x16 ) /
891 12.0;
892
893 double x42 = x4 - x2;
894 double x74 = x7 - x4;
895 double x27 = x2 - x7;
896 gradop[3][2] =
897 ( z4 * ( x8 - x1 - x27 ) + z1 * x42 + z2 * ( x1 - x6 - x74 ) + z7 * ( x6 - x8 - x42 ) + z8 * x74 + z6 * x27 ) /
898 12.0;
899
900 double x13 = x1 - x3;
901 double x81 = x8 - x1;
902 double x38 = x3 - x8;
903 gradop[4][2] =
904 ( z1 * ( x5 - x2 - x38 ) + z2 * x13 + z3 * ( x2 - x7 - x81 ) + z8 * ( x7 - x5 - x13 ) + z5 * x81 + z7 * x38 ) /
905 12.0;
906
907 double x86 = x8 - x6;
908 double x18 = x1 - x8;
909 double x61 = x6 - x1;
910 gradop[5][2] =
911 ( z8 * ( x4 - x7 - x61 ) + z7 * x86 + z6 * ( x7 - x2 - x18 ) + z1 * ( x2 - x4 - x86 ) + z4 * x18 + z2 * x61 ) /
912 12.0;
913
914 double x57 = x5 - x7;
915 double x25 = x2 - x5;
916 double x72 = x7 - x2;
917 gradop[6][2] =
918 ( z5 * ( x1 - x8 - x72 ) + z8 * x57 + z7 * ( x8 - x3 - x25 ) + z2 * ( x3 - x1 - x57 ) + z1 * x25 + z3 * x72 ) /
919 12.0;
920
921 double x68 = x6 - x8;
922 double x36 = x3 - x6;
923 double x83 = x8 - x3;
924 gradop[7][2] =
925 ( z6 * ( x2 - x5 - x83 ) + z5 * x68 + z8 * ( x5 - x4 - x36 ) + z3 * ( x4 - x2 - x68 ) + z2 * x36 + z4 * x83 ) /
926 12.0;
927
928 double x75 = x7 - x5;
929 double x47 = x4 - x7;
930 double x54 = x5 - x4;
931 gradop[8][2] =
932 ( z7 * ( x3 - x6 - x54 ) + z6 * x75 + z5 * ( x6 - x1 - x47 ) + z4 * ( x1 - x3 - x75 ) + z3 * x47 + z1 * x54 ) /
933 12.0;
934
935 double y24 = y2 - y4;
936 double y52 = y5 - y2;
937 double y45 = y4 - y5;
938 gradop[1][3] =
939 ( x2 * ( y6 - y3 - y45 ) + x3 * y24 + x4 * ( y3 - y8 - y52 ) + x5 * ( y8 - y6 - y24 ) + x6 * y52 + x8 * y45 ) /
940 12.0;
941
942 double y31 = y3 - y1;
943 double y63 = y6 - y3;
944 double y16 = y1 - y6;
945 gradop[2][3] =
946 ( x3 * ( y7 - y4 - y16 ) + x4 * y31 + x1 * ( y4 - y5 - y63 ) + x6 * ( y5 - y7 - y31 ) + x7 * y63 + x5 * y16 ) /
947 12.0;
948
949 double y42 = y4 - y2;
950 double y74 = y7 - y4;
951 double y27 = y2 - y7;
952 gradop[3][3] =
953 ( x4 * ( y8 - y1 - y27 ) + x1 * y42 + x2 * ( y1 - y6 - y74 ) + x7 * ( y6 - y8 - y42 ) + x8 * y74 + x6 * y27 ) /
954 12.0;
955
956 double y13 = y1 - y3;
957 double y81 = y8 - y1;
958 double y38 = y3 - y8;
959 gradop[4][3] =
960 ( x1 * ( y5 - y2 - y38 ) + x2 * y13 + x3 * ( y2 - y7 - y81 ) + x8 * ( y7 - y5 - y13 ) + x5 * y81 + x7 * y38 ) /
961 12.0;
962
963 double y86 = y8 - y6;
964 double y18 = y1 - y8;
965 double y61 = y6 - y1;
966 gradop[5][3] =
967 ( x8 * ( y4 - y7 - y61 ) + x7 * y86 + x6 * ( y7 - y2 - y18 ) + x1 * ( y2 - y4 - y86 ) + x4 * y18 + x2 * y61 ) /
968 12.0;
969
970 double y57 = y5 - y7;
971 double y25 = y2 - y5;
972 double y72 = y7 - y2;
973 gradop[6][3] =
974 ( x5 * ( y1 - y8 - y72 ) + x8 * y57 + x7 * ( y8 - y3 - y25 ) + x2 * ( y3 - y1 - y57 ) + x1 * y25 + x3 * y72 ) /
975 12.0;
976
977 double y68 = y6 - y8;
978 double y36 = y3 - y6;
979 double y83 = y8 - y3;
980 gradop[7][3] =
981 ( x6 * ( y2 - y5 - y83 ) + x5 * y68 + x8 * ( y5 - y4 - y36 ) + x3 * ( y4 - y2 - y68 ) + x2 * y36 + x4 * y83 ) /
982 12.0;
983
984 double y75 = y7 - y5;
985 double y47 = y4 - y7;
986 double y54 = y5 - y4;
987 gradop[8][3] =
988 ( x7 * ( y3 - y6 - y54 ) + x6 * y75 + x5 * ( y6 - y1 - y47 ) + x4 * ( y1 - y3 - y75 ) + x3 * y47 + x1 * y54 ) /
989 12.0;
990
991 // calculate element volume and characteristic element aspect ratio
992 // (used in time step and hourglass control) -
993
994 double volume = coordinates[0][0] * gradop[1][1] + coordinates[1][0] * gradop[2][1] +
995 coordinates[2][0] * gradop[3][1] + coordinates[3][0] * gradop[4][1] +
996 coordinates[4][0] * gradop[5][1] + coordinates[5][0] * gradop[6][1] +
997 coordinates[6][0] * gradop[7][1] + coordinates[7][0] * gradop[8][1];
998 double aspect =
999 .5 * SQR( volume ) /
1000 ( SQR( gradop[1][1] ) + SQR( gradop[2][1] ) + SQR( gradop[3][1] ) + SQR( gradop[4][1] ) + SQR( gradop[5][1] ) +
1001 SQR( gradop[6][1] ) + SQR( gradop[7][1] ) + SQR( gradop[8][1] ) + SQR( gradop[1][2] ) + SQR( gradop[2][2] ) +
1002 SQR( gradop[3][2] ) + SQR( gradop[4][2] ) + SQR( gradop[5][2] ) + SQR( gradop[6][2] ) + SQR( gradop[7][2] ) +
1003 SQR( gradop[8][2] ) + SQR( gradop[1][3] ) + SQR( gradop[2][3] ) + SQR( gradop[3][3] ) + SQR( gradop[4][3] ) +
1004 SQR( gradop[5][3] ) + SQR( gradop[6][3] ) + SQR( gradop[7][3] ) + SQR( gradop[8][3] ) );
1005
1006 return (double)sqrt( aspect );
1007 }
References SQR.
Referenced by moab::VerdictWrapper::quality_measure(), and v_hex_quality().
C_FUNC_DEF double v_hex_distortion | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex distortion metric.
{min(|J|)/actual volume}*parent volume, parent volume = 8 for hex. Reference — SDRC/IDEAS Simulation: Finite Element Modeling–User's Guide
distortion of a hex
Definition at line 2228 of file V_HexMetric.cpp.
2229 {
2230
2231 // use 2x2 gauss points for linear hex and 3x3 for 2nd order hex
2232 int number_of_gauss_points = 0;
2233 if( num_nodes == 8 )
2234 // 2x2 quadrature rule
2235 number_of_gauss_points = 2;
2236 else if( num_nodes == 20 )
2237 // 3x3 quadrature rule
2238 number_of_gauss_points = 3;
2239
2240 int number_dimension = 3;
2241 int total_number_of_gauss_points = number_of_gauss_points * number_of_gauss_points * number_of_gauss_points;
2242 double distortion = VERDICT_DBL_MAX;
2243
2244 // maxTotalNumberGaussPoints =27, maxNumberNodes = 20
2245 // they are defined in GaussIntegration.hpp
2246 // This is used to make these arrays static.
2247 // I tried dynamically allocated arrays but the new and delete
2248 // was very expensive
2249
2250 double shape_function[maxTotalNumberGaussPoints][maxNumberNodes];
2251 double dndy1[maxTotalNumberGaussPoints][maxNumberNodes];
2252 double dndy2[maxTotalNumberGaussPoints][maxNumberNodes];
2253 double dndy3[maxTotalNumberGaussPoints][maxNumberNodes];
2254 double weight[maxTotalNumberGaussPoints];
2255
2256 // create an object of GaussIntegration
2257 GaussIntegration::initialize( number_of_gauss_points, num_nodes, number_dimension );
2258 GaussIntegration::calculate_shape_function_3d_hex();
2259 GaussIntegration::get_shape_func( shape_function[0], dndy1[0], dndy2[0], dndy3[0], weight );
2260
2261 VerdictVector xxi, xet, xze, xin;
2262
2263 double jacobian, minimum_jacobian;
2264 double element_volume = 0.0;
2265 minimum_jacobian = VERDICT_DBL_MAX;
2266 // calculate element volume
2267 int ife, ja;
2268 for( ife = 0; ife < total_number_of_gauss_points; ife++ )
2269 {
2270
2271 xxi.set( 0.0, 0.0, 0.0 );
2272 xet.set( 0.0, 0.0, 0.0 );
2273 xze.set( 0.0, 0.0, 0.0 );
2274
2275 for( ja = 0; ja < num_nodes; ja++ )
2276 {
2277 xin.set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] );
2278 xxi += dndy1[ife][ja] * xin;
2279 xet += dndy2[ife][ja] * xin;
2280 xze += dndy3[ife][ja] * xin;
2281 }
2282
2283 jacobian = xxi % ( xet * xze );
2284 if( minimum_jacobian > jacobian ) minimum_jacobian = jacobian;
2285
2286 element_volume += weight[ife] * jacobian;
2287 }
2288
2289 // loop through all nodes
2290 double dndy1_at_node[maxNumberNodes][maxNumberNodes];
2291 double dndy2_at_node[maxNumberNodes][maxNumberNodes];
2292 double dndy3_at_node[maxNumberNodes][maxNumberNodes];
2293
2294 GaussIntegration::calculate_derivative_at_nodes_3d( dndy1_at_node, dndy2_at_node, dndy3_at_node );
2295 int node_id;
2296 for( node_id = 0; node_id < num_nodes; node_id++ )
2297 {
2298
2299 xxi.set( 0.0, 0.0, 0.0 );
2300 xet.set( 0.0, 0.0, 0.0 );
2301 xze.set( 0.0, 0.0, 0.0 );
2302
2303 for( ja = 0; ja < num_nodes; ja++ )
2304 {
2305 xin.set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] );
2306 xxi += dndy1_at_node[node_id][ja] * xin;
2307 xet += dndy2_at_node[node_id][ja] * xin;
2308 xze += dndy3_at_node[node_id][ja] * xin;
2309 }
2310
2311 jacobian = xxi % ( xet * xze );
2312 if( minimum_jacobian > jacobian ) minimum_jacobian = jacobian;
2313 }
2314 distortion = minimum_jacobian / element_volume * 8.;
2315 return (double)distortion;
2316 }
References GaussIntegration::calculate_derivative_at_nodes_3d(), GaussIntegration::calculate_shape_function_3d_hex(), GaussIntegration::get_shape_func(), GaussIntegration::initialize(), maxNumberNodes, maxTotalNumberGaussPoints, VerdictVector::set(), and VERDICT_DBL_MAX.
Referenced by moab::VerdictWrapper::quality_measure(), and v_hex_quality().
C_FUNC_DEF double v_hex_edge_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex edge ratio metric.
Hmax / Hmin where Hmax and Hmin are respectively the maximum and the minimum edge lengths
the edge ratio of a hex
NB (P. Pebay 01/23/07): Hmax / Hmin where Hmax and Hmin are respectively the maximum and the minimum edge lengths
Definition at line 529 of file V_HexMetric.cpp.
530 {
531
532 VerdictVector edges[12];
533 make_hex_edges( coordinates, edges );
534
535 double a2 = edges[0].length_squared();
536 double b2 = edges[1].length_squared();
537 double c2 = edges[2].length_squared();
538 double d2 = edges[3].length_squared();
539 double e2 = edges[4].length_squared();
540 double f2 = edges[5].length_squared();
541 double g2 = edges[6].length_squared();
542 double h2 = edges[7].length_squared();
543 double i2 = edges[8].length_squared();
544 double j2 = edges[9].length_squared();
545 double k2 = edges[10].length_squared();
546 double l2 = edges[11].length_squared();
547
548 double mab, mcd, mef, Mab, Mcd, Mef;
549 double mgh, mij, mkl, Mgh, Mij, Mkl;
550
551 if( a2 < b2 )
552 {
553 mab = a2;
554 Mab = b2;
555 }
556 else // b2 <= a2
557 {
558 mab = b2;
559 Mab = a2;
560 }
561 if( c2 < d2 )
562 {
563 mcd = c2;
564 Mcd = d2;
565 }
566 else // d2 <= c2
567 {
568 mcd = d2;
569 Mcd = c2;
570 }
571 if( e2 < f2 )
572 {
573 mef = e2;
574 Mef = f2;
575 }
576 else // f2 <= e2
577 {
578 mef = f2;
579 Mef = e2;
580 }
581 if( g2 < h2 )
582 {
583 mgh = g2;
584 Mgh = h2;
585 }
586 else // h2 <= g2
587 {
588 mgh = h2;
589 Mgh = g2;
590 }
591 if( i2 < j2 )
592 {
593 mij = i2;
594 Mij = j2;
595 }
596 else // j2 <= i2
597 {
598 mij = j2;
599 Mij = i2;
600 }
601 if( k2 < l2 )
602 {
603 mkl = k2;
604 Mkl = l2;
605 }
606 else // l2 <= k2
607 {
608 mkl = l2;
609 Mkl = k2;
610 }
611
612 double m2;
613 m2 = mab < mcd ? mab : mcd;
614 m2 = m2 < mef ? m2 : mef;
615 m2 = m2 < mgh ? m2 : mgh;
616 m2 = m2 < mij ? m2 : mij;
617 m2 = m2 < mkl ? m2 : mkl;
618
619 if( m2 < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX;
620
621 double M2;
622 M2 = Mab > Mcd ? Mab : Mcd;
623 M2 = M2 > Mef ? M2 : Mef;
624 M2 = M2 > Mgh ? M2 : Mgh;
625 M2 = M2 > Mij ? M2 : Mij;
626 M2 = M2 > Mkl ? M2 : Mkl;
627 m2 = m2 < mef ? m2 : mef;
628
629 M2 = Mab > Mcd ? Mab : Mcd;
630 M2 = M2 > Mef ? M2 : Mef;
631
632 double edge_ratio = sqrt( M2 / m2 );
633
634 if( edge_ratio > 0 ) return (double)VERDICT_MIN( edge_ratio, VERDICT_DBL_MAX );
635 return (double)VERDICT_MAX( edge_ratio, -VERDICT_DBL_MAX );
636 }
References VerdictVector::length_squared(), make_hex_edges(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_hex_quality().
C_FUNC_DEF double v_hex_jacobian | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex jacobian metric.
Minimum pointwise volume of local map at 8 corners & center of hex. Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
jacobian of a hex
Minimum pointwise volume of local map at 8 corners & center of hex
Definition at line 1382 of file V_HexMetric.cpp.
1383 {
1384
1385 VerdictVector node_pos[8];
1386 make_hex_nodes( coordinates, node_pos );
1387
1388 double jacobian = VERDICT_DBL_MAX;
1389 double current_jacobian;
1390 VerdictVector xxi, xet, xze;
1391
1392 xxi = calc_hex_efg( 1, node_pos );
1393 xet = calc_hex_efg( 2, node_pos );
1394 xze = calc_hex_efg( 3, node_pos );
1395
1396 current_jacobian = xxi % ( xet * xze ) / 64.0;
1397 if( current_jacobian < jacobian )
1398 {
1399 jacobian = current_jacobian;
1400 }
1401
1402 // J(0,0,0):
1403
1404 xxi = node_pos[1] - node_pos[0];
1405 xet = node_pos[3] - node_pos[0];
1406 xze = node_pos[4] - node_pos[0];
1407
1408 current_jacobian = xxi % ( xet * xze );
1409 if( current_jacobian < jacobian )
1410 {
1411 jacobian = current_jacobian;
1412 }
1413
1414 // J(1,0,0):
1415
1416 xxi = node_pos[2] - node_pos[1];
1417 xet = node_pos[0] - node_pos[1];
1418 xze = node_pos[5] - node_pos[1];
1419
1420 current_jacobian = xxi % ( xet * xze );
1421 if( current_jacobian < jacobian )
1422 {
1423 jacobian = current_jacobian;
1424 }
1425
1426 // J(1,1,0):
1427
1428 xxi = node_pos[3] - node_pos[2];
1429 xet = node_pos[1] - node_pos[2];
1430 xze = node_pos[6] - node_pos[2];
1431
1432 current_jacobian = xxi % ( xet * xze );
1433 if( current_jacobian < jacobian )
1434 {
1435 jacobian = current_jacobian;
1436 }
1437
1438 // J(0,1,0):
1439
1440 xxi = node_pos[0] - node_pos[3];
1441 xet = node_pos[2] - node_pos[3];
1442 xze = node_pos[7] - node_pos[3];
1443
1444 current_jacobian = xxi % ( xet * xze );
1445 if( current_jacobian < jacobian )
1446 {
1447 jacobian = current_jacobian;
1448 }
1449
1450 // J(0,0,1):
1451
1452 xxi = node_pos[7] - node_pos[4];
1453 xet = node_pos[5] - node_pos[4];
1454 xze = node_pos[0] - node_pos[4];
1455
1456 current_jacobian = xxi % ( xet * xze );
1457 if( current_jacobian < jacobian )
1458 {
1459 jacobian = current_jacobian;
1460 }
1461
1462 // J(1,0,1):
1463
1464 xxi = node_pos[4] - node_pos[5];
1465 xet = node_pos[6] - node_pos[5];
1466 xze = node_pos[1] - node_pos[5];
1467
1468 current_jacobian = xxi % ( xet * xze );
1469 if( current_jacobian < jacobian )
1470 {
1471 jacobian = current_jacobian;
1472 }
1473
1474 // J(1,1,1):
1475
1476 xxi = node_pos[5] - node_pos[6];
1477 xet = node_pos[7] - node_pos[6];
1478 xze = node_pos[2] - node_pos[6];
1479
1480 current_jacobian = xxi % ( xet * xze );
1481 if( current_jacobian < jacobian )
1482 {
1483 jacobian = current_jacobian;
1484 }
1485
1486 // J(0,1,1):
1487
1488 xxi = node_pos[6] - node_pos[7];
1489 xet = node_pos[4] - node_pos[7];
1490 xze = node_pos[3] - node_pos[7];
1491
1492 current_jacobian = xxi % ( xet * xze );
1493 if( current_jacobian < jacobian )
1494 {
1495 jacobian = current_jacobian;
1496 }
1497
1498 if( jacobian > 0 ) return (double)VERDICT_MIN( jacobian, VERDICT_DBL_MAX );
1499 return (double)VERDICT_MAX( jacobian, -VERDICT_DBL_MAX );
1500 }
References calc_hex_efg(), make_hex_nodes, VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_hex_max_aspect_frobenius | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex condition metric.
Maximum Frobenius condition number of the Jacobian matrix at 8 corners. Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
maximum Frobenius condition number of a hex
Maximum Frobenius condition number of the Jacobian matrix at 8 corners NB (P. Pebay 01/25/07): this metric is calculated by taking the maximum of the 8 Frobenius aspects at each corner of the hex, when the reference corner is right isosceles.
Definition at line 1243 of file V_HexMetric.cpp.
1244 {
1245
1246 VerdictVector node_pos[8];
1247 make_hex_nodes( coordinates, node_pos );
1248
1249 double condition = 0.0, current_condition;
1250 VerdictVector xxi, xet, xze;
1251
1252 xxi = calc_hex_efg( 1, node_pos );
1253 xet = calc_hex_efg( 2, node_pos );
1254 xze = calc_hex_efg( 3, node_pos );
1255
1256 current_condition = condition_comp( xxi, xet, xze );
1257 if( current_condition > condition )
1258 {
1259 condition = current_condition;
1260 }
1261
1262 // J(0,0,0):
1263
1264 xxi = node_pos[1] - node_pos[0];
1265 xet = node_pos[3] - node_pos[0];
1266 xze = node_pos[4] - node_pos[0];
1267
1268 current_condition = condition_comp( xxi, xet, xze );
1269 if( current_condition > condition )
1270 {
1271 condition = current_condition;
1272 }
1273
1274 // J(1,0,0):
1275
1276 xxi = node_pos[2] - node_pos[1];
1277 xet = node_pos[0] - node_pos[1];
1278 xze = node_pos[5] - node_pos[1];
1279
1280 current_condition = condition_comp( xxi, xet, xze );
1281 if( current_condition > condition )
1282 {
1283 condition = current_condition;
1284 }
1285
1286 // J(1,1,0):
1287
1288 xxi = node_pos[3] - node_pos[2];
1289 xet = node_pos[1] - node_pos[2];
1290 xze = node_pos[6] - node_pos[2];
1291
1292 current_condition = condition_comp( xxi, xet, xze );
1293 if( current_condition > condition )
1294 {
1295 condition = current_condition;
1296 }
1297
1298 // J(0,1,0):
1299
1300 xxi = node_pos[0] - node_pos[3];
1301 xet = node_pos[2] - node_pos[3];
1302 xze = node_pos[7] - node_pos[3];
1303
1304 current_condition = condition_comp( xxi, xet, xze );
1305 if( current_condition > condition )
1306 {
1307 condition = current_condition;
1308 }
1309
1310 // J(0,0,1):
1311
1312 xxi = node_pos[7] - node_pos[4];
1313 xet = node_pos[5] - node_pos[4];
1314 xze = node_pos[0] - node_pos[4];
1315
1316 current_condition = condition_comp( xxi, xet, xze );
1317 if( current_condition > condition )
1318 {
1319 condition = current_condition;
1320 }
1321
1322 // J(1,0,1):
1323
1324 xxi = node_pos[4] - node_pos[5];
1325 xet = node_pos[6] - node_pos[5];
1326 xze = node_pos[1] - node_pos[5];
1327
1328 current_condition = condition_comp( xxi, xet, xze );
1329 if( current_condition > condition )
1330 {
1331 condition = current_condition;
1332 }
1333
1334 // J(1,1,1):
1335
1336 xxi = node_pos[5] - node_pos[6];
1337 xet = node_pos[7] - node_pos[6];
1338 xze = node_pos[2] - node_pos[6];
1339
1340 current_condition = condition_comp( xxi, xet, xze );
1341 if( current_condition > condition )
1342 {
1343 condition = current_condition;
1344 }
1345
1346 // J(1,1,1):
1347
1348 xxi = node_pos[6] - node_pos[7];
1349 xet = node_pos[4] - node_pos[7];
1350 xze = node_pos[3] - node_pos[7];
1351
1352 current_condition = condition_comp( xxi, xet, xze );
1353 if( current_condition > condition )
1354 {
1355 condition = current_condition;
1356 }
1357
1358 condition /= 3.0;
1359
1360 if( condition > 0 ) return (double)VERDICT_MIN( condition, VERDICT_DBL_MAX );
1361 return (double)VERDICT_MAX( condition, -VERDICT_DBL_MAX );
1362 }
References calc_hex_efg(), condition_comp(), make_hex_nodes, VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_hex_condition().
C_FUNC_DEF double v_hex_max_edge_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex maximum of edge ratio.
Maximum edge length ratio at hex center. Reference — L.M. Taylor, and D.P. Flanagan, Pronto3D - A Three Dimensional Transient Solid Dynamics Program, SAND87-1912, Sandia National Laboratories, 1989.
max edge ratio of a hex
Maximum edge length ratio at hex center
Definition at line 643 of file V_HexMetric.cpp.
644 {
645 double aspect;
646 VerdictVector node_pos[8];
647 make_hex_nodes( coordinates, node_pos );
648
649 double aspect_12, aspect_13, aspect_23;
650
651 VerdictVector efg1 = calc_hex_efg( 1, node_pos );
652 VerdictVector efg2 = calc_hex_efg( 2, node_pos );
653 VerdictVector efg3 = calc_hex_efg( 3, node_pos );
654
655 double mag_efg1 = efg1.length();
656 double mag_efg2 = efg2.length();
657 double mag_efg3 = efg3.length();
658
659 aspect_12 = safe_ratio( VERDICT_MAX( mag_efg1, mag_efg2 ), VERDICT_MIN( mag_efg1, mag_efg2 ) );
660 aspect_13 = safe_ratio( VERDICT_MAX( mag_efg1, mag_efg3 ), VERDICT_MIN( mag_efg1, mag_efg3 ) );
661 aspect_23 = safe_ratio( VERDICT_MAX( mag_efg2, mag_efg3 ), VERDICT_MIN( mag_efg2, mag_efg3 ) );
662
663 aspect = VERDICT_MAX( aspect_12, VERDICT_MAX( aspect_13, aspect_23 ) );
664
665 if( aspect > 0 ) return (double)VERDICT_MIN( aspect, VERDICT_DBL_MAX );
666 return (double)VERDICT_MAX( aspect, -VERDICT_DBL_MAX );
667 }
References calc_hex_efg(), VerdictVector::length(), make_hex_nodes, safe_ratio(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_hex_med_aspect_frobenius | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex condition metric.
Average Frobenius condition number of the Jacobian matrix at 8 corners.
the average Frobenius aspect of a hex
NB (P. Pebay 01/20/07): this metric is calculated by averaging the 8 Frobenius aspects at each corner of the hex, when the reference corner is right isosceles.
Definition at line 1164 of file V_HexMetric.cpp.
1165 {
1166
1167 VerdictVector node_pos[8];
1168 make_hex_nodes( coordinates, node_pos );
1169
1170 double med_aspect_frobenius = 0.;
1171 VerdictVector xxi, xet, xze;
1172
1173 // J(0,0,0):
1174
1175 xxi = node_pos[1] - node_pos[0];
1176 xet = node_pos[3] - node_pos[0];
1177 xze = node_pos[4] - node_pos[0];
1178
1179 med_aspect_frobenius += condition_comp( xxi, xet, xze );
1180 // J(1,0,0):
1181
1182 xxi = node_pos[2] - node_pos[1];
1183 xet = node_pos[0] - node_pos[1];
1184 xze = node_pos[5] - node_pos[1];
1185
1186 med_aspect_frobenius += condition_comp( xxi, xet, xze );
1187 // J(1,1,0):
1188
1189 xxi = node_pos[3] - node_pos[2];
1190 xet = node_pos[1] - node_pos[2];
1191 xze = node_pos[6] - node_pos[2];
1192
1193 med_aspect_frobenius += condition_comp( xxi, xet, xze );
1194 // J(0,1,0):
1195
1196 xxi = node_pos[0] - node_pos[3];
1197 xet = node_pos[2] - node_pos[3];
1198 xze = node_pos[7] - node_pos[3];
1199
1200 med_aspect_frobenius += condition_comp( xxi, xet, xze );
1201 // J(0,0,1):
1202
1203 xxi = node_pos[7] - node_pos[4];
1204 xet = node_pos[5] - node_pos[4];
1205 xze = node_pos[0] - node_pos[4];
1206
1207 med_aspect_frobenius += condition_comp( xxi, xet, xze );
1208 // J(1,0,1):
1209
1210 xxi = node_pos[4] - node_pos[5];
1211 xet = node_pos[6] - node_pos[5];
1212 xze = node_pos[1] - node_pos[5];
1213
1214 med_aspect_frobenius += condition_comp( xxi, xet, xze );
1215 // J(1,1,1):
1216
1217 xxi = node_pos[5] - node_pos[6];
1218 xet = node_pos[7] - node_pos[6];
1219 xze = node_pos[2] - node_pos[6];
1220
1221 med_aspect_frobenius += condition_comp( xxi, xet, xze );
1222 // J(1,1,1):
1223
1224 xxi = node_pos[6] - node_pos[7];
1225 xet = node_pos[4] - node_pos[7];
1226 xze = node_pos[3] - node_pos[7];
1227
1228 med_aspect_frobenius += condition_comp( xxi, xet, xze );
1229 med_aspect_frobenius /= 24.;
1230
1231 if( med_aspect_frobenius > 0 ) return (double)VERDICT_MIN( med_aspect_frobenius, VERDICT_DBL_MAX );
1232 return (double)VERDICT_MAX( med_aspect_frobenius, -VERDICT_DBL_MAX );
1233 }
References condition_comp(), make_hex_nodes, VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_hex_quality().
C_FUNC_DEF double v_hex_oddy | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex oddy metric.
oddy of a hex
General distortion measure based on left Cauchy-Green Tensor
Definition at line 1014 of file V_HexMetric.cpp.
1015 {
1016
1017 double oddy = 0.0, current_oddy;
1018 VerdictVector xxi, xet, xze;
1019
1020 VerdictVector node_pos[8];
1021 make_hex_nodes( coordinates, node_pos );
1022
1023 xxi = calc_hex_efg( 1, node_pos );
1024 xet = calc_hex_efg( 2, node_pos );
1025 xze = calc_hex_efg( 3, node_pos );
1026
1027 current_oddy = oddy_comp( xxi, xet, xze );
1028 if( current_oddy > oddy )
1029 {
1030 oddy = current_oddy;
1031 }
1032
1033 xxi.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
1034 coordinates[1][2] - coordinates[0][2] );
1035
1036 xet.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
1037 coordinates[3][2] - coordinates[0][2] );
1038
1039 xze.set( coordinates[4][0] - coordinates[0][0], coordinates[4][1] - coordinates[0][1],
1040 coordinates[4][2] - coordinates[0][2] );
1041
1042 current_oddy = oddy_comp( xxi, xet, xze );
1043 if( current_oddy > oddy )
1044 {
1045 oddy = current_oddy;
1046 }
1047
1048 xxi.set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
1049 coordinates[2][2] - coordinates[1][2] );
1050
1051 xet.set( coordinates[0][0] - coordinates[1][0], coordinates[0][1] - coordinates[1][1],
1052 coordinates[0][2] - coordinates[1][2] );
1053
1054 xze.set( coordinates[5][0] - coordinates[1][0], coordinates[5][1] - coordinates[1][1],
1055 coordinates[5][2] - coordinates[1][2] );
1056
1057 current_oddy = oddy_comp( xxi, xet, xze );
1058 if( current_oddy > oddy )
1059 {
1060 oddy = current_oddy;
1061 }
1062
1063 xxi.set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
1064 coordinates[3][2] - coordinates[2][2] );
1065
1066 xet.set( coordinates[1][0] - coordinates[2][0], coordinates[1][1] - coordinates[2][1],
1067 coordinates[1][2] - coordinates[2][2] );
1068
1069 xze.set( coordinates[6][0] - coordinates[2][0], coordinates[6][1] - coordinates[2][1],
1070 coordinates[6][2] - coordinates[2][2] );
1071
1072 current_oddy = oddy_comp( xxi, xet, xze );
1073 if( current_oddy > oddy )
1074 {
1075 oddy = current_oddy;
1076 }
1077
1078 xxi.set( coordinates[0][0] - coordinates[3][0], coordinates[0][1] - coordinates[3][1],
1079 coordinates[0][2] - coordinates[3][2] );
1080
1081 xet.set( coordinates[2][0] - coordinates[3][0], coordinates[2][1] - coordinates[3][1],
1082 coordinates[2][2] - coordinates[3][2] );
1083
1084 xze.set( coordinates[7][0] - coordinates[3][0], coordinates[7][1] - coordinates[3][1],
1085 coordinates[7][2] - coordinates[3][2] );
1086
1087 current_oddy = oddy_comp( xxi, xet, xze );
1088 if( current_oddy > oddy )
1089 {
1090 oddy = current_oddy;
1091 }
1092
1093 xxi.set( coordinates[7][0] - coordinates[4][0], coordinates[7][1] - coordinates[4][1],
1094 coordinates[7][2] - coordinates[4][2] );
1095
1096 xet.set( coordinates[5][0] - coordinates[4][0], coordinates[5][1] - coordinates[4][1],
1097 coordinates[5][2] - coordinates[4][2] );
1098
1099 xze.set( coordinates[0][0] - coordinates[4][0], coordinates[0][1] - coordinates[4][1],
1100 coordinates[0][2] - coordinates[4][2] );
1101
1102 current_oddy = oddy_comp( xxi, xet, xze );
1103 if( current_oddy > oddy )
1104 {
1105 oddy = current_oddy;
1106 }
1107
1108 xxi.set( coordinates[4][0] - coordinates[5][0], coordinates[4][1] - coordinates[5][1],
1109 coordinates[4][2] - coordinates[5][2] );
1110
1111 xet.set( coordinates[6][0] - coordinates[5][0], coordinates[6][1] - coordinates[5][1],
1112 coordinates[6][2] - coordinates[5][2] );
1113
1114 xze.set( coordinates[1][0] - coordinates[5][0], coordinates[1][1] - coordinates[5][1],
1115 coordinates[1][2] - coordinates[5][2] );
1116
1117 current_oddy = oddy_comp( xxi, xet, xze );
1118 if( current_oddy > oddy )
1119 {
1120 oddy = current_oddy;
1121 }
1122
1123 xxi.set( coordinates[5][0] - coordinates[6][0], coordinates[5][1] - coordinates[6][1],
1124 coordinates[5][2] - coordinates[6][2] );
1125
1126 xet.set( coordinates[7][0] - coordinates[6][0], coordinates[7][1] - coordinates[6][1],
1127 coordinates[7][2] - coordinates[6][2] );
1128
1129 xze.set( coordinates[2][0] - coordinates[6][0], coordinates[2][1] - coordinates[6][1],
1130 coordinates[2][2] - coordinates[6][2] );
1131
1132 current_oddy = oddy_comp( xxi, xet, xze );
1133 if( current_oddy > oddy )
1134 {
1135 oddy = current_oddy;
1136 }
1137
1138 xxi.set( coordinates[6][0] - coordinates[7][0], coordinates[6][1] - coordinates[7][1],
1139 coordinates[6][2] - coordinates[7][2] );
1140
1141 xet.set( coordinates[4][0] - coordinates[7][0], coordinates[4][1] - coordinates[7][1],
1142 coordinates[4][2] - coordinates[7][2] );
1143
1144 xze.set( coordinates[3][0] - coordinates[7][0], coordinates[3][1] - coordinates[7][1],
1145 coordinates[3][2] - coordinates[7][2] );
1146
1147 current_oddy = oddy_comp( xxi, xet, xze );
1148 if( current_oddy > oddy )
1149 {
1150 oddy = current_oddy;
1151 }
1152
1153 if( oddy > 0 ) return (double)VERDICT_MIN( oddy, VERDICT_DBL_MAX );
1154 return (double)VERDICT_MAX( oddy, -VERDICT_DBL_MAX );
1155 }
References calc_hex_efg(), make_hex_nodes, oddy_comp(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF void v_hex_quality | ( | int | num_nodes, |
double | coordinates[][3], | ||
unsigned int | metrics_request_flag, | ||
HexMetricVals * | metric_vals | ||
) |
Calculates quality metrics for hexahedral elements.
multiple quality metrics of a hex
Definition at line 2651 of file V_HexMetric.cpp.
2655 {
2656 memset( metric_vals, 0, sizeof( HexMetricVals ) );
2657
2658 // max edge ratio, skew, taper, and volume
2659 if( metrics_request_flag & ( V_HEX_MAX_EDGE_RATIO | V_HEX_SKEW | V_HEX_TAPER ) )
2660 {
2661 VerdictVector node_pos[8];
2662 make_hex_nodes( coordinates, node_pos );
2663
2664 VerdictVector efg1, efg2, efg3;
2665 efg1 = calc_hex_efg( 1, node_pos );
2666 efg2 = calc_hex_efg( 2, node_pos );
2667 efg3 = calc_hex_efg( 3, node_pos );
2668
2669 if( metrics_request_flag & V_HEX_MAX_EDGE_RATIO )
2670 {
2671 double max_edge_ratio_12, max_edge_ratio_13, max_edge_ratio_23;
2672
2673 double mag_efg1 = efg1.length();
2674 double mag_efg2 = efg2.length();
2675 double mag_efg3 = efg3.length();
2676
2677 max_edge_ratio_12 = safe_ratio( VERDICT_MAX( mag_efg1, mag_efg2 ), VERDICT_MIN( mag_efg1, mag_efg2 ) );
2678 max_edge_ratio_13 = safe_ratio( VERDICT_MAX( mag_efg1, mag_efg3 ), VERDICT_MIN( mag_efg1, mag_efg3 ) );
2679 max_edge_ratio_23 = safe_ratio( VERDICT_MAX( mag_efg2, mag_efg3 ), VERDICT_MIN( mag_efg2, mag_efg3 ) );
2680
2681 metric_vals->max_edge_ratio =
2682 (double)VERDICT_MAX( max_edge_ratio_12, VERDICT_MAX( max_edge_ratio_13, max_edge_ratio_23 ) );
2683 }
2684
2685 if( metrics_request_flag & V_HEX_SKEW )
2686 {
2687
2688 VerdictVector vec1 = efg1;
2689 VerdictVector vec2 = efg2;
2690 VerdictVector vec3 = efg3;
2691
2692 if( vec1.normalize() <= VERDICT_DBL_MIN || vec2.normalize() <= VERDICT_DBL_MIN ||
2693 vec3.normalize() <= VERDICT_DBL_MIN )
2694 {
2695 metric_vals->skew = (double)VERDICT_DBL_MAX;
2696 }
2697 else
2698 {
2699 double skewx = fabs( vec1 % vec2 );
2700 double skewy = fabs( vec1 % vec3 );
2701 double skewz = fabs( vec2 % vec3 );
2702
2703 metric_vals->skew = (double)( VERDICT_MAX( skewx, VERDICT_MAX( skewy, skewz ) ) );
2704 }
2705 }
2706
2707 if( metrics_request_flag & V_HEX_TAPER )
2708 {
2709 VerdictVector efg12 = calc_hex_efg( 12, node_pos );
2710 VerdictVector efg13 = calc_hex_efg( 13, node_pos );
2711 VerdictVector efg23 = calc_hex_efg( 23, node_pos );
2712
2713 double taperx = fabs( safe_ratio( efg12.length(), VERDICT_MIN( efg1.length(), efg2.length() ) ) );
2714 double tapery = fabs( safe_ratio( efg13.length(), VERDICT_MIN( efg1.length(), efg3.length() ) ) );
2715 double taperz = fabs( safe_ratio( efg23.length(), VERDICT_MIN( efg2.length(), efg3.length() ) ) );
2716
2717 metric_vals->taper = (double)VERDICT_MAX( taperx, VERDICT_MAX( tapery, taperz ) );
2718 }
2719 }
2720
2721 if( metrics_request_flag & V_HEX_VOLUME )
2722 {
2723 metric_vals->volume = v_hex_volume( 8, coordinates );
2724 }
2725
2726 if( metrics_request_flag &
2727 ( V_HEX_JACOBIAN | V_HEX_SCALED_JACOBIAN | V_HEX_CONDITION | V_HEX_SHEAR | V_HEX_SHAPE |
2728 V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE | V_HEX_STRETCH ) )
2729 {
2730
2731 static const double two_thirds = 2.0 / 3.0;
2732 VerdictVector edges[12];
2733 // the length squares
2734 double length_squared[12];
2735 // make vectors from coordinates
2736 make_hex_edges( coordinates, edges );
2737
2738 // calculate the length squares if we need to
2739 if( metrics_request_flag &
2740 ( V_HEX_JACOBIAN | V_HEX_SHEAR | V_HEX_SCALED_JACOBIAN | V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE |
2741 V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHEAR_AND_SIZE | V_HEX_STRETCH ) )
2742 make_edge_length_squares( edges, length_squared );
2743
2744 double jacobian = VERDICT_DBL_MAX, scaled_jacobian = VERDICT_DBL_MAX, condition = 0.0, shear = 1.0, shape = 1.0,
2745 oddy = 0.0;
2746 double current_jacobian, current_scaled_jacobian, current_condition, current_shape, detw = 0, det_sum = 0,
2747 current_oddy;
2748 VerdictBoolean rel_size_error = VERDICT_FALSE;
2749
2750 VerdictVector xxi, xet, xze;
2751
2752 // get weights if we need based on average size of a hex
2753 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) )
2754 {
2755 v_hex_get_weight( xxi, xet, xze );
2756 detw = xxi % ( xet * xze );
2757 if( detw < VERDICT_DBL_MIN ) rel_size_error = VERDICT_TRUE;
2758 }
2759
2760 xxi = edges[0] - edges[2] + edges[4] - edges[6];
2761 xet = edges[1] - edges[3] + edges[5] - edges[7];
2762 xze = edges[8] + edges[9] + edges[10] + edges[11];
2763
2764 current_jacobian = xxi % ( xet * xze ) / 64.0;
2765 if( current_jacobian < jacobian ) jacobian = current_jacobian;
2766
2767 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) )
2768 {
2769 current_jacobian *= 64.0;
2770 current_scaled_jacobian =
2771 current_jacobian / sqrt( xxi.length_squared() * xet.length_squared() * xze.length_squared() );
2772 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian;
2773 }
2774
2775 if( metrics_request_flag & V_HEX_CONDITION )
2776 {
2777 current_condition = condition_comp( xxi, xet, xze );
2778 if( current_condition > condition )
2779 {
2780 condition = current_condition;
2781 }
2782 }
2783
2784 if( metrics_request_flag & V_HEX_ODDY )
2785 {
2786 current_oddy = oddy_comp( xxi, xet, xze );
2787 if( current_oddy > oddy )
2788 {
2789 oddy = current_oddy;
2790 }
2791 }
2792
2793 // J(0,0,0)
2794 current_jacobian = edges[0] % ( -edges[3] * edges[8] );
2795 if( current_jacobian < jacobian ) jacobian = current_jacobian;
2796
2797 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) )
2798 {
2799 det_sum += current_jacobian;
2800 }
2801
2802 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) )
2803 {
2804 if( length_squared[0] <= VERDICT_DBL_MIN || length_squared[3] <= VERDICT_DBL_MIN ||
2805 length_squared[8] <= VERDICT_DBL_MIN )
2806 {
2807 current_scaled_jacobian = VERDICT_DBL_MAX;
2808 }
2809 else
2810 {
2811 current_scaled_jacobian =
2812 current_jacobian / sqrt( length_squared[0] * length_squared[3] * length_squared[8] );
2813 }
2814 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian;
2815 }
2816
2817 if( metrics_request_flag & V_HEX_CONDITION )
2818 {
2819 current_condition = condition_comp( edges[0], -edges[3], edges[8] );
2820 if( current_condition > condition )
2821 {
2822 condition = current_condition;
2823 }
2824 }
2825
2826 if( metrics_request_flag & V_HEX_ODDY )
2827 {
2828 current_oddy = oddy_comp( edges[0], -edges[3], edges[8] );
2829 if( current_oddy > oddy )
2830 {
2831 oddy = current_oddy;
2832 }
2833 }
2834
2835 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) )
2836 {
2837 if( current_jacobian > VERDICT_DBL_MIN )
2838 current_shape = 3 * pow( current_jacobian, two_thirds ) /
2839 ( length_squared[0] + length_squared[3] + length_squared[8] );
2840 else
2841 current_shape = 0;
2842
2843 if( current_shape < shape )
2844 {
2845 shape = current_shape;
2846 }
2847 }
2848
2849 // J(1,0,0)
2850 current_jacobian = edges[1] % ( -edges[0] * edges[9] );
2851 if( current_jacobian < jacobian ) jacobian = current_jacobian;
2852
2853 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) )
2854 {
2855 det_sum += current_jacobian;
2856 }
2857
2858 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) )
2859 {
2860 if( length_squared[1] <= VERDICT_DBL_MIN || length_squared[0] <= VERDICT_DBL_MIN ||
2861 length_squared[9] <= VERDICT_DBL_MIN )
2862 {
2863 current_scaled_jacobian = VERDICT_DBL_MAX;
2864 }
2865 else
2866 {
2867 current_scaled_jacobian =
2868 current_jacobian / sqrt( length_squared[1] * length_squared[0] * length_squared[9] );
2869 }
2870 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian;
2871 }
2872
2873 if( metrics_request_flag & V_HEX_CONDITION )
2874 {
2875 current_condition = condition_comp( edges[1], -edges[0], edges[9] );
2876 if( current_condition > condition )
2877 {
2878 condition = current_condition;
2879 }
2880 }
2881
2882 if( metrics_request_flag & V_HEX_ODDY )
2883 {
2884 current_oddy = oddy_comp( edges[1], -edges[0], edges[9] );
2885 if( current_oddy > oddy )
2886 {
2887 oddy = current_oddy;
2888 }
2889 }
2890
2891 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) )
2892 {
2893 if( current_jacobian > VERDICT_DBL_MIN )
2894 current_shape = 3 * pow( current_jacobian, two_thirds ) /
2895 ( length_squared[1] + length_squared[0] + length_squared[9] );
2896 else
2897 current_shape = 0;
2898
2899 if( current_shape < shape )
2900 {
2901 shape = current_shape;
2902 }
2903 }
2904
2905 // J(1,1,0)
2906 current_jacobian = edges[2] % ( -edges[1] * edges[10] );
2907 if( current_jacobian < jacobian ) jacobian = current_jacobian;
2908
2909 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) )
2910 {
2911 det_sum += current_jacobian;
2912 }
2913
2914 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) )
2915 {
2916 if( length_squared[2] <= VERDICT_DBL_MIN || length_squared[1] <= VERDICT_DBL_MIN ||
2917 length_squared[10] <= VERDICT_DBL_MIN )
2918 {
2919 current_scaled_jacobian = VERDICT_DBL_MAX;
2920 }
2921 else
2922 {
2923 current_scaled_jacobian =
2924 current_jacobian / sqrt( length_squared[2] * length_squared[1] * length_squared[10] );
2925 }
2926 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian;
2927 }
2928
2929 if( metrics_request_flag & V_HEX_CONDITION )
2930 {
2931 current_condition = condition_comp( edges[2], -edges[1], edges[10] );
2932 if( current_condition > condition )
2933 {
2934 condition = current_condition;
2935 }
2936 }
2937
2938 if( metrics_request_flag & V_HEX_ODDY )
2939 {
2940 current_oddy = oddy_comp( edges[2], -edges[1], edges[10] );
2941 if( current_oddy > oddy )
2942 {
2943 oddy = current_oddy;
2944 }
2945 }
2946
2947 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) )
2948 {
2949 if( current_jacobian > VERDICT_DBL_MIN )
2950 current_shape = 3 * pow( current_jacobian, two_thirds ) /
2951 ( length_squared[2] + length_squared[1] + length_squared[10] );
2952 else
2953 current_shape = 0;
2954
2955 if( current_shape < shape )
2956 {
2957 shape = current_shape;
2958 }
2959 }
2960
2961 // J(0,1,0)
2962 current_jacobian = edges[3] % ( -edges[2] * edges[11] );
2963 if( current_jacobian < jacobian ) jacobian = current_jacobian;
2964
2965 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) )
2966 {
2967 det_sum += current_jacobian;
2968 }
2969
2970 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) )
2971 {
2972 if( length_squared[3] <= VERDICT_DBL_MIN || length_squared[2] <= VERDICT_DBL_MIN ||
2973 length_squared[11] <= VERDICT_DBL_MIN )
2974 {
2975 current_scaled_jacobian = VERDICT_DBL_MAX;
2976 }
2977 else
2978 {
2979 current_scaled_jacobian =
2980 current_jacobian / sqrt( length_squared[3] * length_squared[2] * length_squared[11] );
2981 }
2982 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian;
2983 }
2984
2985 if( metrics_request_flag & V_HEX_CONDITION )
2986 {
2987 current_condition = condition_comp( edges[3], -edges[2], edges[11] );
2988 if( current_condition > condition )
2989 {
2990 condition = current_condition;
2991 }
2992 }
2993
2994 if( metrics_request_flag & V_HEX_ODDY )
2995 {
2996 current_oddy = oddy_comp( edges[3], -edges[2], edges[11] );
2997 if( current_oddy > oddy )
2998 {
2999 oddy = current_oddy;
3000 }
3001 }
3002
3003 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) )
3004 {
3005 if( current_jacobian > VERDICT_DBL_MIN )
3006 current_shape = 3 * pow( current_jacobian, two_thirds ) /
3007 ( length_squared[3] + length_squared[2] + length_squared[11] );
3008 else
3009 current_shape = 0;
3010
3011 if( current_shape < shape )
3012 {
3013 shape = current_shape;
3014 }
3015 }
3016
3017 // J(0,0,1)
3018 current_jacobian = edges[4] % ( -edges[8] * -edges[7] );
3019 if( current_jacobian < jacobian ) jacobian = current_jacobian;
3020
3021 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) )
3022 {
3023 det_sum += current_jacobian;
3024 }
3025
3026 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) )
3027 {
3028 if( length_squared[4] <= VERDICT_DBL_MIN || length_squared[8] <= VERDICT_DBL_MIN ||
3029 length_squared[7] <= VERDICT_DBL_MIN )
3030 {
3031 current_scaled_jacobian = VERDICT_DBL_MAX;
3032 }
3033 else
3034 {
3035 current_scaled_jacobian =
3036 current_jacobian / sqrt( length_squared[4] * length_squared[8] * length_squared[7] );
3037 }
3038 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian;
3039 }
3040
3041 if( metrics_request_flag & V_HEX_CONDITION )
3042 {
3043 current_condition = condition_comp( edges[4], -edges[8], -edges[7] );
3044 if( current_condition > condition )
3045 {
3046 condition = current_condition;
3047 }
3048 }
3049
3050 if( metrics_request_flag & V_HEX_ODDY )
3051 {
3052 current_oddy = oddy_comp( edges[4], -edges[8], -edges[7] );
3053 if( current_oddy > oddy )
3054 {
3055 oddy = current_oddy;
3056 }
3057 }
3058
3059 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) )
3060 {
3061 if( current_jacobian > VERDICT_DBL_MIN )
3062 current_shape = 3 * pow( current_jacobian, two_thirds ) /
3063 ( length_squared[4] + length_squared[8] + length_squared[7] );
3064 else
3065 current_shape = 0;
3066
3067 if( current_shape < shape )
3068 {
3069 shape = current_shape;
3070 }
3071 }
3072
3073 // J(1,0,1)
3074 current_jacobian = -edges[4] % ( edges[5] * -edges[9] );
3075 if( current_jacobian < jacobian ) jacobian = current_jacobian;
3076
3077 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) )
3078 {
3079 det_sum += current_jacobian;
3080 }
3081
3082 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) )
3083 {
3084 if( length_squared[4] <= VERDICT_DBL_MIN || length_squared[5] <= VERDICT_DBL_MIN ||
3085 length_squared[9] <= VERDICT_DBL_MIN )
3086 {
3087 current_scaled_jacobian = VERDICT_DBL_MAX;
3088 }
3089 else
3090 {
3091 current_scaled_jacobian =
3092 current_jacobian / sqrt( length_squared[4] * length_squared[5] * length_squared[9] );
3093 }
3094 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian;
3095 }
3096
3097 if( metrics_request_flag & V_HEX_CONDITION )
3098 {
3099 current_condition = condition_comp( -edges[4], edges[5], -edges[9] );
3100 if( current_condition > condition )
3101 {
3102 condition = current_condition;
3103 }
3104 }
3105
3106 if( metrics_request_flag & V_HEX_ODDY )
3107 {
3108 current_oddy = oddy_comp( -edges[4], edges[5], -edges[9] );
3109 if( current_oddy > oddy )
3110 {
3111 oddy = current_oddy;
3112 }
3113 }
3114
3115 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) )
3116 {
3117 if( current_jacobian > VERDICT_DBL_MIN )
3118 current_shape = 3 * pow( current_jacobian, two_thirds ) /
3119 ( length_squared[4] + length_squared[5] + length_squared[9] );
3120 else
3121 current_shape = 0;
3122
3123 if( current_shape < shape )
3124 {
3125 shape = current_shape;
3126 }
3127 }
3128
3129 // J(1,1,1)
3130 current_jacobian = -edges[5] % ( edges[6] * -edges[10] );
3131 if( current_jacobian < jacobian ) jacobian = current_jacobian;
3132
3133 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) )
3134 {
3135 det_sum += current_jacobian;
3136 }
3137
3138 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) )
3139 {
3140 if( length_squared[5] <= VERDICT_DBL_MIN || length_squared[6] <= VERDICT_DBL_MIN ||
3141 length_squared[10] <= VERDICT_DBL_MIN )
3142 {
3143 current_scaled_jacobian = VERDICT_DBL_MAX;
3144 }
3145 else
3146 {
3147 current_scaled_jacobian =
3148 current_jacobian / sqrt( length_squared[5] * length_squared[6] * length_squared[10] );
3149 }
3150 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian;
3151 }
3152
3153 if( metrics_request_flag & V_HEX_CONDITION )
3154 {
3155 current_condition = condition_comp( -edges[5], edges[6], -edges[10] );
3156 if( current_condition > condition )
3157 {
3158 condition = current_condition;
3159 }
3160 }
3161
3162 if( metrics_request_flag & V_HEX_ODDY )
3163 {
3164 current_oddy = oddy_comp( -edges[5], edges[6], -edges[10] );
3165 if( current_oddy > oddy )
3166 {
3167 oddy = current_oddy;
3168 }
3169 }
3170
3171 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) )
3172 {
3173 if( current_jacobian > VERDICT_DBL_MIN )
3174 current_shape = 3 * pow( current_jacobian, two_thirds ) /
3175 ( length_squared[5] + length_squared[6] + length_squared[10] );
3176 else
3177 current_shape = 0;
3178
3179 if( current_shape < shape )
3180 {
3181 shape = current_shape;
3182 }
3183 }
3184
3185 // J(0,1,1)
3186 current_jacobian = -edges[6] % ( edges[7] * -edges[11] );
3187 if( current_jacobian < jacobian ) jacobian = current_jacobian;
3188
3189 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) )
3190 {
3191 det_sum += current_jacobian;
3192 }
3193
3194 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) )
3195 {
3196 if( length_squared[6] <= VERDICT_DBL_MIN || length_squared[7] <= VERDICT_DBL_MIN ||
3197 length_squared[11] <= VERDICT_DBL_MIN )
3198 {
3199 current_scaled_jacobian = VERDICT_DBL_MAX;
3200 }
3201 else
3202 {
3203 current_scaled_jacobian =
3204 current_jacobian / sqrt( length_squared[6] * length_squared[7] * length_squared[11] );
3205 }
3206 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian;
3207 }
3208
3209 if( metrics_request_flag & V_HEX_CONDITION )
3210 {
3211 current_condition = condition_comp( -edges[6], edges[7], -edges[11] );
3212 if( current_condition > condition )
3213 {
3214 condition = current_condition;
3215 }
3216 }
3217
3218 if( metrics_request_flag & V_HEX_ODDY )
3219 {
3220 current_oddy = oddy_comp( -edges[6], edges[7], -edges[11] );
3221 if( current_oddy > oddy )
3222 {
3223 oddy = current_oddy;
3224 }
3225 }
3226
3227 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) )
3228 {
3229 if( current_jacobian > VERDICT_DBL_MIN )
3230 current_shape = 3 * pow( current_jacobian, two_thirds ) /
3231 ( length_squared[6] + length_squared[7] + length_squared[11] );
3232 else
3233 current_shape = 0;
3234
3235 if( current_shape < shape )
3236 {
3237 shape = current_shape;
3238 }
3239 }
3240
3241 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) )
3242 {
3243 if( det_sum > VERDICT_DBL_MIN && rel_size_error != VERDICT_TRUE )
3244 {
3245 double tau = det_sum / ( 8 * detw );
3246 metric_vals->relative_size_squared = (double)VERDICT_MIN( tau * tau, 1.0 / tau / tau );
3247 }
3248 else
3249 metric_vals->relative_size_squared = 0.0;
3250 }
3251
3252 // set values from above calculations
3253 if( metrics_request_flag & V_HEX_JACOBIAN ) metric_vals->jacobian = (double)jacobian;
3254
3255 if( metrics_request_flag & V_HEX_SCALED_JACOBIAN ) metric_vals->scaled_jacobian = (double)scaled_jacobian;
3256
3257 if( metrics_request_flag & V_HEX_CONDITION ) metric_vals->condition = (double)( condition / 3.0 );
3258
3259 if( metrics_request_flag & V_HEX_SHEAR )
3260 {
3261 if( shear < VERDICT_DBL_MIN ) // shear has range 0 to +1
3262 shear = 0;
3263 metric_vals->shear = (double)shear;
3264 }
3265
3266 if( metrics_request_flag & V_HEX_SHAPE ) metric_vals->shape = (double)shape;
3267
3268 if( metrics_request_flag & V_HEX_SHAPE_AND_SIZE )
3269 metric_vals->shape_and_size = (double)( shape * metric_vals->relative_size_squared );
3270
3271 if( metrics_request_flag & V_HEX_SHEAR_AND_SIZE )
3272 metric_vals->shear_and_size = (double)( shear * metric_vals->relative_size_squared );
3273
3274 if( metrics_request_flag & V_HEX_ODDY ) metric_vals->oddy = (double)oddy;
3275
3276 if( metrics_request_flag & V_HEX_STRETCH )
3277 {
3278 static const double HEX_STRETCH_SCALE_FACTOR = sqrt( 3.0 );
3279 double min_edge = length_squared[0];
3280 for( int j = 1; j < 12; j++ )
3281 min_edge = VERDICT_MIN( min_edge, length_squared[j] );
3282
3283 double max_diag = diag_length( 1, coordinates );
3284
3285 metric_vals->stretch = (double)( HEX_STRETCH_SCALE_FACTOR * ( safe_ratio( sqrt( min_edge ), max_diag ) ) );
3286 }
3287 }
3288
3289 if( metrics_request_flag & V_HEX_DIAGONAL ) metric_vals->diagonal = v_hex_diagonal( num_nodes, coordinates );
3290 if( metrics_request_flag & V_HEX_DIMENSION ) metric_vals->dimension = v_hex_dimension( num_nodes, coordinates );
3291 if( metrics_request_flag & V_HEX_DISTORTION ) metric_vals->distortion = v_hex_distortion( num_nodes, coordinates );
3292
3293 // take care of any overflow problems
3294 // max_edge_ratio
3295 if( metric_vals->max_edge_ratio > 0 )
3296 metric_vals->max_edge_ratio = (double)VERDICT_MIN( metric_vals->max_edge_ratio, VERDICT_DBL_MAX );
3297 else
3298 metric_vals->max_edge_ratio = (double)VERDICT_MAX( metric_vals->max_edge_ratio, -VERDICT_DBL_MAX );
3299
3300 // skew
3301 if( metric_vals->skew > 0 )
3302 metric_vals->skew = (double)VERDICT_MIN( metric_vals->skew, VERDICT_DBL_MAX );
3303 else
3304 metric_vals->skew = (double)VERDICT_MAX( metric_vals->skew, -VERDICT_DBL_MAX );
3305
3306 // taper
3307 if( metric_vals->taper > 0 )
3308 metric_vals->taper = (double)VERDICT_MIN( metric_vals->taper, VERDICT_DBL_MAX );
3309 else
3310 metric_vals->taper = (double)VERDICT_MAX( metric_vals->taper, -VERDICT_DBL_MAX );
3311
3312 // volume
3313 if( metric_vals->volume > 0 )
3314 metric_vals->volume = (double)VERDICT_MIN( metric_vals->volume, VERDICT_DBL_MAX );
3315 else
3316 metric_vals->volume = (double)VERDICT_MAX( metric_vals->volume, -VERDICT_DBL_MAX );
3317
3318 // stretch
3319 if( metric_vals->stretch > 0 )
3320 metric_vals->stretch = (double)VERDICT_MIN( metric_vals->stretch, VERDICT_DBL_MAX );
3321 else
3322 metric_vals->stretch = (double)VERDICT_MAX( metric_vals->stretch, -VERDICT_DBL_MAX );
3323
3324 // diagonal
3325 if( metric_vals->diagonal > 0 )
3326 metric_vals->diagonal = (double)VERDICT_MIN( metric_vals->diagonal, VERDICT_DBL_MAX );
3327 else
3328 metric_vals->diagonal = (double)VERDICT_MAX( metric_vals->diagonal, -VERDICT_DBL_MAX );
3329
3330 // dimension
3331 if( metric_vals->dimension > 0 )
3332 metric_vals->dimension = (double)VERDICT_MIN( metric_vals->dimension, VERDICT_DBL_MAX );
3333 else
3334 metric_vals->dimension = (double)VERDICT_MAX( metric_vals->dimension, -VERDICT_DBL_MAX );
3335
3336 // oddy
3337 if( metric_vals->oddy > 0 )
3338 metric_vals->oddy = (double)VERDICT_MIN( metric_vals->oddy, VERDICT_DBL_MAX );
3339 else
3340 metric_vals->oddy = (double)VERDICT_MAX( metric_vals->oddy, -VERDICT_DBL_MAX );
3341
3342 // condition
3343 if( metric_vals->condition > 0 )
3344 metric_vals->condition = (double)VERDICT_MIN( metric_vals->condition, VERDICT_DBL_MAX );
3345 else
3346 metric_vals->condition = (double)VERDICT_MAX( metric_vals->condition, -VERDICT_DBL_MAX );
3347
3348 // jacobian
3349 if( metric_vals->jacobian > 0 )
3350 metric_vals->jacobian = (double)VERDICT_MIN( metric_vals->jacobian, VERDICT_DBL_MAX );
3351 else
3352 metric_vals->jacobian = (double)VERDICT_MAX( metric_vals->jacobian, -VERDICT_DBL_MAX );
3353
3354 // scaled_jacobian
3355 if( metric_vals->scaled_jacobian > 0 )
3356 metric_vals->scaled_jacobian = (double)VERDICT_MIN( metric_vals->scaled_jacobian, VERDICT_DBL_MAX );
3357 else
3358 metric_vals->scaled_jacobian = (double)VERDICT_MAX( metric_vals->scaled_jacobian, -VERDICT_DBL_MAX );
3359
3360 // shear
3361 if( metric_vals->shear > 0 )
3362 metric_vals->shear = (double)VERDICT_MIN( metric_vals->shear, VERDICT_DBL_MAX );
3363 else
3364 metric_vals->shear = (double)VERDICT_MAX( metric_vals->shear, -VERDICT_DBL_MAX );
3365
3366 // shape
3367 if( metric_vals->shape > 0 )
3368 metric_vals->shape = (double)VERDICT_MIN( metric_vals->shape, VERDICT_DBL_MAX );
3369 else
3370 metric_vals->shape = (double)VERDICT_MAX( metric_vals->shape, -VERDICT_DBL_MAX );
3371
3372 // relative_size_squared
3373 if( metric_vals->relative_size_squared > 0 )
3374 metric_vals->relative_size_squared = (double)VERDICT_MIN( metric_vals->relative_size_squared, VERDICT_DBL_MAX );
3375 else
3376 metric_vals->relative_size_squared =
3377 (double)VERDICT_MAX( metric_vals->relative_size_squared, -VERDICT_DBL_MAX );
3378
3379 // shape_and_size
3380 if( metric_vals->shape_and_size > 0 )
3381 metric_vals->shape_and_size = (double)VERDICT_MIN( metric_vals->shape_and_size, VERDICT_DBL_MAX );
3382 else
3383 metric_vals->shape_and_size = (double)VERDICT_MAX( metric_vals->shape_and_size, -VERDICT_DBL_MAX );
3384
3385 // shear_and_size
3386 if( metric_vals->shear_and_size > 0 )
3387 metric_vals->shear_and_size = (double)VERDICT_MIN( metric_vals->shear_and_size, VERDICT_DBL_MAX );
3388 else
3389 metric_vals->shear_and_size = (double)VERDICT_MAX( metric_vals->shear_and_size, -VERDICT_DBL_MAX );
3390
3391 // distortion
3392 if( metric_vals->distortion > 0 )
3393 metric_vals->distortion = (double)VERDICT_MIN( metric_vals->distortion, VERDICT_DBL_MAX );
3394 else
3395 metric_vals->distortion = (double)VERDICT_MAX( metric_vals->distortion, -VERDICT_DBL_MAX );
3396
3397 if( metrics_request_flag & V_HEX_MED_ASPECT_FROBENIUS )
3398 metric_vals->med_aspect_frobenius = v_hex_med_aspect_frobenius( 8, coordinates );
3399
3400 if( metrics_request_flag & V_HEX_EDGE_RATIO ) metric_vals->edge_ratio = v_hex_edge_ratio( 8, coordinates );
3401 }
References calc_hex_efg(), HexMetricVals::condition, condition_comp(), diag_length(), HexMetricVals::diagonal, HexMetricVals::dimension, HexMetricVals::distortion, HexMetricVals::edge_ratio, HexMetricVals::jacobian, VerdictVector::length(), VerdictVector::length_squared(), length_squared(), make_edge_length_squares, make_hex_edges(), make_hex_nodes, HexMetricVals::max_edge_ratio, HexMetricVals::med_aspect_frobenius, VerdictVector::normalize(), HexMetricVals::oddy, oddy_comp(), HexMetricVals::relative_size_squared, safe_ratio(), HexMetricVals::scaled_jacobian, HexMetricVals::shape, HexMetricVals::shape_and_size, HexMetricVals::shear, HexMetricVals::shear_and_size, HexMetricVals::skew, HexMetricVals::stretch, HexMetricVals::taper, V_HEX_CONDITION, V_HEX_DIAGONAL, v_hex_diagonal(), V_HEX_DIMENSION, v_hex_dimension(), V_HEX_DISTORTION, v_hex_distortion(), V_HEX_EDGE_RATIO, v_hex_edge_ratio(), v_hex_get_weight(), V_HEX_JACOBIAN, V_HEX_MAX_EDGE_RATIO, V_HEX_MED_ASPECT_FROBENIUS, v_hex_med_aspect_frobenius(), V_HEX_ODDY, V_HEX_RELATIVE_SIZE_SQUARED, V_HEX_SCALED_JACOBIAN, V_HEX_SHAPE, V_HEX_SHAPE_AND_SIZE, V_HEX_SHEAR, V_HEX_SHEAR_AND_SIZE, V_HEX_SKEW, V_HEX_STRETCH, V_HEX_TAPER, V_HEX_VOLUME, v_hex_volume(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_FALSE, VERDICT_MAX, VERDICT_MIN, VERDICT_TRUE, and HexMetricVals::volume.
Referenced by moab::VerdictWrapper::all_quality_measures().
C_FUNC_DEF double v_hex_relative_size_squared | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex relative size metric.
3/Mean Ratio of weighted Jacobian matrix. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
relative size of a hex
Min( J, 1/J ), where J is determinant of weighted Jacobian matrix
Definition at line 2090 of file V_HexMetric.cpp.
2091 {
2092 double size = 0;
2093 double tau;
2094
2095 VerdictVector xxi, xet, xze;
2096 double det, det_sum = 0;
2097
2098 v_hex_get_weight( xxi, xet, xze );
2099
2100 // This is the average relative size
2101 double detw = xxi % ( xet * xze );
2102
2103 if( detw < VERDICT_DBL_MIN ) return 0;
2104
2105 VerdictVector node_pos[8];
2106 make_hex_nodes( coordinates, node_pos );
2107
2108 // J(0,0,0):
2109
2110 xxi = node_pos[1] - node_pos[0];
2111 xet = node_pos[3] - node_pos[0];
2112 xze = node_pos[4] - node_pos[0];
2113
2114 det = xxi % ( xet * xze );
2115 det_sum += det;
2116
2117 // J(1,0,0):
2118
2119 xxi = node_pos[2] - node_pos[1];
2120 xet = node_pos[0] - node_pos[1];
2121 xze = node_pos[5] - node_pos[1];
2122
2123 det = xxi % ( xet * xze );
2124 det_sum += det;
2125
2126 // J(0,1,0):
2127
2128 xxi = node_pos[3] - node_pos[2];
2129 xet = node_pos[1] - node_pos[2];
2130 xze = node_pos[6] - node_pos[2];
2131
2132 det = xxi % ( xet * xze );
2133 det_sum += det;
2134
2135 // J(1,1,0):
2136
2137 xxi = node_pos[0] - node_pos[3];
2138 xet = node_pos[2] - node_pos[3];
2139 xze = node_pos[7] - node_pos[3];
2140
2141 det = xxi % ( xet * xze );
2142 det_sum += det;
2143
2144 // J(0,1,0):
2145
2146 xxi = node_pos[7] - node_pos[4];
2147 xet = node_pos[5] - node_pos[4];
2148 xze = node_pos[0] - node_pos[4];
2149
2150 det = xxi % ( xet * xze );
2151 det_sum += det;
2152
2153 // J(1,0,1):
2154
2155 xxi = node_pos[4] - node_pos[5];
2156 xet = node_pos[6] - node_pos[5];
2157 xze = node_pos[1] - node_pos[5];
2158
2159 det = xxi % ( xet * xze );
2160 det_sum += det;
2161
2162 // J(1,1,1):
2163
2164 xxi = node_pos[5] - node_pos[6];
2165 xet = node_pos[7] - node_pos[6];
2166 xze = node_pos[2] - node_pos[6];
2167
2168 det = xxi % ( xet * xze );
2169 det_sum += det;
2170
2171 // J(1,1,1):
2172
2173 xxi = node_pos[6] - node_pos[7];
2174 xet = node_pos[4] - node_pos[7];
2175 xze = node_pos[3] - node_pos[7];
2176
2177 det = xxi % ( xet * xze );
2178 det_sum += det;
2179
2180 if( det_sum > VERDICT_DBL_MIN )
2181 {
2182 tau = det_sum / ( 8 * detw );
2183
2184 tau = VERDICT_MIN( tau, 1.0 / tau );
2185
2186 size = tau * tau;
2187 }
2188
2189 if( size > 0 ) return (double)VERDICT_MIN( size, VERDICT_DBL_MAX );
2190 return (double)VERDICT_MAX( size, -VERDICT_DBL_MAX );
2191 }
References make_hex_nodes, size, v_hex_get_weight(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), v_hex_shape_and_size(), and v_hex_shear_and_size().
C_FUNC_DEF double v_hex_scaled_jacobian | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex scaled jacobian metric.
Minimum Jacobian divided by the lengths of the 3 edge vectors. Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
scaled jacobian of a hex
Minimum Jacobian divided by the lengths of the 3 edge vectors
Definition at line 1507 of file V_HexMetric.cpp.
1508 {
1509
1510 double jacobi, min_norm_jac = VERDICT_DBL_MAX;
1511 // double min_jacobi = VERDICT_DBL_MAX;
1512 double temp_norm_jac, lengths;
1513 double len1_sq, len2_sq, len3_sq;
1514 VerdictVector xxi, xet, xze;
1515
1516 VerdictVector node_pos[8];
1517 make_hex_nodes( coordinates, node_pos );
1518
1519 xxi = calc_hex_efg( 1, node_pos );
1520 xet = calc_hex_efg( 2, node_pos );
1521 xze = calc_hex_efg( 3, node_pos );
1522
1523 jacobi = xxi % ( xet * xze );
1524 // if( jacobi < min_jacobi) { min_jacobi = jacobi; }
1525
1526 len1_sq = xxi.length_squared();
1527 len2_sq = xet.length_squared();
1528 len3_sq = xze.length_squared();
1529
1530 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN )
1531 return (double)VERDICT_DBL_MAX;
1532
1533 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1534 temp_norm_jac = jacobi / lengths;
1535
1536 if( temp_norm_jac < min_norm_jac )
1537 min_norm_jac = temp_norm_jac;
1538 else
1539 temp_norm_jac = jacobi;
1540
1541 // J(0,0,0):
1542
1543 xxi = node_pos[1] - node_pos[0];
1544 xet = node_pos[3] - node_pos[0];
1545 xze = node_pos[4] - node_pos[0];
1546
1547 jacobi = xxi % ( xet * xze );
1548 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; }
1549
1550 len1_sq = xxi.length_squared();
1551 len2_sq = xet.length_squared();
1552 len3_sq = xze.length_squared();
1553
1554 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN )
1555 return (double)VERDICT_DBL_MAX;
1556
1557 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1558 temp_norm_jac = jacobi / lengths;
1559 if( temp_norm_jac < min_norm_jac )
1560 min_norm_jac = temp_norm_jac;
1561 else
1562 temp_norm_jac = jacobi;
1563
1564 // J(1,0,0):
1565
1566 xxi = node_pos[2] - node_pos[1];
1567 xet = node_pos[0] - node_pos[1];
1568 xze = node_pos[5] - node_pos[1];
1569
1570 jacobi = xxi % ( xet * xze );
1571 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; }
1572
1573 len1_sq = xxi.length_squared();
1574 len2_sq = xet.length_squared();
1575 len3_sq = xze.length_squared();
1576
1577 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN )
1578 return (double)VERDICT_DBL_MAX;
1579
1580 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1581 temp_norm_jac = jacobi / lengths;
1582 if( temp_norm_jac < min_norm_jac )
1583 min_norm_jac = temp_norm_jac;
1584 else
1585 temp_norm_jac = jacobi;
1586
1587 // J(1,1,0):
1588
1589 xxi = node_pos[3] - node_pos[2];
1590 xet = node_pos[1] - node_pos[2];
1591 xze = node_pos[6] - node_pos[2];
1592
1593 jacobi = xxi % ( xet * xze );
1594 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; }
1595
1596 len1_sq = xxi.length_squared();
1597 len2_sq = xet.length_squared();
1598 len3_sq = xze.length_squared();
1599
1600 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN )
1601 return (double)VERDICT_DBL_MAX;
1602
1603 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1604 temp_norm_jac = jacobi / lengths;
1605 if( temp_norm_jac < min_norm_jac )
1606 min_norm_jac = temp_norm_jac;
1607 else
1608 temp_norm_jac = jacobi;
1609
1610 // J(0,1,0):
1611
1612 xxi = node_pos[0] - node_pos[3];
1613 xet = node_pos[2] - node_pos[3];
1614 xze = node_pos[7] - node_pos[3];
1615
1616 jacobi = xxi % ( xet * xze );
1617 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; }
1618
1619 len1_sq = xxi.length_squared();
1620 len2_sq = xet.length_squared();
1621 len3_sq = xze.length_squared();
1622
1623 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN )
1624 return (double)VERDICT_DBL_MAX;
1625
1626 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1627 temp_norm_jac = jacobi / lengths;
1628 if( temp_norm_jac < min_norm_jac )
1629 min_norm_jac = temp_norm_jac;
1630 else
1631 temp_norm_jac = jacobi;
1632
1633 // J(0,0,1):
1634
1635 xxi = node_pos[7] - node_pos[4];
1636 xet = node_pos[5] - node_pos[4];
1637 xze = node_pos[0] - node_pos[4];
1638
1639 jacobi = xxi % ( xet * xze );
1640 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; }
1641
1642 len1_sq = xxi.length_squared();
1643 len2_sq = xet.length_squared();
1644 len3_sq = xze.length_squared();
1645
1646 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN )
1647 return (double)VERDICT_DBL_MAX;
1648
1649 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1650 temp_norm_jac = jacobi / lengths;
1651 if( temp_norm_jac < min_norm_jac )
1652 min_norm_jac = temp_norm_jac;
1653 else
1654 temp_norm_jac = jacobi;
1655
1656 // J(1,0,1):
1657
1658 xxi = node_pos[4] - node_pos[5];
1659 xet = node_pos[6] - node_pos[5];
1660 xze = node_pos[1] - node_pos[5];
1661
1662 jacobi = xxi % ( xet * xze );
1663 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; }
1664
1665 len1_sq = xxi.length_squared();
1666 len2_sq = xet.length_squared();
1667 len3_sq = xze.length_squared();
1668
1669 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN )
1670 return (double)VERDICT_DBL_MAX;
1671
1672 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1673 temp_norm_jac = jacobi / lengths;
1674 if( temp_norm_jac < min_norm_jac )
1675 min_norm_jac = temp_norm_jac;
1676 else
1677 temp_norm_jac = jacobi;
1678
1679 // J(1,1,1):
1680
1681 xxi = node_pos[5] - node_pos[6];
1682 xet = node_pos[7] - node_pos[6];
1683 xze = node_pos[2] - node_pos[6];
1684
1685 jacobi = xxi % ( xet * xze );
1686 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; }
1687
1688 len1_sq = xxi.length_squared();
1689 len2_sq = xet.length_squared();
1690 len3_sq = xze.length_squared();
1691
1692 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN )
1693 return (double)VERDICT_DBL_MAX;
1694
1695 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1696 temp_norm_jac = jacobi / lengths;
1697 if( temp_norm_jac < min_norm_jac )
1698 min_norm_jac = temp_norm_jac;
1699 else
1700 temp_norm_jac = jacobi;
1701
1702 // J(0,1,1):
1703
1704 xxi = node_pos[6] - node_pos[7];
1705 xet = node_pos[4] - node_pos[7];
1706 xze = node_pos[3] - node_pos[7];
1707
1708 jacobi = xxi % ( xet * xze );
1709 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; }
1710
1711 len1_sq = xxi.length_squared();
1712 len2_sq = xet.length_squared();
1713 len3_sq = xze.length_squared();
1714
1715 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN )
1716 return (double)VERDICT_DBL_MAX;
1717
1718 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1719 temp_norm_jac = jacobi / lengths;
1720 if( temp_norm_jac < min_norm_jac ) min_norm_jac = temp_norm_jac;
1721 // else
1722 // temp_norm_jac = jacobi;
1723
1724 if( min_norm_jac > 0 ) return (double)VERDICT_MIN( min_norm_jac, VERDICT_DBL_MAX );
1725 return (double)VERDICT_MAX( min_norm_jac, -VERDICT_DBL_MAX );
1726 }
References calc_hex_efg(), VerdictVector::length_squared(), make_hex_nodes, VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_hex_shape | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex shape metric.
3/Mean Ratio of weighted Jacobian matrix. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
shape of a hex
3/Condition number of weighted Jacobian matrix
Definition at line 1931 of file V_HexMetric.cpp.
1932 {
1933
1934 double det, shape;
1935 double min_shape = 1.0;
1936 static const double two_thirds = 2.0 / 3.0;
1937
1938 VerdictVector xxi, xet, xze;
1939
1940 VerdictVector node_pos[8];
1941 make_hex_nodes( coordinates, node_pos );
1942
1943 // J(0,0,0):
1944
1945 xxi = node_pos[1] - node_pos[0];
1946 xet = node_pos[3] - node_pos[0];
1947 xze = node_pos[4] - node_pos[0];
1948
1949 det = xxi % ( xet * xze );
1950 if( det > VERDICT_DBL_MIN )
1951 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze );
1952 else
1953 return 0;
1954
1955 if( shape < min_shape )
1956 {
1957 min_shape = shape;
1958 }
1959
1960 // J(1,0,0):
1961
1962 xxi = node_pos[2] - node_pos[1];
1963 xet = node_pos[0] - node_pos[1];
1964 xze = node_pos[5] - node_pos[1];
1965
1966 det = xxi % ( xet * xze );
1967 if( det > VERDICT_DBL_MIN )
1968 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze );
1969 else
1970 return 0;
1971
1972 if( shape < min_shape )
1973 {
1974 min_shape = shape;
1975 }
1976
1977 // J(1,1,0):
1978
1979 xxi = node_pos[3] - node_pos[2];
1980 xet = node_pos[1] - node_pos[2];
1981 xze = node_pos[6] - node_pos[2];
1982
1983 det = xxi % ( xet * xze );
1984 if( det > VERDICT_DBL_MIN )
1985 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze );
1986 else
1987 return 0;
1988
1989 if( shape < min_shape )
1990 {
1991 min_shape = shape;
1992 }
1993
1994 // J(0,1,0):
1995
1996 xxi = node_pos[0] - node_pos[3];
1997 xet = node_pos[2] - node_pos[3];
1998 xze = node_pos[7] - node_pos[3];
1999
2000 det = xxi % ( xet * xze );
2001 if( det > VERDICT_DBL_MIN )
2002 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze );
2003 else
2004 return 0;
2005
2006 if( shape < min_shape )
2007 {
2008 min_shape = shape;
2009 }
2010
2011 // J(0,0,1):
2012
2013 xxi = node_pos[7] - node_pos[4];
2014 xet = node_pos[5] - node_pos[4];
2015 xze = node_pos[0] - node_pos[4];
2016
2017 det = xxi % ( xet * xze );
2018 if( det > VERDICT_DBL_MIN )
2019 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze );
2020 else
2021 return 0;
2022
2023 if( shape < min_shape )
2024 {
2025 min_shape = shape;
2026 }
2027
2028 // J(1,0,1):
2029
2030 xxi = node_pos[4] - node_pos[5];
2031 xet = node_pos[6] - node_pos[5];
2032 xze = node_pos[1] - node_pos[5];
2033
2034 det = xxi % ( xet * xze );
2035 if( det > VERDICT_DBL_MIN )
2036 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze );
2037 else
2038 return 0;
2039
2040 if( shape < min_shape )
2041 {
2042 min_shape = shape;
2043 }
2044
2045 // J(1,1,1):
2046
2047 xxi = node_pos[5] - node_pos[6];
2048 xet = node_pos[7] - node_pos[6];
2049 xze = node_pos[2] - node_pos[6];
2050
2051 det = xxi % ( xet * xze );
2052 if( det > VERDICT_DBL_MIN )
2053 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze );
2054 else
2055 return 0;
2056
2057 if( shape < min_shape )
2058 {
2059 min_shape = shape;
2060 }
2061
2062 // J(1,1,1):
2063
2064 xxi = node_pos[6] - node_pos[7];
2065 xet = node_pos[4] - node_pos[7];
2066 xze = node_pos[3] - node_pos[7];
2067
2068 det = xxi % ( xet * xze );
2069 if( det > VERDICT_DBL_MIN )
2070 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze );
2071 else
2072 return 0;
2073
2074 if( shape < min_shape )
2075 {
2076 min_shape = shape;
2077 }
2078
2079 if( min_shape <= VERDICT_DBL_MIN ) min_shape = 0;
2080
2081 if( min_shape > 0 ) return (double)VERDICT_MIN( min_shape, VERDICT_DBL_MAX );
2082 return (double)VERDICT_MAX( min_shape, -VERDICT_DBL_MAX );
2083 }
References make_hex_nodes, VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_hex_shape_and_size().
C_FUNC_DEF double v_hex_shape_and_size | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex shape-size metric.
Product of Shape and Relative Size. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
shape and size of a hex
Product of Shape and Relative Size
Definition at line 2198 of file V_HexMetric.cpp.
2199 {
2200 double size = v_hex_relative_size_squared( num_nodes, coordinates );
2201 double shape = v_hex_shape( num_nodes, coordinates );
2202
2203 double shape_size = size * shape;
2204
2205 if( shape_size > 0 ) return (double)VERDICT_MIN( shape_size, VERDICT_DBL_MAX );
2206 return (double)VERDICT_MAX( shape_size, -VERDICT_DBL_MAX );
2207 }
References size, v_hex_relative_size_squared(), v_hex_shape(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_hex_shear | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex shear metric.
3/Mean Ratio of Jacobian Skew matrix. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
shear of a hex
3/Condition number of Jacobian Skew matrix
Definition at line 1733 of file V_HexMetric.cpp.
1734 {
1735
1736 double shear;
1737 double min_shear = 1.0;
1738 VerdictVector xxi, xet, xze;
1739 double det, len1_sq, len2_sq, len3_sq, lengths;
1740
1741 VerdictVector node_pos[8];
1742 make_hex_nodes( coordinates, node_pos );
1743
1744 // J(0,0,0):
1745
1746 xxi = node_pos[1] - node_pos[0];
1747 xet = node_pos[3] - node_pos[0];
1748 xze = node_pos[4] - node_pos[0];
1749
1750 len1_sq = xxi.length_squared();
1751 len2_sq = xet.length_squared();
1752 len3_sq = xze.length_squared();
1753
1754 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0;
1755
1756 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1757 det = xxi % ( xet * xze );
1758 if( det < VERDICT_DBL_MIN )
1759 {
1760 return 0;
1761 }
1762
1763 shear = det / lengths;
1764 min_shear = VERDICT_MIN( shear, min_shear );
1765
1766 // J(1,0,0):
1767
1768 xxi = node_pos[2] - node_pos[1];
1769 xet = node_pos[0] - node_pos[1];
1770 xze = node_pos[5] - node_pos[1];
1771
1772 len1_sq = xxi.length_squared();
1773 len2_sq = xet.length_squared();
1774 len3_sq = xze.length_squared();
1775
1776 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0;
1777
1778 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1779 det = xxi % ( xet * xze );
1780 if( det < VERDICT_DBL_MIN )
1781 {
1782 return 0;
1783 }
1784
1785 shear = det / lengths;
1786 min_shear = VERDICT_MIN( shear, min_shear );
1787
1788 // J(1,1,0):
1789
1790 xxi = node_pos[3] - node_pos[2];
1791 xet = node_pos[1] - node_pos[2];
1792 xze = node_pos[6] - node_pos[2];
1793
1794 len1_sq = xxi.length_squared();
1795 len2_sq = xet.length_squared();
1796 len3_sq = xze.length_squared();
1797
1798 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0;
1799
1800 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1801 det = xxi % ( xet * xze );
1802 if( det < VERDICT_DBL_MIN )
1803 {
1804 return 0;
1805 }
1806
1807 shear = det / lengths;
1808 min_shear = VERDICT_MIN( shear, min_shear );
1809
1810 // J(0,1,0):
1811
1812 xxi = node_pos[0] - node_pos[3];
1813 xet = node_pos[2] - node_pos[3];
1814 xze = node_pos[7] - node_pos[3];
1815
1816 len1_sq = xxi.length_squared();
1817 len2_sq = xet.length_squared();
1818 len3_sq = xze.length_squared();
1819
1820 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0;
1821
1822 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1823 det = xxi % ( xet * xze );
1824 if( det < VERDICT_DBL_MIN )
1825 {
1826 return 0;
1827 }
1828
1829 shear = det / lengths;
1830 min_shear = VERDICT_MIN( shear, min_shear );
1831
1832 // J(0,0,1):
1833
1834 xxi = node_pos[7] - node_pos[4];
1835 xet = node_pos[5] - node_pos[4];
1836 xze = node_pos[0] - node_pos[4];
1837
1838 len1_sq = xxi.length_squared();
1839 len2_sq = xet.length_squared();
1840 len3_sq = xze.length_squared();
1841
1842 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0;
1843
1844 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1845 det = xxi % ( xet * xze );
1846 if( det < VERDICT_DBL_MIN )
1847 {
1848 return 0;
1849 }
1850
1851 shear = det / lengths;
1852 min_shear = VERDICT_MIN( shear, min_shear );
1853
1854 // J(1,0,1):
1855
1856 xxi = node_pos[4] - node_pos[5];
1857 xet = node_pos[6] - node_pos[5];
1858 xze = node_pos[1] - node_pos[5];
1859
1860 len1_sq = xxi.length_squared();
1861 len2_sq = xet.length_squared();
1862 len3_sq = xze.length_squared();
1863
1864 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0;
1865
1866 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1867 det = xxi % ( xet * xze );
1868 if( det < VERDICT_DBL_MIN )
1869 {
1870 return 0;
1871 }
1872
1873 shear = det / lengths;
1874 min_shear = VERDICT_MIN( shear, min_shear );
1875
1876 // J(1,1,1):
1877
1878 xxi = node_pos[5] - node_pos[6];
1879 xet = node_pos[7] - node_pos[6];
1880 xze = node_pos[2] - node_pos[6];
1881
1882 len1_sq = xxi.length_squared();
1883 len2_sq = xet.length_squared();
1884 len3_sq = xze.length_squared();
1885
1886 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0;
1887
1888 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1889 det = xxi % ( xet * xze );
1890 if( det < VERDICT_DBL_MIN )
1891 {
1892 return 0;
1893 }
1894
1895 shear = det / lengths;
1896 min_shear = VERDICT_MIN( shear, min_shear );
1897
1898 // J(0,1,1):
1899
1900 xxi = node_pos[6] - node_pos[7];
1901 xet = node_pos[4] - node_pos[7];
1902 xze = node_pos[3] - node_pos[7];
1903
1904 len1_sq = xxi.length_squared();
1905 len2_sq = xet.length_squared();
1906 len3_sq = xze.length_squared();
1907
1908 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0;
1909
1910 lengths = sqrt( len1_sq * len2_sq * len3_sq );
1911 det = xxi % ( xet * xze );
1912 if( det < VERDICT_DBL_MIN )
1913 {
1914 return 0;
1915 }
1916
1917 shear = det / lengths;
1918 min_shear = VERDICT_MIN( shear, min_shear );
1919
1920 if( min_shear <= VERDICT_DBL_MIN ) min_shear = 0;
1921
1922 if( min_shear > 0 ) return (double)VERDICT_MIN( min_shear, VERDICT_DBL_MAX );
1923 return (double)VERDICT_MAX( min_shear, -VERDICT_DBL_MAX );
1924 }
References VerdictVector::length_squared(), make_hex_nodes, VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_hex_shear_and_size().
C_FUNC_DEF double v_hex_shear_and_size | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex shear-size metric.
Product of Shear and Relative Size. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
shear and size of a hex
Product of Shear and Relative Size
Definition at line 2214 of file V_HexMetric.cpp.
2215 {
2216 double size = v_hex_relative_size_squared( num_nodes, coordinates );
2217 double shear = v_hex_shear( num_nodes, coordinates );
2218
2219 double shear_size = shear * size;
2220
2221 if( shear_size > 0 ) return (double)VERDICT_MIN( shear_size, VERDICT_DBL_MAX );
2222 return (double)VERDICT_MAX( shear_size, -VERDICT_DBL_MAX );
2223 }
References size, v_hex_relative_size_squared(), v_hex_shear(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_hex_skew | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex skew metric.
Maximum |cos A| where A is the angle between edges at hex center.
Reference — L.M. Taylor, and D.P. Flanagan, Pronto3D - A Three Dimensional Transient Solid Dynamics Program, SAND87-1912, Sandia National Laboratories, 1989.
skew of a hex
Maximum ||cosA|| where A is the angle between edges at hex center.
Definition at line 674 of file V_HexMetric.cpp.
675 {
676 VerdictVector node_pos[8];
677 make_hex_nodes( coordinates, node_pos );
678
679 double skew_1, skew_2, skew_3;
680
681 VerdictVector efg1 = calc_hex_efg( 1, node_pos );
682 VerdictVector efg2 = calc_hex_efg( 2, node_pos );
683 VerdictVector efg3 = calc_hex_efg( 3, node_pos );
684
685 if( efg1.normalize() <= VERDICT_DBL_MIN ) return VERDICT_DBL_MAX;
686 if( efg2.normalize() <= VERDICT_DBL_MIN ) return VERDICT_DBL_MAX;
687 if( efg3.normalize() <= VERDICT_DBL_MIN ) return VERDICT_DBL_MAX;
688
689 skew_1 = fabs( efg1 % efg2 );
690 skew_2 = fabs( efg1 % efg3 );
691 skew_3 = fabs( efg2 % efg3 );
692
693 double skew = ( VERDICT_MAX( skew_1, VERDICT_MAX( skew_2, skew_3 ) ) );
694
695 if( skew > 0 ) return (double)VERDICT_MIN( skew, VERDICT_DBL_MAX );
696 return (double)VERDICT_MAX( skew, -VERDICT_DBL_MAX );
697 }
References calc_hex_efg(), make_hex_nodes, VerdictVector::normalize(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_hex_stretch | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex stretch metric.
Sqrt(3) * minimum edge length / maximum diagonal length. Reference — FIMESH code
stretch of a hex
sqrt(3) * minimum edge length / maximum diagonal length
Definition at line 753 of file V_HexMetric.cpp.
754 {
755 static const double HEX_STRETCH_SCALE_FACTOR = sqrt( 3.0 );
756
757 double min_edge = hex_edge_length( 0, coordinates );
758 double max_diag = diag_length( 1, coordinates );
759
760 double stretch = HEX_STRETCH_SCALE_FACTOR * safe_ratio( min_edge, max_diag );
761
762 if( stretch > 0 ) return (double)VERDICT_MIN( stretch, VERDICT_DBL_MAX );
763 return (double)VERDICT_MAX( stretch, -VERDICT_DBL_MAX );
764 }
References diag_length(), hex_edge_length(), safe_ratio(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_hex_taper | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex taper metric.
Maximum ratio of lengths derived from opposite edges. Reference — L.M. Taylor, and D.P. Flanagan, Pronto3D - A Three Dimensional Transient Solid Dynamics Program, SAND87-1912, Sandia National Laboratories, 1989.
taper of a hex
Maximum ratio of lengths derived from opposite edges.
Definition at line 704 of file V_HexMetric.cpp.
705 {
706 VerdictVector node_pos[8];
707 make_hex_nodes( coordinates, node_pos );
708
709 VerdictVector efg1 = calc_hex_efg( 1, node_pos );
710 VerdictVector efg2 = calc_hex_efg( 2, node_pos );
711 VerdictVector efg3 = calc_hex_efg( 3, node_pos );
712
713 VerdictVector efg12 = calc_hex_efg( 12, node_pos );
714 VerdictVector efg13 = calc_hex_efg( 13, node_pos );
715 VerdictVector efg23 = calc_hex_efg( 23, node_pos );
716
717 double taper_1 = fabs( safe_ratio( efg12.length(), VERDICT_MIN( efg1.length(), efg2.length() ) ) );
718 double taper_2 = fabs( safe_ratio( efg13.length(), VERDICT_MIN( efg1.length(), efg3.length() ) ) );
719 double taper_3 = fabs( safe_ratio( efg23.length(), VERDICT_MIN( efg2.length(), efg3.length() ) ) );
720
721 double taper = (double)VERDICT_MAX( taper_1, VERDICT_MAX( taper_2, taper_3 ) );
722
723 if( taper > 0 ) return (double)VERDICT_MIN( taper, VERDICT_DBL_MAX );
724 return (double)VERDICT_MAX( taper, -VERDICT_DBL_MAX );
725 }
References calc_hex_efg(), VerdictVector::length(), make_hex_nodes, safe_ratio(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_hex_volume | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates hex volume.
Jacobian at hex center. Reference — L.M. Taylor, and D.P. Flanagan, Pronto3D - A Three Dimensional Transient Solid Dynamics Program, SAND87-1912, Sandia National Laboratories, 1989.
volume of a hex
Jacobian at hex center
Definition at line 732 of file V_HexMetric.cpp.
733 {
734 VerdictVector node_pos[8];
735 make_hex_nodes( coordinates, node_pos );
736
737 VerdictVector efg1 = calc_hex_efg( 1, node_pos );
738 VerdictVector efg2 = calc_hex_efg( 2, node_pos );
739 VerdictVector efg3 = calc_hex_efg( 3, node_pos );
740
741 double volume;
742 volume = (double)( efg1 % ( efg2 * efg3 ) ) / 64.0;
743
744 if( volume > 0 ) return (double)VERDICT_MIN( volume, VERDICT_DBL_MAX );
745 return (double)VERDICT_MAX( volume, -VERDICT_DBL_MAX );
746 }
References calc_hex_efg(), make_hex_nodes, VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_hex_quality().
C_FUNC_DEF void v_knife_quality | ( | int | num_nodes, |
double | coordinates[][3], | ||
unsigned int | metrics_request_flag, | ||
KnifeMetricVals * | metric_vals | ||
) |
Calculates quality metrics for knife elements.
calculate the quality metrics of a knife element.
There is only one, but we put this here to be consistent with functions for other element types. Who knows if we'll add more metrics.
Definition at line 117 of file V_KnifeMetric.cpp.
121 {
122 memset( metric_vals, 0, sizeof( KnifeMetricVals ) );
123
124 if( metrics_request_flag & V_KNIFE_VOLUME ) metric_vals->volume = v_knife_volume( num_nodes, coordinates );
125 }
References V_KNIFE_VOLUME, v_knife_volume(), and KnifeMetricVals::volume.
C_FUNC_DEF double v_knife_volume | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates knife volume.
calculates the volume of a knife element
this is done by dividing the knife into 4 tets and summing the volumes of each.
Definition at line 58 of file V_KnifeMetric.cpp.
59 {
60 double volume = 0;
61 VerdictVector side1, side2, side3;
62
63 if( num_nodes == 7 )
64 {
65
66 // divide the knife into 4 tets and calculate the volume
67
68 side1.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
69 coordinates[1][2] - coordinates[0][2] );
70 side2.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
71 coordinates[3][2] - coordinates[0][2] );
72 side3.set( coordinates[4][0] - coordinates[0][0], coordinates[4][1] - coordinates[0][1],
73 coordinates[4][2] - coordinates[0][2] );
74
75 volume = side3 % ( side1 * side2 ) / 6;
76
77 side1.set( coordinates[5][0] - coordinates[1][0], coordinates[5][1] - coordinates[1][1],
78 coordinates[5][2] - coordinates[1][2] );
79 side2.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
80 coordinates[3][2] - coordinates[1][2] );
81 side3.set( coordinates[4][0] - coordinates[1][0], coordinates[4][1] - coordinates[1][1],
82 coordinates[4][2] - coordinates[1][2] );
83
84 volume += side3 % ( side1 * side2 ) / 6;
85
86 side1.set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
87 coordinates[2][2] - coordinates[1][2] );
88 side2.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
89 coordinates[3][2] - coordinates[1][2] );
90 side3.set( coordinates[6][0] - coordinates[1][0], coordinates[6][1] - coordinates[1][1],
91 coordinates[6][2] - coordinates[1][2] );
92
93 volume += side3 % ( side1 * side2 ) / 6;
94
95 side1.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
96 coordinates[3][2] - coordinates[1][2] );
97 side2.set( coordinates[5][0] - coordinates[1][0], coordinates[5][1] - coordinates[1][1],
98 coordinates[5][2] - coordinates[1][2] );
99 side3.set( coordinates[6][0] - coordinates[1][0], coordinates[6][1] - coordinates[1][1],
100 coordinates[6][2] - coordinates[1][2] );
101
102 volume += side3 % ( side1 * side2 ) / 6;
103 }
104
105 return (double)volume;
106 }
References VerdictVector::set().
Referenced by moab::VerdictWrapper::all_quality_measures(), moab::VerdictWrapper::quality_measure(), and v_knife_quality().
C_FUNC_DEF void v_pyramid_quality | ( | int | num_nodes, |
double | coordinates[][3], | ||
unsigned int | metrics_request_flag, | ||
struct PyramidMetricVals * | metric_vals | ||
) |
Calculates quality metrics for pyramid elements.
Definition at line 96 of file V_PyramidMetric.cpp.
100 {
101 memset( metric_vals, 0, sizeof( PyramidMetricVals ) );
102
103 if( metrics_request_flag & V_PYRAMID_VOLUME ) metric_vals->volume = v_pyramid_volume( num_nodes, coordinates );
104 }
References V_PYRAMID_VOLUME, v_pyramid_volume(), and PyramidMetricVals::volume.
C_FUNC_DEF double v_pyramid_volume | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates pyramid volume.
the volume of a pyramid
the volume is calculated by dividing the pyramid into 2 tets and summing the volumes of the 2 tets.
Definition at line 59 of file V_PyramidMetric.cpp.
60 {
61
62 double volume = 0;
63 VerdictVector side1, side2, side3;
64
65 if( num_nodes == 5 )
66 {
67 // divide the pyramid into 2 tets and calculate each
68
69 side1.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
70 coordinates[1][2] - coordinates[0][2] );
71
72 side2.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
73 coordinates[3][2] - coordinates[0][2] );
74
75 side3.set( coordinates[4][0] - coordinates[0][0], coordinates[4][1] - coordinates[0][1],
76 coordinates[4][2] - coordinates[0][2] );
77
78 // volume of the first tet
79 volume = ( side3 % ( side1 * side2 ) ) / 6.0;
80
81 side1.set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
82 coordinates[3][2] - coordinates[2][2] );
83
84 side2.set( coordinates[1][0] - coordinates[2][0], coordinates[1][1] - coordinates[2][1],
85 coordinates[1][2] - coordinates[2][2] );
86
87 side3.set( coordinates[4][0] - coordinates[2][0], coordinates[4][1] - coordinates[2][1],
88 coordinates[4][2] - coordinates[2][2] );
89
90 // volume of the second tet
91 volume += ( side3 % ( side1 * side2 ) ) / 6.0;
92 }
93 return (double)volume;
94 }
References VerdictVector::set().
Referenced by v_pyramid_quality().
C_FUNC_DEF double v_quad_area | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad area.
Jacobian at quad center. Reference — J. Robinson, CRE Method of element testing and the Jacobian shape parameters, Eng. Comput., Vol 4, 1987.
the area of a quad
jacobian at quad center
Definition at line 611 of file V_QuadMetric.cpp.
612 {
613
614 double corner_areas[4];
615 signed_corner_areas( corner_areas, coordinates );
616
617 double area = 0.25 * ( corner_areas[0] + corner_areas[1] + corner_areas[2] + corner_areas[3] );
618
619 if( area > 0 ) return (double)VERDICT_MIN( area, VERDICT_DBL_MAX );
620 return (double)VERDICT_MAX( area, -VERDICT_DBL_MAX );
621 }
References signed_corner_areas(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), v_quad_quality(), and v_quad_relative_size_squared().
C_FUNC_DEF double v_quad_aspect_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad aspect ratio.
aspect ratio Reference — P. P. Pebay, Planar Quadrangle Quality Measures, Eng. Comp., 2004, 20(2):157-173
the aspect ratio of a quad
NB (P. Pebay 01/20/07): this is a generalization of the triangle aspect ratio using Heron's formula.
Definition at line 351 of file V_QuadMetric.cpp.
352 {
353
354 VerdictVector edges[4];
355 make_quad_edges( edges, coordinates );
356
357 double a1 = edges[0].length();
358 double b1 = edges[1].length();
359 double c1 = edges[2].length();
360 double d1 = edges[3].length();
361
362 double ma = a1 > b1 ? a1 : b1;
363 double mb = c1 > d1 ? c1 : d1;
364 double hm = ma > mb ? ma : mb;
365
366 VerdictVector ab = edges[0] * edges[1];
367 VerdictVector cd = edges[2] * edges[3];
368 double denominator = ab.length() + cd.length();
369
370 if( denominator < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX;
371
372 double aspect_ratio = .5 * hm * ( a1 + b1 + c1 + d1 ) / denominator;
373
374 if( aspect_ratio > 0 ) return (double)VERDICT_MIN( aspect_ratio, VERDICT_DBL_MAX );
375 return (double)VERDICT_MAX( aspect_ratio, -VERDICT_DBL_MAX );
376 }
References VerdictVector::length(), make_quad_edges(), mb, VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_quad_quality().
C_FUNC_DEF double v_quad_condition | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad condition number metric.
Maximum condition number of the Jacobian matrix at 4 corners. Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
the condition of a quad
maximum condition number of the Jacobian matrix at 4 corners
Definition at line 828 of file V_QuadMetric.cpp.
829 {
830
831 if( is_collapsed_quad( coordinates ) == VERDICT_TRUE ) return v_tri_condition( 3, coordinates );
832
833 double areas[4];
834 signed_corner_areas( areas, coordinates );
835
836 double max_condition = 0.;
837
838 VerdictVector xxi, xet;
839
840 double condition;
841
842 for( int i = 0; i < 4; i++ )
843 {
844
845 xxi.set( coordinates[i][0] - coordinates[( i + 1 ) % 4][0], coordinates[i][1] - coordinates[( i + 1 ) % 4][1],
846 coordinates[i][2] - coordinates[( i + 1 ) % 4][2] );
847
848 xet.set( coordinates[i][0] - coordinates[( i + 3 ) % 4][0], coordinates[i][1] - coordinates[( i + 3 ) % 4][1],
849 coordinates[i][2] - coordinates[( i + 3 ) % 4][2] );
850
851 if( areas[i] < VERDICT_DBL_MIN )
852 condition = VERDICT_DBL_MAX;
853 else
854 condition = ( xxi % xxi + xet % xet ) / areas[i];
855
856 max_condition = VERDICT_MAX( max_condition, condition );
857 }
858
859 max_condition /= 2;
860
861 if( max_condition > 0 ) return (double)VERDICT_MIN( max_condition, VERDICT_DBL_MAX );
862 return (double)VERDICT_MAX( max_condition, -VERDICT_DBL_MAX );
863 }
References is_collapsed_quad(), VerdictVector::set(), signed_corner_areas(), v_tri_condition(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, VERDICT_MIN, and VERDICT_TRUE.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_quad_distortion | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad distortion metric.
{min(|J|)/actual area}*parent area, parent area = 4 for quad. Reference — SDRC/IDEAS Simulation: Finite Element Modeling–User's Guide
the distortion of a quad
Definition at line 1052 of file V_QuadMetric.cpp.
1053 {
1054 // To calculate distortion for linear and 2nd order quads
1055 // distortion = {min(|J|)/actual area}*{parent area}
1056 // parent area = 4 for a quad.
1057 // min |J| is the minimum over nodes and gaussian integration points
1058 // created by Ling Pan, CAT on 4/30/01
1059
1060 double element_area = 0.0, distrt, thickness_gauss;
1061 double cur_jacobian = 0., sign_jacobian, jacobian;
1062 VerdictVector aa, bb, cc, normal_at_point, xin;
1063
1064 // use 2x2 gauss points for linear quads and 3x3 for 2nd order quads
1065 int number_of_gauss_points = 0;
1066 if( num_nodes == 4 )
1067 { // 2x2 quadrature rule
1068 number_of_gauss_points = 2;
1069 }
1070 else if( num_nodes == 8 )
1071 { // 3x3 quadrature rule
1072 number_of_gauss_points = 3;
1073 }
1074
1075 int total_number_of_gauss_points = number_of_gauss_points * number_of_gauss_points;
1076
1077 VerdictVector face_normal = quad_normal( coordinates );
1078
1079 double distortion = VERDICT_DBL_MAX;
1080
1081 VerdictVector first, second;
1082
1083 int i;
1084 // Will work out the case for collapsed quad later
1085 if( is_collapsed_quad( coordinates ) == VERDICT_TRUE )
1086 {
1087 for( i = 0; i < 3; i++ )
1088 {
1089
1090 first.set( coordinates[i][0] - coordinates[( i + 1 ) % 3][0],
1091 coordinates[i][1] - coordinates[( i + 1 ) % 3][1],
1092 coordinates[i][2] - coordinates[( i + 1 ) % 3][2] );
1093
1094 second.set( coordinates[i][0] - coordinates[( i + 2 ) % 3][0],
1095 coordinates[i][1] - coordinates[( i + 2 ) % 3][1],
1096 coordinates[i][2] - coordinates[( i + 2 ) % 3][2] );
1097
1098 sign_jacobian = ( face_normal % ( first * second ) ) > 0 ? 1. : -1.;
1099 cur_jacobian = sign_jacobian * ( first * second ).length();
1100 distortion = VERDICT_MIN( distortion, cur_jacobian );
1101 }
1102 element_area = ( first * second ).length() / 2.0;
1103 distortion /= element_area;
1104 }
1105 else
1106 {
1107 double shape_function[maxTotalNumberGaussPoints][maxNumberNodes];
1108 double dndy1[maxTotalNumberGaussPoints][maxNumberNodes];
1109 double dndy2[maxTotalNumberGaussPoints][maxNumberNodes];
1110 double weight[maxTotalNumberGaussPoints];
1111
1112 // create an object of GaussIntegration
1113 GaussIntegration::initialize( number_of_gauss_points, num_nodes );
1114 GaussIntegration::calculate_shape_function_2d_quad();
1115 GaussIntegration::get_shape_func( shape_function[0], dndy1[0], dndy2[0], weight );
1116
1117 // calculate element area
1118 int ife, ja;
1119 for( ife = 0; ife < total_number_of_gauss_points; ife++ )
1120 {
1121 aa.set( 0.0, 0.0, 0.0 );
1122 bb.set( 0.0, 0.0, 0.0 );
1123
1124 for( ja = 0; ja < num_nodes; ja++ )
1125 {
1126 xin.set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] );
1127 aa += dndy1[ife][ja] * xin;
1128 bb += dndy2[ife][ja] * xin;
1129 }
1130 normal_at_point = aa * bb;
1131 jacobian = normal_at_point.length();
1132 element_area += weight[ife] * jacobian;
1133 }
1134
1135 double dndy1_at_node[maxNumberNodes][maxNumberNodes];
1136 double dndy2_at_node[maxNumberNodes][maxNumberNodes];
1137
1138 GaussIntegration::calculate_derivative_at_nodes( dndy1_at_node, dndy2_at_node );
1139
1140 VerdictVector normal_at_nodes[9];
1141
1142 // evaluate normal at nodes and distortion values at nodes
1143 int jai;
1144 for( ja = 0; ja < num_nodes; ja++ )
1145 {
1146 aa.set( 0.0, 0.0, 0.0 );
1147 bb.set( 0.0, 0.0, 0.0 );
1148 for( jai = 0; jai < num_nodes; jai++ )
1149 {
1150 xin.set( coordinates[jai][0], coordinates[jai][1], coordinates[jai][2] );
1151 aa += dndy1_at_node[ja][jai] * xin;
1152 bb += dndy2_at_node[ja][jai] * xin;
1153 }
1154 normal_at_nodes[ja] = aa * bb;
1155 normal_at_nodes[ja].normalize();
1156 }
1157
1158 // determine if element is flat
1159 bool flat_element = true;
1160 double dot_product;
1161
1162 for( ja = 0; ja < num_nodes; ja++ )
1163 {
1164 dot_product = normal_at_nodes[0] % normal_at_nodes[ja];
1165 if( fabs( dot_product ) < 0.99 )
1166 {
1167 flat_element = false;
1168 break;
1169 }
1170 }
1171
1172 // take into consideration of the thickness of the element
1173 double thickness;
1174 // get_quad_thickness(face, element_area, thickness );
1175 thickness = 0.001 * sqrt( element_area );
1176
1177 // set thickness gauss point location
1178 double zl = 0.5773502691896;
1179 if( flat_element ) zl = 0.0;
1180
1181 int no_gauss_pts_z = ( flat_element ) ? 1 : 2;
1182 double thickness_z;
1183 int igz;
1184 // loop on Gauss points
1185 for( ife = 0; ife < total_number_of_gauss_points; ife++ )
1186 {
1187 // loop on the thickness direction gauss points
1188 for( igz = 0; igz < no_gauss_pts_z; igz++ )
1189 {
1190 zl = -zl;
1191 thickness_z = zl * thickness / 2.0;
1192
1193 aa.set( 0.0, 0.0, 0.0 );
1194 bb.set( 0.0, 0.0, 0.0 );
1195 cc.set( 0.0, 0.0, 0.0 );
1196
1197 for( ja = 0; ja < num_nodes; ja++ )
1198 {
1199 xin.set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] );
1200 xin += thickness_z * normal_at_nodes[ja];
1201 aa += dndy1[ife][ja] * xin;
1202 bb += dndy2[ife][ja] * xin;
1203 thickness_gauss = shape_function[ife][ja] * thickness / 2.0;
1204 cc += thickness_gauss * normal_at_nodes[ja];
1205 }
1206
1207 normal_at_point = aa * bb;
1208 // jacobian = normal_at_point.length();
1209 distrt = cc % normal_at_point;
1210 if( distrt < distortion ) distortion = distrt;
1211 }
1212 }
1213
1214 // loop through nodal points
1215 for( ja = 0; ja < num_nodes; ja++ )
1216 {
1217 for( igz = 0; igz < no_gauss_pts_z; igz++ )
1218 {
1219 zl = -zl;
1220 thickness_z = zl * thickness / 2.0;
1221
1222 aa.set( 0.0, 0.0, 0.0 );
1223 bb.set( 0.0, 0.0, 0.0 );
1224 cc.set( 0.0, 0.0, 0.0 );
1225
1226 for( jai = 0; jai < num_nodes; jai++ )
1227 {
1228 xin.set( coordinates[jai][0], coordinates[jai][1], coordinates[jai][2] );
1229 xin += thickness_z * normal_at_nodes[ja];
1230 aa += dndy1_at_node[ja][jai] * xin;
1231 bb += dndy2_at_node[ja][jai] * xin;
1232 if( jai == ja )
1233 thickness_gauss = thickness / 2.0;
1234 else
1235 thickness_gauss = 0.;
1236 cc += thickness_gauss * normal_at_nodes[jai];
1237 }
1238 }
1239 normal_at_point = aa * bb;
1240 sign_jacobian = ( face_normal % normal_at_point ) > 0 ? 1. : -1.;
1241 distrt = sign_jacobian * ( cc % normal_at_point );
1242
1243 if( distrt < distortion ) distortion = distrt;
1244 }
1245
1246 if( element_area * thickness != 0 )
1247 distortion *= 8. / ( element_area * thickness );
1248 else
1249 distortion *= 8.;
1250 }
1251
1252 return (double)distortion;
1253 }
References GaussIntegration::calculate_derivative_at_nodes(), GaussIntegration::calculate_shape_function_2d_quad(), dot_product(), moab::GeomUtil::first(), GaussIntegration::get_shape_func(), GaussIntegration::initialize(), is_collapsed_quad(), VerdictVector::length(), length(), maxNumberNodes, maxTotalNumberGaussPoints, VerdictVector::normalize(), quad_normal(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_MIN, and VERDICT_TRUE.
Referenced by moab::VerdictWrapper::quality_measure(), and v_quad_quality().
C_FUNC_DEF double v_quad_edge_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad edge ratio.
edge ratio Reference — P. P. Pebay, Planar Quadrangle Quality Measures, Eng. Comp., 2004, 20(2):157-173
the edge ratio of a quad
NB (P. Pebay 01/19/07): Hmax / Hmin where Hmax and Hmin are respectively the maximum and the minimum edge lengths
Definition at line 271 of file V_QuadMetric.cpp.
272 {
273 VerdictVector edges[4];
274 make_quad_edges( edges, coordinates );
275
276 double a2 = edges[0].length_squared();
277 double b2 = edges[1].length_squared();
278 double c2 = edges[2].length_squared();
279 double d2 = edges[3].length_squared();
280
281 double mab, Mab, mcd, Mcd, m2, M2;
282 if( a2 < b2 )
283 {
284 mab = a2;
285 Mab = b2;
286 }
287 else // b2 <= a2
288 {
289 mab = b2;
290 Mab = a2;
291 }
292 if( c2 < d2 )
293 {
294 mcd = c2;
295 Mcd = d2;
296 }
297 else // d2 <= c2
298 {
299 mcd = d2;
300 Mcd = c2;
301 }
302 m2 = mab < mcd ? mab : mcd;
303 M2 = Mab > Mcd ? Mab : Mcd;
304
305 if( m2 < VERDICT_DBL_MIN )
306 return (double)VERDICT_DBL_MAX;
307 else
308 {
309 double edge_ratio = sqrt( M2 / m2 );
310
311 if( edge_ratio > 0 ) return (double)VERDICT_MIN( edge_ratio, VERDICT_DBL_MAX );
312 return (double)VERDICT_MAX( edge_ratio, -VERDICT_DBL_MAX );
313 }
314 }
References VerdictVector::length_squared(), make_quad_edges(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_quad_quality().
C_FUNC_DEF double v_quad_jacobian | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad jacobian.
Minimum pointwise volume of local map at 4 corners & center of quad. Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
the jacobian of a quad
minimum pointwise volume of local map at 4 corners and center of quad
Definition at line 870 of file V_QuadMetric.cpp.
871 {
872
873 if( is_collapsed_quad( coordinates ) == VERDICT_TRUE ) return (double)( v_tri_area( 3, coordinates ) * 2.0 );
874
875 double areas[4];
876 signed_corner_areas( areas, coordinates );
877
878 double jacobian = VERDICT_MIN( VERDICT_MIN( areas[0], areas[1] ), VERDICT_MIN( areas[2], areas[3] ) );
879 if( jacobian > 0 ) return (double)VERDICT_MIN( jacobian, VERDICT_DBL_MAX );
880 return (double)VERDICT_MAX( jacobian, -VERDICT_DBL_MAX );
881 }
References is_collapsed_quad(), signed_corner_areas(), v_tri_area(), VERDICT_DBL_MAX, VERDICT_MAX, VERDICT_MIN, and VERDICT_TRUE.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_quad_max_aspect_frobenius | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad maximum Frobenius aspect.
average Frobenius aspect Reference — P. P. Pebay, Planar Quadrangle Quality Measures, Eng. Comp., 2004, 20(2):157-173
the maximum Frobenius aspect of a quad
NB (P. Pebay 01/20/07): this metric is calculated by taking the maximum of the 4 Frobenius aspects at each corner of the quad, when the reference triangle is right isosceles.
Definition at line 484 of file V_QuadMetric.cpp.
485 {
486
487 VerdictVector edges[4];
488 make_quad_edges( edges, coordinates );
489
490 double a2 = edges[0].length_squared();
491 double b2 = edges[1].length_squared();
492 double c2 = edges[2].length_squared();
493 double d2 = edges[3].length_squared();
494
495 VerdictVector ab = edges[0] * edges[1];
496 VerdictVector bc = edges[1] * edges[2];
497 VerdictVector cd = edges[2] * edges[3];
498 VerdictVector da = edges[3] * edges[0];
499
500 double ab1 = ab.length();
501 double bc1 = bc.length();
502 double cd1 = cd.length();
503 double da1 = da.length();
504
505 if( ab1 < VERDICT_DBL_MIN || bc1 < VERDICT_DBL_MIN || cd1 < VERDICT_DBL_MIN || da1 < VERDICT_DBL_MIN )
506 return (double)VERDICT_DBL_MAX;
507
508 double qmax = ( a2 + b2 ) / ab1;
509
510 double qcur = ( b2 + c2 ) / bc1;
511 qmax = qmax > qcur ? qmax : qcur;
512
513 qcur = ( c2 + d2 ) / cd1;
514 qmax = qmax > qcur ? qmax : qcur;
515
516 qcur = ( d2 + a2 ) / da1;
517 qmax = qmax > qcur ? qmax : qcur;
518
519 double max_aspect_frobenius = .5 * qmax;
520
521 if( max_aspect_frobenius > 0 ) return (double)VERDICT_MIN( max_aspect_frobenius, VERDICT_DBL_MAX );
522 return (double)VERDICT_MAX( max_aspect_frobenius, -VERDICT_DBL_MAX );
523 }
References VerdictVector::length(), VerdictVector::length_squared(), make_quad_edges(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_quad_quality().
C_FUNC_DEF double v_quad_max_edge_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad maximum of edge ratio.
Maximum edge length ratio at quad center. Reference — J. Robinson, CRE Method of element testing and the Jacobian shape parameters, Eng. Comput., Vol 4, 1987.
maximum of edge ratio of a quad
maximum edge length ratio at quad center
Definition at line 321 of file V_QuadMetric.cpp.
322 {
323 VerdictVector quad_nodes[4];
324 quad_nodes[0].set( coordinates[0][0], coordinates[0][1], coordinates[0][2] );
325 quad_nodes[1].set( coordinates[1][0], coordinates[1][1], coordinates[1][2] );
326 quad_nodes[2].set( coordinates[2][0], coordinates[2][1], coordinates[2][2] );
327 quad_nodes[3].set( coordinates[3][0], coordinates[3][1], coordinates[3][2] );
328
329 VerdictVector principal_axes[2];
330 principal_axes[0] = quad_nodes[1] + quad_nodes[2] - quad_nodes[0] - quad_nodes[3];
331 principal_axes[1] = quad_nodes[2] + quad_nodes[3] - quad_nodes[0] - quad_nodes[1];
332
333 double len1 = principal_axes[0].length();
334 double len2 = principal_axes[1].length();
335
336 if( len1 < VERDICT_DBL_MIN || len2 < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX;
337
338 double max_edge_ratio = VERDICT_MAX( len1 / len2, len2 / len1 );
339
340 if( max_edge_ratio > 0 ) return (double)VERDICT_MIN( max_edge_ratio, VERDICT_DBL_MAX );
341 return (double)VERDICT_MAX( max_edge_ratio, -VERDICT_DBL_MAX );
342 }
References VerdictVector::length(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_quad_maximum_angle | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad's largest angle.
Largest included quad angle (degrees). Reference — Unknown.
the largest angle of a quad
largest included quad area (degrees)
Definition at line 670 of file V_QuadMetric.cpp.
671 {
672
673 // if this is a collapsed quad, just pass it on to
674 // the tri_largest_angle routine
675 if( is_collapsed_quad( coordinates ) == VERDICT_TRUE ) return v_tri_maximum_angle( 3, coordinates );
676
677 double angle;
678 double max_angle = 0.0;
679
680 VerdictVector edges[4];
681 edges[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
682 coordinates[1][2] - coordinates[0][2] );
683 edges[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
684 coordinates[2][2] - coordinates[1][2] );
685 edges[2].set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
686 coordinates[3][2] - coordinates[2][2] );
687 edges[3].set( coordinates[0][0] - coordinates[3][0], coordinates[0][1] - coordinates[3][1],
688 coordinates[0][2] - coordinates[3][2] );
689
690 // go around each node and calculate the angle
691 // at each node
692 double length[4];
693 length[0] = edges[0].length();
694 length[1] = edges[1].length();
695 length[2] = edges[2].length();
696 length[3] = edges[3].length();
697
698 if( length[0] <= VERDICT_DBL_MIN || length[1] <= VERDICT_DBL_MIN || length[2] <= VERDICT_DBL_MIN ||
699 length[3] <= VERDICT_DBL_MIN )
700 return 0.0;
701
702 angle = acos( -( edges[0] % edges[1] ) / ( length[0] * length[1] ) );
703 max_angle = VERDICT_MAX( angle, max_angle );
704
705 angle = acos( -( edges[1] % edges[2] ) / ( length[1] * length[2] ) );
706 max_angle = VERDICT_MAX( angle, max_angle );
707
708 angle = acos( -( edges[2] % edges[3] ) / ( length[2] * length[3] ) );
709 max_angle = VERDICT_MAX( angle, max_angle );
710
711 angle = acos( -( edges[3] % edges[0] ) / ( length[3] * length[0] ) );
712 max_angle = VERDICT_MAX( angle, max_angle );
713
714 max_angle = max_angle * 180.0 / VERDICT_PI;
715
716 // if any signed areas are < 0, then you are getting the wrong angle
717 double areas[4];
718 signed_corner_areas( areas, coordinates );
719
720 if( areas[0] < 0 || areas[1] < 0 || areas[2] < 0 || areas[3] < 0 )
721 {
722 max_angle = 360 - max_angle;
723 }
724
725 if( max_angle > 0 ) return (double)VERDICT_MIN( max_angle, VERDICT_DBL_MAX );
726 return (double)VERDICT_MAX( max_angle, -VERDICT_DBL_MAX );
727 }
References moab::angle(), is_collapsed_quad(), VerdictVector::length(), length(), VerdictVector::set(), signed_corner_areas(), v_tri_maximum_angle(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, VERDICT_MIN, VERDICT_PI, and VERDICT_TRUE.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_quad_med_aspect_frobenius | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad average Frobenius aspect.
average Frobenius aspect Reference — P. P. Pebay, Planar Quadrangle Quality Measures, Eng. Comp., 2004, 20(2):157-173
the average Frobenius aspect of a quad
NB (P. Pebay 01/20/07): this metric is calculated by averaging the 4 Frobenius aspects at each corner of the quad, when the reference triangle is right isosceles.
Definition at line 442 of file V_QuadMetric.cpp.
443 {
444
445 VerdictVector edges[4];
446 make_quad_edges( edges, coordinates );
447
448 double a2 = edges[0].length_squared();
449 double b2 = edges[1].length_squared();
450 double c2 = edges[2].length_squared();
451 double d2 = edges[3].length_squared();
452
453 VerdictVector ab = edges[0] * edges[1];
454 VerdictVector bc = edges[1] * edges[2];
455 VerdictVector cd = edges[2] * edges[3];
456 VerdictVector da = edges[3] * edges[0];
457
458 double ab1 = ab.length();
459 double bc1 = bc.length();
460 double cd1 = cd.length();
461 double da1 = da.length();
462
463 if( ab1 < VERDICT_DBL_MIN || bc1 < VERDICT_DBL_MIN || cd1 < VERDICT_DBL_MIN || da1 < VERDICT_DBL_MIN )
464 return (double)VERDICT_DBL_MAX;
465
466 double qsum = ( a2 + b2 ) / ab1;
467 qsum += ( b2 + c2 ) / bc1;
468 qsum += ( c2 + d2 ) / cd1;
469 qsum += ( d2 + a2 ) / da1;
470
471 double med_aspect_frobenius = .125 * qsum;
472
473 if( med_aspect_frobenius > 0 ) return (double)VERDICT_MIN( med_aspect_frobenius, VERDICT_DBL_MAX );
474 return (double)VERDICT_MAX( med_aspect_frobenius, -VERDICT_DBL_MAX );
475 }
References VerdictVector::length(), VerdictVector::length_squared(), make_quad_edges(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_quad_quality().
C_FUNC_DEF double v_quad_minimum_angle | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad's smallest angle.
Smallest included quad angle (degrees). Reference — Unknown.
the smallest angle of a quad
smallest included quad angle (degrees)
Definition at line 734 of file V_QuadMetric.cpp.
735 {
736 // if this quad is a collapsed quad, then just
737 // send it to the tri_smallest_angle routine
738 if( is_collapsed_quad( coordinates ) == VERDICT_TRUE ) return v_tri_minimum_angle( 3, coordinates );
739
740 double angle;
741 double min_angle = 360.0;
742
743 VerdictVector edges[4];
744 edges[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
745 coordinates[1][2] - coordinates[0][2] );
746 edges[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
747 coordinates[2][2] - coordinates[1][2] );
748 edges[2].set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
749 coordinates[3][2] - coordinates[2][2] );
750 edges[3].set( coordinates[0][0] - coordinates[3][0], coordinates[0][1] - coordinates[3][1],
751 coordinates[0][2] - coordinates[3][2] );
752
753 // go around each node and calculate the angle
754 // at each node
755 double length[4];
756 length[0] = edges[0].length();
757 length[1] = edges[1].length();
758 length[2] = edges[2].length();
759 length[3] = edges[3].length();
760
761 if( length[0] <= VERDICT_DBL_MIN || length[1] <= VERDICT_DBL_MIN || length[2] <= VERDICT_DBL_MIN ||
762 length[3] <= VERDICT_DBL_MIN )
763 return 360.0;
764
765 angle = acos( -( edges[0] % edges[1] ) / ( length[0] * length[1] ) );
766 min_angle = VERDICT_MIN( angle, min_angle );
767
768 angle = acos( -( edges[1] % edges[2] ) / ( length[1] * length[2] ) );
769 min_angle = VERDICT_MIN( angle, min_angle );
770
771 angle = acos( -( edges[2] % edges[3] ) / ( length[2] * length[3] ) );
772 min_angle = VERDICT_MIN( angle, min_angle );
773
774 angle = acos( -( edges[3] % edges[0] ) / ( length[3] * length[0] ) );
775 min_angle = VERDICT_MIN( angle, min_angle );
776
777 min_angle = min_angle * 180.0 / VERDICT_PI;
778
779 if( min_angle > 0 ) return (double)VERDICT_MIN( min_angle, VERDICT_DBL_MAX );
780 return (double)VERDICT_MAX( min_angle, -VERDICT_DBL_MAX );
781 }
References moab::angle(), is_collapsed_quad(), VerdictVector::length(), length(), VerdictVector::set(), v_tri_minimum_angle(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, VERDICT_MIN, VERDICT_PI, and VERDICT_TRUE.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_quad_oddy | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad oddy metric.
the oddy of a quad
general distortion measure based on left Cauchy-Green Tensor
Definition at line 788 of file V_QuadMetric.cpp.
789 {
790
791 double max_oddy = 0.;
792
793 VerdictVector first, second, node_pos[4];
794
795 double g, g11, g12, g22, cur_oddy;
796 int i;
797
798 for( i = 0; i < 4; i++ )
799 node_pos[i].set( coordinates[i][0], coordinates[i][1], coordinates[i][2] );
800
801 for( i = 0; i < 4; i++ )
802 {
803 first = node_pos[i] - node_pos[( i + 1 ) % 4];
804 second = node_pos[i] - node_pos[( i + 3 ) % 4];
805
806 g11 = first % first;
807 g12 = first % second;
808 g22 = second % second;
809 g = g11 * g22 - g12 * g12;
810
811 if( g < VERDICT_DBL_MIN )
812 cur_oddy = VERDICT_DBL_MAX;
813 else
814 cur_oddy = ( ( g11 - g22 ) * ( g11 - g22 ) + 4. * g12 * g12 ) / 2. / g;
815
816 max_oddy = VERDICT_MAX( max_oddy, cur_oddy );
817 }
818
819 if( max_oddy > 0 ) return (double)VERDICT_MIN( max_oddy, VERDICT_DBL_MAX );
820 return (double)VERDICT_MAX( max_oddy, -VERDICT_DBL_MAX );
821 }
References moab::GeomUtil::first(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF void v_quad_quality | ( | int | num_nodes, |
double | coordinates[][3], | ||
unsigned int | metrics_request_flag, | ||
QuadMetricVals * | metric_vals | ||
) |
Calculates quality metrics for quadrilateral elements.
multiple quality measures of a quad
Definition at line 1258 of file V_QuadMetric.cpp.
1262 {
1263
1264 memset( metric_vals, 0, sizeof( QuadMetricVals ) );
1265
1266 // for starts, lets set up some basic and common information
1267
1268 /* node numbers and side numbers used below
1269
1270 2
1271 3 +--------- 2
1272 / +
1273 / |
1274 3 / | 1
1275 / |
1276 + |
1277 0 -------------+ 1
1278 0
1279 */
1280
1281 // vectors for each side
1282 VerdictVector edges[4];
1283 make_quad_edges( edges, coordinates );
1284
1285 double areas[4];
1286 signed_corner_areas( areas, coordinates );
1287
1288 double lengths[4];
1289 lengths[0] = edges[0].length();
1290 lengths[1] = edges[1].length();
1291 lengths[2] = edges[2].length();
1292 lengths[3] = edges[3].length();
1293
1294 VerdictBoolean is_collapsed = is_collapsed_quad( coordinates );
1295
1296 // handle collapsed quads metrics here
1297 if( is_collapsed == VERDICT_TRUE && metrics_request_flag & ( V_QUAD_MINIMUM_ANGLE | V_QUAD_MAXIMUM_ANGLE |
1298 V_QUAD_JACOBIAN | V_QUAD_SCALED_JACOBIAN ) )
1299 {
1300 if( metrics_request_flag & V_QUAD_MINIMUM_ANGLE )
1301 metric_vals->minimum_angle = v_tri_minimum_angle( 3, coordinates );
1302 if( metrics_request_flag & V_QUAD_MAXIMUM_ANGLE )
1303 metric_vals->maximum_angle = v_tri_maximum_angle( 3, coordinates );
1304 if( metrics_request_flag & V_QUAD_JACOBIAN )
1305 metric_vals->jacobian = (double)( v_tri_area( 3, coordinates ) * 2.0 );
1306 if( metrics_request_flag & V_QUAD_SCALED_JACOBIAN )
1307 metric_vals->jacobian = (double)( v_tri_scaled_jacobian( 3, coordinates ) * 2.0 );
1308 }
1309
1310 // calculate both largest and smallest angles
1311 if( metrics_request_flag & ( V_QUAD_MINIMUM_ANGLE | V_QUAD_MAXIMUM_ANGLE ) && is_collapsed == VERDICT_FALSE )
1312 {
1313 // gather the angles
1314 double angles[4];
1315 angles[0] = acos( -( edges[0] % edges[1] ) / ( lengths[0] * lengths[1] ) );
1316 angles[1] = acos( -( edges[1] % edges[2] ) / ( lengths[1] * lengths[2] ) );
1317 angles[2] = acos( -( edges[2] % edges[3] ) / ( lengths[2] * lengths[3] ) );
1318 angles[3] = acos( -( edges[3] % edges[0] ) / ( lengths[3] * lengths[0] ) );
1319
1320 if( lengths[0] <= VERDICT_DBL_MIN || lengths[1] <= VERDICT_DBL_MIN || lengths[2] <= VERDICT_DBL_MIN ||
1321 lengths[3] <= VERDICT_DBL_MIN )
1322 {
1323 metric_vals->minimum_angle = 360.0;
1324 metric_vals->maximum_angle = 0.0;
1325 }
1326 else
1327 {
1328 // if smallest angle, find the smallest angle
1329 if( metrics_request_flag & V_QUAD_MINIMUM_ANGLE )
1330 {
1331 metric_vals->minimum_angle = VERDICT_DBL_MAX;
1332 for( int i = 0; i < 4; i++ )
1333 metric_vals->minimum_angle = VERDICT_MIN( angles[i], metric_vals->minimum_angle );
1334 metric_vals->minimum_angle *= 180.0 / VERDICT_PI;
1335 }
1336 // if largest angle, find the largest angle
1337 if( metrics_request_flag & V_QUAD_MAXIMUM_ANGLE )
1338 {
1339 metric_vals->maximum_angle = 0.0;
1340 for( int i = 0; i < 4; i++ )
1341 metric_vals->maximum_angle = VERDICT_MAX( angles[i], metric_vals->maximum_angle );
1342 metric_vals->maximum_angle *= 180.0 / VERDICT_PI;
1343
1344 if( areas[0] < 0 || areas[1] < 0 || areas[2] < 0 || areas[3] < 0 )
1345 metric_vals->maximum_angle = 360 - metric_vals->maximum_angle;
1346 }
1347 }
1348 }
1349
1350 // handle max_edge_ratio, skew, taper, and area together
1351 if( metrics_request_flag & ( V_QUAD_MAX_EDGE_RATIO | V_QUAD_SKEW | V_QUAD_TAPER ) )
1352 {
1353 // get principle axes
1354 VerdictVector principal_axes[2];
1355 principal_axes[0] = edges[0] - edges[2];
1356 principal_axes[1] = edges[1] - edges[3];
1357
1358 if( metrics_request_flag & ( V_QUAD_MAX_EDGE_RATIO | V_QUAD_SKEW | V_QUAD_TAPER ) )
1359 {
1360 double len1 = principal_axes[0].length();
1361 double len2 = principal_axes[1].length();
1362
1363 // calculate the max_edge_ratio ratio
1364 if( metrics_request_flag & V_QUAD_MAX_EDGE_RATIO )
1365 {
1366 if( len1 < VERDICT_DBL_MIN || len2 < VERDICT_DBL_MIN )
1367 metric_vals->max_edge_ratio = VERDICT_DBL_MAX;
1368 else
1369 metric_vals->max_edge_ratio = VERDICT_MAX( len1 / len2, len2 / len1 );
1370 }
1371
1372 // calculate the taper
1373 if( metrics_request_flag & V_QUAD_TAPER )
1374 {
1375 double min_length = VERDICT_MIN( len1, len2 );
1376
1377 VerdictVector cross_derivative = edges[1] + edges[3];
1378
1379 if( min_length < VERDICT_DBL_MIN )
1380 metric_vals->taper = VERDICT_DBL_MAX;
1381 else
1382 metric_vals->taper = cross_derivative.length() / min_length;
1383 }
1384
1385 // calculate the skew
1386 if( metrics_request_flag & V_QUAD_SKEW )
1387 {
1388 if( principal_axes[0].normalize() < VERDICT_DBL_MIN || principal_axes[1].normalize() < VERDICT_DBL_MIN )
1389 metric_vals->skew = 0.0;
1390 else
1391 metric_vals->skew = fabs( principal_axes[0] % principal_axes[1] );
1392 }
1393 }
1394 }
1395
1396 // calculate the area
1397 if( metrics_request_flag & ( V_QUAD_AREA | V_QUAD_RELATIVE_SIZE_SQUARED ) )
1398 {
1399 metric_vals->area = 0.25 * ( areas[0] + areas[1] + areas[2] + areas[3] );
1400 }
1401
1402 // calculate the relative size
1403 if( metrics_request_flag & ( V_QUAD_RELATIVE_SIZE_SQUARED | V_QUAD_SHAPE_AND_SIZE | V_QUAD_SHEAR_AND_SIZE ) )
1404 {
1405 double quad_area = v_quad_area( 4, coordinates );
1406 v_set_quad_size( quad_area );
1407 double w11, w21, w12, w22;
1408 get_weight( w11, w21, w12, w22 );
1409 double avg_area = determinant( w11, w21, w12, w22 );
1410
1411 if( avg_area < VERDICT_DBL_MIN )
1412 metric_vals->relative_size_squared = 0.0;
1413 else
1414 metric_vals->relative_size_squared =
1415 pow( VERDICT_MIN( metric_vals->area / avg_area, avg_area / metric_vals->area ), 2 );
1416 }
1417
1418 // calculate the jacobian
1419 if( metrics_request_flag & V_QUAD_JACOBIAN )
1420 {
1421 metric_vals->jacobian = VERDICT_MIN( VERDICT_MIN( areas[0], areas[1] ), VERDICT_MIN( areas[2], areas[3] ) );
1422 }
1423
1424 if( metrics_request_flag & ( V_QUAD_SCALED_JACOBIAN | V_QUAD_SHEAR | V_QUAD_SHEAR_AND_SIZE ) )
1425 {
1426 double scaled_jac, min_scaled_jac = VERDICT_DBL_MAX;
1427
1428 if( lengths[0] < VERDICT_DBL_MIN || lengths[1] < VERDICT_DBL_MIN || lengths[2] < VERDICT_DBL_MIN ||
1429 lengths[3] < VERDICT_DBL_MIN )
1430 {
1431 metric_vals->scaled_jacobian = 0.0;
1432 metric_vals->shear = 0.0;
1433 }
1434 else
1435 {
1436 scaled_jac = areas[0] / ( lengths[0] * lengths[3] );
1437 min_scaled_jac = VERDICT_MIN( scaled_jac, min_scaled_jac );
1438
1439 scaled_jac = areas[1] / ( lengths[1] * lengths[0] );
1440 min_scaled_jac = VERDICT_MIN( scaled_jac, min_scaled_jac );
1441
1442 scaled_jac = areas[2] / ( lengths[2] * lengths[1] );
1443 min_scaled_jac = VERDICT_MIN( scaled_jac, min_scaled_jac );
1444
1445 scaled_jac = areas[3] / ( lengths[3] * lengths[2] );
1446 min_scaled_jac = VERDICT_MIN( scaled_jac, min_scaled_jac );
1447
1448 metric_vals->scaled_jacobian = min_scaled_jac;
1449
1450 // what the heck...set shear as well
1451 if( min_scaled_jac <= VERDICT_DBL_MIN )
1452 metric_vals->shear = 0.0;
1453 else
1454 metric_vals->shear = min_scaled_jac;
1455 }
1456 }
1457
1458 if( metrics_request_flag & ( V_QUAD_WARPAGE | V_QUAD_ODDY ) )
1459 {
1460 VerdictVector corner_normals[4];
1461 corner_normals[0] = edges[3] * edges[0];
1462 corner_normals[1] = edges[0] * edges[1];
1463 corner_normals[2] = edges[1] * edges[2];
1464 corner_normals[3] = edges[2] * edges[3];
1465
1466 if( metrics_request_flag & V_QUAD_ODDY )
1467 {
1468 double oddy, max_oddy = 0.0;
1469
1470 double diff, dot_prod;
1471
1472 double length_squared[4];
1473 length_squared[0] = corner_normals[0].length_squared();
1474 length_squared[1] = corner_normals[1].length_squared();
1475 length_squared[2] = corner_normals[2].length_squared();
1476 length_squared[3] = corner_normals[3].length_squared();
1477
1478 if( length_squared[0] < VERDICT_DBL_MIN || length_squared[1] < VERDICT_DBL_MIN ||
1479 length_squared[2] < VERDICT_DBL_MIN || length_squared[3] < VERDICT_DBL_MIN )
1480 metric_vals->oddy = VERDICT_DBL_MAX;
1481 else
1482 {
1483 diff = ( lengths[0] * lengths[0] ) - ( lengths[1] * lengths[1] );
1484 dot_prod = edges[0] % edges[1];
1485 oddy = ( ( diff * diff ) + 4 * dot_prod * dot_prod ) / ( 2 * length_squared[1] );
1486 max_oddy = VERDICT_MAX( oddy, max_oddy );
1487
1488 diff = ( lengths[1] * lengths[1] ) - ( lengths[2] * lengths[2] );
1489 dot_prod = edges[1] % edges[2];
1490 oddy = ( ( diff * diff ) + 4 * dot_prod * dot_prod ) / ( 2 * length_squared[2] );
1491 max_oddy = VERDICT_MAX( oddy, max_oddy );
1492
1493 diff = ( lengths[2] * lengths[2] ) - ( lengths[3] * lengths[3] );
1494 dot_prod = edges[2] % edges[3];
1495 oddy = ( ( diff * diff ) + 4 * dot_prod * dot_prod ) / ( 2 * length_squared[3] );
1496 max_oddy = VERDICT_MAX( oddy, max_oddy );
1497
1498 diff = ( lengths[3] * lengths[3] ) - ( lengths[0] * lengths[0] );
1499 dot_prod = edges[3] % edges[0];
1500 oddy = ( ( diff * diff ) + 4 * dot_prod * dot_prod ) / ( 2 * length_squared[0] );
1501 max_oddy = VERDICT_MAX( oddy, max_oddy );
1502
1503 metric_vals->oddy = max_oddy;
1504 }
1505 }
1506
1507 if( metrics_request_flag & V_QUAD_WARPAGE )
1508 {
1509 if( corner_normals[0].normalize() < VERDICT_DBL_MIN || corner_normals[1].normalize() < VERDICT_DBL_MIN ||
1510 corner_normals[2].normalize() < VERDICT_DBL_MIN || corner_normals[3].normalize() < VERDICT_DBL_MIN )
1511 metric_vals->warpage = VERDICT_DBL_MAX;
1512 else
1513 {
1514 metric_vals->warpage =
1515 pow( VERDICT_MIN( corner_normals[0] % corner_normals[2], corner_normals[1] % corner_normals[3] ),
1516 3 );
1517 }
1518 }
1519 }
1520
1521 if( metrics_request_flag & V_QUAD_STRETCH )
1522 {
1523 VerdictVector temp;
1524
1525 temp.set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
1526 coordinates[2][2] - coordinates[0][2] );
1527 double diag02 = temp.length_squared();
1528
1529 temp.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
1530 coordinates[3][2] - coordinates[1][2] );
1531 double diag13 = temp.length_squared();
1532
1533 static const double QUAD_STRETCH_FACTOR = sqrt( 2.0 );
1534
1535 // 'diag02' is now the max diagonal of the quad
1536 diag02 = VERDICT_MAX( diag02, diag13 );
1537
1538 if( diag02 < VERDICT_DBL_MIN )
1539 metric_vals->stretch = VERDICT_DBL_MAX;
1540 else
1541 metric_vals->stretch =
1542 QUAD_STRETCH_FACTOR *
1543 VERDICT_MIN( VERDICT_MIN( lengths[0], lengths[1] ), VERDICT_MIN( lengths[2], lengths[3] ) ) /
1544 sqrt( diag02 );
1545 }
1546
1547 if( metrics_request_flag & ( V_QUAD_CONDITION | V_QUAD_SHAPE | V_QUAD_SHAPE_AND_SIZE ) )
1548 {
1549 double lengths_squared[4];
1550 lengths_squared[0] = edges[0].length_squared();
1551 lengths_squared[1] = edges[1].length_squared();
1552 lengths_squared[2] = edges[2].length_squared();
1553 lengths_squared[3] = edges[3].length_squared();
1554
1555 if( areas[0] < VERDICT_DBL_MIN || areas[1] < VERDICT_DBL_MIN || areas[2] < VERDICT_DBL_MIN ||
1556 areas[3] < VERDICT_DBL_MIN )
1557 {
1558 metric_vals->condition = VERDICT_DBL_MAX;
1559 metric_vals->shape = 0.0;
1560 }
1561 else
1562 {
1563 double max_condition = 0.0, condition;
1564
1565 condition = ( lengths_squared[0] + lengths_squared[3] ) / areas[0];
1566 max_condition = VERDICT_MAX( max_condition, condition );
1567
1568 condition = ( lengths_squared[1] + lengths_squared[0] ) / areas[1];
1569 max_condition = VERDICT_MAX( max_condition, condition );
1570
1571 condition = ( lengths_squared[2] + lengths_squared[1] ) / areas[2];
1572 max_condition = VERDICT_MAX( max_condition, condition );
1573
1574 condition = ( lengths_squared[3] + lengths_squared[2] ) / areas[3];
1575 max_condition = VERDICT_MAX( max_condition, condition );
1576
1577 metric_vals->condition = 0.5 * max_condition;
1578 metric_vals->shape = 2 / max_condition;
1579 }
1580 }
1581
1582 if( metrics_request_flag & V_QUAD_AREA )
1583 {
1584 if( metric_vals->area > 0 ) metric_vals->area = (double)VERDICT_MIN( metric_vals->area, VERDICT_DBL_MAX );
1585 metric_vals->area = (double)VERDICT_MAX( metric_vals->area, -VERDICT_DBL_MAX );
1586 }
1587
1588 if( metrics_request_flag & V_QUAD_MAX_EDGE_RATIO )
1589 {
1590 if( metric_vals->max_edge_ratio > 0 )
1591 metric_vals->max_edge_ratio = (double)VERDICT_MIN( metric_vals->max_edge_ratio, VERDICT_DBL_MAX );
1592 metric_vals->max_edge_ratio = (double)VERDICT_MAX( metric_vals->max_edge_ratio, -VERDICT_DBL_MAX );
1593 }
1594
1595 if( metrics_request_flag & V_QUAD_CONDITION )
1596 {
1597 if( metric_vals->condition > 0 )
1598 metric_vals->condition = (double)VERDICT_MIN( metric_vals->condition, VERDICT_DBL_MAX );
1599 metric_vals->condition = (double)VERDICT_MAX( metric_vals->condition, -VERDICT_DBL_MAX );
1600 }
1601
1602 // calculate distortion
1603 if( metrics_request_flag & V_QUAD_DISTORTION )
1604 {
1605 metric_vals->distortion = v_quad_distortion( num_nodes, coordinates );
1606
1607 if( metric_vals->distortion > 0 )
1608 metric_vals->distortion = (double)VERDICT_MIN( metric_vals->distortion, VERDICT_DBL_MAX );
1609 metric_vals->distortion = (double)VERDICT_MAX( metric_vals->distortion, -VERDICT_DBL_MAX );
1610 }
1611
1612 if( metrics_request_flag & V_QUAD_JACOBIAN )
1613 {
1614 if( metric_vals->jacobian > 0 )
1615 metric_vals->jacobian = (double)VERDICT_MIN( metric_vals->jacobian, VERDICT_DBL_MAX );
1616 metric_vals->jacobian = (double)VERDICT_MAX( metric_vals->jacobian, -VERDICT_DBL_MAX );
1617 }
1618
1619 if( metrics_request_flag & V_QUAD_MAXIMUM_ANGLE )
1620 {
1621 if( metric_vals->maximum_angle > 0 )
1622 metric_vals->maximum_angle = (double)VERDICT_MIN( metric_vals->maximum_angle, VERDICT_DBL_MAX );
1623 metric_vals->maximum_angle = (double)VERDICT_MAX( metric_vals->maximum_angle, -VERDICT_DBL_MAX );
1624 }
1625
1626 if( metrics_request_flag & V_QUAD_MINIMUM_ANGLE )
1627 {
1628 if( metric_vals->minimum_angle > 0 )
1629 metric_vals->minimum_angle = (double)VERDICT_MIN( metric_vals->minimum_angle, VERDICT_DBL_MAX );
1630 metric_vals->minimum_angle = (double)VERDICT_MAX( metric_vals->minimum_angle, -VERDICT_DBL_MAX );
1631 }
1632
1633 if( metrics_request_flag & V_QUAD_ODDY )
1634 {
1635 if( metric_vals->oddy > 0 ) metric_vals->oddy = (double)VERDICT_MIN( metric_vals->oddy, VERDICT_DBL_MAX );
1636 metric_vals->oddy = (double)VERDICT_MAX( metric_vals->oddy, -VERDICT_DBL_MAX );
1637 }
1638
1639 if( metrics_request_flag & V_QUAD_RELATIVE_SIZE_SQUARED )
1640 {
1641 if( metric_vals->relative_size_squared > 0 )
1642 metric_vals->relative_size_squared =
1643 (double)VERDICT_MIN( metric_vals->relative_size_squared, VERDICT_DBL_MAX );
1644 metric_vals->relative_size_squared =
1645 (double)VERDICT_MAX( metric_vals->relative_size_squared, -VERDICT_DBL_MAX );
1646 }
1647
1648 if( metrics_request_flag & V_QUAD_SCALED_JACOBIAN )
1649 {
1650 if( metric_vals->scaled_jacobian > 0 )
1651 metric_vals->scaled_jacobian = (double)VERDICT_MIN( metric_vals->scaled_jacobian, VERDICT_DBL_MAX );
1652 metric_vals->scaled_jacobian = (double)VERDICT_MAX( metric_vals->scaled_jacobian, -VERDICT_DBL_MAX );
1653 }
1654
1655 if( metrics_request_flag & V_QUAD_SHEAR )
1656 {
1657 if( metric_vals->shear > 0 ) metric_vals->shear = (double)VERDICT_MIN( metric_vals->shear, VERDICT_DBL_MAX );
1658 metric_vals->shear = (double)VERDICT_MAX( metric_vals->shear, -VERDICT_DBL_MAX );
1659 }
1660
1661 // calculate shear and size
1662 // reuse values from above
1663 if( metrics_request_flag & V_QUAD_SHEAR_AND_SIZE )
1664 {
1665 metric_vals->shear_and_size = metric_vals->shear * metric_vals->relative_size_squared;
1666
1667 if( metric_vals->shear_and_size > 0 )
1668 metric_vals->shear_and_size = (double)VERDICT_MIN( metric_vals->shear_and_size, VERDICT_DBL_MAX );
1669 metric_vals->shear_and_size = (double)VERDICT_MAX( metric_vals->shear_and_size, -VERDICT_DBL_MAX );
1670 }
1671
1672 if( metrics_request_flag & V_QUAD_SHAPE )
1673 {
1674 if( metric_vals->shape > 0 ) metric_vals->shape = (double)VERDICT_MIN( metric_vals->shape, VERDICT_DBL_MAX );
1675 metric_vals->shape = (double)VERDICT_MAX( metric_vals->shape, -VERDICT_DBL_MAX );
1676 }
1677
1678 // calculate shape and size
1679 // reuse values from above
1680 if( metrics_request_flag & V_QUAD_SHAPE_AND_SIZE )
1681 {
1682 metric_vals->shape_and_size = metric_vals->shape * metric_vals->relative_size_squared;
1683
1684 if( metric_vals->shape_and_size > 0 )
1685 metric_vals->shape_and_size = (double)VERDICT_MIN( metric_vals->shape_and_size, VERDICT_DBL_MAX );
1686 metric_vals->shape_and_size = (double)VERDICT_MAX( metric_vals->shape_and_size, -VERDICT_DBL_MAX );
1687 }
1688
1689 if( metrics_request_flag & V_QUAD_SKEW )
1690 {
1691 if( metric_vals->skew > 0 ) metric_vals->skew = (double)VERDICT_MIN( metric_vals->skew, VERDICT_DBL_MAX );
1692 metric_vals->skew = (double)VERDICT_MAX( metric_vals->skew, -VERDICT_DBL_MAX );
1693 }
1694
1695 if( metrics_request_flag & V_QUAD_STRETCH )
1696 {
1697 if( metric_vals->stretch > 0 )
1698 metric_vals->stretch = (double)VERDICT_MIN( metric_vals->stretch, VERDICT_DBL_MAX );
1699 metric_vals->stretch = (double)VERDICT_MAX( metric_vals->stretch, -VERDICT_DBL_MAX );
1700 }
1701
1702 if( metrics_request_flag & V_QUAD_TAPER )
1703 {
1704 if( metric_vals->taper > 0 ) metric_vals->taper = (double)VERDICT_MIN( metric_vals->taper, VERDICT_DBL_MAX );
1705 metric_vals->taper = (double)VERDICT_MAX( metric_vals->taper, -VERDICT_DBL_MAX );
1706 }
1707
1708 if( metrics_request_flag & V_QUAD_WARPAGE )
1709 {
1710 if( metric_vals->warpage > 0 )
1711 metric_vals->warpage = (double)VERDICT_MIN( metric_vals->warpage, VERDICT_DBL_MAX );
1712 metric_vals->warpage = (double)VERDICT_MAX( metric_vals->warpage, -VERDICT_DBL_MAX );
1713 }
1714
1715 if( metrics_request_flag & V_QUAD_MED_ASPECT_FROBENIUS )
1716 metric_vals->med_aspect_frobenius = v_quad_med_aspect_frobenius( 4, coordinates );
1717 if( metrics_request_flag & V_QUAD_MAX_ASPECT_FROBENIUS )
1718 metric_vals->max_aspect_frobenius = v_quad_max_aspect_frobenius( 4, coordinates );
1719 if( metrics_request_flag & V_QUAD_EDGE_RATIO ) metric_vals->edge_ratio = v_quad_edge_ratio( 4, coordinates );
1720 if( metrics_request_flag & V_QUAD_ASPECT_RATIO ) metric_vals->aspect_ratio = v_quad_aspect_ratio( 4, coordinates );
1721 if( metrics_request_flag & V_QUAD_RADIUS_RATIO ) metric_vals->radius_ratio = v_quad_radius_ratio( 4, coordinates );
1722 }
References QuadMetricVals::area, QuadMetricVals::aspect_ratio, QuadMetricVals::condition, determinant(), QuadMetricVals::distortion, QuadMetricVals::edge_ratio, get_weight(), is_collapsed_quad(), QuadMetricVals::jacobian, VerdictVector::length(), VerdictVector::length_squared(), length_squared(), make_quad_edges(), QuadMetricVals::max_aspect_frobenius, QuadMetricVals::max_edge_ratio, QuadMetricVals::maximum_angle, QuadMetricVals::med_aspect_frobenius, QuadMetricVals::minimum_angle, normalize(), QuadMetricVals::oddy, QuadMetricVals::radius_ratio, QuadMetricVals::relative_size_squared, QuadMetricVals::scaled_jacobian, VerdictVector::set(), QuadMetricVals::shape, QuadMetricVals::shape_and_size, QuadMetricVals::shear, QuadMetricVals::shear_and_size, signed_corner_areas(), QuadMetricVals::skew, QuadMetricVals::stretch, QuadMetricVals::taper, V_QUAD_AREA, v_quad_area(), V_QUAD_ASPECT_RATIO, v_quad_aspect_ratio(), V_QUAD_CONDITION, V_QUAD_DISTORTION, v_quad_distortion(), V_QUAD_EDGE_RATIO, v_quad_edge_ratio(), V_QUAD_JACOBIAN, V_QUAD_MAX_ASPECT_FROBENIUS, v_quad_max_aspect_frobenius(), V_QUAD_MAX_EDGE_RATIO, V_QUAD_MAXIMUM_ANGLE, V_QUAD_MED_ASPECT_FROBENIUS, v_quad_med_aspect_frobenius(), V_QUAD_MINIMUM_ANGLE, V_QUAD_ODDY, V_QUAD_RADIUS_RATIO, v_quad_radius_ratio(), V_QUAD_RELATIVE_SIZE_SQUARED, V_QUAD_SCALED_JACOBIAN, V_QUAD_SHAPE, V_QUAD_SHAPE_AND_SIZE, V_QUAD_SHEAR, V_QUAD_SHEAR_AND_SIZE, V_QUAD_SKEW, V_QUAD_STRETCH, V_QUAD_TAPER, V_QUAD_WARPAGE, v_set_quad_size(), v_tri_area(), v_tri_maximum_angle(), v_tri_minimum_angle(), v_tri_scaled_jacobian(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_FALSE, VERDICT_MAX, VERDICT_MIN, VERDICT_PI, VERDICT_TRUE, and QuadMetricVals::warpage.
Referenced by moab::VerdictWrapper::all_quality_measures().
C_FUNC_DEF double v_quad_radius_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad radius ratio.
radius ratio Reference — P. P. Pebay, Planar Quadrangle Quality Measures, Eng. Comp., 2004, 20(2):157-173
the radius ratio of a quad
NB (P. Pebay 01/19/07): this metric is called "radius ratio" by extension of a concept that does not exist in general with quads – although a different name should probably be used in the future.
Definition at line 386 of file V_QuadMetric.cpp.
387 {
388 static const double normal_coeff = 1. / ( 2. * sqrt( 2. ) );
389
390 VerdictVector edges[4];
391 make_quad_edges( edges, coordinates );
392
393 double a2 = edges[0].length_squared();
394 double b2 = edges[1].length_squared();
395 double c2 = edges[2].length_squared();
396 double d2 = edges[3].length_squared();
397
398 VerdictVector diag;
399 diag.set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
400 coordinates[2][2] - coordinates[0][2] );
401 double m2 = diag.length_squared();
402
403 diag.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
404 coordinates[3][2] - coordinates[1][2] );
405 double n2 = diag.length_squared();
406
407 double t0 = a2 > b2 ? a2 : b2;
408 double t1 = c2 > d2 ? c2 : d2;
409 double t2 = m2 > n2 ? m2 : n2;
410 double h2 = t0 > t1 ? t0 : t1;
411 h2 = h2 > t2 ? h2 : t2;
412
413 VerdictVector ab = edges[0] * edges[1];
414 VerdictVector bc = edges[1] * edges[2];
415 VerdictVector cd = edges[2] * edges[3];
416 VerdictVector da = edges[3] * edges[0];
417
418 t0 = da.length();
419 t1 = ab.length();
420 t2 = bc.length();
421 double t3 = cd.length();
422
423 t0 = t0 < t1 ? t0 : t1;
424 t2 = t2 < t3 ? t2 : t3;
425 t0 = t0 < t2 ? t0 : t2;
426
427 if( t0 < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX;
428
429 double radius_ratio = normal_coeff * sqrt( ( a2 + b2 + c2 + d2 ) * h2 ) / t0;
430
431 if( radius_ratio > 0 ) return (double)VERDICT_MIN( radius_ratio, VERDICT_DBL_MAX );
432 return (double)VERDICT_MAX( radius_ratio, -VERDICT_DBL_MAX );
433 }
References VerdictVector::length(), VerdictVector::length_squared(), make_quad_edges(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_quad_quality().
C_FUNC_DEF double v_quad_relative_size_squared | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad relative size metric.
Min( J, 1/J ), where J is determinant of weighted Jacobian matrix. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
the relative size of a quad
Min( J, 1/J ), where J is determinant of weighted Jacobian matrix
Definition at line 988 of file V_QuadMetric.cpp.
989 {
990
991 double quad_area = v_quad_area( 4, coordinates );
992 double rel_size = 0;
993
994 v_set_quad_size( quad_area );
995 double w11, w21, w12, w22;
996 get_weight( w11, w21, w12, w22 );
997 double avg_area = determinant( w11, w21, w12, w22 );
998
999 if( avg_area > VERDICT_DBL_MIN )
1000 {
1001
1002 w11 = quad_area / avg_area;
1003
1004 if( w11 > VERDICT_DBL_MIN )
1005 {
1006 rel_size = VERDICT_MIN( w11, 1 / w11 );
1007 rel_size *= rel_size;
1008 }
1009 }
1010
1011 if( rel_size > 0 ) return (double)VERDICT_MIN( rel_size, VERDICT_DBL_MAX );
1012 return (double)VERDICT_MAX( rel_size, -VERDICT_DBL_MAX );
1013 }
References determinant(), get_weight(), v_quad_area(), v_set_quad_size(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), v_quad_shape_and_size(), and v_quad_shear_and_size().
C_FUNC_DEF double v_quad_scaled_jacobian | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad scaled jacobian.
Minimum Jacobian divided by the lengths of the 2 edge vectors. Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
scaled jacobian of a quad
Minimum Jacobian divided by the lengths of the 2 edge vector
Definition at line 888 of file V_QuadMetric.cpp.
889 {
890 if( is_collapsed_quad( coordinates ) == VERDICT_TRUE ) return v_tri_scaled_jacobian( 3, coordinates );
891
892 double corner_areas[4], min_scaled_jac = VERDICT_DBL_MAX, scaled_jac;
893 signed_corner_areas( corner_areas, coordinates );
894
895 VerdictVector edges[4];
896 make_quad_edges( edges, coordinates );
897
898 double length[4];
899 length[0] = edges[0].length();
900 length[1] = edges[1].length();
901 length[2] = edges[2].length();
902 length[3] = edges[3].length();
903
904 if( length[0] < VERDICT_DBL_MIN || length[1] < VERDICT_DBL_MIN || length[2] < VERDICT_DBL_MIN ||
905 length[3] < VERDICT_DBL_MIN )
906 return 0.0;
907
908 scaled_jac = corner_areas[0] / ( length[0] * length[3] );
909 min_scaled_jac = VERDICT_MIN( scaled_jac, min_scaled_jac );
910
911 scaled_jac = corner_areas[1] / ( length[1] * length[0] );
912 min_scaled_jac = VERDICT_MIN( scaled_jac, min_scaled_jac );
913
914 scaled_jac = corner_areas[2] / ( length[2] * length[1] );
915 min_scaled_jac = VERDICT_MIN( scaled_jac, min_scaled_jac );
916
917 scaled_jac = corner_areas[3] / ( length[3] * length[2] );
918 min_scaled_jac = VERDICT_MIN( scaled_jac, min_scaled_jac );
919
920 if( min_scaled_jac > 0 ) return (double)VERDICT_MIN( min_scaled_jac, VERDICT_DBL_MAX );
921 return (double)VERDICT_MAX( min_scaled_jac, -VERDICT_DBL_MAX );
922 }
References is_collapsed_quad(), VerdictVector::length(), length(), make_quad_edges(), signed_corner_areas(), v_tri_scaled_jacobian(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, VERDICT_MIN, and VERDICT_TRUE.
Referenced by moab::VerdictWrapper::quality_measure(), and v_quad_shear().
C_FUNC_DEF double v_quad_shape | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad shape metric.
2/Condition number of weighted Jacobian matrix. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
the shape of a quad
2/Condition number of weighted Jacobian matrix
Definition at line 944 of file V_QuadMetric.cpp.
945 {
946
947 double corner_areas[4], min_shape = VERDICT_DBL_MAX, shape;
948 signed_corner_areas( corner_areas, coordinates );
949
950 VerdictVector edges[4];
951 make_quad_edges( edges, coordinates );
952
953 double length_squared[4];
954 length_squared[0] = edges[0].length_squared();
955 length_squared[1] = edges[1].length_squared();
956 length_squared[2] = edges[2].length_squared();
957 length_squared[3] = edges[3].length_squared();
958
959 if( length_squared[0] <= VERDICT_DBL_MIN || length_squared[1] <= VERDICT_DBL_MIN ||
960 length_squared[2] <= VERDICT_DBL_MIN || length_squared[3] <= VERDICT_DBL_MIN )
961 return 0.0;
962
963 shape = corner_areas[0] / ( length_squared[0] + length_squared[3] );
964 min_shape = VERDICT_MIN( shape, min_shape );
965
966 shape = corner_areas[1] / ( length_squared[1] + length_squared[0] );
967 min_shape = VERDICT_MIN( shape, min_shape );
968
969 shape = corner_areas[2] / ( length_squared[2] + length_squared[1] );
970 min_shape = VERDICT_MIN( shape, min_shape );
971
972 shape = corner_areas[3] / ( length_squared[3] + length_squared[2] );
973 min_shape = VERDICT_MIN( shape, min_shape );
974
975 min_shape *= 2;
976
977 if( min_shape < VERDICT_DBL_MIN ) min_shape = 0;
978
979 if( min_shape > 0 ) return (double)VERDICT_MIN( min_shape, VERDICT_DBL_MAX );
980 return (double)VERDICT_MAX( min_shape, -VERDICT_DBL_MAX );
981 }
References VerdictVector::length_squared(), length_squared(), make_quad_edges(), signed_corner_areas(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_quad_shape_and_size().
C_FUNC_DEF double v_quad_shape_and_size | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad shape-size metric.
Product of Shape and Relative Size. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
the relative shape and size of a quad
Product of Shape and Relative Size
Definition at line 1020 of file V_QuadMetric.cpp.
1021 {
1022 double shape, size;
1023 size = v_quad_relative_size_squared( num_nodes, coordinates );
1024 shape = v_quad_shape( num_nodes, coordinates );
1025
1026 double shape_and_size = shape * size;
1027
1028 if( shape_and_size > 0 ) return (double)VERDICT_MIN( shape_and_size, VERDICT_DBL_MAX );
1029 return (double)VERDICT_MAX( shape_and_size, -VERDICT_DBL_MAX );
1030 }
References size, v_quad_relative_size_squared(), v_quad_shape(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_quad_shear | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad shear metric.
2/Condition number of Jacobian Skew matrix. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
the shear of a quad
2/Condition number of Jacobian Skew matrix
Definition at line 929 of file V_QuadMetric.cpp.
930 {
931 double scaled_jacobian = v_quad_scaled_jacobian( 4, coordinates );
932
933 if( scaled_jacobian <= VERDICT_DBL_MIN )
934 return 0.0;
935 else
936 return (double)VERDICT_MIN( scaled_jacobian, VERDICT_DBL_MAX );
937 }
References v_quad_scaled_jacobian(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_quad_shear_and_size().
C_FUNC_DEF double v_quad_shear_and_size | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad shear-size metric.
Product of Shear and Relative Size. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
the shear and size of a quad
product of shear and relative size
Definition at line 1037 of file V_QuadMetric.cpp.
1038 {
1039 double shear, size;
1040 shear = v_quad_shear( num_nodes, coordinates );
1041 size = v_quad_relative_size_squared( num_nodes, coordinates );
1042
1043 double shear_and_size = shear * size;
1044
1045 if( shear_and_size > 0 ) return (double)VERDICT_MIN( shear_and_size, VERDICT_DBL_MAX );
1046 return (double)VERDICT_MAX( shear_and_size, -VERDICT_DBL_MAX );
1047 }
References size, v_quad_relative_size_squared(), v_quad_shear(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_quad_skew | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad skew metric.
Maximum |cos A| where A is the angle between edges at quad center. Reference — J. Robinson, CRE Method of element testing and the Jacobian shape parameters, Eng. Comput., Vol 4, 1987.
skew of a quad
maximum ||cos A|| where A is the angle between edges at quad center
Definition at line 530 of file V_QuadMetric.cpp.
531 {
532 VerdictVector node_pos[4];
533 for( int i = 0; i < 4; i++ )
534 node_pos[i].set( coordinates[i][0], coordinates[i][1], coordinates[i][2] );
535
536 VerdictVector principle_axes[2];
537 principle_axes[0] = node_pos[1] + node_pos[2] - node_pos[3] - node_pos[0];
538 principle_axes[1] = node_pos[2] + node_pos[3] - node_pos[0] - node_pos[1];
539
540 if( principle_axes[0].normalize() < VERDICT_DBL_MIN ) return 0.0;
541 if( principle_axes[1].normalize() < VERDICT_DBL_MIN ) return 0.0;
542
543 double skew = fabs( principle_axes[0] % principle_axes[1] );
544
545 return (double)VERDICT_MIN( skew, VERDICT_DBL_MAX );
546 }
References normalize(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_quad_stretch | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad strech metric.
Sqrt(2) * minimum edge length / maximum diagonal length. Reference — FIMESH code.
the stretch of a quad
sqrt(2) * minimum edge length / maximum diagonal length
Definition at line 628 of file V_QuadMetric.cpp.
629 {
630 VerdictVector edges[4], temp;
631 make_quad_edges( edges, coordinates );
632
633 double lengths_squared[4];
634 lengths_squared[0] = edges[0].length_squared();
635 lengths_squared[1] = edges[1].length_squared();
636 lengths_squared[2] = edges[2].length_squared();
637 lengths_squared[3] = edges[3].length_squared();
638
639 temp.set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
640 coordinates[2][2] - coordinates[0][2] );
641 double diag02 = temp.length_squared();
642
643 temp.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
644 coordinates[3][2] - coordinates[1][2] );
645 double diag13 = temp.length_squared();
646
647 static const double QUAD_STRETCH_FACTOR = sqrt( 2.0 );
648
649 // 'diag02' is now the max diagonal of the quad
650 diag02 = VERDICT_MAX( diag02, diag13 );
651
652 if( diag02 < VERDICT_DBL_MIN )
653 return (double)VERDICT_DBL_MAX;
654 else
655 {
656 double stretch =
657 (double)( QUAD_STRETCH_FACTOR * sqrt( VERDICT_MIN( VERDICT_MIN( lengths_squared[0], lengths_squared[1] ),
658 VERDICT_MIN( lengths_squared[2], lengths_squared[3] ) ) /
659 diag02 ) );
660
661 return (double)VERDICT_MIN( stretch, VERDICT_DBL_MAX );
662 }
663 }
References VerdictVector::length_squared(), make_quad_edges(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_quad_taper | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad taper metric.
Maximum ratio of lengths derived from opposite edges. Reference — J. Robinson, CRE Method of element testing and the Jacobian shape parameters, Eng. Comput., Vol 4, 1987.
taper of a quad
maximum ratio of lengths derived from opposite edges
Definition at line 553 of file V_QuadMetric.cpp.
554 {
555 VerdictVector node_pos[4];
556 for( int i = 0; i < 4; i++ )
557 node_pos[i].set( coordinates[i][0], coordinates[i][1], coordinates[i][2] );
558
559 VerdictVector principle_axes[2];
560 principle_axes[0] = node_pos[1] + node_pos[2] - node_pos[3] - node_pos[0];
561 principle_axes[1] = node_pos[2] + node_pos[3] - node_pos[0] - node_pos[1];
562
563 VerdictVector cross_derivative = node_pos[0] + node_pos[2] - node_pos[1] - node_pos[3];
564
565 double lengths[2];
566 lengths[0] = principle_axes[0].length();
567 lengths[1] = principle_axes[1].length();
568
569 // get min length
570 lengths[0] = VERDICT_MIN( lengths[0], lengths[1] );
571
572 if( lengths[0] < VERDICT_DBL_MIN ) return VERDICT_DBL_MAX;
573
574 double taper = cross_derivative.length() / lengths[0];
575 return (double)VERDICT_MIN( taper, VERDICT_DBL_MAX );
576 }
References VerdictVector::length(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_quad_warpage | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates quad warpage metric.
Cosine of Minimum Dihedral Angle formed by Planes Intersecting in Diagonals. Reference — J. Robinson, CRE Method of element testing and the Jacobian shape parameters, Eng. Comput., Vol 4, 1987.
warpage of a quad
deviation of element from planarity
Definition at line 583 of file V_QuadMetric.cpp.
584 {
585
586 VerdictVector edges[4];
587 make_quad_edges( edges, coordinates );
588
589 VerdictVector corner_normals[4];
590 corner_normals[0] = edges[3] * edges[0];
591 corner_normals[1] = edges[0] * edges[1];
592 corner_normals[2] = edges[1] * edges[2];
593 corner_normals[3] = edges[2] * edges[3];
594
595 if( corner_normals[0].normalize() < VERDICT_DBL_MIN || corner_normals[1].normalize() < VERDICT_DBL_MIN ||
596 corner_normals[2].normalize() < VERDICT_DBL_MIN || corner_normals[3].normalize() < VERDICT_DBL_MIN )
597 return (double)VERDICT_DBL_MIN;
598
599 double warpage =
600 pow( VERDICT_MIN( corner_normals[0] % corner_normals[2], corner_normals[1] % corner_normals[3] ), 3 );
601
602 if( warpage > 0 ) return (double)VERDICT_MIN( warpage, VERDICT_DBL_MAX );
603 return (double)VERDICT_MAX( warpage, -VERDICT_DBL_MAX );
604 }
References make_quad_edges(), normalize(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF void v_set_hex_size | ( | double | size | ) |
Sets average size (volume) of hex, needed for v_hex_relative_size(...)
Sets average size (volume) of hex, needed for v_hex_relative_size(...)
Definition at line 57 of file V_HexMetric.cpp.
58 {
59 verdict_hex_size = size;
60 }
References size, and verdict_hex_size.
Referenced by moab::VerdictWrapper::set_size().
C_FUNC_DEF void v_set_quad_size | ( | double | size | ) |
Sets average size (area) of quad, needed for v_quad_relative_size(...)
Sets average size (area) of quad, needed for v_quad_relative_size(...)
Definition at line 56 of file V_QuadMetric.cpp.
57 {
58 verdict_quad_size = size;
59 }
References size, and verdict_quad_size.
Referenced by moab::VerdictWrapper::set_size(), v_quad_quality(), and v_quad_relative_size_squared().
C_FUNC_DEF void v_set_tet_size | ( | double | size | ) |
Sets average size (volume) of tet, needed for v_tet_relative_size(...)
set the average volume of a tet
Definition at line 37 of file V_TetMetric.cpp.
38 {
39 verdict_tet_size = size;
40 }
References size, and verdict_tet_size.
Referenced by moab::VerdictWrapper::set_size().
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.
64 { 65 compute_normal = func; 66 }
References compute_normal.
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.
59 {
60 verdict_tri_size = size;
61 }
References size, and verdict_tri_size.
Referenced by moab::VerdictWrapper::set_size().
C_FUNC_DEF double v_tet_aspect_beta | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates the radius ratio metric of a positively oriented tet.
CR / (3.0 * IR) where CR = circumsphere radius, IR = inscribed sphere radius if the element is positively-oriented. Reference — V. N. Parthasarathy et al, A comparison of tetrahedron quality measures, Finite Elem. Anal. Des., Vol 15(1993), 255-261.
The radius ratio of a positively-oriented tet, a.k.a. "aspect beta"
NB (P. Pebay 04/16/07): CR / (3.0 * IR) where CR is the circumsphere radius and IR is the inscribed sphere radius if the element has positive orientation. Note that this metric is similar to the radius ratio of a tet, except that it returns VERDICT_DBL_MAX if the element has negative orientation.
Definition at line 265 of file V_TetMetric.cpp.
266 {
267
268 // Determine side vectors
269 VerdictVector side[6];
270
271 side[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
272 coordinates[1][2] - coordinates[0][2] );
273
274 side[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
275 coordinates[2][2] - coordinates[1][2] );
276
277 side[2].set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
278 coordinates[0][2] - coordinates[2][2] );
279
280 side[3].set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
281 coordinates[3][2] - coordinates[0][2] );
282
283 side[4].set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
284 coordinates[3][2] - coordinates[1][2] );
285
286 side[5].set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
287 coordinates[3][2] - coordinates[2][2] );
288
289 VerdictVector numerator = side[3].length_squared() * ( side[2] * side[0] ) +
290 side[2].length_squared() * ( side[3] * side[0] ) +
291 side[0].length_squared() * ( side[3] * side[2] );
292
293 double area_sum;
294 area_sum = ( ( side[2] * side[0] ).length() + ( side[3] * side[0] ).length() + ( side[4] * side[1] ).length() +
295 ( side[3] * side[2] ).length() ) *
296 0.5;
297
298 double volume = v_tet_volume( 4, coordinates );
299
300 if( volume < VERDICT_DBL_MIN )
301 return (double)VERDICT_DBL_MAX;
302 else
303 {
304 double radius_ratio;
305 radius_ratio = numerator.length() * area_sum / ( 108 * volume * volume );
306
307 return (double)VERDICT_MIN( radius_ratio, VERDICT_DBL_MAX );
308 }
309 }
References VerdictVector::length(), length(), VerdictVector::length_squared(), length_squared(), VerdictVector::set(), v_tet_volume(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_tet_aspect_frobenius | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet aspect frobenius metric.
Frobenius condition number when the reference element is regular Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
The aspect frobenius of a tet
NB (P. Pebay 01/22/07): Frobenius condition number when the reference element is regular
Definition at line 426 of file V_TetMetric.cpp.
427 {
428 static const double normal_exp = 1. / 3.;
429
430 VerdictVector ab, ac, ad;
431
432 ab.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
433 coordinates[1][2] - coordinates[0][2] );
434
435 ac.set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
436 coordinates[2][2] - coordinates[0][2] );
437
438 ad.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
439 coordinates[3][2] - coordinates[0][2] );
440
441 double denominator = ab % ( ac * ad );
442 denominator *= denominator;
443 denominator *= 2.;
444 denominator = 3. * pow( denominator, normal_exp );
445
446 if( denominator < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX;
447
448 double u[3];
449 ab.get_xyz( u );
450 double v[3];
451 ac.get_xyz( v );
452 double w[3];
453 ad.get_xyz( w );
454
455 double numerator = u[0] * u[0] + u[1] * u[1] + u[2] * u[2];
456 numerator += v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
457 numerator += w[0] * w[0] + w[1] * w[1] + w[2] * w[2];
458 numerator *= 1.5;
459 numerator -= v[0] * u[0] + v[1] * u[1] + v[2] * u[2];
460 numerator -= w[0] * u[0] + w[1] * u[1] + w[2] * u[2];
461 numerator -= w[0] * v[0] + w[1] * v[1] + w[2] * v[2];
462
463 double aspect_frobenius = numerator / denominator;
464
465 if( aspect_frobenius > 0 ) return (double)VERDICT_MIN( aspect_frobenius, VERDICT_DBL_MAX );
466 return (double)VERDICT_MAX( aspect_frobenius, -VERDICT_DBL_MAX );
467 }
References VerdictVector::get_xyz(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tet_quality().
C_FUNC_DEF double v_tet_aspect_gamma | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet aspect gamma metric.
Srms**3 / (8.479670*V) where Srms = sqrt(Sum(Si**2)/6), Si = edge length. Reference — V. N. Parthasarathy et al, A comparison of tetrahedron quality measures, Finite Elem. Anal. Des., Vol 15(1993), 255-261.
the aspect gamma of a tet
srms^3 / (8.48528137423857*V) where srms = sqrt(sum(Si^2)/6), where Si is the edge length
Definition at line 381 of file V_TetMetric.cpp.
382 {
383
384 // Determine side vectors
385 VerdictVector side0, side1, side2, side3, side4, side5;
386
387 side0.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
388 coordinates[1][2] - coordinates[0][2] );
389
390 side1.set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
391 coordinates[2][2] - coordinates[1][2] );
392
393 side2.set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
394 coordinates[0][2] - coordinates[2][2] );
395
396 side3.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
397 coordinates[3][2] - coordinates[0][2] );
398
399 side4.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
400 coordinates[3][2] - coordinates[1][2] );
401
402 side5.set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
403 coordinates[3][2] - coordinates[2][2] );
404
405 double volume = fabs( v_tet_volume( 4, coordinates ) );
406
407 if( volume < VERDICT_DBL_MIN )
408 return (double)VERDICT_DBL_MAX;
409 else
410 {
411 double srms = sqrt( ( side0.length_squared() + side1.length_squared() + side2.length_squared() +
412 side3.length_squared() + side4.length_squared() + side5.length_squared() ) /
413 6.0 );
414
415 double aspect_ratio_gamma = pow( srms, 3 ) / ( 8.48528137423857 * volume );
416 return (double)aspect_ratio_gamma;
417 }
418 }
References VerdictVector::length_squared(), VerdictVector::set(), v_tet_volume(), VERDICT_DBL_MAX, and VERDICT_DBL_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_tet_aspect_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet aspect ratio metric.
Hmax / (2 sqrt(6) r) where Hmax and r respectively denote the greatest edge length and the inradius of the tetrahedron Reference — P. Frey and P.-L. George, Meshing, Hermes (2000).
The aspect ratio of a tet
NB (P. Pebay 01/22/07): Hmax / (2 sqrt(6) r) where Hmax and r respectively denote the greatest edge length and the inradius of the tetrahedron
Definition at line 318 of file V_TetMetric.cpp.
319 {
320 static const double normal_coeff = sqrt( 6. ) / 12.;
321
322 // Determine side vectors
323 VerdictVector ab, bc, ac, ad, bd, cd;
324
325 ab.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
326 coordinates[1][2] - coordinates[0][2] );
327
328 ac.set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
329 coordinates[2][2] - coordinates[0][2] );
330
331 ad.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
332 coordinates[3][2] - coordinates[0][2] );
333
334 double detTet = ab % ( ac * ad );
335
336 if( detTet < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX;
337
338 bc.set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
339 coordinates[2][2] - coordinates[1][2] );
340
341 bd.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
342 coordinates[3][2] - coordinates[1][2] );
343
344 cd.set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
345 coordinates[3][2] - coordinates[2][2] );
346
347 double ab2 = ab.length_squared();
348 double bc2 = bc.length_squared();
349 double ac2 = ac.length_squared();
350 double ad2 = ad.length_squared();
351 double bd2 = bd.length_squared();
352 double cd2 = cd.length_squared();
353
354 double A = ab2 > bc2 ? ab2 : bc2;
355 double B = ac2 > ad2 ? ac2 : ad2;
356 double C = bd2 > cd2 ? bd2 : cd2;
357 double D = A > B ? A : B;
358 double hm = D > C ? sqrt( D ) : sqrt( C );
359
360 bd = ab * bc;
361 A = bd.length();
362 bd = ab * ad;
363 B = bd.length();
364 bd = ac * ad;
365 C = bd.length();
366 bd = bc * cd;
367 D = bd.length();
368
369 double aspect_ratio;
370 aspect_ratio = normal_coeff * hm * ( A + B + C + D ) / fabs( detTet );
371
372 if( aspect_ratio > 0 ) return (double)VERDICT_MIN( aspect_ratio, VERDICT_DBL_MAX );
373 return (double)VERDICT_MAX( aspect_ratio, -VERDICT_DBL_MAX );
374 }
References VerdictVector::length(), VerdictVector::length_squared(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tet_quality().
C_FUNC_DEF double v_tet_collapse_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet collapse ratio metric.
Collapse ratio
The collapse ratio of a tet
Definition at line 526 of file V_TetMetric.cpp.
527 {
528 // Determine side vectors
529 VerdictVector e01, e02, e03, e12, e13, e23;
530
531 e01.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
532 coordinates[1][2] - coordinates[0][2] );
533
534 e02.set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
535 coordinates[2][2] - coordinates[0][2] );
536
537 e03.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
538 coordinates[3][2] - coordinates[0][2] );
539
540 e12.set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
541 coordinates[2][2] - coordinates[1][2] );
542
543 e13.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
544 coordinates[3][2] - coordinates[1][2] );
545
546 e23.set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
547 coordinates[3][2] - coordinates[2][2] );
548
549 double l[6];
550 l[0] = e01.length();
551 l[1] = e02.length();
552 l[2] = e03.length();
553 l[3] = e12.length();
554 l[4] = e13.length();
555 l[5] = e23.length();
556
557 // Find longest edge for each bounding triangle of tetrahedron
558 double l012 = l[4] > l[0] ? l[4] : l[0];
559 l012 = l[1] > l012 ? l[1] : l012;
560 double l031 = l[0] > l[2] ? l[0] : l[2];
561 l031 = l[3] > l031 ? l[3] : l031;
562 double l023 = l[2] > l[1] ? l[2] : l[1];
563 l023 = l[5] > l023 ? l[5] : l023;
564 double l132 = l[4] > l[3] ? l[4] : l[3];
565 l132 = l[5] > l132 ? l[5] : l132;
566
567 // Compute collapse ratio for each vertex/triangle pair
568 VerdictVector N;
569 double h, magN;
570 double cr;
571 double crMin;
572
573 N = e01 * e02;
574 magN = N.length();
575 h = ( e03 % N ) / magN; // height of vertex 3 above 0-1-2
576 crMin = h / l012; // ratio of height to longest edge of 0-1-2
577
578 N = e03 * e01;
579 magN = N.length();
580 h = ( e02 % N ) / magN; // height of vertex 2 above 0-3-1
581 cr = h / l031; // ratio of height to longest edge of 0-3-1
582 if( cr < crMin ) crMin = cr;
583
584 N = e02 * e03;
585 magN = N.length();
586 h = ( e01 % N ) / magN; // height of vertex 1 above 0-2-3
587 cr = h / l023; // ratio of height to longest edge of 0-2-3
588 if( cr < crMin ) crMin = cr;
589
590 N = e12 * e13;
591 magN = N.length();
592 h = ( e01 % N ) / magN; // height of vertex 0 above 1-3-2
593 cr = h / l132; // ratio of height to longest edge of 1-3-2
594 if( cr < crMin ) crMin = cr;
595
596 if( crMin < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX;
597 if( crMin > 0 ) return (double)VERDICT_MIN( crMin, VERDICT_DBL_MAX );
598 return (double)VERDICT_MAX( crMin, -VERDICT_DBL_MAX );
599 }
References VerdictVector::length(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tet_quality().
C_FUNC_DEF double v_tet_condition | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet condition metric.
Condition number of the Jacobian matrix at any corner. Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
the condition of a tet
condition number of the jacobian matrix at any corner
Definition at line 629 of file V_TetMetric.cpp.
630 {
631
632 double condition, term1, term2, det;
633 double rt3 = sqrt( 3.0 );
634 double rt6 = sqrt( 6.0 );
635
636 VerdictVector side0, side2, side3;
637
638 side0.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
639 coordinates[1][2] - coordinates[0][2] );
640
641 side2.set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
642 coordinates[0][2] - coordinates[2][2] );
643
644 side3.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
645 coordinates[3][2] - coordinates[0][2] );
646
647 VerdictVector c_1, c_2, c_3;
648
649 c_1 = side0;
650 c_2 = ( -2 * side2 - side0 ) / rt3;
651 c_3 = ( 3 * side3 + side2 - side0 ) / rt6;
652
653 term1 = c_1 % c_1 + c_2 % c_2 + c_3 % c_3;
654 term2 = ( c_1 * c_2 ) % ( c_1 * c_2 ) + ( c_2 * c_3 ) % ( c_2 * c_3 ) + ( c_1 * c_3 ) % ( c_1 * c_3 );
655 det = c_1 % ( c_2 * c_3 );
656
657 if( det <= VERDICT_DBL_MIN )
658 return VERDICT_DBL_MAX;
659 else
660 condition = sqrt( term1 * term2 ) / ( 3.0 * det );
661
662 return (double)condition;
663 }
References VerdictVector::set(), VERDICT_DBL_MAX, and VERDICT_DBL_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_tet_distortion | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet distortion metric.
{min(|J|)/actual volume}*parent volume, parent volume = 1/6 for tet. Reference — SDRC/IDEAS Simulation: Finite Element Modeling–User's Guide
the distortion of a tet
Definition at line 765 of file V_TetMetric.cpp.
766 {
767
768 double distortion = VERDICT_DBL_MAX;
769 int number_of_gauss_points = 0;
770 if( num_nodes == 4 )
771 // for linear tet, the distortion is always 1 because
772 // straight edge tets are the target shape for tet
773 return 1.0;
774
775 else if( num_nodes == 10 )
776 // use four integration points for quadratic tet
777 number_of_gauss_points = 4;
778
779 int number_dims = 3;
780 int total_number_of_gauss_points = number_of_gauss_points;
781 // use is_tri=1 to indicate this is for tet in 3D
782 int is_tri = 1;
783
784 double shape_function[maxTotalNumberGaussPoints][maxNumberNodes];
785 double dndy1[maxTotalNumberGaussPoints][maxNumberNodes];
786 double dndy2[maxTotalNumberGaussPoints][maxNumberNodes];
787 double dndy3[maxTotalNumberGaussPoints][maxNumberNodes];
788 double weight[maxTotalNumberGaussPoints];
789
790 // create an object of GaussIntegration for tet
791 GaussIntegration::initialize( number_of_gauss_points, num_nodes, number_dims, is_tri );
792 GaussIntegration::calculate_shape_function_3d_tet();
793 GaussIntegration::get_shape_func( shape_function[0], dndy1[0], dndy2[0], dndy3[0], weight );
794
795 // vector xxi is the derivative vector of coordinates w.r.t local xi coordinate in the
796 // computation space
797 // vector xet is the derivative vector of coordinates w.r.t local et coordinate in the
798 // computation space
799 // vector xze is the derivative vector of coordinates w.r.t local ze coordinate in the
800 // computation space
801 VerdictVector xxi, xet, xze, xin;
802
803 double jacobian, minimum_jacobian;
804 double element_volume = 0.0;
805 minimum_jacobian = VERDICT_DBL_MAX;
806
807 // calculate element volume
808 int ife, ja;
809 for( ife = 0; ife < total_number_of_gauss_points; ife++ )
810 {
811 xxi.set( 0.0, 0.0, 0.0 );
812 xet.set( 0.0, 0.0, 0.0 );
813 xze.set( 0.0, 0.0, 0.0 );
814
815 for( ja = 0; ja < num_nodes; ja++ )
816 {
817 xin.set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] );
818 xxi += dndy1[ife][ja] * xin;
819 xet += dndy2[ife][ja] * xin;
820 xze += dndy3[ife][ja] * xin;
821 }
822
823 // determinant
824 jacobian = xxi % ( xet * xze );
825 if( minimum_jacobian > jacobian ) minimum_jacobian = jacobian;
826
827 element_volume += weight[ife] * jacobian;
828 } // element_volume is 6 times the actual volume
829
830 // loop through all nodes
831 double dndy1_at_node[maxNumberNodes][maxNumberNodes];
832 double dndy2_at_node[maxNumberNodes][maxNumberNodes];
833 double dndy3_at_node[maxNumberNodes][maxNumberNodes];
834
835 GaussIntegration::calculate_derivative_at_nodes_3d_tet( dndy1_at_node, dndy2_at_node, dndy3_at_node );
836 int node_id;
837 for( node_id = 0; node_id < num_nodes; node_id++ )
838 {
839 xxi.set( 0.0, 0.0, 0.0 );
840 xet.set( 0.0, 0.0, 0.0 );
841 xze.set( 0.0, 0.0, 0.0 );
842
843 for( ja = 0; ja < num_nodes; ja++ )
844 {
845 xin.set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] );
846 xxi += dndy1_at_node[node_id][ja] * xin;
847 xet += dndy2_at_node[node_id][ja] * xin;
848 xze += dndy3_at_node[node_id][ja] * xin;
849 }
850
851 jacobian = xxi % ( xet * xze );
852 if( minimum_jacobian > jacobian ) minimum_jacobian = jacobian;
853 }
854 distortion = minimum_jacobian / element_volume;
855
856 return (double)distortion;
857 }
References GaussIntegration::calculate_derivative_at_nodes_3d_tet(), GaussIntegration::calculate_shape_function_3d_tet(), GaussIntegration::get_shape_func(), GaussIntegration::initialize(), maxNumberNodes, maxTotalNumberGaussPoints, VerdictVector::set(), and VERDICT_DBL_MAX.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tet_quality().
C_FUNC_DEF double v_tet_edge_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet edge ratio metric.
Hmax / Hmin where Hmax and Hmin are respectively the maximum and the minimum edge lengths
the edge ratio of a tet
NB (P. Pebay 01/22/07): Hmax / Hmin where Hmax and Hmin are respectively the maximum and the minimum edge lengths
Definition at line 71 of file V_TetMetric.cpp.
72 {
73 VerdictVector a, b, c, d, e, f;
74
75 a.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
76 coordinates[1][2] - coordinates[0][2] );
77
78 b.set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
79 coordinates[2][2] - coordinates[1][2] );
80
81 c.set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
82 coordinates[0][2] - coordinates[2][2] );
83
84 d.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
85 coordinates[3][2] - coordinates[0][2] );
86
87 e.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
88 coordinates[3][2] - coordinates[1][2] );
89
90 f.set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
91 coordinates[3][2] - coordinates[2][2] );
92
93 double a2 = a.length_squared();
94 double b2 = b.length_squared();
95 double c2 = c.length_squared();
96 double d2 = d.length_squared();
97 double e2 = e.length_squared();
98 double f2 = f.length_squared();
99
100 double m2, M2, mab, mcd, mef, Mab, Mcd, Mef;
101
102 if( a2 < b2 )
103 {
104 mab = a2;
105 Mab = b2;
106 }
107 else // b2 <= a2
108 {
109 mab = b2;
110 Mab = a2;
111 }
112 if( c2 < d2 )
113 {
114 mcd = c2;
115 Mcd = d2;
116 }
117 else // d2 <= c2
118 {
119 mcd = d2;
120 Mcd = c2;
121 }
122 if( e2 < f2 )
123 {
124 mef = e2;
125 Mef = f2;
126 }
127 else // f2 <= e2
128 {
129 mef = f2;
130 Mef = e2;
131 }
132
133 m2 = mab < mcd ? mab : mcd;
134 m2 = m2 < mef ? m2 : mef;
135
136 if( m2 < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX;
137
138 M2 = Mab > Mcd ? Mab : Mcd;
139 M2 = M2 > Mef ? M2 : Mef;
140
141 double edge_ratio = sqrt( M2 / m2 );
142
143 if( edge_ratio > 0 ) return (double)VERDICT_MIN( edge_ratio, VERDICT_DBL_MAX );
144 return (double)VERDICT_MAX( edge_ratio, -VERDICT_DBL_MAX );
145 }
References VerdictVector::length_squared(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_tet_jacobian | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet jacobian.
Minimum pointwise volume at any corner. Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
the jacobian of a tet
TODO
Definition at line 670 of file V_TetMetric.cpp.
671 {
672 VerdictVector side0, side2, side3;
673
674 side0.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
675 coordinates[1][2] - coordinates[0][2] );
676
677 side2.set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
678 coordinates[0][2] - coordinates[2][2] );
679
680 side3.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
681 coordinates[3][2] - coordinates[0][2] );
682
683 return (double)( side3 % ( side2 * side0 ) );
684 }
References VerdictVector::set().
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_tet_minimum_angle | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet minimum dihedral angle.
Minimum (nonoriented) dihedral angle of a tetrahedron, expressed in degrees.
The minimum angle of a tet
NB (P. Pebay 01/22/07): minimum nonoriented dihedral angle
Definition at line 475 of file V_TetMetric.cpp.
476 {
477 static const double normal_coeff = 180. * .3183098861837906715377675267450287;
478
479 // Determine side vectors
480 VerdictVector ab, bc, ad, cd;
481
482 ab.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
483 coordinates[1][2] - coordinates[0][2] );
484
485 ad.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
486 coordinates[3][2] - coordinates[0][2] );
487
488 bc.set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
489 coordinates[2][2] - coordinates[1][2] );
490
491 cd.set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
492 coordinates[3][2] - coordinates[2][2] );
493
494 VerdictVector abc = ab * bc;
495 double nabc = abc.length();
496 VerdictVector abd = ab * ad;
497 double nabd = abd.length();
498 VerdictVector acd = ad * cd;
499 double nacd = acd.length();
500 VerdictVector bcd = bc * cd;
501 double nbcd = bcd.length();
502
503 double alpha = acos( ( abc % abd ) / ( nabc * nabd ) );
504 double beta = acos( ( abc % acd ) / ( nabc * nacd ) );
505 double gamma = acos( ( abc % bcd ) / ( nabc * nbcd ) );
506 double delta = acos( ( abd % acd ) / ( nabd * nacd ) );
507 double epsilon = acos( ( abd % bcd ) / ( nabd * nbcd ) );
508 double zeta = acos( ( acd % bcd ) / ( nacd * nbcd ) );
509
510 alpha = alpha < beta ? alpha : beta;
511 alpha = alpha < gamma ? alpha : gamma;
512 alpha = alpha < delta ? alpha : delta;
513 alpha = alpha < epsilon ? alpha : epsilon;
514 alpha = alpha < zeta ? alpha : zeta;
515 alpha *= normal_coeff;
516
517 if( alpha < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX;
518
519 if( alpha > 0 ) return (double)VERDICT_MIN( alpha, VERDICT_DBL_MAX );
520 return (double)VERDICT_MAX( alpha, -VERDICT_DBL_MAX );
521 }
References VerdictVector::length(), VerdictVector::set(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tet_quality().
C_FUNC_DEF void v_tet_quality | ( | int | num_nodes, |
double | coordinates[][3], | ||
unsigned int | metrics_request_flag, | ||
TetMetricVals * | metric_vals | ||
) |
Calculates quality metrics for tetrahedral elements.
the quality metrics of a tet
Definition at line 862 of file V_TetMetric.cpp.
866 {
867
868 memset( metric_vals, 0, sizeof( TetMetricVals ) );
869
870 /*
871
872 node numbers and edge numbers below
873
874
875
876 3
877 + edge 0 is node 0 to 1
878 +|+ edge 1 is node 1 to 2
879 3/ | \5 edge 2 is node 0 to 2
880 / 4| \ edge 3 is node 0 to 3
881 0 - -|- + 2 edge 4 is node 1 to 3
882 \ | + edge 5 is node 2 to 3
883 0\ | /1
884 +|/ edge 2 is behind edge 4
885 1
886
887
888 */
889
890 // lets start with making the vectors
891 VerdictVector edges[6];
892 edges[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
893 coordinates[1][2] - coordinates[0][2] );
894
895 edges[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
896 coordinates[2][2] - coordinates[1][2] );
897
898 edges[2].set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
899 coordinates[0][2] - coordinates[2][2] );
900
901 edges[3].set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
902 coordinates[3][2] - coordinates[0][2] );
903
904 edges[4].set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
905 coordinates[3][2] - coordinates[1][2] );
906
907 edges[5].set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
908 coordinates[3][2] - coordinates[2][2] );
909
910 // common numbers
911 static const double root_of_2 = sqrt( 2.0 );
912
913 // calculate the jacobian
914 static const int do_jacobian = V_TET_JACOBIAN | V_TET_VOLUME | V_TET_ASPECT_BETA | V_TET_ASPECT_GAMMA |
915 V_TET_SHAPE | V_TET_RELATIVE_SIZE_SQUARED | V_TET_SHAPE_AND_SIZE |
916 V_TET_SCALED_JACOBIAN | V_TET_CONDITION;
917 if( metrics_request_flag & do_jacobian )
918 {
919 metric_vals->jacobian = (double)( edges[3] % ( edges[2] * edges[0] ) );
920 }
921
922 // calculate the volume
923 if( metrics_request_flag & V_TET_VOLUME )
924 {
925 metric_vals->volume = (double)( metric_vals->jacobian / 6.0 );
926 }
927
928 // calculate aspect ratio
929 if( metrics_request_flag & V_TET_ASPECT_BETA )
930 {
931 double surface_area = ( ( edges[2] * edges[0] ).length() + ( edges[3] * edges[0] ).length() +
932 ( edges[4] * edges[1] ).length() + ( edges[3] * edges[2] ).length() ) *
933 0.5;
934
935 VerdictVector numerator = edges[3].length_squared() * ( edges[2] * edges[0] ) +
936 edges[2].length_squared() * ( edges[3] * edges[0] ) +
937 edges[0].length_squared() * ( edges[3] * edges[2] );
938
939 double volume = metric_vals->jacobian / 6.0;
940
941 if( volume < VERDICT_DBL_MIN )
942 metric_vals->aspect_beta = (double)( VERDICT_DBL_MAX );
943 else
944 metric_vals->aspect_beta = (double)( numerator.length() * surface_area / ( 108 * volume * volume ) );
945 }
946
947 // calculate the aspect gamma
948 if( metrics_request_flag & V_TET_ASPECT_GAMMA )
949 {
950 double volume = fabs( metric_vals->jacobian / 6.0 );
951 if( fabs( volume ) < VERDICT_DBL_MIN )
952 metric_vals->aspect_gamma = VERDICT_DBL_MAX;
953 else
954 {
955 double srms = sqrt( ( edges[0].length_squared() + edges[1].length_squared() + edges[2].length_squared() +
956 edges[3].length_squared() + edges[4].length_squared() + edges[5].length_squared() ) /
957 6.0 );
958
959 // cube the srms
960 srms *= ( srms * srms );
961 metric_vals->aspect_gamma = (double)( srms / ( 8.48528137423857 * volume ) );
962 }
963 }
964
965 // calculate the shape of the tet
966 if( metrics_request_flag & ( V_TET_SHAPE | V_TET_SHAPE_AND_SIZE ) )
967 {
968 // if the jacobian is non-positive, the shape is 0
969 if( metric_vals->jacobian < VERDICT_DBL_MIN )
970 {
971 metric_vals->shape = (double)0.0;
972 }
973 else
974 {
975 static const double two_thirds = 2.0 / 3.0;
976 double num = 3.0 * pow( root_of_2 * metric_vals->jacobian, two_thirds );
977 double den = 1.5 * ( edges[0] % edges[0] + edges[2] % edges[2] + edges[3] % edges[3] ) -
978 ( edges[0] % -edges[2] + -edges[2] % edges[3] + edges[3] % edges[0] );
979
980 if( den < VERDICT_DBL_MIN )
981 metric_vals->shape = (double)0.0;
982 else
983 metric_vals->shape = (double)VERDICT_MAX( num / den, 0 );
984 }
985 }
986
987 // calculate the relative size of the tet
988 if( metrics_request_flag & ( V_TET_RELATIVE_SIZE_SQUARED | V_TET_SHAPE_AND_SIZE ) )
989 {
990 VerdictVector w1, w2, w3;
991 get_weight( w1, w2, w3 );
992 double avg_vol = ( w1 % ( w2 * w3 ) ) / 6;
993
994 if( avg_vol < VERDICT_DBL_MIN )
995 metric_vals->relative_size_squared = 0.0;
996 else
997 {
998 double tmp = metric_vals->jacobian / ( 6 * avg_vol );
999 if( tmp < VERDICT_DBL_MIN )
1000 metric_vals->relative_size_squared = 0.0;
1001 else
1002 {
1003 tmp *= tmp;
1004 metric_vals->relative_size_squared = (double)VERDICT_MIN( tmp, 1 / tmp );
1005 }
1006 }
1007 }
1008
1009 // calculate the shape and size
1010 if( metrics_request_flag & V_TET_SHAPE_AND_SIZE )
1011 {
1012 metric_vals->shape_and_size = (double)( metric_vals->shape * metric_vals->relative_size_squared );
1013 }
1014
1015 // calculate the scaled jacobian
1016 if( metrics_request_flag & V_TET_SCALED_JACOBIAN )
1017 {
1018 // find out which node the normalized jacobian can be calculated at
1019 // and it will be the smaller than at other nodes
1020 double length_squared[4] = { edges[0].length_squared() * edges[2].length_squared() * edges[3].length_squared(),
1021 edges[0].length_squared() * edges[1].length_squared() * edges[4].length_squared(),
1022 edges[1].length_squared() * edges[2].length_squared() * edges[5].length_squared(),
1023 edges[3].length_squared() * edges[4].length_squared() *
1024 edges[5].length_squared() };
1025
1026 int which_node = 0;
1027 if( length_squared[1] > length_squared[which_node] ) which_node = 1;
1028 if( length_squared[2] > length_squared[which_node] ) which_node = 2;
1029 if( length_squared[3] > length_squared[which_node] ) which_node = 3;
1030
1031 // find the scaled jacobian at this node
1032 double length_product = sqrt( length_squared[which_node] );
1033 if( length_product < fabs( metric_vals->jacobian ) ) length_product = fabs( metric_vals->jacobian );
1034
1035 if( length_product < VERDICT_DBL_MIN )
1036 metric_vals->scaled_jacobian = (double)VERDICT_DBL_MAX;
1037 else
1038 metric_vals->scaled_jacobian = (double)( root_of_2 * metric_vals->jacobian / length_product );
1039 }
1040
1041 // calculate the condition number
1042 if( metrics_request_flag & V_TET_CONDITION )
1043 {
1044 static const double root_of_3 = sqrt( 3.0 );
1045 static const double root_of_6 = sqrt( 6.0 );
1046
1047 VerdictVector c_1, c_2, c_3;
1048 c_1 = edges[0];
1049 c_2 = ( -2 * edges[2] - edges[0] ) / root_of_3;
1050 c_3 = ( 3 * edges[3] + edges[2] - edges[0] ) / root_of_6;
1051
1052 double term1 = c_1 % c_1 + c_2 % c_2 + c_3 % c_3;
1053 double term2 = ( c_1 * c_2 ) % ( c_1 * c_2 ) + ( c_2 * c_3 ) % ( c_2 * c_3 ) + ( c_3 * c_1 ) % ( c_3 * c_1 );
1054
1055 double det = c_1 % ( c_2 * c_3 );
1056
1057 if( det <= VERDICT_DBL_MIN )
1058 metric_vals->condition = (double)VERDICT_DBL_MAX;
1059 else
1060 metric_vals->condition = (double)( sqrt( term1 * term2 ) / ( 3.0 * det ) );
1061 }
1062
1063 // calculate the distortion
1064 if( metrics_request_flag & V_TET_DISTORTION )
1065 {
1066 metric_vals->distortion = v_tet_distortion( num_nodes, coordinates );
1067 }
1068
1069 // check for overflow
1070 if( metrics_request_flag & V_TET_ASPECT_BETA )
1071 {
1072 if( metric_vals->aspect_beta > 0 )
1073 metric_vals->aspect_beta = (double)VERDICT_MIN( metric_vals->aspect_beta, VERDICT_DBL_MAX );
1074 metric_vals->aspect_beta = (double)VERDICT_MAX( metric_vals->aspect_beta, -VERDICT_DBL_MAX );
1075 }
1076
1077 if( metrics_request_flag & V_TET_ASPECT_GAMMA )
1078 {
1079 if( metric_vals->aspect_gamma > 0 )
1080 metric_vals->aspect_gamma = (double)VERDICT_MIN( metric_vals->aspect_gamma, VERDICT_DBL_MAX );
1081 metric_vals->aspect_gamma = (double)VERDICT_MAX( metric_vals->aspect_gamma, -VERDICT_DBL_MAX );
1082 }
1083
1084 if( metrics_request_flag & V_TET_VOLUME )
1085 {
1086 if( metric_vals->volume > 0 ) metric_vals->volume = (double)VERDICT_MIN( metric_vals->volume, VERDICT_DBL_MAX );
1087 metric_vals->volume = (double)VERDICT_MAX( metric_vals->volume, -VERDICT_DBL_MAX );
1088 }
1089
1090 if( metrics_request_flag & V_TET_CONDITION )
1091 {
1092 if( metric_vals->condition > 0 )
1093 metric_vals->condition = (double)VERDICT_MIN( metric_vals->condition, VERDICT_DBL_MAX );
1094 metric_vals->condition = (double)VERDICT_MAX( metric_vals->condition, -VERDICT_DBL_MAX );
1095 }
1096
1097 if( metrics_request_flag & V_TET_JACOBIAN )
1098 {
1099 if( metric_vals->jacobian > 0 )
1100 metric_vals->jacobian = (double)VERDICT_MIN( metric_vals->jacobian, VERDICT_DBL_MAX );
1101 metric_vals->jacobian = (double)VERDICT_MAX( metric_vals->jacobian, -VERDICT_DBL_MAX );
1102 }
1103
1104 if( metrics_request_flag & V_TET_SCALED_JACOBIAN )
1105 {
1106 if( metric_vals->scaled_jacobian > 0 )
1107 metric_vals->scaled_jacobian = (double)VERDICT_MIN( metric_vals->scaled_jacobian, VERDICT_DBL_MAX );
1108 metric_vals->scaled_jacobian = (double)VERDICT_MAX( metric_vals->scaled_jacobian, -VERDICT_DBL_MAX );
1109 }
1110
1111 if( metrics_request_flag & V_TET_SHAPE )
1112 {
1113 if( metric_vals->shape > 0 ) metric_vals->shape = (double)VERDICT_MIN( metric_vals->shape, VERDICT_DBL_MAX );
1114 metric_vals->shape = (double)VERDICT_MAX( metric_vals->shape, -VERDICT_DBL_MAX );
1115 }
1116
1117 if( metrics_request_flag & V_TET_RELATIVE_SIZE_SQUARED )
1118 {
1119 if( metric_vals->relative_size_squared > 0 )
1120 metric_vals->relative_size_squared =
1121 (double)VERDICT_MIN( metric_vals->relative_size_squared, VERDICT_DBL_MAX );
1122 metric_vals->relative_size_squared =
1123 (double)VERDICT_MAX( metric_vals->relative_size_squared, -VERDICT_DBL_MAX );
1124 }
1125
1126 if( metrics_request_flag & V_TET_SHAPE_AND_SIZE )
1127 {
1128 if( metric_vals->shape_and_size > 0 )
1129 metric_vals->shape_and_size = (double)VERDICT_MIN( metric_vals->shape_and_size, VERDICT_DBL_MAX );
1130 metric_vals->shape_and_size = (double)VERDICT_MAX( metric_vals->shape_and_size, -VERDICT_DBL_MAX );
1131 }
1132
1133 if( metrics_request_flag & V_TET_DISTORTION )
1134 {
1135 if( metric_vals->distortion > 0 )
1136 metric_vals->distortion = (double)VERDICT_MIN( metric_vals->distortion, VERDICT_DBL_MAX );
1137 metric_vals->distortion = (double)VERDICT_MAX( metric_vals->distortion, -VERDICT_DBL_MAX );
1138 }
1139
1140 if( metrics_request_flag & V_TET_ASPECT_RATIO ) metric_vals->aspect_ratio = v_tet_aspect_ratio( 4, coordinates );
1141
1142 if( metrics_request_flag & V_TET_ASPECT_FROBENIUS )
1143 metric_vals->aspect_frobenius = v_tet_aspect_frobenius( 4, coordinates );
1144
1145 if( metrics_request_flag & V_TET_MINIMUM_ANGLE ) metric_vals->minimum_angle = v_tet_minimum_angle( 4, coordinates );
1146
1147 if( metrics_request_flag & V_TET_COLLAPSE_RATIO )
1148 metric_vals->collapse_ratio = v_tet_collapse_ratio( 4, coordinates );
1149
1150 if( metrics_request_flag & V_TET_RADIUS_RATIO ) metric_vals->radius_ratio = v_tet_radius_ratio( 4, coordinates );
1151 }
References TetMetricVals::aspect_beta, TetMetricVals::aspect_frobenius, TetMetricVals::aspect_gamma, TetMetricVals::aspect_ratio, TetMetricVals::collapse_ratio, TetMetricVals::condition, TetMetricVals::distortion, get_weight(), TetMetricVals::jacobian, VerdictVector::length(), length(), VerdictVector::length_squared(), length_squared(), TetMetricVals::minimum_angle, TetMetricVals::radius_ratio, TetMetricVals::relative_size_squared, TetMetricVals::scaled_jacobian, VerdictVector::set(), TetMetricVals::shape, TetMetricVals::shape_and_size, V_TET_ASPECT_BETA, V_TET_ASPECT_FROBENIUS, v_tet_aspect_frobenius(), V_TET_ASPECT_GAMMA, V_TET_ASPECT_RATIO, v_tet_aspect_ratio(), V_TET_COLLAPSE_RATIO, v_tet_collapse_ratio(), V_TET_CONDITION, V_TET_DISTORTION, v_tet_distortion(), V_TET_JACOBIAN, V_TET_MINIMUM_ANGLE, v_tet_minimum_angle(), V_TET_RADIUS_RATIO, v_tet_radius_ratio(), V_TET_RELATIVE_SIZE_SQUARED, V_TET_SCALED_JACOBIAN, V_TET_SHAPE, V_TET_SHAPE_AND_SIZE, V_TET_VOLUME, VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, VERDICT_MIN, and TetMetricVals::volume.
Referenced by moab::VerdictWrapper::all_quality_measures().
C_FUNC_DEF double v_tet_radius_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet radius ratio metric.
CR / (3.0 * IR) where CR = circumsphere radius, IR = inscribed sphere radius. Reference — V. N. Parthasarathy et al, A comparison of tetrahedron quality measures, Finite Elem. Anal. Des., Vol 15(1993), 255-261.
The radius ratio of a tet
NB (P. Pebay 04/16/07): CR / (3.0 * IR) where CR is the circumsphere radius and IR is the inscribed sphere radius. Note that this metric is similar to the aspect beta of a tet, except that it does not return VERDICT_DBL_MAX if the element has negative orientation.
Definition at line 209 of file V_TetMetric.cpp.
210 {
211
212 // Determine side vectors
213 VerdictVector side[6];
214
215 side[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
216 coordinates[1][2] - coordinates[0][2] );
217
218 side[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
219 coordinates[2][2] - coordinates[1][2] );
220
221 side[2].set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
222 coordinates[0][2] - coordinates[2][2] );
223
224 side[3].set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
225 coordinates[3][2] - coordinates[0][2] );
226
227 side[4].set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
228 coordinates[3][2] - coordinates[1][2] );
229
230 side[5].set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
231 coordinates[3][2] - coordinates[2][2] );
232
233 VerdictVector numerator = side[3].length_squared() * ( side[2] * side[0] ) +
234 side[2].length_squared() * ( side[3] * side[0] ) +
235 side[0].length_squared() * ( side[3] * side[2] );
236
237 double area_sum;
238 area_sum = ( ( side[2] * side[0] ).length() + ( side[3] * side[0] ).length() + ( side[4] * side[1] ).length() +
239 ( side[3] * side[2] ).length() ) *
240 0.5;
241
242 double volume = v_tet_volume( 4, coordinates );
243
244 if( fabs( volume ) < VERDICT_DBL_MIN )
245 return (double)VERDICT_DBL_MAX;
246 else
247 {
248 double radius_ratio;
249 radius_ratio = numerator.length() * area_sum / ( 108 * volume * volume );
250
251 return (double)VERDICT_MIN( radius_ratio, VERDICT_DBL_MAX );
252 }
253 }
References VerdictVector::length(), length(), VerdictVector::length_squared(), length_squared(), VerdictVector::set(), v_tet_volume(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tet_quality().
C_FUNC_DEF double v_tet_relative_size_squared | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet relative size metric.
Min( J, 1/J ), where J is determinant of weighted Jacobian matrix. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
the relative size of a tet
Min(J,1/J), where J is the determinant of the weighted Jacobian matrix
Definition at line 727 of file V_TetMetric.cpp.
728 {
729 double size;
730 VerdictVector w1, w2, w3;
731 get_weight( w1, w2, w3 );
732 double avg_volume = ( w1 % ( w2 * w3 ) ) / 6.0;
733
734 double volume = v_tet_volume( 4, coordinates );
735
736 if( avg_volume < VERDICT_DBL_MIN )
737 return 0.0;
738 else
739 {
740 size = volume / avg_volume;
741 if( size <= VERDICT_DBL_MIN ) return 0.0;
742 if( size > 1 ) size = (double)( 1 ) / size;
743 }
744 return (double)( size * size );
745 }
References get_weight(), size, v_tet_volume(), and VERDICT_DBL_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tet_shape_and_size().
C_FUNC_DEF double v_tet_scaled_jacobian | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet scaled jacobian.
Minimum Jacobian divided by the lengths of 3 edge vectors Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
the scaled jacobian of a tet
minimum of the jacobian divided by the lengths of 3 edge vectors
Definition at line 153 of file V_TetMetric.cpp.
154 {
155
156 VerdictVector side0, side1, side2, side3, side4, side5;
157
158 side0.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
159 coordinates[1][2] - coordinates[0][2] );
160
161 side1.set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
162 coordinates[2][2] - coordinates[1][2] );
163
164 side2.set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
165 coordinates[0][2] - coordinates[2][2] );
166
167 side3.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
168 coordinates[3][2] - coordinates[0][2] );
169
170 side4.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
171 coordinates[3][2] - coordinates[1][2] );
172
173 side5.set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
174 coordinates[3][2] - coordinates[2][2] );
175
176 double jacobi;
177
178 jacobi = side3 % ( side2 * side0 );
179
180 // products of lengths squared of each edge attached to a node.
181 double length_squared[4] = { side0.length_squared() * side2.length_squared() * side3.length_squared(),
182 side0.length_squared() * side1.length_squared() * side4.length_squared(),
183 side1.length_squared() * side2.length_squared() * side5.length_squared(),
184 side3.length_squared() * side4.length_squared() * side5.length_squared() };
185 int which_node = 0;
186 if( length_squared[1] > length_squared[which_node] ) which_node = 1;
187 if( length_squared[2] > length_squared[which_node] ) which_node = 2;
188 if( length_squared[3] > length_squared[which_node] ) which_node = 3;
189
190 double length_product = sqrt( length_squared[which_node] );
191 if( length_product < fabs( jacobi ) ) length_product = fabs( jacobi );
192
193 if( length_product < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX;
194
195 static const double root_of_2 = sqrt( 2.0 );
196
197 return (double)( root_of_2 * jacobi / length_product );
198 }
References VerdictVector::length_squared(), length_squared(), VerdictVector::set(), VERDICT_DBL_MAX, and VERDICT_DBL_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_tet_shape | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet shape metric.
3/Mean Ratio of weighted Jacobian matrix. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
the shape of a tet
3/ condition number of weighted jacobian matrix
Definition at line 691 of file V_TetMetric.cpp.
692 {
693
694 static const double two_thirds = 2.0 / 3.0;
695 static const double root_of_2 = sqrt( 2.0 );
696
697 VerdictVector edge0, edge2, edge3;
698
699 edge0.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
700 coordinates[1][2] - coordinates[0][2] );
701
702 edge2.set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
703 coordinates[0][2] - coordinates[2][2] );
704
705 edge3.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
706 coordinates[3][2] - coordinates[0][2] );
707
708 double jacobian = edge3 % ( edge2 * edge0 );
709 if( jacobian < VERDICT_DBL_MIN )
710 {
711 return (double)0.0;
712 }
713 double num = 3 * pow( root_of_2 * jacobian, two_thirds );
714 double den =
715 1.5 * ( edge0 % edge0 + edge2 % edge2 + edge3 % edge3 ) - ( edge0 % -edge2 + -edge2 % edge3 + edge3 % edge0 );
716
717 if( den < VERDICT_DBL_MIN ) return (double)0.0;
718
719 return (double)VERDICT_MAX( num / den, 0 );
720 }
References VerdictVector::set(), VERDICT_DBL_MIN, and VERDICT_MAX.
Referenced by moab::VerdictWrapper::quality_measure(), and v_tet_shape_and_size().
C_FUNC_DEF double v_tet_shape_and_size | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet shape-size metric.
Product of Shape and Relative Size. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
the shape and size of a tet
Product of the shape and relative size
Definition at line 752 of file V_TetMetric.cpp.
753 {
754
755 double shape, size;
756 shape = v_tet_shape( num_nodes, coordinates );
757 size = v_tet_relative_size_squared( num_nodes, coordinates );
758
759 return (double)( shape * size );
760 }
References size, v_tet_relative_size_squared(), and v_tet_shape().
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_tet_volume | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tet volume.
(1/6) * Jacobian at corner node. Reference — V. N. Parthasarathy et al, A comparison of tetrahedron quality measures, Finite Elem. Anal. Des., Vol 15(1993), 255-261.
the volume of a tet
1/6 * jacobian at a corner node
Definition at line 606 of file V_TetMetric.cpp.
607 {
608
609 // Determine side vectors
610 VerdictVector side0, side2, side3;
611
612 side0.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
613 coordinates[1][2] - coordinates[0][2] );
614
615 side2.set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
616 coordinates[0][2] - coordinates[2][2] );
617
618 side3.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
619 coordinates[3][2] - coordinates[0][2] );
620
621 return (double)( ( side3 % ( side2 * side0 ) ) / 6.0 );
622 }
References VerdictVector::set().
Referenced by moab::VerdictWrapper::quality_measure(), v_tet_aspect_beta(), v_tet_aspect_gamma(), v_tet_radius_ratio(), and v_tet_relative_size_squared().
C_FUNC_DEF double v_tri_area | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
Maximum included angle in triangle
The area of a tri
0.5 * jacobian at a node
Definition at line 278 of file V_TriMetric.cpp.
279 {
280 // two vectors for two sides
281 VerdictVector side1( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
282 coordinates[1][2] - coordinates[0][2] );
283
284 VerdictVector side3( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
285 coordinates[2][2] - coordinates[0][2] );
286
287 // the cross product of the two vectors representing two sides of the
288 // triangle
289 VerdictVector tmp = side1 * side3;
290
291 // return the magnitude of the vector divided by two
292 double area = 0.5 * tmp.length();
293 if( area > 0 ) return (double)VERDICT_MIN( area, VERDICT_DBL_MAX );
294 return (double)VERDICT_MAX( area, -VERDICT_DBL_MAX );
295 }
References VerdictVector::length(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), v_quad_jacobian(), and v_quad_quality().
C_FUNC_DEF double v_tri_aspect_frobenius | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
Frobenius aspect
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.
247 {
248 static const double two_times_root_of_3 = 2 * sqrt( 3.0 );
249
250 // three vectors for each side
251 VerdictVector side1( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
252 coordinates[1][2] - coordinates[0][2] );
253
254 VerdictVector side2( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
255 coordinates[2][2] - coordinates[1][2] );
256
257 VerdictVector side3( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
258 coordinates[0][2] - coordinates[2][2] );
259
260 // sum the lengths squared of each side
261 double srms = ( side1.length_squared() + side2.length_squared() + side3.length_squared() );
262
263 // find two times the area of the triangle by cross product
264 double areaX2 = ( ( side1 * ( -side3 ) ).length() );
265
266 if( areaX2 == 0.0 ) return (double)VERDICT_DBL_MAX;
267
268 double aspect = (double)( srms / ( two_times_root_of_3 * ( areaX2 ) ) );
269 if( aspect > 0 ) return (double)VERDICT_MIN( aspect, VERDICT_DBL_MAX );
270 return (double)VERDICT_MAX( aspect, -VERDICT_DBL_MAX );
271 }
References VerdictVector::length_squared(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_tri_aspect_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
aspect ratio Reference — P. P. Pebay & T. J. Baker, Analysis of Triangle Quality Measures, AMS Math. Comp., 2003, 72(244):1817-1839
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.
161 {
162 static const double normal_coeff = sqrt( 3. ) / 6.;
163
164 // three vectors for each side
165 VerdictVector a( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
166 coordinates[1][2] - coordinates[0][2] );
167
168 VerdictVector b( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
169 coordinates[2][2] - coordinates[1][2] );
170
171 VerdictVector c( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
172 coordinates[0][2] - coordinates[2][2] );
173
174 double a1 = a.length();
175 double b1 = b.length();
176 double c1 = c.length();
177
178 double hm = a1 > b1 ? a1 : b1;
179 hm = hm > c1 ? hm : c1;
180
181 VerdictVector ab = a * b;
182 double denominator = ab.length();
183
184 if( denominator < VERDICT_DBL_MIN )
185 return (double)VERDICT_DBL_MAX;
186 else
187 {
188 double aspect_ratio;
189 aspect_ratio = normal_coeff * hm * ( a1 + b1 + c1 ) / denominator;
190
191 if( aspect_ratio > 0 ) return (double)VERDICT_MIN( aspect_ratio, VERDICT_DBL_MAX );
192 return (double)VERDICT_MAX( aspect_ratio, -VERDICT_DBL_MAX );
193 }
194 }
References VerdictVector::length(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF double v_tri_condition | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
Condition number of the Jacobian matrix. Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
The condition of a tri
Condition number of the jacobian matrix at any corner
Definition at line 421 of file V_TriMetric.cpp.
422 {
423 static const double rt3 = sqrt( 3.0 );
424
425 VerdictVector v1( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
426 coordinates[1][2] - coordinates[0][2] );
427
428 VerdictVector v2( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
429 coordinates[2][2] - coordinates[0][2] );
430
431 VerdictVector tri_normal = v1 * v2;
432 double areax2 = tri_normal.length();
433
434 if( areax2 == 0.0 ) return (double)VERDICT_DBL_MAX;
435
436 double condition = (double)( ( ( v1 % v1 ) + ( v2 % v2 ) - ( v1 % v2 ) ) / ( areax2 * rt3 ) );
437
438 // check for inverted if we have access to the normal
439 if( compute_normal )
440 {
441 // center of tri
442 double point[3], surf_normal[3];
443 point[0] = ( coordinates[0][0] + coordinates[1][0] + coordinates[2][0] ) / 3;
444 point[1] = ( coordinates[0][1] + coordinates[1][1] + coordinates[2][1] ) / 3;
445 point[2] = ( coordinates[0][2] + coordinates[1][2] + coordinates[2][2] ) / 3;
446
447 // dot product
448 compute_normal( point, surf_normal );
449 if( ( tri_normal.x() * surf_normal[0] + tri_normal.y() * surf_normal[1] + tri_normal.z() * surf_normal[2] ) <
450 0 )
451 return (double)VERDICT_DBL_MAX;
452 }
453 return (double)VERDICT_MIN( condition, VERDICT_DBL_MAX );
454 }
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().
C_FUNC_DEF double v_tri_distortion | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
{min(|J|)/actual area}*parent area, parent area = 1/2 for triangular element. Reference — SDRC/IDEAS Simulation: Finite Element Modeling–User's Guide
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.
589 {
590
591 double distortion;
592 int total_number_of_gauss_points = 0;
593 VerdictVector aa, bb, cc, normal_at_point, xin;
594 double element_area = 0.;
595
596 aa.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
597 coordinates[1][2] - coordinates[0][2] );
598
599 bb.set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
600 coordinates[2][2] - coordinates[0][2] );
601
602 VerdictVector tri_normal = aa * bb;
603
604 int number_of_gauss_points = 0;
605 if( num_nodes == 3 )
606 {
607 distortion = 1.0;
608 return (double)distortion;
609 }
610
611 else if( num_nodes == 6 )
612 {
613 total_number_of_gauss_points = 6;
614 number_of_gauss_points = 6;
615 }
616
617 distortion = VERDICT_DBL_MAX;
618 double shape_function[maxTotalNumberGaussPoints][maxNumberNodes];
619 double dndy1[maxTotalNumberGaussPoints][maxNumberNodes];
620 double dndy2[maxTotalNumberGaussPoints][maxNumberNodes];
621 double weight[maxTotalNumberGaussPoints];
622
623 // create an object of GaussIntegration
624 int number_dims = 2;
625 int is_tri = 1;
626 GaussIntegration::initialize( number_of_gauss_points, num_nodes, number_dims, is_tri );
627 GaussIntegration::calculate_shape_function_2d_tri();
628 GaussIntegration::get_shape_func( shape_function[0], dndy1[0], dndy2[0], weight );
629
630 // calculate element area
631 int ife, ja;
632 for( ife = 0; ife < total_number_of_gauss_points; ife++ )
633 {
634 aa.set( 0.0, 0.0, 0.0 );
635 bb.set( 0.0, 0.0, 0.0 );
636
637 for( ja = 0; ja < num_nodes; ja++ )
638 {
639 xin.set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] );
640 aa += dndy1[ife][ja] * xin;
641 bb += dndy2[ife][ja] * xin;
642 }
643 normal_at_point = aa * bb;
644 double jacobian = normal_at_point.length();
645 element_area += weight[ife] * jacobian;
646 }
647
648 element_area *= 0.8660254;
649 double dndy1_at_node[maxNumberNodes][maxNumberNodes];
650 double dndy2_at_node[maxNumberNodes][maxNumberNodes];
651
652 GaussIntegration::calculate_derivative_at_nodes_2d_tri( dndy1_at_node, dndy2_at_node );
653
654 VerdictVector normal_at_nodes[7];
655
656 // evaluate normal at nodes and distortion values at nodes
657 int jai = 0;
658 for( ja = 0; ja < num_nodes; ja++ )
659 {
660 aa.set( 0.0, 0.0, 0.0 );
661 bb.set( 0.0, 0.0, 0.0 );
662 for( jai = 0; jai < num_nodes; jai++ )
663 {
664 xin.set( coordinates[jai][0], coordinates[jai][1], coordinates[jai][2] );
665 aa += dndy1_at_node[ja][jai] * xin;
666 bb += dndy2_at_node[ja][jai] * xin;
667 }
668 normal_at_nodes[ja] = aa * bb;
669 normal_at_nodes[ja].normalize();
670 }
671
672 // determine if element is flat
673 bool flat_element = true;
674 double dot_product;
675
676 for( ja = 0; ja < num_nodes; ja++ )
677 {
678 dot_product = normal_at_nodes[0] % normal_at_nodes[ja];
679 if( fabs( dot_product ) < 0.99 )
680 {
681 flat_element = false;
682 break;
683 }
684 }
685
686 // take into consideration of the thickness of the element
687 double thickness, thickness_gauss;
688 double distrt;
689 // get_tri_thickness(tri, element_area, thickness );
690 thickness = 0.001 * sqrt( element_area );
691
692 // set thickness gauss point location
693 double zl = 0.5773502691896;
694 if( flat_element ) zl = 0.0;
695
696 int no_gauss_pts_z = ( flat_element ) ? 1 : 2;
697 double thickness_z;
698
699 // loop on integration points
700 int igz;
701 for( ife = 0; ife < total_number_of_gauss_points; ife++ )
702 {
703 // loop on the thickness direction gauss points
704 for( igz = 0; igz < no_gauss_pts_z; igz++ )
705 {
706 zl = -zl;
707 thickness_z = zl * thickness / 2.0;
708
709 aa.set( 0.0, 0.0, 0.0 );
710 bb.set( 0.0, 0.0, 0.0 );
711 cc.set( 0.0, 0.0, 0.0 );
712
713 for( ja = 0; ja < num_nodes; ja++ )
714 {
715 xin.set( coordinates[jai][0], coordinates[jai][1], coordinates[jai][2] );
716 xin += thickness_z * normal_at_nodes[ja];
717 aa += dndy1[ife][ja] * xin;
718 bb += dndy2[ife][ja] * xin;
719 thickness_gauss = shape_function[ife][ja] * thickness / 2.0;
720 cc += thickness_gauss * normal_at_nodes[ja];
721 }
722
723 normal_at_point = aa * bb;
724 distrt = cc % normal_at_point;
725 if( distrt < distortion ) distortion = distrt;
726 }
727 }
728
729 // loop through nodal points
730 for( ja = 0; ja < num_nodes; ja++ )
731 {
732 for( igz = 0; igz < no_gauss_pts_z; igz++ )
733 {
734 zl = -zl;
735 thickness_z = zl * thickness / 2.0;
736
737 aa.set( 0.0, 0.0, 0.0 );
738 bb.set( 0.0, 0.0, 0.0 );
739 cc.set( 0.0, 0.0, 0.0 );
740
741 for( jai = 0; jai < num_nodes; jai++ )
742 {
743 xin.set( coordinates[jai][0], coordinates[jai][1], coordinates[jai][2] );
744 xin += thickness_z * normal_at_nodes[ja];
745 aa += dndy1_at_node[ja][jai] * xin;
746 bb += dndy2_at_node[ja][jai] * xin;
747 if( jai == ja )
748 thickness_gauss = thickness / 2.0;
749 else
750 thickness_gauss = 0.;
751 cc += thickness_gauss * normal_at_nodes[jai];
752 }
753 }
754
755 normal_at_point = aa * bb;
756 double sign_jacobian = ( tri_normal % normal_at_point ) > 0 ? 1. : -1.;
757 distrt = sign_jacobian * ( cc % normal_at_point );
758
759 if( distrt < distortion ) distortion = distrt;
760 }
761 if( element_area * thickness != 0 )
762 distortion *= 1. / ( element_area * thickness );
763 else
764 distortion *= 1.;
765
766 if( distortion > 0 ) return (double)VERDICT_MIN( distortion, VERDICT_DBL_MAX );
767 return (double)VERDICT_MAX( distortion, -VERDICT_DBL_MAX );
768 }
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().
C_FUNC_DEF double v_tri_edge_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
edge ratio Reference — P. P. Pebay & T. J. Baker, Analysis of Triangle Quality Measures, AMS Math. Comp., 2003, 72(244):1817-1839
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.
77 {
78
79 // three vectors for each side
80 VerdictVector a( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
81 coordinates[1][2] - coordinates[0][2] );
82
83 VerdictVector b( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
84 coordinates[2][2] - coordinates[1][2] );
85
86 VerdictVector c( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
87 coordinates[0][2] - coordinates[2][2] );
88
89 double a2 = a.length_squared();
90 double b2 = b.length_squared();
91 double c2 = c.length_squared();
92
93 double m2, M2;
94 if( a2 < b2 )
95 {
96 if( b2 < c2 )
97 {
98 m2 = a2;
99 M2 = c2;
100 }
101 else // b2 <= a2
102 {
103 if( a2 < c2 )
104 {
105 m2 = a2;
106 M2 = b2;
107 }
108 else // c2 <= a2
109 {
110 m2 = c2;
111 M2 = b2;
112 }
113 }
114 }
115 else // b2 <= a2
116 {
117 if( a2 < c2 )
118 {
119 m2 = b2;
120 M2 = c2;
121 }
122 else // c2 <= a2
123 {
124 if( b2 < c2 )
125 {
126 m2 = b2;
127 M2 = a2;
128 }
129 else // c2 <= b2
130 {
131 m2 = c2;
132 M2 = a2;
133 }
134 }
135 }
136
137 if( m2 < VERDICT_DBL_MIN )
138 return (double)VERDICT_DBL_MAX;
139 else
140 {
141 double edge_ratio;
142 edge_ratio = sqrt( M2 / m2 );
143
144 if( edge_ratio > 0 ) return (double)VERDICT_MIN( edge_ratio, VERDICT_DBL_MAX );
145 return (double)VERDICT_MAX( edge_ratio, -VERDICT_DBL_MAX );
146 }
147 }
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().
C_FUNC_DEF double v_tri_maximum_angle | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
Maximum included angle in triangle
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.
362 {
363
364 // vectors for all the sides
365 VerdictVector sides[4];
366 sides[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
367 coordinates[1][2] - coordinates[0][2] );
368 sides[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
369 coordinates[2][2] - coordinates[1][2] );
370 sides[2].set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
371 coordinates[2][2] - coordinates[0][2] );
372
373 // in case we need to find the interior angle
374 // between sides 0 and 1
375 sides[3] = -sides[1];
376
377 // calculate the lengths squared of the sides
378 double sides_lengths[3];
379 sides_lengths[0] = sides[0].length_squared();
380 sides_lengths[1] = sides[1].length_squared();
381 sides_lengths[2] = sides[2].length_squared();
382
383 if( sides_lengths[0] == 0.0 || sides_lengths[1] == 0.0 || sides_lengths[2] == 0.0 )
384 {
385 return 0.0;
386 }
387
388 // using the law of sines, we know that the maximum
389 // angle is opposite of the longest side
390
391 // find the longest side
392 int short_side = 0;
393 if( sides_lengths[1] > sides_lengths[0] ) short_side = 1;
394 if( sides_lengths[2] > sides_lengths[short_side] ) short_side = 2;
395
396 // from the longest side, calculate the angle of the
397 // opposite angle
398 double max_angle;
399 if( short_side == 0 )
400 {
401 max_angle = sides[2].interior_angle( sides[1] );
402 }
403 else if( short_side == 1 )
404 {
405 max_angle = sides[0].interior_angle( sides[2] );
406 }
407 else
408 {
409 max_angle = sides[0].interior_angle( sides[3] );
410 }
411
412 if( max_angle > 0 ) return (double)VERDICT_MIN( max_angle, VERDICT_DBL_MAX );
413 return (double)VERDICT_MAX( max_angle, -VERDICT_DBL_MAX );
414 }
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().
C_FUNC_DEF double v_tri_minimum_angle | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
Minimum included angle in triangle
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.
304 {
305
306 // vectors for all the sides
307 VerdictVector sides[4];
308 sides[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
309 coordinates[1][2] - coordinates[0][2] );
310 sides[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
311 coordinates[2][2] - coordinates[1][2] );
312 sides[2].set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
313 coordinates[2][2] - coordinates[0][2] );
314
315 // in case we need to find the interior angle
316 // between sides 0 and 1
317 sides[3] = -sides[1];
318
319 // calculate the lengths squared of the sides
320 double sides_lengths[3];
321 sides_lengths[0] = sides[0].length_squared();
322 sides_lengths[1] = sides[1].length_squared();
323 sides_lengths[2] = sides[2].length_squared();
324
325 if( sides_lengths[0] == 0.0 || sides_lengths[1] == 0.0 || sides_lengths[2] == 0.0 ) return 0.0;
326
327 // using the law of sines, we know that the minimum
328 // angle is opposite of the shortest side
329
330 // find the shortest side
331 int short_side = 0;
332 if( sides_lengths[1] < sides_lengths[0] ) short_side = 1;
333 if( sides_lengths[2] < sides_lengths[short_side] ) short_side = 2;
334
335 // from the shortest side, calculate the angle of the
336 // opposite angle
337 double min_angle;
338 if( short_side == 0 )
339 {
340 min_angle = sides[2].interior_angle( sides[1] );
341 }
342 else if( short_side == 1 )
343 {
344 min_angle = sides[0].interior_angle( sides[2] );
345 }
346 else
347 {
348 min_angle = sides[0].interior_angle( sides[3] );
349 }
350
351 if( min_angle > 0 ) return (double)VERDICT_MIN( min_angle, VERDICT_DBL_MAX );
352 return (double)VERDICT_MAX( min_angle, -VERDICT_DBL_MAX );
353 }
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().
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.
781 {
782
783 memset( metric_vals, 0, sizeof( TriMetricVals ) );
784
785 // for starts, lets set up some basic and common information
786
787 /* node numbers and side numbers used below
788
789 2
790 ++
791 / \
792 2 / \ 1
793 / \
794 / \
795 0 ---------+ 1
796 0
797 */
798
799 // vectors for each side
800 VerdictVector sides[3];
801 sides[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
802 coordinates[1][2] - coordinates[0][2] );
803 sides[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
804 coordinates[2][2] - coordinates[1][2] );
805 sides[2].set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
806 coordinates[2][2] - coordinates[0][2] );
807 VerdictVector tri_normal = sides[0] * sides[2];
808 // if we have access to normal information, check to see if the
809 // element is inverted. If we don't have the normal information
810 // that we need for this, assume the element is not inverted.
811 // This flag will be used for condition number, jacobian, shape,
812 // and size and shape.
813 bool is_inverted = false;
814 if( compute_normal )
815 {
816 // center of tri
817 double point[3], surf_normal[3];
818 point[0] = ( coordinates[0][0] + coordinates[1][0] + coordinates[2][0] ) / 3;
819 point[1] = ( coordinates[0][1] + coordinates[1][1] + coordinates[2][1] ) / 3;
820 point[2] = ( coordinates[0][2] + coordinates[1][2] + coordinates[2][2] ) / 3;
821 // dot product
822 compute_normal( point, surf_normal );
823 if( ( tri_normal.x() * surf_normal[0] + tri_normal.y() * surf_normal[1] + tri_normal.z() * surf_normal[2] ) <
824 0 )
825 is_inverted = true;
826 }
827
828 // lengths squared of each side
829 double sides_lengths_squared[3];
830 sides_lengths_squared[0] = sides[0].length_squared();
831 sides_lengths_squared[1] = sides[1].length_squared();
832 sides_lengths_squared[2] = sides[2].length_squared();
833
834 // if we are doing angle calcuations
835 if( metrics_request_flag & ( V_TRI_MINIMUM_ANGLE | V_TRI_MAXIMUM_ANGLE ) )
836 {
837 // which is short and long side
838 int short_side = 0, long_side = 0;
839
840 if( sides_lengths_squared[1] < sides_lengths_squared[0] ) short_side = 1;
841 if( sides_lengths_squared[2] < sides_lengths_squared[short_side] ) short_side = 2;
842
843 if( sides_lengths_squared[1] > sides_lengths_squared[0] ) long_side = 1;
844 if( sides_lengths_squared[2] > sides_lengths_squared[long_side] ) long_side = 2;
845
846 // calculate the minimum angle of the tri
847 if( metrics_request_flag & V_TRI_MINIMUM_ANGLE )
848 {
849 if( sides_lengths_squared[0] == 0.0 || sides_lengths_squared[1] == 0.0 || sides_lengths_squared[2] == 0.0 )
850 {
851 metric_vals->minimum_angle = 0.0;
852 }
853 else if( short_side == 0 )
854 metric_vals->minimum_angle = (double)sides[2].interior_angle( sides[1] );
855 else if( short_side == 1 )
856 metric_vals->minimum_angle = (double)sides[0].interior_angle( sides[2] );
857 else
858 metric_vals->minimum_angle = (double)sides[0].interior_angle( -sides[1] );
859 }
860
861 // calculate the maximum angle of the tri
862 if( metrics_request_flag & V_TRI_MAXIMUM_ANGLE )
863 {
864 if( sides_lengths_squared[0] == 0.0 || sides_lengths_squared[1] == 0.0 || sides_lengths_squared[2] == 0.0 )
865 {
866 metric_vals->maximum_angle = 0.0;
867 }
868 else if( long_side == 0 )
869 metric_vals->maximum_angle = (double)sides[2].interior_angle( sides[1] );
870 else if( long_side == 1 )
871 metric_vals->maximum_angle = (double)sides[0].interior_angle( sides[2] );
872 else
873 metric_vals->maximum_angle = (double)sides[0].interior_angle( -sides[1] );
874 }
875 }
876
877 // calculate the area of the tri
878 // the following metrics depend on area
879 if( metrics_request_flag &
880 ( V_TRI_AREA | V_TRI_SCALED_JACOBIAN | V_TRI_SHAPE | V_TRI_RELATIVE_SIZE_SQUARED | V_TRI_SHAPE_AND_SIZE ) )
881 {
882 metric_vals->area = (double)( ( sides[0] * sides[2] ).length() * 0.5 );
883 }
884
885 // calculate the aspect ratio
886 if( metrics_request_flag & V_TRI_ASPECT_FROBENIUS )
887 {
888 // sum the lengths squared
889 double srms = sides_lengths_squared[0] + sides_lengths_squared[1] + sides_lengths_squared[2];
890
891 // calculate once and reuse
892 static const double twoTimesRootOf3 = 2 * sqrt( 3.0 );
893
894 double div = ( twoTimesRootOf3 * ( ( sides[0] * sides[2] ).length() ) );
895
896 if( div == 0.0 )
897 metric_vals->aspect_frobenius = (double)VERDICT_DBL_MAX;
898 else
899 metric_vals->aspect_frobenius = (double)( srms / div );
900 }
901
902 // calculate the scaled jacobian
903 if( metrics_request_flag & V_TRI_SCALED_JACOBIAN )
904 {
905 // calculate once and reuse
906 static const double twoOverRootOf3 = 2 / sqrt( 3.0 );
907 // use the area from above
908
909 double tmp = tri_normal.length() * twoOverRootOf3;
910
911 // now scale it by the lengths of the sides
912 double min_scaled_jac = VERDICT_DBL_MAX;
913 double temp_scaled_jac;
914 for( int i = 0; i < 3; i++ )
915 {
916 if( sides_lengths_squared[i % 3] == 0.0 || sides_lengths_squared[( i + 2 ) % 3] == 0.0 )
917 temp_scaled_jac = 0.0;
918 else
919 temp_scaled_jac =
920 tmp / sqrt( sides_lengths_squared[i % 3] ) / sqrt( sides_lengths_squared[( i + 2 ) % 3] );
921 if( temp_scaled_jac < min_scaled_jac ) min_scaled_jac = temp_scaled_jac;
922 }
923 // multiply by -1 if the normals are in opposite directions
924 if( is_inverted )
925 {
926 min_scaled_jac *= -1;
927 }
928 metric_vals->scaled_jacobian = (double)min_scaled_jac;
929 }
930
931 // calculate the condition number
932 if( metrics_request_flag & V_TRI_CONDITION )
933 {
934 // calculate once and reuse
935 static const double rootOf3 = sqrt( 3.0 );
936 // if it is inverted, the condition number is considered to be infinity.
937 if( is_inverted )
938 {
939 metric_vals->condition = VERDICT_DBL_MAX;
940 }
941 else
942 {
943 double area2x = ( sides[0] * sides[2] ).length();
944 if( area2x == 0.0 )
945 metric_vals->condition = (double)( VERDICT_DBL_MAX );
946 else
947 metric_vals->condition = (double)( ( sides[0] % sides[0] + sides[2] % sides[2] - sides[0] % sides[2] ) /
948 ( area2x * rootOf3 ) );
949 }
950 }
951
952 // calculate the shape
953 if( metrics_request_flag & V_TRI_SHAPE || metrics_request_flag & V_TRI_SHAPE_AND_SIZE )
954 {
955 // if element is inverted, shape is zero. We don't need to
956 // calculate anything.
957 if( is_inverted )
958 {
959 metric_vals->shape = 0.0;
960 }
961 else
962 { // otherwise, we calculate the shape
963 // calculate once and reuse
964 static const double rootOf3 = sqrt( 3.0 );
965 // reuse area from before
966 double area2x = metric_vals->area * 2;
967 // dot products
968 double dots[3] = { sides[0] % sides[0], sides[2] % sides[2], sides[0] % sides[2] };
969
970 // add the dots
971 double sum_dots = dots[0] + dots[1] - dots[2];
972
973 // then the finale
974 if( sum_dots == 0.0 )
975 metric_vals->shape = 0.0;
976 else
977 metric_vals->shape = (double)( rootOf3 * area2x / sum_dots );
978 }
979 }
980
981 // calculate relative size squared
982 if( metrics_request_flag & V_TRI_RELATIVE_SIZE_SQUARED || metrics_request_flag & V_TRI_SHAPE_AND_SIZE )
983 {
984 // get weights
985 double w11, w21, w12, w22;
986 v_tri_get_weight( w11, w21, w12, w22 );
987 // get the determinant
988 double detw = determinant( w11, w21, w12, w22 );
989 // use the area from above and divide with the determinant
990 if( metric_vals->area == 0.0 || detw == 0.0 )
991 metric_vals->relative_size_squared = 0.0;
992 else
993 {
994 double size = metric_vals->area * 2.0 / detw;
995 // square the size
996 size *= size;
997 // value ranges between 0 to 1
998 metric_vals->relative_size_squared = (double)VERDICT_MIN( size, 1.0 / size );
999 }
1000 }
1001
1002 // calculate shape and size
1003 if( metrics_request_flag & V_TRI_SHAPE_AND_SIZE )
1004 {
1005 metric_vals->shape_and_size = metric_vals->relative_size_squared * metric_vals->shape;
1006 }
1007
1008 // calculate distortion
1009 if( metrics_request_flag & V_TRI_DISTORTION ) metric_vals->distortion = v_tri_distortion( num_nodes, coordinates );
1010
1011 // take care of any over-flow problems
1012 if( metric_vals->aspect_frobenius > 0 )
1013 metric_vals->aspect_frobenius = (double)VERDICT_MIN( metric_vals->aspect_frobenius, VERDICT_DBL_MAX );
1014 else
1015 metric_vals->aspect_frobenius = (double)VERDICT_MAX( metric_vals->aspect_frobenius, -VERDICT_DBL_MAX );
1016
1017 if( metric_vals->area > 0 )
1018 metric_vals->area = (double)VERDICT_MIN( metric_vals->area, VERDICT_DBL_MAX );
1019 else
1020 metric_vals->area = (double)VERDICT_MAX( metric_vals->area, -VERDICT_DBL_MAX );
1021
1022 if( metric_vals->minimum_angle > 0 )
1023 metric_vals->minimum_angle = (double)VERDICT_MIN( metric_vals->minimum_angle, VERDICT_DBL_MAX );
1024 else
1025 metric_vals->minimum_angle = (double)VERDICT_MAX( metric_vals->minimum_angle, -VERDICT_DBL_MAX );
1026
1027 if( metric_vals->maximum_angle > 0 )
1028 metric_vals->maximum_angle = (double)VERDICT_MIN( metric_vals->maximum_angle, VERDICT_DBL_MAX );
1029 else
1030 metric_vals->maximum_angle = (double)VERDICT_MAX( metric_vals->maximum_angle, -VERDICT_DBL_MAX );
1031
1032 if( metric_vals->condition > 0 )
1033 metric_vals->condition = (double)VERDICT_MIN( metric_vals->condition, VERDICT_DBL_MAX );
1034 else
1035 metric_vals->condition = (double)VERDICT_MAX( metric_vals->condition, -VERDICT_DBL_MAX );
1036
1037 if( metric_vals->shape > 0 )
1038 metric_vals->shape = (double)VERDICT_MIN( metric_vals->shape, VERDICT_DBL_MAX );
1039 else
1040 metric_vals->shape = (double)VERDICT_MAX( metric_vals->shape, -VERDICT_DBL_MAX );
1041
1042 if( metric_vals->scaled_jacobian > 0 )
1043 metric_vals->scaled_jacobian = (double)VERDICT_MIN( metric_vals->scaled_jacobian, VERDICT_DBL_MAX );
1044 else
1045 metric_vals->scaled_jacobian = (double)VERDICT_MAX( metric_vals->scaled_jacobian, -VERDICT_DBL_MAX );
1046
1047 if( metric_vals->relative_size_squared > 0 )
1048 metric_vals->relative_size_squared = (double)VERDICT_MIN( metric_vals->relative_size_squared, VERDICT_DBL_MAX );
1049 else
1050 metric_vals->relative_size_squared =
1051 (double)VERDICT_MAX( metric_vals->relative_size_squared, -VERDICT_DBL_MAX );
1052
1053 if( metric_vals->shape_and_size > 0 )
1054 metric_vals->shape_and_size = (double)VERDICT_MIN( metric_vals->shape_and_size, VERDICT_DBL_MAX );
1055 else
1056 metric_vals->shape_and_size = (double)VERDICT_MAX( metric_vals->shape_and_size, -VERDICT_DBL_MAX );
1057
1058 if( metric_vals->distortion > 0 )
1059 metric_vals->distortion = (double)VERDICT_MIN( metric_vals->distortion, VERDICT_DBL_MAX );
1060 else
1061 metric_vals->distortion = (double)VERDICT_MAX( metric_vals->distortion, -VERDICT_DBL_MAX );
1062
1063 if( metrics_request_flag & V_TRI_EDGE_RATIO )
1064 {
1065 metric_vals->edge_ratio = v_tri_edge_ratio( 3, coordinates );
1066 }
1067 if( metrics_request_flag & V_TRI_RADIUS_RATIO )
1068 {
1069 metric_vals->radius_ratio = v_tri_radius_ratio( 3, coordinates );
1070 }
1071 if( metrics_request_flag & V_TRI_ASPECT_FROBENIUS ) // there is no V_TRI_ASPECT_RATIO !
1072 {
1073 metric_vals->aspect_ratio = v_tri_radius_ratio( 3, coordinates );
1074 }
1075 }
References TriMetricVals::area, TriMetricVals::aspect_frobenius, TriMetricVals::aspect_ratio, compute_normal, TriMetricVals::condition, determinant(), TriMetricVals::distortion, TriMetricVals::edge_ratio, interior_angle(), VerdictVector::length(), length(), VerdictVector::length_squared(), 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().
C_FUNC_DEF double v_tri_radius_ratio | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
radius ratio Reference — P. P. Pebay & T. J. Baker, Analysis of Triangle Quality Measures, AMS Math. Comp., 2003, 72(244):1817-1839
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.
207 {
208
209 // three vectors for each side
210 VerdictVector a( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
211 coordinates[1][2] - coordinates[0][2] );
212
213 VerdictVector b( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
214 coordinates[2][2] - coordinates[1][2] );
215
216 VerdictVector c( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
217 coordinates[0][2] - coordinates[2][2] );
218
219 double a2 = a.length_squared();
220 double b2 = b.length_squared();
221 double c2 = c.length_squared();
222
223 VerdictVector ab = a * b;
224 double denominator = ab.length_squared();
225
226 if( denominator < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX;
227
228 double radius_ratio;
229 radius_ratio = .25 * a2 * b2 * c2 * ( a2 + b2 + c2 ) / denominator;
230
231 if( radius_ratio > 0 ) return (double)VERDICT_MIN( radius_ratio, VERDICT_DBL_MAX );
232 return (double)VERDICT_MAX( radius_ratio, -VERDICT_DBL_MAX );
233 }
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().
C_FUNC_DEF double v_tri_relative_size_squared | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
Min( J, 1/J ), where J is determinant of weighted Jacobian matrix. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
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.
535 {
536 double w11, w21, w12, w22;
537
538 VerdictVector xxi, xet, tri_normal;
539
540 v_tri_get_weight( w11, w21, w12, w22 );
541
542 double detw = determinant( w11, w21, w12, w22 );
543
544 if( detw == 0.0 ) return 0.0;
545
546 xxi.set( coordinates[0][0] - coordinates[1][0], coordinates[0][1] - coordinates[1][1],
547 coordinates[0][2] - coordinates[1][2] );
548
549 xet.set( coordinates[0][0] - coordinates[2][0], coordinates[0][1] - coordinates[2][1],
550 coordinates[0][2] - coordinates[2][2] );
551
552 tri_normal = xxi * xet;
553
554 double deta = tri_normal.length();
555 if( deta == 0.0 || detw == 0.0 ) return 0.0;
556
557 double size = pow( deta / detw, 2 );
558
559 double rel_size = VERDICT_MIN( size, 1.0 / size );
560
561 if( rel_size > 0 ) return (double)VERDICT_MIN( rel_size, VERDICT_DBL_MAX );
562 return (double)VERDICT_MAX( rel_size, -VERDICT_DBL_MAX );
563 }
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().
C_FUNC_DEF double v_tri_scaled_jacobian | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
Minimum Jacobian divided by the lengths of 2 edge vectors. Reference — P. Knupp, Achieving Finite Element Mesh Quality via Optimization of the Jacobian Matrix Norm and Associated Quantities, Intl. J. Numer. Meth. Engng. 2000, 48:1165-1185.
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.
462 {
463 static const double detw = 2. / sqrt( 3.0 );
464 VerdictVector first, second;
465 double jacobian;
466
467 VerdictVector edge[3];
468 edge[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
469 coordinates[1][2] - coordinates[0][2] );
470
471 edge[1].set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
472 coordinates[2][2] - coordinates[0][2] );
473
474 edge[2].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
475 coordinates[2][2] - coordinates[1][2] );
476 first = edge[1] - edge[0];
477 second = edge[2] - edge[0];
478
479 VerdictVector cross = first * second;
480 jacobian = cross.length();
481
482 double max_edge_length_product;
483 max_edge_length_product =
484 VERDICT_MAX( edge[0].length() * edge[1].length(),
485 VERDICT_MAX( edge[1].length() * edge[2].length(), edge[0].length() * edge[2].length() ) );
486
487 if( max_edge_length_product < VERDICT_DBL_MIN ) return (double)0.0;
488
489 jacobian *= detw;
490 jacobian /= max_edge_length_product;
491
492 if( compute_normal )
493 {
494 // center of tri
495 double point[3], surf_normal[3];
496 point[0] = ( coordinates[0][0] + coordinates[1][0] + coordinates[2][0] ) / 3;
497 point[1] = ( coordinates[0][1] + coordinates[1][1] + coordinates[2][1] ) / 3;
498 point[2] = ( coordinates[0][2] + coordinates[1][2] + coordinates[2][2] ) / 3;
499
500 // dot product
501 compute_normal( point, surf_normal );
502 if( ( cross.x() * surf_normal[0] + cross.y() * surf_normal[1] + cross.z() * surf_normal[2] ) < 0 )
503 jacobian *= -1;
504 }
505
506 if( jacobian > 0 ) return (double)VERDICT_MIN( jacobian, VERDICT_DBL_MAX );
507 return (double)VERDICT_MAX( jacobian, -VERDICT_DBL_MAX );
508 }
References compute_normal, moab::cross(), moab::GeomUtil::first(), length(), VERDICT_DBL_MAX, VERDICT_DBL_MIN, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure(), v_quad_quality(), and v_quad_scaled_jacobian().
C_FUNC_DEF double v_tri_shape | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
2/Condition number of weighted Jacobian matrix. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
The shape of a tri
2 / condition number of weighted jacobian matrix
Definition at line 515 of file V_TriMetric.cpp.
516 {
517 double condition = v_tri_condition( num_nodes, coordinates );
518
519 double shape;
520 if( condition <= VERDICT_DBL_MIN )
521 shape = VERDICT_DBL_MAX;
522 else
523 shape = ( 1 / condition );
524
525 if( shape > 0 ) return (double)VERDICT_MIN( shape, VERDICT_DBL_MAX );
526 return (double)VERDICT_MAX( shape, -VERDICT_DBL_MAX );
527 }
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().
C_FUNC_DEF double v_tri_shape_and_size | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates tri metric.
Product of Shape and Relative Size. Reference — P. Knupp, Algebraic Mesh Quality Metrics for Unstructured Initial Meshes, submitted for publication.
The shape and size of a tri
Product of the Shape and Relative Size
Definition at line 570 of file V_TriMetric.cpp.
571 {
572 double size, shape;
573
574 size = v_tri_relative_size_squared( num_nodes, coordinates );
575 shape = v_tri_shape( num_nodes, coordinates );
576
577 double shape_and_size = size * shape;
578
579 if( shape_and_size > 0 ) return (double)VERDICT_MIN( shape_and_size, VERDICT_DBL_MAX );
580 return (double)VERDICT_MAX( shape_and_size, -VERDICT_DBL_MAX );
581 }
References size, v_tri_relative_size_squared(), v_tri_shape(), VERDICT_DBL_MAX, VERDICT_MAX, and VERDICT_MIN.
Referenced by moab::VerdictWrapper::quality_measure().
C_FUNC_DEF void v_wedge_quality | ( | int | num_nodes, |
double | coordinates[][3], | ||
unsigned int | metrics_request_flag, | ||
struct WedgeMetricVals * | metric_vals | ||
) |
Calculates quality metrics for wedge elements.
Definition at line 102 of file V_WedgeMetric.cpp.
106 {
107 memset( metric_vals, 0, sizeof( WedgeMetricVals ) );
108
109 if( metrics_request_flag & V_WEDGE_VOLUME ) metric_vals->volume = v_wedge_volume( num_nodes, coordinates );
110 }
References V_WEDGE_VOLUME, v_wedge_volume(), and WedgeMetricVals::volume.
C_FUNC_DEF double v_wedge_volume | ( | int | num_nodes, |
double | coordinates[][3] | ||
) |
Calculates wedge volume.
calculate the volume of a wedge
this is done by dividing the wedge into 3 tets and summing the volume of each tet
Definition at line 54 of file V_WedgeMetric.cpp.
55 {
56
57 double volume = 0;
58 VerdictVector side1, side2, side3;
59
60 if( num_nodes == 6 )
61 {
62
63 // divide the wedge into 3 tets and calculate each volume
64
65 side1.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
66 coordinates[1][2] - coordinates[0][2] );
67
68 side2.set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
69 coordinates[2][2] - coordinates[0][2] );
70
71 side3.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
72 coordinates[3][2] - coordinates[0][2] );
73
74 volume = side3 % ( side1 * side2 ) / 6;
75
76 side1.set( coordinates[4][0] - coordinates[1][0], coordinates[4][1] - coordinates[1][1],
77 coordinates[4][2] - coordinates[1][2] );
78
79 side2.set( coordinates[5][0] - coordinates[1][0], coordinates[5][1] - coordinates[1][1],
80 coordinates[5][2] - coordinates[1][2] );
81
82 side3.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
83 coordinates[3][2] - coordinates[1][2] );
84
85 volume += side3 % ( side1 * side2 ) / 6;
86
87 side1.set( coordinates[5][0] - coordinates[1][0], coordinates[5][1] - coordinates[1][1],
88 coordinates[5][2] - coordinates[1][2] );
89
90 side2.set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
91 coordinates[2][2] - coordinates[1][2] );
92
93 side3.set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
94 coordinates[3][2] - coordinates[1][2] );
95
96 volume += side3 % ( side1 * side2 ) / 6;
97 }
98
99 return (double)volume;
100 }
References VerdictVector::set().
Referenced by moab::VerdictWrapper::all_quality_measures(), moab::VerdictWrapper::quality_measure(), and v_wedge_quality().