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 IdealWeightMeanRatio.cpp 00029 \brief 00030 00031 \author Michael Brewer 00032 \date 2002-11-11 00033 */ 00034 #include "IdealWeightMeanRatio.hpp" 00035 #include "MeanRatioFunctions.hpp" 00036 #include "Vector3D.hpp" 00037 #include "MsqTimer.hpp" 00038 #include "MsqDebug.hpp" 00039 #include "MsqError.hpp" 00040 #include "PatchData.hpp" 00041 00042 #include <cmath> 00043 #include <vector> 00044 using std::vector; 00045 00046 using namespace MBMesquite; 00047 00048 std::string IdealWeightMeanRatio::get_name() const 00049 { 00050 return "Mean Ratio"; 00051 } 00052 00053 int IdealWeightMeanRatio::get_negate_flag() const 00054 { 00055 return -1; 00056 } 00057 00058 bool IdealWeightMeanRatio::evaluate( PatchData& pd, size_t handle, double& m, MsqError& err ) 00059 { 00060 const MsqMeshEntity* e = &pd.element_by_index( handle ); 00061 EntityTopology topo = e->get_element_type(); 00062 00063 const MsqVertex* vertices = pd.get_vertex_array( err ); 00064 const size_t* v_i = e->get_vertex_index_array(); 00065 00066 Vector3D n; // Surface normal for 2D objects 00067 00068 // Prism and Hex element descriptions 00069 static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 }, 00070 { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } }; 00071 static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 }, 00072 { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } }; 00073 00074 const Vector3D d_con( 1.0, 1.0, 1.0 ); 00075 00076 int i; 00077 00078 m = 0.0; 00079 bool metric_valid = false; 00080 switch( topo ) 00081 { 00082 case TRIANGLE: 00083 pd.get_domain_normal_at_element( e, n, err ); 00084 MSQ_ERRZERO( err ); 00085 n = n / n.length(); // Need unit normal 00086 mCoords[0] = vertices[v_i[0]]; 00087 mCoords[1] = vertices[v_i[1]]; 00088 mCoords[2] = vertices[v_i[2]]; 00089 metric_valid = m_fcn_2e( m, mCoords, n, a2Con, b2Con, c2Con ); 00090 if( !metric_valid ) return false; 00091 break; 00092 00093 case QUADRILATERAL: 00094 pd.get_domain_normal_at_element( e, n, err ); 00095 MSQ_ERRZERO( err ); 00096 for( i = 0; i < 4; ++i ) 00097 { 00098 n = n / n.length(); // Need unit normal 00099 mCoords[0] = vertices[v_i[locs_hex[i][0]]]; 00100 mCoords[1] = vertices[v_i[locs_hex[i][1]]]; 00101 mCoords[2] = vertices[v_i[locs_hex[i][2]]]; 00102 metric_valid = m_fcn_2i( mMetrics[i], mCoords, n, a2Con, b2Con, c2Con, d_con ); 00103 if( !metric_valid ) return false; 00104 } 00105 m = average_metrics( mMetrics, 4, err ); 00106 MSQ_ERRZERO( err ); 00107 break; 00108 00109 case TETRAHEDRON: 00110 mCoords[0] = vertices[v_i[0]]; 00111 mCoords[1] = vertices[v_i[1]]; 00112 mCoords[2] = vertices[v_i[2]]; 00113 mCoords[3] = vertices[v_i[3]]; 00114 metric_valid = m_fcn_3e( m, mCoords, a3Con, b3Con, c3Con ); 00115 if( !metric_valid ) return false; 00116 break; 00117 00118 case PYRAMID: 00119 for( i = 0; i < 4; ++i ) 00120 { 00121 mCoords[0] = vertices[v_i[i]]; 00122 mCoords[1] = vertices[v_i[( i + 1 ) % 4]]; 00123 mCoords[2] = vertices[v_i[( i + 3 ) % 4]]; 00124 mCoords[3] = vertices[v_i[4]]; 00125 metric_valid = m_fcn_3p( mMetrics[i], mCoords, a3Con, b3Con, c3Con ); 00126 if( !metric_valid ) return false; 00127 } 00128 m = average_metrics( mMetrics, 4, err ); 00129 MSQ_ERRZERO( err ); 00130 break; 00131 00132 case PRISM: 00133 for( i = 0; i < 6; ++i ) 00134 { 00135 mCoords[0] = vertices[v_i[locs_pri[i][0]]]; 00136 mCoords[1] = vertices[v_i[locs_pri[i][1]]]; 00137 mCoords[2] = vertices[v_i[locs_pri[i][2]]]; 00138 mCoords[3] = vertices[v_i[locs_pri[i][3]]]; 00139 metric_valid = m_fcn_3w( mMetrics[i], mCoords, a3Con, b3Con, c3Con ); 00140 if( !metric_valid ) return false; 00141 } 00142 m = average_metrics( mMetrics, 6, err ); 00143 MSQ_ERRZERO( err ); 00144 break; 00145 00146 case HEXAHEDRON: 00147 for( i = 0; i < 8; ++i ) 00148 { 00149 mCoords[0] = vertices[v_i[locs_hex[i][0]]]; 00150 mCoords[1] = vertices[v_i[locs_hex[i][1]]]; 00151 mCoords[2] = vertices[v_i[locs_hex[i][2]]]; 00152 mCoords[3] = vertices[v_i[locs_hex[i][3]]]; 00153 metric_valid = m_fcn_3i( mMetrics[i], mCoords, a3Con, b3Con, c3Con, d_con ); 00154 if( !metric_valid ) return false; 00155 } 00156 m = average_metrics( mMetrics, 8, err ); 00157 MSQ_ERRZERO( err ); 00158 break; 00159 00160 default: 00161 MSQ_SETERR( err ) 00162 ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightMeanRatio", (int)topo ); 00163 return false; 00164 } // end switch over element type 00165 return true; 00166 } 00167 00168 bool IdealWeightMeanRatio::evaluate_with_gradient( PatchData& pd, 00169 size_t handle, 00170 double& m, 00171 std::vector< size_t >& indices, 00172 std::vector< Vector3D >& g, 00173 MsqError& err ) 00174 { 00175 // FUNCTION_TIMER_START(__FUNC__); 00176 const MsqMeshEntity* e = &pd.element_by_index( handle ); 00177 EntityTopology topo = e->get_element_type(); 00178 00179 if( !analytical_average_gradient() && topo != TRIANGLE && topo != TETRAHEDRON ) 00180 { 00181 static bool print = true; 00182 if( print ) 00183 { 00184 MSQ_DBGOUT( 1 ) << "Analyical gradient not available for selected averaging scheme. " 00185 << "Using (possibly much slower) numerical approximation of gradient" 00186 << " of quality metric. " << std::endl; 00187 print = false; 00188 } 00189 return QualityMetric::evaluate_with_gradient( pd, handle, m, indices, g, err ); 00190 } 00191 00192 const MsqVertex* vertices = pd.get_vertex_array( err ); 00193 const size_t* v_i = e->get_vertex_index_array(); 00194 00195 Vector3D n; // Surface normal for 2D objects 00196 00197 // double nm, t=0; 00198 00199 // Prism and Hex element descriptions 00200 static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 }, 00201 { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } }; 00202 static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 }, 00203 { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } }; 00204 00205 const Vector3D d_con( 1.0, 1.0, 1.0 ); 00206 00207 int i; 00208 00209 bool metric_valid = false; 00210 const uint32_t fm = fixed_vertex_bitmap( pd, e, indices ); 00211 00212 m = 0.0; 00213 00214 switch( topo ) 00215 { 00216 case TRIANGLE: 00217 pd.get_domain_normal_at_element( e, n, err ); 00218 MSQ_ERRZERO( err ); 00219 n = n / n.length(); // Need unit normal 00220 mCoords[0] = vertices[v_i[0]]; 00221 mCoords[1] = vertices[v_i[1]]; 00222 mCoords[2] = vertices[v_i[2]]; 00223 g.resize( 3 ); 00224 if( !g_fcn_2e( m, arrptr( g ), mCoords, n, a2Con, b2Con, c2Con ) ) return false; 00225 break; 00226 00227 case QUADRILATERAL: 00228 pd.get_domain_normal_at_element( e, n, err ); 00229 MSQ_ERRZERO( err ); 00230 n /= n.length(); // Need unit normal 00231 for( i = 0; i < 4; ++i ) 00232 { 00233 mCoords[0] = vertices[v_i[locs_hex[i][0]]]; 00234 mCoords[1] = vertices[v_i[locs_hex[i][1]]]; 00235 mCoords[2] = vertices[v_i[locs_hex[i][2]]]; 00236 if( !g_fcn_2i( mMetrics[i], mGradients + 3 * i, mCoords, n, a2Con, b2Con, c2Con, d_con ) ) return false; 00237 } 00238 00239 g.resize( 4 ); 00240 m = average_corner_gradients( QUADRILATERAL, fm, 4, mMetrics, mGradients, arrptr( g ), err ); 00241 MSQ_ERRZERO( err ); 00242 break; 00243 00244 case TETRAHEDRON: 00245 mCoords[0] = vertices[v_i[0]]; 00246 mCoords[1] = vertices[v_i[1]]; 00247 mCoords[2] = vertices[v_i[2]]; 00248 mCoords[3] = vertices[v_i[3]]; 00249 g.resize( 4 ); 00250 metric_valid = g_fcn_3e( m, arrptr( g ), mCoords, a3Con, b3Con, c3Con ); 00251 if( !metric_valid ) return false; 00252 break; 00253 00254 case PYRAMID: 00255 for( i = 0; i < 4; ++i ) 00256 { 00257 mCoords[0] = vertices[v_i[i]]; 00258 mCoords[1] = vertices[v_i[( i + 1 ) % 4]]; 00259 mCoords[2] = vertices[v_i[( i + 3 ) % 4]]; 00260 mCoords[3] = vertices[v_i[4]]; 00261 metric_valid = g_fcn_3p( mMetrics[i], mGradients + 4 * i, mCoords, a3Con, b3Con, c3Con ); 00262 if( !metric_valid ) return false; 00263 } 00264 g.resize( 5 ); 00265 m = average_corner_gradients( PYRAMID, fm, 4, mMetrics, mGradients, arrptr( g ), err ); 00266 MSQ_ERRZERO( err ); 00267 break; 00268 00269 case PRISM: 00270 for( i = 0; i < 6; ++i ) 00271 { 00272 mCoords[0] = vertices[v_i[locs_pri[i][0]]]; 00273 mCoords[1] = vertices[v_i[locs_pri[i][1]]]; 00274 mCoords[2] = vertices[v_i[locs_pri[i][2]]]; 00275 mCoords[3] = vertices[v_i[locs_pri[i][3]]]; 00276 if( !g_fcn_3w( mMetrics[i], mGradients + 4 * i, mCoords, a3Con, b3Con, c3Con ) ) return false; 00277 } 00278 g.resize( 6 ); 00279 m = average_corner_gradients( PRISM, fm, 6, mMetrics, mGradients, arrptr( g ), err ); 00280 MSQ_ERRZERO( err ); 00281 break; 00282 00283 case HEXAHEDRON: 00284 for( i = 0; i < 8; ++i ) 00285 { 00286 mCoords[0] = vertices[v_i[locs_hex[i][0]]]; 00287 mCoords[1] = vertices[v_i[locs_hex[i][1]]]; 00288 mCoords[2] = vertices[v_i[locs_hex[i][2]]]; 00289 mCoords[3] = vertices[v_i[locs_hex[i][3]]]; 00290 if( !g_fcn_3i( mMetrics[i], mGradients + 4 * i, mCoords, a3Con, b3Con, c3Con, d_con ) ) return false; 00291 } 00292 g.resize( 8 ); 00293 m = average_corner_gradients( HEXAHEDRON, fm, 8, mMetrics, mGradients, arrptr( g ), err ); 00294 MSQ_ERRZERO( err ); 00295 break; 00296 00297 default: 00298 MSQ_SETERR( err ) 00299 ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightMeanRatio", (int)topo ); 00300 return false; 00301 } 00302 00303 remove_fixed_gradients( topo, fm, g ); 00304 return true; 00305 } 00306 00307 bool IdealWeightMeanRatio::evaluate_with_Hessian_diagonal( PatchData& pd, 00308 size_t handle, 00309 double& m, 00310 std::vector< size_t >& indices, 00311 std::vector< Vector3D >& g, 00312 std::vector< SymMatrix3D >& h, 00313 MsqError& err ) 00314 { 00315 const MsqMeshEntity* e = &pd.element_by_index( handle ); 00316 EntityTopology topo = e->get_element_type(); 00317 00318 if( !analytical_average_hessian() && topo != TRIANGLE && topo != TETRAHEDRON ) 00319 { 00320 static bool print = true; 00321 if( print ) 00322 { 00323 MSQ_DBGOUT( 1 ) << "Analyical gradient not available for selected averaging scheme. " 00324 << "Using (possibly much slower) numerical approximation of gradient" 00325 << " of quality metric. " << std::endl; 00326 print = false; 00327 } 00328 return QualityMetric::evaluate_with_Hessian_diagonal( pd, handle, m, indices, g, h, err ); 00329 } 00330 00331 const MsqVertex* vertices = pd.get_vertex_array( err ); 00332 const size_t* v_i = e->get_vertex_index_array(); 00333 00334 Vector3D n; // Surface normal for 2D objects 00335 00336 // Prism and Hex element descriptions 00337 static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 }, 00338 { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } }; 00339 static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 }, 00340 { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } }; 00341 00342 const Vector3D d_con( 1.0, 1.0, 1.0 ); 00343 00344 int i; 00345 00346 bool metric_valid = false; 00347 const uint32_t fm = fixed_vertex_bitmap( pd, e, indices ); 00348 00349 m = 0.0; 00350 00351 switch( topo ) 00352 { 00353 case TRIANGLE: 00354 pd.get_domain_normal_at_element( e, n, err ); 00355 MSQ_ERRZERO( err ); 00356 n = n / n.length(); // Need unit normal 00357 mCoords[0] = vertices[v_i[0]]; 00358 mCoords[1] = vertices[v_i[1]]; 00359 mCoords[2] = vertices[v_i[2]]; 00360 g.resize( 3 ), h.resize( 3 ); 00361 if( !h_fcn_2e( m, arrptr( g ), mHessians, mCoords, n, a2Con, b2Con, c2Con ) ) return false; 00362 h[0] = mHessians[0].upper(); 00363 h[1] = mHessians[3].upper(); 00364 h[2] = mHessians[5].upper(); 00365 break; 00366 00367 case QUADRILATERAL: 00368 pd.get_domain_normal_at_element( e, n, err ); 00369 MSQ_ERRZERO( err ); 00370 n = n / n.length(); // Need unit normal 00371 for( i = 0; i < 4; ++i ) 00372 { 00373 mCoords[0] = vertices[v_i[locs_hex[i][0]]]; 00374 mCoords[1] = vertices[v_i[locs_hex[i][1]]]; 00375 mCoords[2] = vertices[v_i[locs_hex[i][2]]]; 00376 if( !h_fcn_2i( mMetrics[i], mGradients + 3 * i, mHessians + 6 * i, mCoords, n, a2Con, b2Con, c2Con, 00377 d_con ) ) 00378 return false; 00379 } 00380 00381 g.resize( 4 ), h.resize( 4 ); 00382 m = average_corner_hessian_diagonals( QUADRILATERAL, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ), 00383 arrptr( h ), err ); 00384 MSQ_ERRZERO( err ); 00385 break; 00386 00387 case TETRAHEDRON: 00388 mCoords[0] = vertices[v_i[0]]; 00389 mCoords[1] = vertices[v_i[1]]; 00390 mCoords[2] = vertices[v_i[2]]; 00391 mCoords[3] = vertices[v_i[3]]; 00392 g.resize( 4 ), h.resize( 4 ); 00393 metric_valid = h_fcn_3e( m, arrptr( g ), mHessians, mCoords, a3Con, b3Con, c3Con ); 00394 if( !metric_valid ) return false; 00395 h[0] = mHessians[0].upper(); 00396 h[1] = mHessians[4].upper(); 00397 h[2] = mHessians[7].upper(); 00398 h[3] = mHessians[9].upper(); 00399 break; 00400 00401 case PYRAMID: 00402 for( i = 0; i < 4; ++i ) 00403 { 00404 mCoords[0] = vertices[v_i[i]]; 00405 mCoords[1] = vertices[v_i[( i + 1 ) % 4]]; 00406 mCoords[2] = vertices[v_i[( i + 3 ) % 4]]; 00407 mCoords[3] = vertices[v_i[4]]; 00408 metric_valid = 00409 h_fcn_3p( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con ); 00410 if( !metric_valid ) return false; 00411 } 00412 00413 g.resize( 5 ), h.resize( 5 ); 00414 m = average_corner_hessian_diagonals( PYRAMID, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ), 00415 arrptr( h ), err ); 00416 MSQ_ERRZERO( err ); 00417 break; 00418 00419 case PRISM: 00420 for( i = 0; i < 6; ++i ) 00421 { 00422 mCoords[0] = vertices[v_i[locs_pri[i][0]]]; 00423 mCoords[1] = vertices[v_i[locs_pri[i][1]]]; 00424 mCoords[2] = vertices[v_i[locs_pri[i][2]]]; 00425 mCoords[3] = vertices[v_i[locs_pri[i][3]]]; 00426 if( !h_fcn_3w( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con ) ) 00427 return false; 00428 } 00429 00430 g.resize( 6 ), h.resize( 6 ); 00431 m = average_corner_hessian_diagonals( PRISM, fm, 6, mMetrics, mGradients, mHessians, arrptr( g ), 00432 arrptr( h ), err ); 00433 MSQ_ERRZERO( err ); 00434 break; 00435 00436 case HEXAHEDRON: 00437 for( i = 0; i < 8; ++i ) 00438 { 00439 mCoords[0] = vertices[v_i[locs_hex[i][0]]]; 00440 mCoords[1] = vertices[v_i[locs_hex[i][1]]]; 00441 mCoords[2] = vertices[v_i[locs_hex[i][2]]]; 00442 mCoords[3] = vertices[v_i[locs_hex[i][3]]]; 00443 if( !h_fcn_3i( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con, 00444 d_con ) ) 00445 return false; 00446 } 00447 00448 g.resize( 8 ), h.resize( 8 ); 00449 m = average_corner_hessian_diagonals( HEXAHEDRON, fm, 8, mMetrics, mGradients, mHessians, arrptr( g ), 00450 arrptr( h ), err ); 00451 MSQ_ERRZERO( err ); 00452 break; 00453 00454 default: 00455 MSQ_SETERR( err ) 00456 ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightMeanRatio", (int)topo ); 00457 return false; 00458 } // end switch over element type 00459 00460 remove_fixed_diagonals( topo, fm, g, h ); 00461 return true; 00462 } 00463 00464 bool IdealWeightMeanRatio::evaluate_with_Hessian( PatchData& pd, 00465 size_t handle, 00466 double& m, 00467 std::vector< size_t >& indices, 00468 std::vector< Vector3D >& g, 00469 std::vector< Matrix3D >& h, 00470 MsqError& err ) 00471 { 00472 // FUNCTION_TIMER_START(__FUNC__); 00473 const MsqMeshEntity* e = &pd.element_by_index( handle ); 00474 EntityTopology topo = e->get_element_type(); 00475 00476 if( !analytical_average_hessian() && topo != TRIANGLE && topo != TETRAHEDRON ) 00477 { 00478 static bool print = true; 00479 if( print ) 00480 { 00481 MSQ_DBGOUT( 1 ) << "Analyical gradient not available for selected averaging scheme. " 00482 << "Using (possibly much slower) numerical approximation of gradient" 00483 << " of quality metric. " << std::endl; 00484 print = false; 00485 } 00486 return QualityMetric::evaluate_with_Hessian( pd, handle, m, indices, g, h, err ); 00487 } 00488 00489 const MsqVertex* vertices = pd.get_vertex_array( err ); 00490 const size_t* v_i = e->get_vertex_index_array(); 00491 00492 Vector3D n; // Surface normal for 2D objects 00493 00494 // Prism and Hex element descriptions 00495 static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 }, 00496 { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } }; 00497 static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 }, 00498 { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } }; 00499 00500 const Vector3D d_con( 1.0, 1.0, 1.0 ); 00501 00502 int i; 00503 00504 bool metric_valid = false; 00505 const uint32_t fm = fixed_vertex_bitmap( pd, e, indices ); 00506 00507 m = 0.0; 00508 00509 switch( topo ) 00510 { 00511 case TRIANGLE: 00512 pd.get_domain_normal_at_element( e, n, err ); 00513 MSQ_ERRZERO( err ); 00514 n = n / n.length(); // Need unit normal 00515 mCoords[0] = vertices[v_i[0]]; 00516 mCoords[1] = vertices[v_i[1]]; 00517 mCoords[2] = vertices[v_i[2]]; 00518 g.resize( 3 ), h.resize( 6 ); 00519 if( !h_fcn_2e( m, arrptr( g ), arrptr( h ), mCoords, n, a2Con, b2Con, c2Con ) ) return false; 00520 break; 00521 00522 case QUADRILATERAL: 00523 pd.get_domain_normal_at_element( e, n, err ); 00524 MSQ_ERRZERO( err ); 00525 n = n / n.length(); // Need unit normal 00526 for( i = 0; i < 4; ++i ) 00527 { 00528 mCoords[0] = vertices[v_i[locs_hex[i][0]]]; 00529 mCoords[1] = vertices[v_i[locs_hex[i][1]]]; 00530 mCoords[2] = vertices[v_i[locs_hex[i][2]]]; 00531 if( !h_fcn_2i( mMetrics[i], mGradients + 3 * i, mHessians + 6 * i, mCoords, n, a2Con, b2Con, c2Con, 00532 d_con ) ) 00533 return false; 00534 } 00535 00536 g.resize( 4 ), h.resize( 10 ); 00537 m = average_corner_hessians( QUADRILATERAL, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ), 00538 arrptr( h ), err ); 00539 MSQ_ERRZERO( err ); 00540 break; 00541 00542 case TETRAHEDRON: 00543 mCoords[0] = vertices[v_i[0]]; 00544 mCoords[1] = vertices[v_i[1]]; 00545 mCoords[2] = vertices[v_i[2]]; 00546 mCoords[3] = vertices[v_i[3]]; 00547 g.resize( 4 ), h.resize( 10 ); 00548 metric_valid = h_fcn_3e( m, arrptr( g ), arrptr( h ), mCoords, a3Con, b3Con, c3Con ); 00549 if( !metric_valid ) return false; 00550 break; 00551 00552 case PYRAMID: 00553 for( i = 0; i < 4; ++i ) 00554 { 00555 mCoords[0] = vertices[v_i[i]]; 00556 mCoords[1] = vertices[v_i[( i + 1 ) % 4]]; 00557 mCoords[2] = vertices[v_i[( i + 3 ) % 4]]; 00558 mCoords[3] = vertices[v_i[4]]; 00559 metric_valid = 00560 h_fcn_3p( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con ); 00561 if( !metric_valid ) return false; 00562 } 00563 00564 g.resize( 5 ), h.resize( 15 ); 00565 m = average_corner_hessians( PYRAMID, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ), arrptr( h ), 00566 err ); 00567 MSQ_ERRZERO( err ); 00568 break; 00569 00570 case PRISM: 00571 for( i = 0; i < 6; ++i ) 00572 { 00573 mCoords[0] = vertices[v_i[locs_pri[i][0]]]; 00574 mCoords[1] = vertices[v_i[locs_pri[i][1]]]; 00575 mCoords[2] = vertices[v_i[locs_pri[i][2]]]; 00576 mCoords[3] = vertices[v_i[locs_pri[i][3]]]; 00577 if( !h_fcn_3w( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con ) ) 00578 return false; 00579 } 00580 00581 g.resize( 6 ), h.resize( 21 ); 00582 m = average_corner_hessians( PRISM, fm, 6, mMetrics, mGradients, mHessians, arrptr( g ), arrptr( h ), err ); 00583 MSQ_ERRZERO( err ); 00584 break; 00585 00586 case HEXAHEDRON: 00587 for( i = 0; i < 8; ++i ) 00588 { 00589 mCoords[0] = vertices[v_i[locs_hex[i][0]]]; 00590 mCoords[1] = vertices[v_i[locs_hex[i][1]]]; 00591 mCoords[2] = vertices[v_i[locs_hex[i][2]]]; 00592 mCoords[3] = vertices[v_i[locs_hex[i][3]]]; 00593 if( !h_fcn_3i( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con, 00594 d_con ) ) 00595 return false; 00596 } 00597 00598 g.resize( 8 ), h.resize( 36 ); 00599 m = average_corner_hessians( HEXAHEDRON, fm, 8, mMetrics, mGradients, mHessians, arrptr( g ), arrptr( h ), 00600 err ); 00601 MSQ_ERRZERO( err ); 00602 break; 00603 00604 default: 00605 MSQ_SETERR( err ) 00606 ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightMeanRatio", (int)topo ); 00607 return false; 00608 } // end switch over element type 00609 00610 remove_fixed_gradients( topo, fm, g ); 00611 remove_fixed_hessians( topo, fm, h ); 00612 // FUNCTION_TIMER_END(); 00613 return true; 00614 }