LCOV - code coverage report
Current view: top level - src/mesquite/QualityMetric - PMeanPMetric.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 94 187 50.3 %
Date: 2020-07-18 00:09:26 Functions: 5 7 71.4 %
Branches: 136 510 26.7 %

           Branch data     Line data    Source code
       1                 :            : /* *****************************************************************
       2                 :            :     MESQUITE -- The Mesh Quality Improvement Toolkit
       3                 :            : 
       4                 :            :     Copyright 2006 Sandia National Laboratories.  Developed at the
       5                 :            :     University of Wisconsin--Madison under SNL contract number
       6                 :            :     624796.  The U.S. Government and the University of Wisconsin
       7                 :            :     retain certain rights to 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                 :            :     (2006) [email protected]
      24                 :            : 
      25                 :            :   ***************************************************************** */
      26                 :            : 
      27                 :            : /** \file PMeanPMetric.cpp
      28                 :            :  *  \brief
      29                 :            :  *  \author Jason Kraftcheck
      30                 :            :  */
      31                 :            : 
      32                 :            : #include "Mesquite.hpp"
      33                 :            : #include "PMeanPMetric.hpp"
      34                 :            : #include "MsqError.hpp"
      35                 :            : #include "QualityMetric.hpp"
      36                 :            : #include "Vector3D.hpp"
      37                 :            : #include "Matrix3D.hpp"
      38                 :            : #include "SymMatrix3D.hpp"
      39                 :            : #include "PatchData.hpp"
      40                 :            : 
      41                 :            : namespace MBMesquite
      42                 :            : {
      43                 :            : 
      44                 :    4360452 : bool PMeanPMetric::average( PatchData& pd, QualityMetric* metric, const std::vector< size_t >& qm_handles,
      45                 :            :                             double& value, MsqError& err )
      46                 :            : {
      47                 :    4360452 :     bool rval = true;
      48                 :    4360452 :     value     = 0;
      49 [ +  - ][ +  - ]:   13168572 :     for( std::vector< size_t >::const_iterator i = qm_handles.begin(); i != qm_handles.end(); ++i )
                 [ +  + ]
      50                 :            :     {
      51                 :            :         double mval;
      52 [ +  - ][ +  - ]:    8808152 :         if( !metric->evaluate( pd, *i, mval, err ) ) rval = false;
                 [ +  + ]
      53 [ +  - ][ +  + ]:    8808152 :         MSQ_ERRZERO( err );
         [ +  - ][ +  - ]
                 [ +  + ]
      54         [ +  - ]:    8808120 :         value += P.raise( mval );
      55                 :            :     }
      56                 :    4360420 :     value /= qm_handles.size();
      57                 :    4360452 :     return rval;
      58                 :            : }
      59                 :            : 
      60                 :          0 : bool PMeanPMetric::average_with_indices( PatchData& pd, QualityMetric* metric, const std::vector< size_t >& qm_handles,
      61                 :            :                                          double& value, std::vector< size_t >& indices, MsqError& err )
      62                 :            : {
      63                 :          0 :     indices.clear();
      64                 :            : 
      65                 :          0 :     bool rval = true;
      66                 :          0 :     value     = 0;
      67 [ #  # ][ #  # ]:          0 :     for( std::vector< size_t >::const_iterator i = qm_handles.begin(); i != qm_handles.end(); ++i )
                 [ #  # ]
      68                 :            :     {
      69                 :            :         double mval;
      70                 :          0 :         mIndices.clear();
      71 [ #  # ][ #  # ]:          0 :         if( !metric->evaluate_with_indices( pd, *i, mval, mIndices, err ) ) rval = false;
                 [ #  # ]
      72 [ #  # ][ #  # ]:          0 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
      73         [ #  # ]:          0 :         value += P.raise( mval );
      74                 :            : 
      75 [ #  # ][ #  # ]:          0 :         std::copy( mIndices.begin(), mIndices.end(), std::back_inserter( indices ) );
      76                 :            :     }
      77                 :          0 :     std::sort( indices.begin(), indices.end() );
      78                 :          0 :     indices.erase( std::unique( indices.begin(), indices.end() ), indices.end() );
      79                 :            : 
      80                 :          0 :     value /= qm_handles.size();
      81                 :          0 :     return rval;
      82                 :            : }
      83                 :            : 
      84                 :     741906 : bool PMeanPMetric::average_with_gradient( PatchData& pd, QualityMetric* metric, const std::vector< size_t >& qm_handles,
      85                 :            :                                           double& value, std::vector< size_t >& indices,
      86                 :            :                                           std::vector< Vector3D >& gradient, MsqError& err )
      87                 :            : {
      88                 :     741906 :     indices.clear();
      89                 :     741906 :     gradient.clear();
      90                 :            : 
      91                 :     741906 :     std::vector< Vector3D >::iterator g;
      92                 :     741906 :     std::vector< size_t >::iterator j, k;
      93                 :     741906 :     std::vector< size_t >::const_iterator i;
      94                 :            : 
      95                 :     741906 :     bool rval = true;
      96                 :     741906 :     value     = 0;
      97 [ +  - ][ +  - ]:    2806311 :     for( i = qm_handles.begin(); i != qm_handles.end(); ++i )
                 [ +  + ]
      98                 :            :     {
      99                 :            : 
     100                 :            :         double mval;
     101                 :    2064405 :         mIndices.clear();
     102                 :    2064405 :         mGrad.clear();
     103 [ +  - ][ +  - ]:    2064405 :         if( !metric->evaluate_with_gradient( pd, *i, mval, mIndices, mGrad, err ) ) rval = false;
                 [ -  + ]
     104 [ +  - ][ -  + ]:    2064405 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     105         [ +  - ]:    2064405 :         value += P.raise( mval );
     106                 :            : 
     107 [ +  - ][ +  - ]:    2064405 :         double p1val = P.value() * P1.raise( mval );
     108 [ +  - ][ +  - ]:    4684911 :         for( j = mIndices.begin(), g = mGrad.begin(); j != mIndices.end(); ++j, ++g )
         [ +  - ][ +  + ]
     109                 :            :         {
     110                 :            : 
     111 [ +  - ][ +  - ]:    2620506 :             *g *= p1val;
     112 [ +  - ][ +  - ]:    2620506 :             k = std::lower_bound( indices.begin(), indices.end(), *j );
     113 [ +  - ][ +  + ]:    2620506 :             if( k == indices.end() || *k != *j )
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
           [ +  +  #  # ]
     114                 :            :             {
     115 [ +  - ][ +  - ]:    1427016 :                 k          = indices.insert( k, *j );
     116         [ +  - ]:    1427016 :                 size_t idx = k - indices.begin();
     117 [ +  - ][ +  - ]:    1427016 :                 gradient.insert( gradient.begin() + idx, *g );
                 [ +  - ]
     118                 :            :             }
     119                 :            :             else
     120                 :            :             {
     121         [ +  - ]:    1193490 :                 size_t idx = k - indices.begin();
     122 [ +  - ][ +  - ]:    1193490 :                 gradient[idx] += *g;
                 [ +  - ]
     123                 :            :             }
     124                 :            :         }
     125                 :            :     }
     126                 :            : 
     127                 :     741906 :     double inv_n = 1.0 / qm_handles.size();
     128                 :     741906 :     value *= inv_n;
     129 [ +  - ][ +  - ]:    2168922 :     for( g = gradient.begin(); g != gradient.end(); ++g )
                 [ +  + ]
     130 [ +  - ][ +  - ]:    1427016 :         *g *= inv_n;
     131                 :            : 
     132                 :     741906 :     return rval;
     133                 :            : }
     134                 :            : 
     135                 :          0 : bool PMeanPMetric::average_with_Hessian_diagonal( PatchData& pd, QualityMetric* metric,
     136                 :            :                                                   const std::vector< size_t >& qm_handles, double& value,
     137                 :            :                                                   std::vector< size_t >& indices, std::vector< Vector3D >& gradient,
     138                 :            :                                                   std::vector< SymMatrix3D >& diagonal, MsqError& err )
     139                 :            : {
     140                 :            :     // clear temporary storage
     141                 :          0 :     mIndices.clear();
     142                 :          0 :     mGrad.clear();
     143                 :          0 :     mDiag.clear();
     144                 :          0 :     mOffsets.clear();
     145                 :          0 :     mValues.clear();
     146                 :            : 
     147                 :            :     // Evaluate metric for all sample points,
     148                 :            :     // accumulating indices, gradients, and Hessians
     149                 :          0 :     bool rval = true;
     150                 :          0 :     std::vector< size_t >::const_iterator q;
     151 [ #  # ][ #  # ]:          0 :     for( q = qm_handles.begin(); q != qm_handles.end(); ++q )
                 [ #  # ]
     152                 :            :     {
     153                 :            :         double mval;
     154                 :          0 :         indices.clear();
     155                 :          0 :         gradient.clear();
     156                 :          0 :         diagonal.clear();
     157 [ #  # ][ #  # ]:          0 :         if( !metric->evaluate_with_Hessian_diagonal( pd, *q, mval, indices, gradient, diagonal, err ) ) rval = false;
                 [ #  # ]
     158 [ #  # ][ #  # ]:          0 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     159                 :            : 
     160         [ #  # ]:          0 :         mValues.push_back( mval );
     161         [ #  # ]:          0 :         mOffsets.push_back( mIndices.size() );
     162 [ #  # ][ #  # ]:          0 :         std::copy( indices.begin(), indices.end(), std::back_inserter( mIndices ) );
     163 [ #  # ][ #  # ]:          0 :         std::copy( gradient.begin(), gradient.end(), std::back_inserter( mGrad ) );
     164 [ #  # ][ #  # ]:          0 :         std::copy( diagonal.begin(), diagonal.end(), std::back_inserter( mDiag ) );
     165                 :            :     }
     166         [ #  # ]:          0 :     mOffsets.push_back( mIndices.size() );
     167                 :            : 
     168                 :            :     // Combine lists of free vertex indices, and update indices
     169                 :            :     // in per-evaluation lists to point into the combined gradient
     170                 :            :     // and Hessian lists.
     171         [ #  # ]:          0 :     indices = mIndices;
     172         [ #  # ]:          0 :     std::sort( indices.begin(), indices.end() );
     173 [ #  # ][ #  # ]:          0 :     indices.erase( std::unique( indices.begin(), indices.end() ), indices.end() );
     174                 :          0 :     std::vector< size_t >::iterator i, j;
     175 [ #  # ][ #  # ]:          0 :     for( i = mIndices.begin(); i != mIndices.end(); ++i )
                 [ #  # ]
     176                 :            :     {
     177 [ #  # ][ #  # ]:          0 :         j = std::lower_bound( indices.begin(), indices.end(), *i );
     178 [ #  # ][ #  # ]:          0 :         assert( *j == *i );
                 [ #  # ]
     179 [ #  # ][ #  # ]:          0 :         *i = j - indices.begin();
     180                 :            :     }
     181                 :            : 
     182                 :            :     // Allocate space and zero output gradient and Hessian lists
     183                 :          0 :     const size_t n     = indices.size();
     184                 :          0 :     const size_t m     = mValues.size();
     185                 :          0 :     const double inv_n = 1.0 / m;
     186                 :            :     double v;
     187                 :          0 :     gradient.clear();
     188 [ #  # ][ #  # ]:          0 :     gradient.resize( n, Vector3D( 0, 0, 0 ) );
     189                 :          0 :     diagonal.clear();
     190 [ #  # ][ #  # ]:          0 :     diagonal.resize( n, SymMatrix3D( 0.0 ) );
     191                 :            : 
     192                 :            :     // Average values, gradients, Hessians
     193                 :          0 :     value = 0.0;
     194         [ #  # ]:          0 :     for( size_t k = 0; k < m; ++k )
     195                 :            :     {  // for each metric evaluate
     196 [ #  # ][ #  # ]:          0 :         if( P.value() == 1.0 )
     197                 :            :         {
     198 [ #  # ][ #  # ]:          0 :             v = P.raise( mValues[k] );
     199                 :            :             // for each gradient (or Hessian) for the local metric evaluation
     200 [ #  # ][ #  # ]:          0 :             for( size_t r = mOffsets[k]; r < mOffsets[k + 1]; ++r )
                 [ #  # ]
     201                 :            :             {
     202         [ #  # ]:          0 :                 const size_t nr = mIndices[r];
     203                 :            : 
     204 [ #  # ][ #  # ]:          0 :                 mDiag[r] *= inv_n;
     205 [ #  # ][ #  # ]:          0 :                 diagonal[nr] += mDiag[r];
                 [ #  # ]
     206 [ #  # ][ #  # ]:          0 :                 mGrad[r] *= inv_n;
     207 [ #  # ][ #  # ]:          0 :                 gradient[nr] += mGrad[r];
                 [ #  # ]
     208                 :            :             }
     209                 :            :         }
     210                 :            :         else
     211                 :            :         {
     212 [ #  # ][ #  # ]:          0 :             const double r2 = P2.raise( mValues[k] );
     213         [ #  # ]:          0 :             const double r1 = r2 * mValues[k];
     214         [ #  # ]:          0 :             v               = r1 * mValues[k];
     215 [ #  # ][ #  # ]:          0 :             const double h  = r2 * P.value() * ( P.value() - 1 ) * inv_n;
     216         [ #  # ]:          0 :             const double g  = r1 * P.value() * inv_n;
     217                 :            :             // for each gradient (or Hessian) for the local metric evaluation
     218 [ #  # ][ #  # ]:          0 :             for( size_t r = mOffsets[k]; r < mOffsets[k + 1]; ++r )
                 [ #  # ]
     219                 :            :             {
     220         [ #  # ]:          0 :                 const size_t nr = mIndices[r];
     221                 :            : 
     222 [ #  # ][ #  # ]:          0 :                 mDiag[r] *= g;
     223 [ #  # ][ #  # ]:          0 :                 diagonal[nr] += mDiag[r];
                 [ #  # ]
     224 [ #  # ][ #  # ]:          0 :                 diagonal[nr] += h * outer( mGrad[r] );
         [ #  # ][ #  # ]
                 [ #  # ]
     225 [ #  # ][ #  # ]:          0 :                 mGrad[r] *= g;
     226 [ #  # ][ #  # ]:          0 :                 gradient[nr] += mGrad[r];
                 [ #  # ]
     227                 :            :             }
     228                 :            :         }
     229                 :          0 :         value += v;
     230                 :            :     }
     231                 :            : 
     232                 :          0 :     value *= inv_n;
     233                 :            : 
     234                 :          0 :     return rval;
     235                 :            : }
     236                 :            : 
     237                 :     124856 : bool PMeanPMetric::average_with_Hessian( PatchData& pd, QualityMetric* metric, const std::vector< size_t >& qm_handles,
     238                 :            :                                          double& value, std::vector< size_t >& indices,
     239                 :            :                                          std::vector< Vector3D >& gradient, std::vector< Matrix3D >& Hessian,
     240                 :            :                                          MsqError& err )
     241                 :            : {
     242                 :            :     // clear temporary storage
     243                 :     124856 :     mIndices.clear();
     244                 :     124856 :     mGrad.clear();
     245                 :     124856 :     mHess.clear();
     246                 :     124856 :     mOffsets.clear();
     247                 :     124856 :     mValues.clear();
     248                 :            : 
     249                 :            :     // Evaluate metric for all sample points,
     250                 :            :     // accumulating indices, gradients, and Hessians
     251                 :     124856 :     bool rval = true;
     252                 :     124856 :     std::vector< size_t >::const_iterator q;
     253 [ +  - ][ +  - ]:     624280 :     for( q = qm_handles.begin(); q != qm_handles.end(); ++q )
                 [ +  + ]
     254                 :            :     {
     255                 :            :         double mval;
     256                 :     499424 :         indices.clear();
     257                 :     499424 :         gradient.clear();
     258                 :     499424 :         Hessian.clear();
     259 [ +  - ][ +  - ]:     499424 :         if( !metric->evaluate_with_Hessian( pd, *q, mval, indices, gradient, Hessian, err ) ) rval = false;
                 [ -  + ]
     260 [ +  - ][ -  + ]:     499424 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     261                 :            : 
     262         [ +  - ]:     499424 :         mValues.push_back( mval );
     263         [ +  - ]:     499424 :         mOffsets.push_back( mIndices.size() );
     264 [ +  - ][ +  - ]:     499424 :         std::copy( indices.begin(), indices.end(), std::back_inserter( mIndices ) );
     265 [ +  - ][ +  - ]:     499424 :         std::copy( gradient.begin(), gradient.end(), std::back_inserter( mGrad ) );
     266 [ +  - ][ +  - ]:     499424 :         std::copy( Hessian.begin(), Hessian.end(), std::back_inserter( mHess ) );
     267                 :            :     }
     268         [ +  - ]:     124856 :     mOffsets.push_back( mIndices.size() );
     269                 :            : 
     270                 :            :     // Combine lists of free vertex indices, and update indices
     271                 :            :     // in per-evaluation lists to point into the combined gradient
     272                 :            :     // and Hessian lists.
     273         [ +  - ]:     124856 :     indices = mIndices;
     274         [ +  - ]:     124856 :     std::sort( indices.begin(), indices.end() );
     275 [ +  - ][ +  - ]:     124856 :     indices.erase( std::unique( indices.begin(), indices.end() ), indices.end() );
     276                 :     124856 :     std::vector< size_t >::iterator i, j;
     277 [ +  - ][ +  - ]:    1613564 :     for( i = mIndices.begin(); i != mIndices.end(); ++i )
                 [ +  + ]
     278                 :            :     {
     279 [ +  - ][ +  - ]:    1488708 :         j = std::lower_bound( indices.begin(), indices.end(), *i );
     280 [ +  - ][ +  - ]:    1488708 :         assert( *j == *i );
                 [ -  + ]
     281 [ +  - ][ +  - ]:    1488708 :         *i = j - indices.begin();
     282                 :            :     }
     283                 :            : 
     284                 :            :     // Allocate space and zero output gradient and Hessian lists
     285                 :     124856 :     const size_t N     = indices.size();
     286                 :     124856 :     const size_t m     = mValues.size();
     287                 :     124856 :     const double inv_n = 1.0 / m;
     288                 :            :     double v;
     289                 :     124856 :     gradient.clear();
     290 [ +  - ][ +  - ]:     124856 :     gradient.resize( N, Vector3D( 0, 0, 0 ) );
     291                 :     124856 :     Hessian.clear();
     292 [ +  - ][ +  - ]:     124856 :     Hessian.resize( N * ( N + 1 ) / 2, Matrix3D( 0.0 ) );
     293                 :            : 
     294                 :            :     // Average values, gradients, Hessians
     295         [ +  - ]:     124856 :     Matrix3D outer;
     296                 :     124856 :     value                                           = 0.0;
     297                 :     124856 :     std::vector< Matrix3D >::iterator met_hess_iter = mHess.begin();
     298         [ +  + ]:     624280 :     for( size_t k = 0; k < m; ++k )
     299                 :            :     {  // for each metric evaluate
     300 [ +  - ][ +  - ]:     499424 :         if( P.value() == 1.0 )
     301                 :            :         {
     302 [ +  - ][ +  - ]:     499424 :             v = P.raise( mValues[k] );
     303                 :            :             // for each gradient (or Hessian row) for the local metric evaluation
     304 [ +  - ][ +  - ]:    1988132 :             for( size_t r = mOffsets[k]; r < mOffsets[k + 1]; ++r )
                 [ +  + ]
     305                 :            :             {
     306         [ +  - ]:    1488708 :                 const size_t nr = mIndices[r];
     307                 :            :                 // for each column of the local metric Hessian
     308 [ +  - ][ +  + ]:    4459904 :                 for( size_t c = r; c < mOffsets[k + 1]; ++c )
     309                 :            :                 {
     310         [ +  - ]:    2971196 :                     const size_t nc = mIndices[c];
     311 [ +  - ][ +  - ]:    2971196 :                     *met_hess_iter *= inv_n;
     312         [ +  + ]:    2971196 :                     if( nr <= nc )
     313 [ +  - ][ +  - ]:    2229952 :                         Hessian[N * nr - nr * ( nr + 1 ) / 2 + nc] += *met_hess_iter;
                 [ +  - ]
     314                 :            :                     else
     315 [ +  - ][ +  - ]:     741244 :                         Hessian[N * nc - nc * ( nc + 1 ) / 2 + nr].plus_transpose_equal( *met_hess_iter );
                 [ +  - ]
     316         [ +  - ]:    2971196 :                     ++met_hess_iter;
     317                 :            :                 }
     318 [ +  - ][ +  - ]:    1488708 :                 mGrad[r] *= inv_n;
     319 [ +  - ][ +  - ]:    1488708 :                 gradient[nr] += mGrad[r];
                 [ +  - ]
     320                 :            :             }
     321                 :            :         }
     322                 :            :         else
     323                 :            :         {
     324 [ #  # ][ #  # ]:          0 :             const double r2 = P2.raise( mValues[k] );
     325         [ #  # ]:          0 :             const double r1 = r2 * mValues[k];
     326         [ #  # ]:          0 :             v               = r1 * mValues[k];
     327 [ #  # ][ #  # ]:          0 :             const double h  = r2 * P.value() * ( P.value() - 1 ) * inv_n;
     328         [ #  # ]:          0 :             const double g  = r1 * P.value() * inv_n;
     329                 :            :             // for each gradient (or Hessian row) for the local metric evaluation
     330 [ #  # ][ #  # ]:          0 :             for( size_t r = mOffsets[k]; r < mOffsets[k + 1]; ++r )
                 [ #  # ]
     331                 :            :             {
     332         [ #  # ]:          0 :                 const size_t nr = mIndices[r];
     333                 :            :                 // for each column of the local metric Hessian
     334 [ #  # ][ #  # ]:          0 :                 for( size_t c = r; c < mOffsets[k + 1]; ++c )
     335                 :            :                 {
     336         [ #  # ]:          0 :                     const size_t nc = mIndices[c];
     337 [ #  # ][ #  # ]:          0 :                     *met_hess_iter *= g;
     338 [ #  # ][ #  # ]:          0 :                     outer.outer_product( mGrad[r], mGrad[c] );
                 [ #  # ]
     339         [ #  # ]:          0 :                     outer *= h;
     340 [ #  # ][ #  # ]:          0 :                     outer += *met_hess_iter;
     341         [ #  # ]:          0 :                     if( nr <= nc )
     342 [ #  # ][ #  # ]:          0 :                         Hessian[N * nr - nr * ( nr + 1 ) / 2 + nc] += outer;
     343                 :            :                     else
     344 [ #  # ][ #  # ]:          0 :                         Hessian[N * nc - nc * ( nc + 1 ) / 2 + nr].plus_transpose_equal( outer );
     345         [ #  # ]:          0 :                     ++met_hess_iter;
     346                 :            :                 }
     347 [ #  # ][ #  # ]:          0 :                 mGrad[r] *= g;
     348 [ #  # ][ #  # ]:          0 :                 gradient[nr] += mGrad[r];
                 [ #  # ]
     349                 :            :             }
     350                 :            :         }
     351                 :     499424 :         value += v;
     352                 :            :     }
     353                 :            : 
     354                 :     124856 :     value *= inv_n;
     355                 :            : 
     356                 :     124856 :     return rval;
     357                 :            : }
     358                 :            : 
     359 [ +  - ][ +  - ]:        120 : }  // namespace MBMesquite

Generated by: LCOV version 1.11