MOAB: Mesh Oriented datABase  (version 5.4.1)
VertexConditionNumberQualityMetric.cpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2004 Sandia Corporation and Argonne National
00005     Laboratory.  Under the terms of Contract DE-AC04-94AL85000
00006     with Sandia Corporation, the U.S. Government retains certain
00007     rights in 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     [email protected], [email protected], [email protected],
00024     [email protected], [email protected], [email protected]
00025 
00026   ***************************************************************** */
00027 /*!
00028   \file   VertexConditionNumberQualityMetric.cpp
00029   \brief
00030 
00031   \author Michael Brewer
00032   \date   2002-06-9
00033 */
00034 #include "VertexConditionNumberQualityMetric.hpp"
00035 #include "Vector3D.hpp"
00036 #include "ConditionNumberFunctions.hpp"
00037 
00038 #include <cmath>
00039 #include <vector>
00040 using std::vector;
00041 
00042 using namespace MBMesquite;
00043 
00044 VertexConditionNumberQualityMetric::VertexConditionNumberQualityMetric() : AveragingQM( QualityMetric::LINEAR ) {}
00045 
00046 std::string VertexConditionNumberQualityMetric::get_name() const
00047 {
00048     return "Vertex Condition Number";
00049 }
00050 
00051 int VertexConditionNumberQualityMetric::get_negate_flag() const
00052 {
00053     return 1;
00054 }
00055 
00056 bool VertexConditionNumberQualityMetric::evaluate( PatchData& pd, size_t this_vert, double& fval, MsqError& err )
00057 {
00058     // pd.generate_vertex_to_element_data();
00059     bool return_flag;
00060     fval = MSQ_MAX_CAP;
00061     // get the element array
00062     MsqMeshEntity* elems = pd.get_element_array( err );
00063     // get the vertex to element array and the offset array
00064     // const size_t* elem_offset = pd.get_vertex_to_elem_offset(err);  MSQ_ERRZERO(err);
00065     // const size_t* v_to_e_array = pd.get_vertex_to_elem_array(err);  MSQ_ERRZERO(err);
00066     // find the offset for this vertex
00067     // size_t this_offset = elem_offset[this_vert];
00068     // get the number of elements attached to this vertex (given by the
00069     // first entry in the vertex to element array)
00070     // size_t num_elems = v_to_e_array[this_offset];
00071     // PRINT_INFO("\nIN LOCAL SIZE CPP, num_elements = %i",num_elems);
00072     // if no elements, then return true
00073     size_t num_elems;
00074     const size_t* v_to_e_array = pd.get_vertex_element_adjacencies( this_vert, num_elems, err );
00075     MSQ_ERRZERO( err );
00076 
00077     if( num_elems <= 0 )
00078     {
00079         return true;
00080     }
00081 
00082     // create an array to store the local metric values before averaging
00083     // Can we remove this dynamic allocatio?
00084     std::vector< double > met_vals( num_elems );
00085     // vector to hold the other verts which form a corner.
00086     vector< size_t > other_vertices;
00087     other_vertices.reserve( 4 );
00088     size_t i = 0;
00089     // only 3 temp_vec will be sent to cond-num calculator, but the
00090     // additional vector3Ds may be needed during the calculations
00091     size_t elem_index;
00092     Vector3D temp_vec[6];
00093     const MsqVertex* vertices = pd.get_vertex_array( err );
00094     // loop over the elements attached to this vertex
00095     for( i = 0; i < num_elems; ++i )
00096     {
00097         // get the vertices connected to this vertex for this element
00098         elem_index = v_to_e_array[i];
00099         elems[elem_index].get_connected_vertices( this_vert, other_vertices, err );
00100         MSQ_ERRZERO( err );
00101         // switch over the element type of this element
00102         switch( elems[v_to_e_array[i]].get_element_type() )
00103         {
00104 
00105             case TRIANGLE:
00106                 temp_vec[0] = vertices[other_vertices[0]] - vertices[this_vert];
00107                 temp_vec[2] = vertices[other_vertices[1]] - vertices[this_vert];
00108                 // make relative to equilateral
00109                 temp_vec[1] = ( ( 2 * temp_vec[2] ) - temp_vec[0] ) * MSQ_SQRT_THREE_INV;
00110                 return_flag = condition_number_2d( temp_vec, elem_index, pd, met_vals[i], err );
00111                 MSQ_ERRZERO( err );
00112                 if( !return_flag ) return return_flag;
00113                 break;
00114             case QUADRILATERAL:
00115                 temp_vec[0] = vertices[other_vertices[0]] - vertices[this_vert];
00116                 temp_vec[1] = vertices[other_vertices[1]] - vertices[this_vert];
00117                 return_flag = condition_number_2d( temp_vec, elem_index, pd, met_vals[i], err );
00118                 MSQ_ERRZERO( err );
00119                 if( !return_flag ) return return_flag;
00120                 break;
00121             case TETRAHEDRON:
00122                 temp_vec[0] = vertices[other_vertices[0]] - vertices[this_vert];
00123                 temp_vec[3] = vertices[other_vertices[1]] - vertices[this_vert];
00124                 temp_vec[4] = vertices[other_vertices[2]] - vertices[this_vert];
00125                 // transform to equilateral tet
00126                 temp_vec[1] = ( ( 2 * temp_vec[3] ) - temp_vec[0] ) / MSQ_SQRT_THREE;
00127                 temp_vec[2] = ( ( 3 * temp_vec[4] ) - temp_vec[0] - temp_vec[3] ) / ( MSQ_SQRT_THREE * MSQ_SQRT_TWO );
00128                 return_flag = condition_number_3d( temp_vec, pd, met_vals[i], err );
00129                 MSQ_ERRZERO( err );
00130                 if( !return_flag ) return return_flag;
00131                 break;
00132             case HEXAHEDRON:
00133                 temp_vec[0] = vertices[other_vertices[0]] - vertices[this_vert];
00134                 temp_vec[1] = vertices[other_vertices[1]] - vertices[this_vert];
00135                 temp_vec[2] = vertices[other_vertices[2]] - vertices[this_vert];
00136                 return_flag = condition_number_3d( temp_vec, pd, met_vals[i], err );
00137                 MSQ_ERRZERO( err );
00138                 if( !return_flag ) return return_flag;
00139                 break;
00140             default:
00141                 MSQ_SETERR( err )
00142                 ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not uspported in VertexConditionNumberQM.\n",
00143                   (int)( elems[v_to_e_array[i]].get_element_type() ) );
00144                 fval = MSQ_MAX_CAP;
00145                 return false;
00146 
00147         }  // end switch over element type
00148         other_vertices.clear();
00149     }  // end loop over elements
00150     fval = average_metrics( arrptr( met_vals ), num_elems, err );
00151     MSQ_ERRZERO( err );
00152     return true;
00153 }
00154 
00155 bool VertexConditionNumberQualityMetric::evaluate_with_indices( PatchData& pd,
00156                                                                 size_t this_vert,
00157                                                                 double& value,
00158                                                                 std::vector< size_t >& indices,
00159                                                                 MsqError& err )
00160 {
00161     bool rval = evaluate( pd, this_vert, value, err );
00162     MSQ_ERRFALSE( err );
00163 
00164     indices.clear();
00165 
00166     MsqMeshEntity* elems = pd.get_element_array( err );
00167     size_t num_elems;
00168     const size_t* v_to_e_array = pd.get_vertex_element_adjacencies( this_vert, num_elems, err );
00169     MSQ_ERRZERO( err );
00170 
00171     // vector to hold the other verts which form a corner.
00172     vector< size_t > other_vertices;
00173     other_vertices.reserve( 4 );
00174     size_t i = 0;
00175 
00176     // loop over the elements attached to this vertex
00177     for( i = 0; i < num_elems; ++i )
00178     {
00179         // get the vertices connected to this vertex for this element
00180         elems[v_to_e_array[i]].get_connected_vertices( this_vert, other_vertices, err );
00181         MSQ_ERRZERO( err );
00182         for( unsigned j = 0; j < other_vertices.size(); ++j )
00183         {
00184             if( other_vertices[j] < pd.num_free_vertices() ) indices.push_back( other_vertices[j] );
00185         }
00186     }
00187 
00188     std::sort( indices.begin(), indices.end() );
00189     indices.erase( std::unique( indices.begin(), indices.end() ), indices.end() );
00190     if( this_vert < pd.num_free_vertices() ) indices.push_back( this_vert );
00191     return rval;
00192 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines