MOAB: Mesh Oriented datABase
(version 5.4.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) [email protected] 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, 00077 size_t supported_elem_types_len, 00078 const Settings* set = 0 ); 00079 00080 /** Ideal pyramids should be considerd to have a heigth 00081 * equal to the length of a side, rather than the default which 00082 * is equilateral triangle faces. 00083 */ 00084 inline void ideal_pyramid_base_equals_height( bool flag ) 00085 { 00086 degenHexPyramid = flag; 00087 } 00088 00089 /** Test that metric evaluation succeeds for all supported element 00090 * types and fails for all unsupported types */ 00091 void test_supported_element_types( QualityMetric* qm ); 00092 00093 /** Test that metric value increases (or decreases if negate_flag is -1) 00094 * as the quality of an element worsens. Compares metric values for 00095 * ideal element with unit edge length to the value for the same 00096 * element with one corner vertex moved 1/2 of the distance towards 00097 * the element centroid. This test is applicable only for element-based 00098 * metrics. 00099 */ 00100 void test_measures_quality( QualityMetric* qm ); 00101 00102 /** Test that metric value increases (or decreases if negate_flag is -1) 00103 * as the quality of the element worsen. Compares metric values for 00104 * ideal elements with unit edge length to the value for the same 00105 * elements with the shared vertex moved 1/2 of the length of one of the 00106 * adjacent edges. This test is done only for TRIANGLE, QUADRILATERAL, 00107 * and HEXAHEDRAL element types. 00108 */ 00109 void test_measures_vertex_quality( QualityMetric* qm ); 00110 00111 /** Test measures deviation from domain */ 00112 void test_domain_deviation_quality( QualityMetric* qm ); 00113 00114 /** Test that metric value increases (or decreases if negate_flag is -1) 00115 * as the quality of an element worsens. Compares gradient values for 00116 * ideal element with unit edge length to the value for the same 00117 * element with one corner vertex moved 1/2 of the distance towards 00118 * the element centroid. This test is applicable only for element-based 00119 * metrics. 00120 */ 00121 void test_gradient_reflects_quality( QualityMetric* qm ); 00122 00123 /** Test that metric value increases (or decreases if negate_flag is -1) 00124 * as the quality of the element worsen. Compares gradient values for 00125 * ideal elements with unit edge length to the value for the same 00126 * elements with the shared vertex moved 1/2 of the length of one of the 00127 * adjacent edges. This test is done only for TRIANGLE, QUADRILATERAL, 00128 * and HEXAHEDRAL element types. 00129 */ 00130 void test_vertex_gradient_reflects_quality( QualityMetric* qm ); 00131 00132 /** Test gradient reflects deviation from domain */ 00133 void test_domain_deviation_gradient( QualityMetric* qm ); 00134 00135 /** Test evaluation of a single ideal element with unit area/volume */ 00136 void test_evaluate_unit_element( QualityMetric* qm, EntityTopology type, double value ); 00137 /** Test evaluation of a single ideal element with unit edge length */ 00138 void test_evaluate_unit_edge_element( QualityMetric* qm, EntityTopology type, double value ); 00139 /** Test evaluation of metric over patch with one free vertex surrounded 00140 * by 6 ideal unit-area tris */ 00141 void test_evaluate_unit_tris_about_vertex( QualityMetric* qm, double expected_val ); 00142 /** Test evaluation of metric over patch with one free vertex surrounded 00143 * by 4 unit-area quads */ 00144 void test_evaluate_unit_quads_about_vertex( QualityMetric* qm, double expected_val ); 00145 /** Test evaluation of metric over patch with one free vertex surrounded 00146 * by 8 unit-volume hexes */ 00147 void test_evaluate_unit_hexes_about_vertex( QualityMetric* qm, double expected_val ); 00148 /** Test evaluation of metric over patch with one free vertex surrounded 00149 * by 6 ideal unit-edge-length tris */ 00150 void test_evaluate_unit_edge_tris_about_vertex( QualityMetric* qm, double expected_val ); 00151 00152 /** Test that evaluation of the metric for an inverted element does 00153 * not pass back an error condition, and that the returned boolean 00154 * feasible value is the specified value */ 00155 void test_evaluate_inverted_element( QualityMetric* qm, bool should_succeed ); 00156 00157 /** Test that evaluation of the metric for degenerate element does 00158 * not pass back an error condition, and that the returned boolean 00159 * feasible value is the specified value */ 00160 void test_evaluate_degenerate_element( QualityMetric* qm, bool should_succeed ); 00161 00162 /** Test that evaluation of the metric for zero area/volume element does 00163 * not pass back an error condition, and that the returned boolean 00164 * feasible value is the specified value */ 00165 void test_evaluate_zero_element( QualityMetric* qm, bool should_succeed ); 00166 00167 /** Test get_evaluatinos() method for element-based metric */ 00168 void test_get_element_evaluations( QualityMetric* qm ); 00169 /** Test get_evaluatinos() method for vertex-based metric */ 00170 void test_get_vertex_evaluations( QualityMetric* qm ); 00171 /** Test get_evaluatinos() method for sample-based metric */ 00172 void test_get_sample_evaluations( QualityMetric* qm ); 00173 /** Test method to get samples in an element in the EdgeQM base class */ 00174 void test_get_edge_evaluations( EdgeQM* qm ); 00175 /** Test method to get samples in an element in the ElemSampleQM base class */ 00176 void test_get_in_element_evaluations( ElemSampleQM* qm ); 00177 00178 /** Test that evaluate_with_indices returns indices only for free vertices */ 00179 void test_get_indices_fixed( QualityMetric* qm ); 00180 00181 /** Test indices from evaluate_with_indices() method */ 00182 void test_get_element_indices( QualityMetric* qm ); 00183 /** Test indices from evaluate_with_indices() method, assuming 00184 * quality at a vertex depends only on edge-connected vertices. 00185 */ 00186 void test_get_vertex_indices( QualityMetric* qm ); 00187 void test_get_edge_indices( EdgeQM* qm ); 00188 /** Test indices from evaluate_with_indices() method */ 00189 void test_get_sample_indices( QualityMetric* qm ); 00190 00191 /** compare results of evaluate() and evaluate_with_indices() methods */ 00192 void compare_eval_and_eval_with_indices( QualityMetric* qm ); 00193 void compare_eval_and_eval_with_indices( QualityMetric* qm, PatchData& pd ); 00194 /** compare results of evaluate_with_indices() and evaluate_with_gradient() methods */ 00195 void compare_eval_with_indices_and_eval_with_gradient( QualityMetric* qm ); 00196 void compare_eval_with_indices_and_eval_with_gradient( QualityMetric* qm, PatchData& pd ); 00197 /** compare results of evaluate_with_indices() and evaluate_with_Hessian() methods */ 00198 void compare_eval_with_indices_and_eval_with_hessian( QualityMetric* qm ); 00199 void compare_eval_with_indices_and_eval_with_hessian( QualityMetric* qm, PatchData& pd ); 00200 /** compare results of evaluate_with_indices() and evaluate_with_Hessian_diagonal() methods */ 00201 void compare_eval_with_indices_and_eval_with_diagonal( QualityMetric* qm ); 00202 void compare_eval_with_indices_and_eval_with_diagonal( QualityMetric* qm, PatchData& pd ); 00203 /** compare results of evaluate_with_gradient() and evaluate_with_Hessian() methods */ 00204 void compare_eval_with_grad_and_eval_with_hessian( QualityMetric* qm ); 00205 void compare_eval_with_grad_and_eval_with_hessian( QualityMetric* qm, PatchData& pd ); 00206 /** compare results of evaluate_with_gradient() and evaluate_with_Hessian_diagonal() methods */ 00207 void compare_eval_with_grad_and_eval_with_diagonal( QualityMetric* qm ); 00208 void compare_eval_with_grad_and_eval_with_diagonal( QualityMetric* qm, PatchData& pd ); 00209 /** compare results of evaluate_with_Hessian_diagonal() and evaluate_with_Hessian() methods */ 00210 void compare_eval_with_diag_and_eval_with_hessian( QualityMetric* qm ); 00211 void compare_eval_with_diag_and_eval_with_hessian( QualityMetric* qm, PatchData& pd ); 00212 /** compare analytical and numerical gradient results */ 00213 void compare_analytical_and_numerical_gradients( QualityMetric* qm ); 00214 void compare_analytical_and_numerical_gradients( QualityMetric* qm, PatchData& pd ); 00215 /** compare analytical and numerical Hessian results */ 00216 void compare_analytical_and_numerical_hessians( QualityMetric* qm ); 00217 void compare_analytical_and_numerical_hessians( QualityMetric* qm, PatchData& pd ); 00218 /** compare analytical and numerical Hessian diagonal results */ 00219 void compare_analytical_and_numerical_diagonals( QualityMetric* qm ); 00220 void compare_analytical_and_numerical_diagonals( QualityMetric* qm, PatchData& pd ); 00221 00222 /** compare gradient w/ no fixed vertices to gradient 00223 * for element with all but one vertex fixed. 00224 */ 00225 void test_gradient_with_fixed_vertex( QualityMetric* qm, const Settings* settings = 0 ); 00226 void test_gradient_with_fixed_vertex( EntityTopology type, QualityMetric* qm, const Settings* settings = 0 ); 00227 /** compare Hessian w/ no fixed vertices to Hessian 00228 * for element with all but one vertex fixed. 00229 */ 00230 void test_hessian_with_fixed_vertex( QualityMetric* qm, const Settings* settings = 0 ); 00231 void test_hessian_with_fixed_vertex( EntityTopology type, QualityMetric* qm, const Settings* settings = 0 ); 00232 /** compare Hessian diagonal w/ no fixed vertices to Hessian 00233 * for element with all but one vertex fixed. 00234 */ 00235 void test_diagonal_with_fixed_vertex( QualityMetric* qm, const Settings* settings = 0 ); 00236 void test_diagonal_with_fixed_vertex( EntityTopology type, QualityMetric* qm, const Settings* settings = 0 ); 00237 00238 /** Test that gradient values are zero for an ideal element. 00239 * If 'unit_area' is true, then ideal elements have unit measure, 00240 * otherwise they have unit edge lengths. This test is applicable 00241 * only to element-based metrics. 00242 */ 00243 void test_ideal_element_zero_gradient( QualityMetric* qm, bool unit_area ); 00244 /** Test that gradient values are zero at the shared vertex in a 00245 * patch of containing ideal elements. 00246 * If 'unit_area' is true, then ideal elements have unit measure, 00247 * otherwise they have unit edge lengths. Test is done only for 00248 * TRIANGLE, QUADRILATERAL, and HEXAHEDRON element types. 00249 */ 00250 void test_ideal_element_zero_vertex_gradient( QualityMetric* qm, bool unit_area ); 00251 00252 /** Test that Hessian is positive-definite for ideal elements */ 00253 void test_ideal_element_positive_definite_Hessian( QualityMetric* qm, bool unit_area ); 00254 00255 /** Test that diagonal bocks of Hessian are symetrical */ 00256 void test_symmetric_Hessian_diagonal_blocks( QualityMetric* qm ); 00257 00258 /** test that metric value is consistent for element translation */ 00259 void test_location_invariant( QualityMetric* qm, bool untangler = false ); 00260 /** test that metric value is consistent for element scalaing */ 00261 void test_scale_invariant( QualityMetric* qm, bool untangler = false ); 00262 /** test that metric value is consistent for element rotation */ 00263 void test_orient_invariant( QualityMetric* qm, bool untangler = false ); 00264 00265 /** test that gradient values don't change with element translation */ 00266 void test_grad_location_invariant( QualityMetric* qm, bool untangler = false ); 00267 /** test that gradient values rotate with element rotation */ 00268 void test_grad_orient_invariant( QualityMetric* qm, bool untangler = false ); 00269 /** test that Hessian values don't change with element translation */ 00270 void test_hessian_location_invariant( QualityMetric* qm, bool untangler = false ); 00271 00272 /** test that metric inceases (decreases) as size deviates from ideal */ 00273 void test_measures_size( QualityMetric* qm, bool unit_area ); 00274 /** test that metric value increases as element orientation changes from ideal */ 00275 void test_measures_in_plane_orientation( QualityMetric* qm ); 00276 /** test that metric value increases as element orientation changes from ideal */ 00277 void test_measures_out_of_plane_orientation( QualityMetric* qm ); 00278 00279 class PatchXform 00280 { 00281 public: 00282 virtual ~PatchXform() {} 00283 virtual void xform( PatchData& pd, PlanarDomain* dom ) = 0; 00284 virtual void xform_grad( std::vector< Vector3D >& grads ) = 0; 00285 }; 00286 00287 void test_transform_invariant( QualityMetric* qm, PatchXform& transform, bool untangler ); 00288 00289 void test_grad_transform_invariant( QualityMetric* qm, PatchXform& transform, bool untangler ); 00290 00291 void test_hessian_transform_invariant( QualityMetric* qm, PatchXform& transform, bool untangler ); 00292 00293 void test_measures_transform( QualityMetric* qm, PatchXform& transform, bool unit_area ); 00294 00295 private: 00296 inline bool type_is_supported( EntityTopology type ) 00297 { 00298 return std::find( types.begin(), types.end(), type ) != types.end(); 00299 } 00300 00301 void test_type_is_supported( EntityTopology type, QualityMetric* qm ); 00302 void test_type_is_not_supported( EntityTopology type, QualityMetric* qm ); 00303 00304 bool degenHexPyramid; //!< See: ideal_pyramid_base_equals_height() 00305 std::vector< EntityTopology > types; 00306 const Settings* mSettings; 00307 PlanarDomain geomPlane; 00308 }; 00309 00310 #endif