MOAB: Mesh Oriented datABase
(version 5.2.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2006 Sandia National Laboratories. Developed at the 00005 University of Wisconsin--Madison under SNL contract number 00006 624796. The U.S. Government and the University of Wisconsin 00007 retain certain rights to this software. 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 (lgpl.txt) along with this library; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 (2006) kraftche@cae.wisc.edu 00024 00025 ***************************************************************** */ 00026 00027 #ifndef QUALITY_METRIC_TESTER_HPP 00028 #define QUALITY_METRIC_TESTER_HPP 00029 00030 #include "Mesquite.hpp" 00031 #include "PlanarDomain.hpp" 00032 #include "Settings.hpp" 00033 #include <algorithm> 00034 00035 using namespace MBMesquite; 00036 00037 namespace MBMesquite 00038 { 00039 class PatchData; 00040 class QualityMetric; 00041 class ElemSampleQM; 00042 class EdgeQM; 00043 } // namespace MBMesquite 00044 00045 class QualityMetricTester 00046 { 00047 public: 00048 void get_ideal_tris( PatchData& pd, bool unit_area ); 00049 void get_ideal_quads( PatchData& pd ); 00050 void get_ideal_hexes( PatchData& pd ); 00051 void get_ideal_element( EntityTopology type, bool unit_area, PatchData& pd, bool first_vertex_fixed = false ); 00052 void get_ideal_element( EntityTopology type, bool unit_area, PatchData& pd, int free_vertex_index ); 00053 void get_nonideal_element( EntityTopology type, PatchData& pd, bool first_vertex_fixed = false ); 00054 void get_nonideal_element( EntityTopology type, PatchData& pd, int free_vertex_index ); 00055 void get_degenerate_element( EntityTopology type, PatchData& pd ); 00056 void get_zero_element( EntityTopology type, PatchData& pd ); 00057 void get_inverted_element( EntityTopology type, PatchData& pd ); 00058 00059 enum ElemTypeGroup 00060 { 00061 SIMPLICIES, // triangle and tetrahedron 00062 NON_MIXED_FE, // tri, quad, tet, hex 00063 TWO_D, // tri, quad, polygon 00064 TWO_D_FE, // tri, quad 00065 THREE_D, // tet, hex, pyr, wedge, septahedron, polyhedron 00066 THREE_D_FE, // tet, hex, pyr, wedge, septahedron 00067 THREE_D_NON_MIXED_FE, // tet, hex, 00068 THREE_D_FE_EXCEPT_SEPTAHEDRON, // tet, hex, pyr, wedge 00069 ALL_FE_EXCEPT_SEPTAHEDRON, // tri, quad, tet, hex, pyr, wedge 00070 ALL_FE, // everything except polygon and polyhedron 00071 ALL 00072 }; // everything (including polyhedron) 00073 00074 QualityMetricTester( ElemTypeGroup group, const Settings* set = 0 ); 00075 00076 QualityMetricTester( const EntityTopology* supported_elem_types, size_t supported_elem_types_len, 00077 const Settings* set = 0 ); 00078 00079 /** Ideal pyramids should be considerd to have a heigth 00080 * equal to the length of a side, rather than the default which 00081 * is equilateral triangle faces. 00082 */ 00083 inline void ideal_pyramid_base_equals_height( bool flag ) 00084 { 00085 degenHexPyramid = flag; 00086 } 00087 00088 /** Test that metric evaluation succeeds for all supported element 00089 * types and fails for all unsupported types */ 00090 void test_supported_element_types( QualityMetric* qm ); 00091 00092 /** Test that metric value increases (or decreases if negate_flag is -1) 00093 * as the quality of an element worsens. Compares metric values for 00094 * ideal element with unit edge length to the value for the same 00095 * element with one corner vertex moved 1/2 of the distance towards 00096 * the element centroid. This test is applicable only for element-based 00097 * metrics. 00098 */ 00099 void test_measures_quality( QualityMetric* qm ); 00100 00101 /** Test that metric value increases (or decreases if negate_flag is -1) 00102 * as the quality of the element worsen. Compares metric values for 00103 * ideal elements with unit edge length to the value for the same 00104 * elements with the shared vertex moved 1/2 of the length of one of the 00105 * adjacent edges. This test is done only for TRIANGLE, QUADRILATERAL, 00106 * and HEXAHEDRAL element types. 00107 */ 00108 void test_measures_vertex_quality( QualityMetric* qm ); 00109 00110 /** Test measures deviation from domain */ 00111 void test_domain_deviation_quality( QualityMetric* qm ); 00112 00113 /** Test that metric value increases (or decreases if negate_flag is -1) 00114 * as the quality of an element worsens. Compares gradient values for 00115 * ideal element with unit edge length to the value for the same 00116 * element with one corner vertex moved 1/2 of the distance towards 00117 * the element centroid. This test is applicable only for element-based 00118 * metrics. 00119 */ 00120 void test_gradient_reflects_quality( QualityMetric* qm ); 00121 00122 /** Test that metric value increases (or decreases if negate_flag is -1) 00123 * as the quality of the element worsen. Compares gradient values for 00124 * ideal elements with unit edge length to the value for the same 00125 * elements with the shared vertex moved 1/2 of the length of one of the 00126 * adjacent edges. This test is done only for TRIANGLE, QUADRILATERAL, 00127 * and HEXAHEDRAL element types. 00128 */ 00129 void test_vertex_gradient_reflects_quality( QualityMetric* qm ); 00130 00131 /** Test gradient reflects deviation from domain */ 00132 void test_domain_deviation_gradient( QualityMetric* qm ); 00133 00134 /** Test evaluation of a single ideal element with unit area/volume */ 00135 void test_evaluate_unit_element( QualityMetric* qm, EntityTopology type, double value ); 00136 /** Test evaluation of a single ideal element with unit edge length */ 00137 void test_evaluate_unit_edge_element( QualityMetric* qm, EntityTopology type, double value ); 00138 /** Test evaluation of metric over patch with one free vertex surrounded 00139 * by 6 ideal unit-area tris */ 00140 void test_evaluate_unit_tris_about_vertex( QualityMetric* qm, double expected_val ); 00141 /** Test evaluation of metric over patch with one free vertex surrounded 00142 * by 4 unit-area quads */ 00143 void test_evaluate_unit_quads_about_vertex( QualityMetric* qm, double expected_val ); 00144 /** Test evaluation of metric over patch with one free vertex surrounded 00145 * by 8 unit-volume hexes */ 00146 void test_evaluate_unit_hexes_about_vertex( QualityMetric* qm, double expected_val ); 00147 /** Test evaluation of metric over patch with one free vertex surrounded 00148 * by 6 ideal unit-edge-length tris */ 00149 void test_evaluate_unit_edge_tris_about_vertex( QualityMetric* qm, double expected_val ); 00150 00151 /** Test that evaluation of the metric for an inverted element does 00152 * not pass back an error condition, and that the returned boolean 00153 * feasible value is the specified value */ 00154 void test_evaluate_inverted_element( QualityMetric* qm, bool should_succeed ); 00155 00156 /** Test that evaluation of the metric for degenerate element does 00157 * not pass back an error condition, and that the returned boolean 00158 * feasible value is the specified value */ 00159 void test_evaluate_degenerate_element( QualityMetric* qm, bool should_succeed ); 00160 00161 /** Test that evaluation of the metric for zero area/volume element does 00162 * not pass back an error condition, and that the returned boolean 00163 * feasible value is the specified value */ 00164 void test_evaluate_zero_element( QualityMetric* qm, bool should_succeed ); 00165 00166 /** Test get_evaluatinos() method for element-based metric */ 00167 void test_get_element_evaluations( QualityMetric* qm ); 00168 /** Test get_evaluatinos() method for vertex-based metric */ 00169 void test_get_vertex_evaluations( QualityMetric* qm ); 00170 /** Test get_evaluatinos() method for sample-based metric */ 00171 void test_get_sample_evaluations( QualityMetric* qm ); 00172 /** Test method to get samples in an element in the EdgeQM base class */ 00173 void test_get_edge_evaluations( EdgeQM* qm ); 00174 /** Test method to get samples in an element in the ElemSampleQM base class */ 00175 void test_get_in_element_evaluations( ElemSampleQM* qm ); 00176 00177 /** Test that evaluate_with_indices returns indices only for free vertices */ 00178 void test_get_indices_fixed( QualityMetric* qm ); 00179 00180 /** Test indices from evaluate_with_indices() method */ 00181 void test_get_element_indices( QualityMetric* qm ); 00182 /** Test indices from evaluate_with_indices() method, assuming 00183 * quality at a vertex depends only on edge-connected vertices. 00184 */ 00185 void test_get_vertex_indices( QualityMetric* qm ); 00186 void test_get_edge_indices( EdgeQM* qm ); 00187 /** Test indices from evaluate_with_indices() method */ 00188 void test_get_sample_indices( QualityMetric* qm ); 00189 00190 /** compare results of evaluate() and evaluate_with_indices() methods */ 00191 void compare_eval_and_eval_with_indices( QualityMetric* qm ); 00192 void compare_eval_and_eval_with_indices( QualityMetric* qm, PatchData& pd ); 00193 /** compare results of evaluate_with_indices() and evaluate_with_gradient() methods */ 00194 void compare_eval_with_indices_and_eval_with_gradient( QualityMetric* qm ); 00195 void compare_eval_with_indices_and_eval_with_gradient( QualityMetric* qm, PatchData& pd ); 00196 /** compare results of evaluate_with_indices() and evaluate_with_Hessian() methods */ 00197 void compare_eval_with_indices_and_eval_with_hessian( QualityMetric* qm ); 00198 void compare_eval_with_indices_and_eval_with_hessian( QualityMetric* qm, PatchData& pd ); 00199 /** compare results of evaluate_with_indices() and evaluate_with_Hessian_diagonal() methods */ 00200 void compare_eval_with_indices_and_eval_with_diagonal( QualityMetric* qm ); 00201 void compare_eval_with_indices_and_eval_with_diagonal( QualityMetric* qm, PatchData& pd ); 00202 /** compare results of evaluate_with_gradient() and evaluate_with_Hessian() methods */ 00203 void compare_eval_with_grad_and_eval_with_hessian( QualityMetric* qm ); 00204 void compare_eval_with_grad_and_eval_with_hessian( QualityMetric* qm, PatchData& pd ); 00205 /** compare results of evaluate_with_gradient() and evaluate_with_Hessian_diagonal() methods */ 00206 void compare_eval_with_grad_and_eval_with_diagonal( QualityMetric* qm ); 00207 void compare_eval_with_grad_and_eval_with_diagonal( QualityMetric* qm, PatchData& pd ); 00208 /** compare results of evaluate_with_Hessian_diagonal() and evaluate_with_Hessian() methods */ 00209 void compare_eval_with_diag_and_eval_with_hessian( QualityMetric* qm ); 00210 void compare_eval_with_diag_and_eval_with_hessian( QualityMetric* qm, PatchData& pd ); 00211 /** compare analytical and numerical gradient results */ 00212 void compare_analytical_and_numerical_gradients( QualityMetric* qm ); 00213 void compare_analytical_and_numerical_gradients( QualityMetric* qm, PatchData& pd ); 00214 /** compare analytical and numerical Hessian results */ 00215 void compare_analytical_and_numerical_hessians( QualityMetric* qm ); 00216 void compare_analytical_and_numerical_hessians( QualityMetric* qm, PatchData& pd ); 00217 /** compare analytical and numerical Hessian diagonal results */ 00218 void compare_analytical_and_numerical_diagonals( QualityMetric* qm ); 00219 void compare_analytical_and_numerical_diagonals( QualityMetric* qm, PatchData& pd ); 00220 00221 /** compare gradient w/ no fixed vertices to gradient 00222 * for element with all but one vertex fixed. 00223 */ 00224 void test_gradient_with_fixed_vertex( QualityMetric* qm, const Settings* settings = 0 ); 00225 void test_gradient_with_fixed_vertex( EntityTopology type, QualityMetric* qm, const Settings* settings = 0 ); 00226 /** compare Hessian w/ no fixed vertices to Hessian 00227 * for element with all but one vertex fixed. 00228 */ 00229 void test_hessian_with_fixed_vertex( QualityMetric* qm, const Settings* settings = 0 ); 00230 void test_hessian_with_fixed_vertex( EntityTopology type, QualityMetric* qm, const Settings* settings = 0 ); 00231 /** compare Hessian diagonal w/ no fixed vertices to Hessian 00232 * for element with all but one vertex fixed. 00233 */ 00234 void test_diagonal_with_fixed_vertex( QualityMetric* qm, const Settings* settings = 0 ); 00235 void test_diagonal_with_fixed_vertex( EntityTopology type, QualityMetric* qm, const Settings* settings = 0 ); 00236 00237 /** Test that gradient values are zero for an ideal element. 00238 * If 'unit_area' is true, then ideal elements have unit measure, 00239 * otherwise they have unit edge lengths. This test is applicable 00240 * only to element-based metrics. 00241 */ 00242 void test_ideal_element_zero_gradient( QualityMetric* qm, bool unit_area ); 00243 /** Test that gradient values are zero at the shared vertex in a 00244 * patch of containing ideal elements. 00245 * If 'unit_area' is true, then ideal elements have unit measure, 00246 * otherwise they have unit edge lengths. Test is done only for 00247 * TRIANGLE, QUADRILATERAL, and HEXAHEDRON element types. 00248 */ 00249 void test_ideal_element_zero_vertex_gradient( QualityMetric* qm, bool unit_area ); 00250 00251 /** Test that Hessian is positive-definite for ideal elements */ 00252 void test_ideal_element_positive_definite_Hessian( QualityMetric* qm, bool unit_area ); 00253 00254 /** Test that diagonal bocks of Hessian are symetrical */ 00255 void test_symmetric_Hessian_diagonal_blocks( QualityMetric* qm ); 00256 00257 /** test that metric value is consistent for element translation */ 00258 void test_location_invariant( QualityMetric* qm, bool untangler = false ); 00259 /** test that metric value is consistent for element scalaing */ 00260 void test_scale_invariant( QualityMetric* qm, bool untangler = false ); 00261 /** test that metric value is consistent for element rotation */ 00262 void test_orient_invariant( QualityMetric* qm, bool untangler = false ); 00263 00264 /** test that gradient values don't change with element translation */ 00265 void test_grad_location_invariant( QualityMetric* qm, bool untangler = false ); 00266 /** test that gradient values rotate with element rotation */ 00267 void test_grad_orient_invariant( QualityMetric* qm, bool untangler = false ); 00268 /** test that Hessian values don't change with element translation */ 00269 void test_hessian_location_invariant( QualityMetric* qm, bool untangler = false ); 00270 00271 /** test that metric inceases (decreases) as size deviates from ideal */ 00272 void test_measures_size( QualityMetric* qm, bool unit_area ); 00273 /** test that metric value increases as element orientation changes from ideal */ 00274 void test_measures_in_plane_orientation( QualityMetric* qm ); 00275 /** test that metric value increases as element orientation changes from ideal */ 00276 void test_measures_out_of_plane_orientation( QualityMetric* qm ); 00277 00278 class PatchXform 00279 { 00280 public: 00281 virtual ~PatchXform() {} 00282 virtual void xform( PatchData& pd, PlanarDomain* dom ) = 0; 00283 virtual void xform_grad( std::vector< Vector3D >& grads ) = 0; 00284 }; 00285 00286 void test_transform_invariant( QualityMetric* qm, PatchXform& transform, bool untangler ); 00287 00288 void test_grad_transform_invariant( QualityMetric* qm, PatchXform& transform, bool untangler ); 00289 00290 void test_hessian_transform_invariant( QualityMetric* qm, PatchXform& transform, bool untangler ); 00291 00292 void test_measures_transform( QualityMetric* qm, PatchXform& transform, bool unit_area ); 00293 00294 private: 00295 inline bool type_is_supported( EntityTopology type ) 00296 { 00297 return std::find( types.begin(), types.end(), type ) != types.end(); 00298 } 00299 00300 void test_type_is_supported( EntityTopology type, QualityMetric* qm ); 00301 void test_type_is_not_supported( EntityTopology type, QualityMetric* qm ); 00302 00303 bool degenHexPyramid; //!< See: ideal_pyramid_base_equals_height() 00304 std::vector< EntityTopology > types; 00305 const Settings* mSettings; 00306 PlanarDomain geomPlane; 00307 }; 00308 00309 #endif