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