MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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 }