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