LCOV - code coverage report
Current view: top level - src/mesquite/QualityMetric/Shape - IdealWeightMeanRatio.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 97 331 29.3 %
Date: 2020-07-18 00:09:26 Functions: 7 8 87.5 %
Branches: 110 936 11.8 %

           Branch data     Line data    Source code
       1                 :            : /* *****************************************************************
       2                 :            :     MESQUITE -- The Mesh Quality Improvement Toolkit
       3                 :            : 
       4                 :            :     Copyright 2004 Sandia Corporation and Argonne National
       5                 :            :     Laboratory.  Under the terms of Contract DE-AC04-94AL85000
       6                 :            :     with Sandia Corporation, the U.S. Government retains certain
       7                 :            :     rights in this software.
       8                 :            : 
       9                 :            :     This library is free software; you can redistribute it and/or
      10                 :            :     modify it under the terms of the GNU Lesser General Public
      11                 :            :     License as published by the Free Software Foundation; either
      12                 :            :     version 2.1 of the License, or (at your option) any later version.
      13                 :            : 
      14                 :            :     This library is distributed in the hope that it will be useful,
      15                 :            :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      16                 :            :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17                 :            :     Lesser General Public License for more details.
      18                 :            : 
      19                 :            :     You should have received a copy of the GNU Lesser General Public License
      20                 :            :     (lgpl.txt) along with this library; if not, write to the Free Software
      21                 :            :     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      22                 :            : 
      23                 :            :     [email protected], [email protected], [email protected],
      24                 :            :     [email protected], [email protected], [email protected]
      25                 :            : 
      26                 :            :   ***************************************************************** */
      27                 :            : /*!
      28                 :            :   \file   IdealWeightMeanRatio.cpp
      29                 :            :   \brief
      30                 :            : 
      31                 :            :   \author Michael Brewer
      32                 :            :   \date   2002-11-11
      33                 :            : */
      34                 :            : #include "IdealWeightMeanRatio.hpp"
      35                 :            : #include "MeanRatioFunctions.hpp"
      36                 :            : #include "Vector3D.hpp"
      37                 :            : #include "MsqTimer.hpp"
      38                 :            : #include "MsqDebug.hpp"
      39                 :            : #include "MsqError.hpp"
      40                 :            : #include "PatchData.hpp"
      41                 :            : 
      42                 :            : #include <math.h>
      43                 :            : #include <vector>
      44                 :            : using std::vector;
      45                 :            : 
      46                 :            : using namespace MBMesquite;
      47                 :            : 
      48                 :         12 : std::string IdealWeightMeanRatio::get_name() const
      49                 :            : {
      50         [ +  - ]:         12 :     return "Mean Ratio";
      51                 :            : }
      52                 :            : 
      53                 :        204 : int IdealWeightMeanRatio::get_negate_flag() const
      54                 :            : {
      55                 :        204 :     return -1;
      56                 :            : }
      57                 :            : 
      58                 :          6 : bool IdealWeightMeanRatio::evaluate( PatchData& pd, size_t handle, double& m, MsqError& err )
      59                 :            : {
      60         [ +  - ]:          6 :     const MsqMeshEntity* e = &pd.element_by_index( handle );
      61         [ +  - ]:          6 :     EntityTopology topo    = e->get_element_type();
      62                 :            : 
      63         [ +  - ]:          6 :     const MsqVertex* vertices = pd.get_vertex_array( err );
      64         [ +  - ]:          6 :     const size_t* v_i         = e->get_vertex_index_array();
      65                 :            : 
      66         [ +  - ]:          6 :     Vector3D n;  // Surface normal for 2D objects
      67                 :            : 
      68                 :            :     // Prism and Hex element descriptions
      69                 :            :     static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 },
      70                 :            :                                         { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } };
      71                 :            :     static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 },
      72                 :            :                                         { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } };
      73                 :            : 
      74         [ +  - ]:          6 :     const Vector3D d_con( 1.0, 1.0, 1.0 );
      75                 :            : 
      76                 :            :     int i;
      77                 :            : 
      78                 :          6 :     m                 = 0.0;
      79                 :          6 :     bool metric_valid = false;
      80   [ -  -  -  -  :          6 :     switch( topo )
                +  -  - ]
      81                 :            :     {
      82                 :            :         case TRIANGLE:
      83         [ #  # ]:          0 :             pd.get_domain_normal_at_element( e, n, err );
      84 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
      85 [ #  # ][ #  # ]:          0 :             n            = n / n.length();  // Need unit normal
                 [ #  # ]
      86         [ #  # ]:          0 :             mCoords[0]   = vertices[v_i[0]];
      87         [ #  # ]:          0 :             mCoords[1]   = vertices[v_i[1]];
      88         [ #  # ]:          0 :             mCoords[2]   = vertices[v_i[2]];
      89         [ #  # ]:          0 :             metric_valid = m_fcn_2e( m, mCoords, n, a2Con, b2Con, c2Con );
      90         [ #  # ]:          0 :             if( !metric_valid ) return false;
      91                 :          0 :             break;
      92                 :            : 
      93                 :            :         case QUADRILATERAL:
      94         [ #  # ]:          0 :             pd.get_domain_normal_at_element( e, n, err );
      95 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
      96         [ #  # ]:          0 :             for( i = 0; i < 4; ++i )
      97                 :            :             {
      98 [ #  # ][ #  # ]:          0 :                 n            = n / n.length();  // Need unit normal
                 [ #  # ]
      99         [ #  # ]:          0 :                 mCoords[0]   = vertices[v_i[locs_hex[i][0]]];
     100         [ #  # ]:          0 :                 mCoords[1]   = vertices[v_i[locs_hex[i][1]]];
     101         [ #  # ]:          0 :                 mCoords[2]   = vertices[v_i[locs_hex[i][2]]];
     102         [ #  # ]:          0 :                 metric_valid = m_fcn_2i( mMetrics[i], mCoords, n, a2Con, b2Con, c2Con, d_con );
     103         [ #  # ]:          0 :                 if( !metric_valid ) return false;
     104                 :            :             }
     105         [ #  # ]:          0 :             m = average_metrics( mMetrics, 4, err );
     106 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     107                 :          0 :             break;
     108                 :            : 
     109                 :            :         case TETRAHEDRON:
     110         [ #  # ]:          0 :             mCoords[0]   = vertices[v_i[0]];
     111         [ #  # ]:          0 :             mCoords[1]   = vertices[v_i[1]];
     112         [ #  # ]:          0 :             mCoords[2]   = vertices[v_i[2]];
     113         [ #  # ]:          0 :             mCoords[3]   = vertices[v_i[3]];
     114         [ #  # ]:          0 :             metric_valid = m_fcn_3e( m, mCoords, a3Con, b3Con, c3Con );
     115         [ #  # ]:          0 :             if( !metric_valid ) return false;
     116                 :          0 :             break;
     117                 :            : 
     118                 :            :         case PYRAMID:
     119         [ #  # ]:          0 :             for( i = 0; i < 4; ++i )
     120                 :            :             {
     121         [ #  # ]:          0 :                 mCoords[0]   = vertices[v_i[i]];
     122         [ #  # ]:          0 :                 mCoords[1]   = vertices[v_i[( i + 1 ) % 4]];
     123         [ #  # ]:          0 :                 mCoords[2]   = vertices[v_i[( i + 3 ) % 4]];
     124         [ #  # ]:          0 :                 mCoords[3]   = vertices[v_i[4]];
     125         [ #  # ]:          0 :                 metric_valid = m_fcn_3p( mMetrics[i], mCoords, a3Con, b3Con, c3Con );
     126         [ #  # ]:          0 :                 if( !metric_valid ) return false;
     127                 :            :             }
     128         [ #  # ]:          0 :             m = average_metrics( mMetrics, 4, err );
     129 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     130                 :          0 :             break;
     131                 :            : 
     132                 :            :         case PRISM:
     133         [ +  + ]:         42 :             for( i = 0; i < 6; ++i )
     134                 :            :             {
     135         [ +  - ]:         36 :                 mCoords[0]   = vertices[v_i[locs_pri[i][0]]];
     136         [ +  - ]:         36 :                 mCoords[1]   = vertices[v_i[locs_pri[i][1]]];
     137         [ +  - ]:         36 :                 mCoords[2]   = vertices[v_i[locs_pri[i][2]]];
     138         [ +  - ]:         36 :                 mCoords[3]   = vertices[v_i[locs_pri[i][3]]];
     139         [ +  - ]:         36 :                 metric_valid = m_fcn_3w( mMetrics[i], mCoords, a3Con, b3Con, c3Con );
     140         [ -  + ]:         36 :                 if( !metric_valid ) return false;
     141                 :            :             }
     142         [ +  - ]:          6 :             m = average_metrics( mMetrics, 6, err );
     143 [ +  - ][ -  + ]:          6 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     144                 :          6 :             break;
     145                 :            : 
     146                 :            :         case HEXAHEDRON:
     147         [ #  # ]:          0 :             for( i = 0; i < 8; ++i )
     148                 :            :             {
     149         [ #  # ]:          0 :                 mCoords[0]   = vertices[v_i[locs_hex[i][0]]];
     150         [ #  # ]:          0 :                 mCoords[1]   = vertices[v_i[locs_hex[i][1]]];
     151         [ #  # ]:          0 :                 mCoords[2]   = vertices[v_i[locs_hex[i][2]]];
     152         [ #  # ]:          0 :                 mCoords[3]   = vertices[v_i[locs_hex[i][3]]];
     153         [ #  # ]:          0 :                 metric_valid = m_fcn_3i( mMetrics[i], mCoords, a3Con, b3Con, c3Con, d_con );
     154         [ #  # ]:          0 :                 if( !metric_valid ) return false;
     155                 :            :             }
     156         [ #  # ]:          0 :             m = average_metrics( mMetrics, 8, err );
     157 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     158                 :          0 :             break;
     159                 :            : 
     160                 :            :         default:
     161                 :            :             MSQ_SETERR( err )
     162 [ #  # ][ #  # ]:          0 :             ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightMeanRatio", (int)topo );
     163                 :          0 :             return false;
     164                 :            :     }  // end switch over element type
     165                 :          6 :     return true;
     166                 :            : }
     167                 :            : 
     168                 :        166 : bool IdealWeightMeanRatio::evaluate_with_gradient( PatchData& pd, size_t handle, double& m,
     169                 :            :                                                    std::vector< size_t >& indices, std::vector< Vector3D >& g,
     170                 :            :                                                    MsqError& err )
     171                 :            : {
     172                 :            :     //  FUNCTION_TIMER_START(__FUNC__);
     173         [ +  - ]:        166 :     const MsqMeshEntity* e = &pd.element_by_index( handle );
     174         [ +  - ]:        166 :     EntityTopology topo    = e->get_element_type();
     175                 :            : 
     176 [ +  - ][ -  + ]:        166 :     if( !analytical_average_gradient() && topo != TRIANGLE && topo != TETRAHEDRON )
         [ #  # ][ #  # ]
                 [ -  + ]
     177                 :            :     {
     178                 :            :         static bool print = true;
     179         [ #  # ]:          0 :         if( print )
     180                 :            :         {
     181                 :            :             MSQ_DBGOUT( 1 ) << "Analyical gradient not available for selected averaging scheme. "
     182                 :            :                             << "Using (possibly much slower) numerical approximation of gradient"
     183                 :            :                             << " of quality metric. " << std::endl;
     184                 :          0 :             print = false;
     185                 :            :         }
     186         [ #  # ]:          0 :         return QualityMetric::evaluate_with_gradient( pd, handle, m, indices, g, err );
     187                 :            :     }
     188                 :            : 
     189         [ +  - ]:        166 :     const MsqVertex* vertices = pd.get_vertex_array( err );
     190         [ +  - ]:        166 :     const size_t* v_i         = e->get_vertex_index_array();
     191                 :            : 
     192         [ +  - ]:        166 :     Vector3D n;  // Surface normal for 2D objects
     193                 :            : 
     194                 :            :     // double   nm, t=0;
     195                 :            : 
     196                 :            :     // Prism and Hex element descriptions
     197                 :            :     static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 },
     198                 :            :                                         { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } };
     199                 :            :     static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 },
     200                 :            :                                         { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } };
     201                 :            : 
     202         [ +  - ]:        166 :     const Vector3D d_con( 1.0, 1.0, 1.0 );
     203                 :            : 
     204                 :            :     int i;
     205                 :            : 
     206                 :        166 :     bool metric_valid = false;
     207         [ +  - ]:        166 :     const uint32_t fm = fixed_vertex_bitmap( pd, e, indices );
     208                 :            : 
     209                 :        166 :     m = 0.0;
     210                 :            : 
     211   [ -  -  -  +  :        166 :     switch( topo )
                +  -  - ]
     212                 :            :     {
     213                 :            :         case TRIANGLE:
     214         [ #  # ]:          0 :             pd.get_domain_normal_at_element( e, n, err );
     215 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     216 [ #  # ][ #  # ]:          0 :             n          = n / n.length();  // Need unit normal
                 [ #  # ]
     217         [ #  # ]:          0 :             mCoords[0] = vertices[v_i[0]];
     218         [ #  # ]:          0 :             mCoords[1] = vertices[v_i[1]];
     219         [ #  # ]:          0 :             mCoords[2] = vertices[v_i[2]];
     220         [ #  # ]:          0 :             g.resize( 3 );
     221 [ #  # ][ #  # ]:          0 :             if( !g_fcn_2e( m, arrptr( g ), mCoords, n, a2Con, b2Con, c2Con ) ) return false;
                 [ #  # ]
     222                 :          0 :             break;
     223                 :            : 
     224                 :            :         case QUADRILATERAL:
     225         [ #  # ]:          0 :             pd.get_domain_normal_at_element( e, n, err );
     226 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     227 [ #  # ][ #  # ]:          0 :             n /= n.length();  // Need unit normal
     228         [ #  # ]:          0 :             for( i = 0; i < 4; ++i )
     229                 :            :             {
     230         [ #  # ]:          0 :                 mCoords[0] = vertices[v_i[locs_hex[i][0]]];
     231         [ #  # ]:          0 :                 mCoords[1] = vertices[v_i[locs_hex[i][1]]];
     232         [ #  # ]:          0 :                 mCoords[2] = vertices[v_i[locs_hex[i][2]]];
     233 [ #  # ][ #  # ]:          0 :                 if( !g_fcn_2i( mMetrics[i], mGradients + 3 * i, mCoords, n, a2Con, b2Con, c2Con, d_con ) ) return false;
     234                 :            :             }
     235                 :            : 
     236         [ #  # ]:          0 :             g.resize( 4 );
     237 [ #  # ][ #  # ]:          0 :             m = average_corner_gradients( QUADRILATERAL, fm, 4, mMetrics, mGradients, arrptr( g ), err );
     238 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     239                 :          0 :             break;
     240                 :            : 
     241                 :            :         case TETRAHEDRON:
     242         [ #  # ]:          0 :             mCoords[0] = vertices[v_i[0]];
     243         [ #  # ]:          0 :             mCoords[1] = vertices[v_i[1]];
     244         [ #  # ]:          0 :             mCoords[2] = vertices[v_i[2]];
     245         [ #  # ]:          0 :             mCoords[3] = vertices[v_i[3]];
     246         [ #  # ]:          0 :             g.resize( 4 );
     247 [ #  # ][ #  # ]:          0 :             metric_valid = g_fcn_3e( m, arrptr( g ), mCoords, a3Con, b3Con, c3Con );
     248         [ #  # ]:          0 :             if( !metric_valid ) return false;
     249                 :          0 :             break;
     250                 :            : 
     251                 :            :         case PYRAMID:
     252         [ +  + ]:        480 :             for( i = 0; i < 4; ++i )
     253                 :            :             {
     254         [ +  - ]:        384 :                 mCoords[0]   = vertices[v_i[i]];
     255         [ +  - ]:        384 :                 mCoords[1]   = vertices[v_i[( i + 1 ) % 4]];
     256         [ +  - ]:        384 :                 mCoords[2]   = vertices[v_i[( i + 3 ) % 4]];
     257         [ +  - ]:        384 :                 mCoords[3]   = vertices[v_i[4]];
     258         [ +  - ]:        384 :                 metric_valid = g_fcn_3p( mMetrics[i], mGradients + 4 * i, mCoords, a3Con, b3Con, c3Con );
     259         [ -  + ]:        384 :                 if( !metric_valid ) return false;
     260                 :            :             }
     261         [ +  - ]:         96 :             g.resize( 5 );
     262 [ +  - ][ +  - ]:         96 :             m = average_corner_gradients( PYRAMID, fm, 4, mMetrics, mGradients, arrptr( g ), err );
     263 [ +  - ][ -  + ]:         96 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     264                 :         96 :             break;
     265                 :            : 
     266                 :            :         case PRISM:
     267         [ +  + ]:        485 :             for( i = 0; i < 6; ++i )
     268                 :            :             {
     269         [ +  - ]:        416 :                 mCoords[0] = vertices[v_i[locs_pri[i][0]]];
     270         [ +  - ]:        416 :                 mCoords[1] = vertices[v_i[locs_pri[i][1]]];
     271         [ +  - ]:        416 :                 mCoords[2] = vertices[v_i[locs_pri[i][2]]];
     272         [ +  - ]:        416 :                 mCoords[3] = vertices[v_i[locs_pri[i][3]]];
     273 [ +  - ][ +  + ]:        416 :                 if( !g_fcn_3w( mMetrics[i], mGradients + 4 * i, mCoords, a3Con, b3Con, c3Con ) ) return false;
     274                 :            :             }
     275         [ +  - ]:         69 :             g.resize( 6 );
     276 [ +  - ][ +  - ]:         69 :             m = average_corner_gradients( PRISM, fm, 6, mMetrics, mGradients, arrptr( g ), err );
     277 [ +  - ][ -  + ]:         69 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     278                 :         69 :             break;
     279                 :            : 
     280                 :            :         case HEXAHEDRON:
     281         [ #  # ]:          0 :             for( i = 0; i < 8; ++i )
     282                 :            :             {
     283         [ #  # ]:          0 :                 mCoords[0] = vertices[v_i[locs_hex[i][0]]];
     284         [ #  # ]:          0 :                 mCoords[1] = vertices[v_i[locs_hex[i][1]]];
     285         [ #  # ]:          0 :                 mCoords[2] = vertices[v_i[locs_hex[i][2]]];
     286         [ #  # ]:          0 :                 mCoords[3] = vertices[v_i[locs_hex[i][3]]];
     287 [ #  # ][ #  # ]:          0 :                 if( !g_fcn_3i( mMetrics[i], mGradients + 4 * i, mCoords, a3Con, b3Con, c3Con, d_con ) ) return false;
     288                 :            :             }
     289         [ #  # ]:          0 :             g.resize( 8 );
     290 [ #  # ][ #  # ]:          0 :             m = average_corner_gradients( HEXAHEDRON, fm, 8, mMetrics, mGradients, arrptr( g ), err );
     291 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     292                 :          0 :             break;
     293                 :            : 
     294                 :            :         default:
     295                 :            :             MSQ_SETERR( err )
     296 [ #  # ][ #  # ]:          0 :             ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightMeanRatio", (int)topo );
     297                 :          0 :             return false;
     298                 :            :     }
     299                 :            : 
     300         [ +  - ]:        165 :     remove_fixed_gradients( topo, fm, g );
     301                 :        166 :     return true;
     302                 :            : }
     303                 :            : 
     304                 :          0 : bool IdealWeightMeanRatio::evaluate_with_Hessian_diagonal( PatchData& pd, size_t handle, double& m,
     305                 :            :                                                            std::vector< size_t >& indices, std::vector< Vector3D >& g,
     306                 :            :                                                            std::vector< SymMatrix3D >& h, MsqError& err )
     307                 :            : {
     308         [ #  # ]:          0 :     const MsqMeshEntity* e = &pd.element_by_index( handle );
     309         [ #  # ]:          0 :     EntityTopology topo    = e->get_element_type();
     310                 :            : 
     311 [ #  # ][ #  # ]:          0 :     if( !analytical_average_hessian() && topo != TRIANGLE && topo != TETRAHEDRON )
         [ #  # ][ #  # ]
                 [ #  # ]
     312                 :            :     {
     313                 :            :         static bool print = true;
     314         [ #  # ]:          0 :         if( print )
     315                 :            :         {
     316                 :            :             MSQ_DBGOUT( 1 ) << "Analyical gradient not available for selected averaging scheme. "
     317                 :            :                             << "Using (possibly much slower) numerical approximation of gradient"
     318                 :            :                             << " of quality metric. " << std::endl;
     319                 :          0 :             print = false;
     320                 :            :         }
     321         [ #  # ]:          0 :         return QualityMetric::evaluate_with_Hessian_diagonal( pd, handle, m, indices, g, h, err );
     322                 :            :     }
     323                 :            : 
     324         [ #  # ]:          0 :     const MsqVertex* vertices = pd.get_vertex_array( err );
     325         [ #  # ]:          0 :     const size_t* v_i         = e->get_vertex_index_array();
     326                 :            : 
     327         [ #  # ]:          0 :     Vector3D n;  // Surface normal for 2D objects
     328                 :            : 
     329                 :            :     // Prism and Hex element descriptions
     330                 :            :     static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 },
     331                 :            :                                         { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } };
     332                 :            :     static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 },
     333                 :            :                                         { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } };
     334                 :            : 
     335         [ #  # ]:          0 :     const Vector3D d_con( 1.0, 1.0, 1.0 );
     336                 :            : 
     337                 :            :     int i;
     338                 :            : 
     339                 :          0 :     bool metric_valid = false;
     340         [ #  # ]:          0 :     const uint32_t fm = fixed_vertex_bitmap( pd, e, indices );
     341                 :            : 
     342                 :          0 :     m = 0.0;
     343                 :            : 
     344   [ #  #  #  #  :          0 :     switch( topo )
                #  #  # ]
     345                 :            :     {
     346                 :            :         case TRIANGLE:
     347         [ #  # ]:          0 :             pd.get_domain_normal_at_element( e, n, err );
     348 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     349 [ #  # ][ #  # ]:          0 :             n          = n / n.length();  // Need unit normal
                 [ #  # ]
     350         [ #  # ]:          0 :             mCoords[0] = vertices[v_i[0]];
     351         [ #  # ]:          0 :             mCoords[1] = vertices[v_i[1]];
     352         [ #  # ]:          0 :             mCoords[2] = vertices[v_i[2]];
     353 [ #  # ][ #  # ]:          0 :             g.resize( 3 ), h.resize( 3 );
     354 [ #  # ][ #  # ]:          0 :             if( !h_fcn_2e( m, arrptr( g ), mHessians, mCoords, n, a2Con, b2Con, c2Con ) ) return false;
                 [ #  # ]
     355 [ #  # ][ #  # ]:          0 :             h[0] = mHessians[0].upper();
     356 [ #  # ][ #  # ]:          0 :             h[1] = mHessians[3].upper();
     357 [ #  # ][ #  # ]:          0 :             h[2] = mHessians[5].upper();
     358                 :          0 :             break;
     359                 :            : 
     360                 :            :         case QUADRILATERAL:
     361         [ #  # ]:          0 :             pd.get_domain_normal_at_element( e, n, err );
     362 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     363 [ #  # ][ #  # ]:          0 :             n = n / n.length();  // Need unit normal
                 [ #  # ]
     364         [ #  # ]:          0 :             for( i = 0; i < 4; ++i )
     365                 :            :             {
     366         [ #  # ]:          0 :                 mCoords[0] = vertices[v_i[locs_hex[i][0]]];
     367         [ #  # ]:          0 :                 mCoords[1] = vertices[v_i[locs_hex[i][1]]];
     368         [ #  # ]:          0 :                 mCoords[2] = vertices[v_i[locs_hex[i][2]]];
     369         [ #  # ]:          0 :                 if( !h_fcn_2i( mMetrics[i], mGradients + 3 * i, mHessians + 6 * i, mCoords, n, a2Con, b2Con, c2Con,
     370         [ #  # ]:          0 :                                d_con ) )
     371                 :          0 :                     return false;
     372                 :            :             }
     373                 :            : 
     374 [ #  # ][ #  # ]:          0 :             g.resize( 4 ), h.resize( 4 );
     375                 :            :             m = average_corner_hessian_diagonals( QUADRILATERAL, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ),
     376 [ #  # ][ #  # ]:          0 :                                                   arrptr( h ), err );
                 [ #  # ]
     377 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     378                 :          0 :             break;
     379                 :            : 
     380                 :            :         case TETRAHEDRON:
     381         [ #  # ]:          0 :             mCoords[0] = vertices[v_i[0]];
     382         [ #  # ]:          0 :             mCoords[1] = vertices[v_i[1]];
     383         [ #  # ]:          0 :             mCoords[2] = vertices[v_i[2]];
     384         [ #  # ]:          0 :             mCoords[3] = vertices[v_i[3]];
     385 [ #  # ][ #  # ]:          0 :             g.resize( 4 ), h.resize( 4 );
     386 [ #  # ][ #  # ]:          0 :             metric_valid = h_fcn_3e( m, arrptr( g ), mHessians, mCoords, a3Con, b3Con, c3Con );
     387         [ #  # ]:          0 :             if( !metric_valid ) return false;
     388 [ #  # ][ #  # ]:          0 :             h[0] = mHessians[0].upper();
     389 [ #  # ][ #  # ]:          0 :             h[1] = mHessians[4].upper();
     390 [ #  # ][ #  # ]:          0 :             h[2] = mHessians[7].upper();
     391 [ #  # ][ #  # ]:          0 :             h[3] = mHessians[9].upper();
     392                 :          0 :             break;
     393                 :            : 
     394                 :            :         case PYRAMID:
     395         [ #  # ]:          0 :             for( i = 0; i < 4; ++i )
     396                 :            :             {
     397         [ #  # ]:          0 :                 mCoords[0] = vertices[v_i[i]];
     398         [ #  # ]:          0 :                 mCoords[1] = vertices[v_i[( i + 1 ) % 4]];
     399         [ #  # ]:          0 :                 mCoords[2] = vertices[v_i[( i + 3 ) % 4]];
     400         [ #  # ]:          0 :                 mCoords[3] = vertices[v_i[4]];
     401                 :            :                 metric_valid =
     402         [ #  # ]:          0 :                     h_fcn_3p( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con );
     403         [ #  # ]:          0 :                 if( !metric_valid ) return false;
     404                 :            :             }
     405                 :            : 
     406 [ #  # ][ #  # ]:          0 :             g.resize( 5 ), h.resize( 5 );
     407                 :            :             m = average_corner_hessian_diagonals( PYRAMID, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ),
     408 [ #  # ][ #  # ]:          0 :                                                   arrptr( h ), err );
                 [ #  # ]
     409 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     410                 :          0 :             break;
     411                 :            : 
     412                 :            :         case PRISM:
     413         [ #  # ]:          0 :             for( i = 0; i < 6; ++i )
     414                 :            :             {
     415         [ #  # ]:          0 :                 mCoords[0] = vertices[v_i[locs_pri[i][0]]];
     416         [ #  # ]:          0 :                 mCoords[1] = vertices[v_i[locs_pri[i][1]]];
     417         [ #  # ]:          0 :                 mCoords[2] = vertices[v_i[locs_pri[i][2]]];
     418         [ #  # ]:          0 :                 mCoords[3] = vertices[v_i[locs_pri[i][3]]];
     419 [ #  # ][ #  # ]:          0 :                 if( !h_fcn_3w( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con ) )
     420                 :          0 :                     return false;
     421                 :            :             }
     422                 :            : 
     423 [ #  # ][ #  # ]:          0 :             g.resize( 6 ), h.resize( 6 );
     424                 :            :             m = average_corner_hessian_diagonals( PRISM, fm, 6, mMetrics, mGradients, mHessians, arrptr( g ),
     425 [ #  # ][ #  # ]:          0 :                                                   arrptr( h ), err );
                 [ #  # ]
     426 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     427                 :          0 :             break;
     428                 :            : 
     429                 :            :         case HEXAHEDRON:
     430         [ #  # ]:          0 :             for( i = 0; i < 8; ++i )
     431                 :            :             {
     432         [ #  # ]:          0 :                 mCoords[0] = vertices[v_i[locs_hex[i][0]]];
     433         [ #  # ]:          0 :                 mCoords[1] = vertices[v_i[locs_hex[i][1]]];
     434         [ #  # ]:          0 :                 mCoords[2] = vertices[v_i[locs_hex[i][2]]];
     435         [ #  # ]:          0 :                 mCoords[3] = vertices[v_i[locs_hex[i][3]]];
     436         [ #  # ]:          0 :                 if( !h_fcn_3i( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con,
     437         [ #  # ]:          0 :                                d_con ) )
     438                 :          0 :                     return false;
     439                 :            :             }
     440                 :            : 
     441 [ #  # ][ #  # ]:          0 :             g.resize( 8 ), h.resize( 8 );
     442                 :            :             m = average_corner_hessian_diagonals( HEXAHEDRON, fm, 8, mMetrics, mGradients, mHessians, arrptr( g ),
     443 [ #  # ][ #  # ]:          0 :                                                   arrptr( h ), err );
                 [ #  # ]
     444 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     445                 :          0 :             break;
     446                 :            : 
     447                 :            :         default:
     448                 :            :             MSQ_SETERR( err )
     449 [ #  # ][ #  # ]:          0 :             ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightMeanRatio", (int)topo );
     450                 :          0 :             return false;
     451                 :            :     }  // end switch over element type
     452                 :            : 
     453         [ #  # ]:          0 :     remove_fixed_diagonals( topo, fm, g, h );
     454                 :          0 :     return true;
     455                 :            : }
     456                 :            : 
     457                 :        162 : bool IdealWeightMeanRatio::evaluate_with_Hessian( PatchData& pd, size_t handle, double& m,
     458                 :            :                                                   std::vector< size_t >& indices, std::vector< Vector3D >& g,
     459                 :            :                                                   std::vector< Matrix3D >& h, MsqError& err )
     460                 :            : {
     461                 :            :     //  FUNCTION_TIMER_START(__FUNC__);
     462         [ +  - ]:        162 :     const MsqMeshEntity* e = &pd.element_by_index( handle );
     463         [ +  - ]:        162 :     EntityTopology topo    = e->get_element_type();
     464                 :            : 
     465 [ +  - ][ -  + ]:        162 :     if( !analytical_average_hessian() && topo != TRIANGLE && topo != TETRAHEDRON )
         [ #  # ][ #  # ]
                 [ -  + ]
     466                 :            :     {
     467                 :            :         static bool print = true;
     468         [ #  # ]:          0 :         if( print )
     469                 :            :         {
     470                 :            :             MSQ_DBGOUT( 1 ) << "Analyical gradient not available for selected averaging scheme. "
     471                 :            :                             << "Using (possibly much slower) numerical approximation of gradient"
     472                 :            :                             << " of quality metric. " << std::endl;
     473                 :          0 :             print = false;
     474                 :            :         }
     475         [ #  # ]:          0 :         return QualityMetric::evaluate_with_Hessian( pd, handle, m, indices, g, h, err );
     476                 :            :     }
     477                 :            : 
     478         [ +  - ]:        162 :     const MsqVertex* vertices = pd.get_vertex_array( err );
     479         [ +  - ]:        162 :     const size_t* v_i         = e->get_vertex_index_array();
     480                 :            : 
     481         [ +  - ]:        162 :     Vector3D n;  // Surface normal for 2D objects
     482                 :            : 
     483                 :            :     // Prism and Hex element descriptions
     484                 :            :     static const int locs_pri[6][4] = { { 0, 1, 2, 3 }, { 1, 2, 0, 4 }, { 2, 0, 1, 5 },
     485                 :            :                                         { 3, 5, 4, 0 }, { 4, 3, 5, 1 }, { 5, 4, 3, 2 } };
     486                 :            :     static const int locs_hex[8][4] = { { 0, 1, 3, 4 }, { 1, 2, 0, 5 }, { 2, 3, 1, 6 }, { 3, 0, 2, 7 },
     487                 :            :                                         { 4, 7, 5, 0 }, { 5, 4, 6, 1 }, { 6, 5, 7, 2 }, { 7, 6, 4, 3 } };
     488                 :            : 
     489         [ +  - ]:        162 :     const Vector3D d_con( 1.0, 1.0, 1.0 );
     490                 :            : 
     491                 :            :     int i;
     492                 :            : 
     493                 :        162 :     bool metric_valid = false;
     494         [ +  - ]:        162 :     const uint32_t fm = fixed_vertex_bitmap( pd, e, indices );
     495                 :            : 
     496                 :        162 :     m = 0.0;
     497                 :            : 
     498   [ -  -  -  +  :        162 :     switch( topo )
                +  -  - ]
     499                 :            :     {
     500                 :            :         case TRIANGLE:
     501         [ #  # ]:          0 :             pd.get_domain_normal_at_element( e, n, err );
     502 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     503 [ #  # ][ #  # ]:          0 :             n          = n / n.length();  // Need unit normal
                 [ #  # ]
     504         [ #  # ]:          0 :             mCoords[0] = vertices[v_i[0]];
     505         [ #  # ]:          0 :             mCoords[1] = vertices[v_i[1]];
     506         [ #  # ]:          0 :             mCoords[2] = vertices[v_i[2]];
     507 [ #  # ][ #  # ]:          0 :             g.resize( 3 ), h.resize( 6 );
     508 [ #  # ][ #  # ]:          0 :             if( !h_fcn_2e( m, arrptr( g ), arrptr( h ), mCoords, n, a2Con, b2Con, c2Con ) ) return false;
         [ #  # ][ #  # ]
     509                 :          0 :             break;
     510                 :            : 
     511                 :            :         case QUADRILATERAL:
     512         [ #  # ]:          0 :             pd.get_domain_normal_at_element( e, n, err );
     513 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     514 [ #  # ][ #  # ]:          0 :             n = n / n.length();  // Need unit normal
                 [ #  # ]
     515         [ #  # ]:          0 :             for( i = 0; i < 4; ++i )
     516                 :            :             {
     517         [ #  # ]:          0 :                 mCoords[0] = vertices[v_i[locs_hex[i][0]]];
     518         [ #  # ]:          0 :                 mCoords[1] = vertices[v_i[locs_hex[i][1]]];
     519         [ #  # ]:          0 :                 mCoords[2] = vertices[v_i[locs_hex[i][2]]];
     520         [ #  # ]:          0 :                 if( !h_fcn_2i( mMetrics[i], mGradients + 3 * i, mHessians + 6 * i, mCoords, n, a2Con, b2Con, c2Con,
     521         [ #  # ]:          0 :                                d_con ) )
     522                 :          0 :                     return false;
     523                 :            :             }
     524                 :            : 
     525 [ #  # ][ #  # ]:          0 :             g.resize( 4 ), h.resize( 10 );
     526                 :            :             m = average_corner_hessians( QUADRILATERAL, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ),
     527 [ #  # ][ #  # ]:          0 :                                          arrptr( h ), err );
                 [ #  # ]
     528 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     529                 :          0 :             break;
     530                 :            : 
     531                 :            :         case TETRAHEDRON:
     532         [ #  # ]:          0 :             mCoords[0] = vertices[v_i[0]];
     533         [ #  # ]:          0 :             mCoords[1] = vertices[v_i[1]];
     534         [ #  # ]:          0 :             mCoords[2] = vertices[v_i[2]];
     535         [ #  # ]:          0 :             mCoords[3] = vertices[v_i[3]];
     536 [ #  # ][ #  # ]:          0 :             g.resize( 4 ), h.resize( 10 );
     537 [ #  # ][ #  # ]:          0 :             metric_valid = h_fcn_3e( m, arrptr( g ), arrptr( h ), mCoords, a3Con, b3Con, c3Con );
                 [ #  # ]
     538         [ #  # ]:          0 :             if( !metric_valid ) return false;
     539                 :          0 :             break;
     540                 :            : 
     541                 :            :         case PYRAMID:
     542         [ +  + ]:        480 :             for( i = 0; i < 4; ++i )
     543                 :            :             {
     544         [ +  - ]:        384 :                 mCoords[0] = vertices[v_i[i]];
     545         [ +  - ]:        384 :                 mCoords[1] = vertices[v_i[( i + 1 ) % 4]];
     546         [ +  - ]:        384 :                 mCoords[2] = vertices[v_i[( i + 3 ) % 4]];
     547         [ +  - ]:        384 :                 mCoords[3] = vertices[v_i[4]];
     548                 :            :                 metric_valid =
     549         [ +  - ]:        384 :                     h_fcn_3p( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con );
     550         [ -  + ]:        384 :                 if( !metric_valid ) return false;
     551                 :            :             }
     552                 :            : 
     553 [ +  - ][ +  - ]:         96 :             g.resize( 5 ), h.resize( 15 );
     554                 :            :             m = average_corner_hessians( PYRAMID, fm, 4, mMetrics, mGradients, mHessians, arrptr( g ), arrptr( h ),
     555 [ +  - ][ +  - ]:         96 :                                          err );
                 [ +  - ]
     556 [ +  - ][ -  + ]:         96 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     557                 :         96 :             break;
     558                 :            : 
     559                 :            :         case PRISM:
     560         [ +  + ]:        462 :             for( i = 0; i < 6; ++i )
     561                 :            :             {
     562         [ +  - ]:        396 :                 mCoords[0] = vertices[v_i[locs_pri[i][0]]];
     563         [ +  - ]:        396 :                 mCoords[1] = vertices[v_i[locs_pri[i][1]]];
     564         [ +  - ]:        396 :                 mCoords[2] = vertices[v_i[locs_pri[i][2]]];
     565         [ +  - ]:        396 :                 mCoords[3] = vertices[v_i[locs_pri[i][3]]];
     566 [ +  - ][ -  + ]:        396 :                 if( !h_fcn_3w( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con ) )
     567                 :          0 :                     return false;
     568                 :            :             }
     569                 :            : 
     570 [ +  - ][ +  - ]:         66 :             g.resize( 6 ), h.resize( 21 );
     571 [ +  - ][ +  - ]:         66 :             m = average_corner_hessians( PRISM, fm, 6, mMetrics, mGradients, mHessians, arrptr( g ), arrptr( h ), err );
                 [ +  - ]
     572 [ +  - ][ -  + ]:         66 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     573                 :         66 :             break;
     574                 :            : 
     575                 :            :         case HEXAHEDRON:
     576         [ #  # ]:          0 :             for( i = 0; i < 8; ++i )
     577                 :            :             {
     578         [ #  # ]:          0 :                 mCoords[0] = vertices[v_i[locs_hex[i][0]]];
     579         [ #  # ]:          0 :                 mCoords[1] = vertices[v_i[locs_hex[i][1]]];
     580         [ #  # ]:          0 :                 mCoords[2] = vertices[v_i[locs_hex[i][2]]];
     581         [ #  # ]:          0 :                 mCoords[3] = vertices[v_i[locs_hex[i][3]]];
     582         [ #  # ]:          0 :                 if( !h_fcn_3i( mMetrics[i], mGradients + 4 * i, mHessians + 10 * i, mCoords, a3Con, b3Con, c3Con,
     583         [ #  # ]:          0 :                                d_con ) )
     584                 :          0 :                     return false;
     585                 :            :             }
     586                 :            : 
     587 [ #  # ][ #  # ]:          0 :             g.resize( 8 ), h.resize( 36 );
     588                 :            :             m = average_corner_hessians( HEXAHEDRON, fm, 8, mMetrics, mGradients, mHessians, arrptr( g ), arrptr( h ),
     589 [ #  # ][ #  # ]:          0 :                                          err );
                 [ #  # ]
     590 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     591                 :          0 :             break;
     592                 :            : 
     593                 :            :         default:
     594                 :            :             MSQ_SETERR( err )
     595 [ #  # ][ #  # ]:          0 :             ( MsqError::UNSUPPORTED_ELEMENT, "Element type (%d) not supported in IdealWeightMeanRatio", (int)topo );
     596                 :          0 :             return false;
     597                 :            :     }  // end switch over element type
     598                 :            : 
     599         [ +  - ]:        162 :     remove_fixed_gradients( topo, fm, g );
     600         [ +  - ]:        162 :     remove_fixed_hessians( topo, fm, h );
     601                 :            :     //  FUNCTION_TIMER_END();
     602                 :        162 :     return true;
     603 [ +  - ][ +  - ]:          8 : }

Generated by: LCOV version 1.11