MOAB: Mesh Oriented datABase  (version 5.4.1)
QualityMetricTester.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines