MOAB: Mesh Oriented datABase  (version 5.2.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) 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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines