LCOV - code coverage report
Current view: top level - src/mesquite/QualityMetric/TMP - AffineMapMetric.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 62 86 72.1 %
Date: 2020-07-18 00:09:26 Functions: 8 10 80.0 %
Branches: 76 254 29.9 %

           Branch data     Line data    Source code
       1                 :            : /* *****************************************************************
       2                 :            :     MESQUITE -- The Mesh Quality Improvement Toolkit
       3                 :            : 
       4                 :            :     Copyright 2007 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                 :            :     (2007) [email protected]
      24                 :            : 
      25                 :            :   ***************************************************************** */
      26                 :            : 
      27                 :            : /** \file AffineMapMetric.cpp
      28                 :            :  *  \brief
      29                 :            :  *  \author Jason Kraftcheck
      30                 :            :  */
      31                 :            : 
      32                 :            : #include "Mesquite.hpp"
      33                 :            : #include "AffineMapMetric.hpp"
      34                 :            : #include "MsqMatrix.hpp"
      35                 :            : #include "ElementQM.hpp"
      36                 :            : #include "MsqError.hpp"
      37                 :            : #include "Vector3D.hpp"
      38                 :            : #include "PatchData.hpp"
      39                 :            : #include "MappingFunction.hpp"
      40                 :            : #include "WeightCalculator.hpp"
      41                 :            : #include "TargetCalculator.hpp"
      42                 :            : #include "TMetric.hpp"
      43                 :            : #include "TargetMetricUtil.hpp"
      44                 :            : 
      45                 :            : #include <functional>
      46                 :            : #include <algorithm>
      47                 :            : 
      48                 :            : namespace MBMesquite
      49                 :            : {
      50                 :            : 
      51                 :            : const double TRI_XFORM_VALS[] = { 1.0, -1.0 / sqrt( 3.0 ), 0.0, 2.0 / sqrt( 3.0 ) };
      52                 :          1 : MsqMatrix< 2, 2 > TRI_XFORM( TRI_XFORM_VALS );
      53                 :            : 
      54                 :            : const double TET_XFORM_VALS[] = {
      55                 :            :     1.0, -1.0 / sqrt( 3.0 ), -1.0 / sqrt( 6.0 ), 0.0, 2.0 / sqrt( 3.0 ), -1.0 / sqrt( 6.0 ), 0.0, 0.0, sqrt( 3.0 / 2.0 )
      56                 :            : };
      57                 :          1 : MsqMatrix< 3, 3 > TET_XFORM( TET_XFORM_VALS );
      58                 :            : 
      59                 :          0 : AffineMapMetric::AffineMapMetric( TargetCalculator* tc, WeightCalculator* wc, TMetric* target_metric )
      60                 :          0 :     : targetCalc( tc ), weightCalc( wc ), targetMetric( target_metric )
      61                 :            : {
      62                 :          0 : }
      63                 :            : 
      64                 :          9 : AffineMapMetric::AffineMapMetric( TargetCalculator* tc, TMetric* target_metric )
      65                 :          9 :     : targetCalc( tc ), weightCalc( 0 ), targetMetric( target_metric )
      66                 :            : {
      67                 :          9 : }
      68                 :            : 
      69                 :       6281 : int AffineMapMetric::get_negate_flag() const
      70                 :            : {
      71                 :       6281 :     return 1;
      72                 :            : }
      73                 :            : 
      74                 :          0 : std::string AffineMapMetric::get_name() const
      75                 :            : {
      76 [ #  # ][ #  # ]:          0 :     return std::string( "AffineMap(" ) + targetMetric->get_name() + ')';
                 [ #  # ]
      77                 :            : }
      78                 :            : 
      79                 :       5720 : void AffineMapMetric::get_evaluations( PatchData& pd, std::vector< size_t >& handles, bool free, MsqError& err )
      80                 :            : {
      81                 :       5720 :     get_sample_pt_evaluations( pd, handles, free, err );
      82                 :       5720 : }
      83                 :            : 
      84                 :      43008 : void AffineMapMetric::get_element_evaluations( PatchData& pd, size_t p_elem, std::vector< size_t >& handles,
      85                 :            :                                                MsqError& err )
      86                 :            : {
      87                 :      43008 :     get_elem_sample_points( pd, p_elem, handles, err );
      88                 :      43008 : }
      89                 :            : 
      90                 :    2596324 : bool AffineMapMetric::evaluate( PatchData& pd, size_t p_handle, double& value, MsqError& err )
      91                 :            : {
      92         [ +  - ]:    2596324 :     Sample s              = ElemSampleQM::sample( p_handle );
      93         [ +  - ]:    2596324 :     size_t e              = ElemSampleQM::elem( p_handle );
      94         [ +  - ]:    2596324 :     MsqMeshEntity& p_elem = pd.element_by_index( e );
      95         [ +  - ]:    2596324 :     EntityTopology type   = p_elem.get_element_type();
      96         [ +  - ]:    2596324 :     unsigned edim         = TopologyInfo::dimension( type );
      97         [ +  - ]:    2596324 :     const size_t* conn    = p_elem.get_vertex_index_array();
      98                 :            : 
      99                 :            :     // This metric only supports sampling at corners, except for simplices.
     100                 :            :     // If element is a simpex, then the Jacobian is constant over a linear
     101                 :            :     // element.  In this case, always evaluate at any vertex.
     102                 :            :     // unsigned corner = s.number;
     103         [ +  + ]:    2596324 :     if( s.dimension != 0 )
     104                 :            :     {
     105 [ -  + ][ #  # ]:    1735923 :         if( type == TRIANGLE || type == TETRAHEDRON )
     106                 :            :             /*corner = 0*/;
     107                 :            :         else
     108                 :            :         {
     109                 :            :             MSQ_SETERR( err )
     110 [ #  # ][ #  # ]:          0 :             ( "Invalid sample point for AffineMapMetric", MsqError::UNSUPPORTED_ELEMENT );
     111                 :          0 :             return false;
     112                 :            :         }
     113                 :            :     }
     114                 :            : 
     115                 :            :     bool rval;
     116         [ -  + ]:    2596324 :     if( edim == 3 )
     117                 :            :     {  // 3x3 or 3x2 targets ?
     118 [ #  # ][ #  # ]:          0 :         Vector3D c[3] = { Vector3D( 0, 0, 0 ), Vector3D( 0, 0, 0 ), Vector3D( 0, 0, 0 ) };
                 [ #  # ]
     119                 :            :         unsigned n;
     120         [ #  # ]:          0 :         const unsigned* adj = TopologyInfo::adjacent_vertices( type, s.number, n );
     121 [ #  # ][ #  # ]:          0 :         c[0]                = pd.vertex_by_index( conn[adj[0]] ) - pd.vertex_by_index( conn[s.number] );
         [ #  # ][ #  # ]
     122 [ #  # ][ #  # ]:          0 :         c[1]                = pd.vertex_by_index( conn[adj[1]] ) - pd.vertex_by_index( conn[s.number] );
         [ #  # ][ #  # ]
     123 [ #  # ][ #  # ]:          0 :         c[2]                = pd.vertex_by_index( conn[adj[2]] ) - pd.vertex_by_index( conn[s.number] );
         [ #  # ][ #  # ]
     124         [ #  # ]:          0 :         MsqMatrix< 3, 3 > A;
     125 [ #  # ][ #  # ]:          0 :         A.set_column( 0, MsqMatrix< 3, 1 >( c[0].to_array() ) );
                 [ #  # ]
     126 [ #  # ][ #  # ]:          0 :         A.set_column( 1, MsqMatrix< 3, 1 >( c[1].to_array() ) );
                 [ #  # ]
     127 [ #  # ][ #  # ]:          0 :         A.set_column( 2, MsqMatrix< 3, 1 >( c[2].to_array() ) );
                 [ #  # ]
     128 [ #  # ][ #  # ]:          0 :         if( type == TETRAHEDRON ) A = A * TET_XFORM;
     129                 :            : 
     130         [ #  # ]:          0 :         MsqMatrix< 3, 3 > W;
     131         [ #  # ]:          0 :         targetCalc->get_3D_target( pd, e, s, W, err );
     132 [ #  # ][ #  # ]:          0 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     133 [ #  # ][ #  # ]:          0 :         rval = targetMetric->evaluate( A * inverse( W ), value, err );
                 [ #  # ]
     134 [ #  # ][ #  # ]:          0 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     135                 :            :     }
     136                 :            :     else
     137                 :            :     {
     138 [ +  - ][ +  - ]:    2596324 :         Vector3D c[2] = { Vector3D( 0, 0, 0 ), Vector3D( 0, 0, 0 ) };
     139                 :            :         unsigned n;
     140         [ +  - ]:    2596324 :         const unsigned* adj = TopologyInfo::adjacent_vertices( type, s.number, n );
     141 [ +  - ][ +  - ]:    2596324 :         c[0]                = pd.vertex_by_index( conn[adj[0]] ) - pd.vertex_by_index( conn[s.number] );
         [ +  - ][ +  - ]
     142 [ +  - ][ +  - ]:    2596324 :         c[1]                = pd.vertex_by_index( conn[adj[1]] ) - pd.vertex_by_index( conn[s.number] );
         [ +  - ][ +  - ]
     143         [ +  - ]:    2596324 :         MsqMatrix< 3, 2 > App;
     144 [ +  - ][ +  - ]:    2596324 :         App.set_column( 0, MsqMatrix< 3, 1 >( c[0].to_array() ) );
                 [ +  - ]
     145 [ +  - ][ +  - ]:    2596324 :         App.set_column( 1, MsqMatrix< 3, 1 >( c[1].to_array() ) );
                 [ +  - ]
     146                 :            : 
     147         [ +  - ]:    2596324 :         MsqMatrix< 3, 2 > Wp;
     148         [ +  - ]:    2596324 :         targetCalc->get_surface_target( pd, e, s, Wp, err );
     149 [ +  - ][ -  + ]:    2596324 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     150                 :            : 
     151 [ +  - ][ +  - ]:    2596324 :         MsqMatrix< 2, 2 > A, W;
     152         [ +  - ]:    2596324 :         MsqMatrix< 3, 2 > RZ;
     153         [ +  - ]:    2596324 :         surface_to_2d( App, Wp, W, RZ );
     154 [ +  - ][ +  - ]:    2596324 :         A = transpose( RZ ) * App;
     155 [ +  + ][ +  - ]:    2596324 :         if( type == TRIANGLE ) A = A * TRI_XFORM;
     156                 :            : 
     157 [ +  - ][ +  - ]:    2596324 :         rval = targetMetric->evaluate( A * inverse( W ), value, err );
                 [ +  - ]
     158 [ +  - ][ -  + ]:    2596324 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     159                 :            :     }
     160                 :            : 
     161                 :            :     // apply target weight to value
     162         [ +  + ]:    2596324 :     if( weightCalc )
     163                 :            :     {
     164         [ +  - ]:     370575 :         double ck = weightCalc->get_weight( pd, e, s, err );
     165 [ +  - ][ -  + ]:     370575 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     166                 :     370575 :         value *= ck;
     167                 :            :     }
     168                 :    2596324 :     return rval;
     169                 :            : }
     170                 :            : 
     171                 :     110331 : bool AffineMapMetric::evaluate_with_indices( PatchData& pd, size_t p_handle, double& value,
     172                 :            :                                              std::vector< size_t >& indices, MsqError& err )
     173                 :            : {
     174         [ +  - ]:     110331 :     Sample s              = ElemSampleQM::sample( p_handle );
     175         [ +  - ]:     110331 :     size_t e              = ElemSampleQM::elem( p_handle );
     176         [ +  - ]:     110331 :     MsqMeshEntity& p_elem = pd.element_by_index( e );
     177         [ +  - ]:     110331 :     EntityTopology type   = p_elem.get_element_type();
     178         [ +  - ]:     110331 :     const size_t* conn    = p_elem.get_vertex_index_array();
     179                 :            : 
     180                 :            :     // this metric only supports sampling at corners
     181         [ +  + ]:     110331 :     if( s.dimension != 0 )
     182                 :            :     {
     183 [ -  + ][ #  # ]:      73431 :         if( type != TRIANGLE && type != TETRAHEDRON )
     184                 :            :         {
     185                 :            :             MSQ_SETERR( err )
     186 [ #  # ][ #  # ]:          0 :             ( "Invalid sample point for AffineMapMetric", MsqError::UNSUPPORTED_ELEMENT );
     187                 :          0 :             return false;
     188                 :            :         }
     189                 :      73431 :         s.dimension = 0;
     190                 :      73431 :         s.number    = 0;
     191                 :            :     }
     192                 :            : 
     193                 :            :     unsigned n;
     194         [ +  - ]:     110331 :     const unsigned* adj = TopologyInfo::adjacent_vertices( type, s.number, n );
     195                 :     110331 :     indices.clear();
     196 [ +  - ][ +  + ]:     110331 :     if( conn[s.number] < pd.num_free_vertices() ) indices.push_back( conn[s.number] );
                 [ +  - ]
     197         [ +  + ]:     330993 :     for( unsigned i = 0; i < n; ++i )
     198 [ +  - ][ +  + ]:     220662 :         if( conn[adj[i]] < pd.num_free_vertices() ) indices.push_back( conn[adj[i]] );
                 [ +  - ]
     199                 :            : 
     200         [ +  - ]:     110331 :     return evaluate( pd, p_handle, value, err );
     201                 :            : }
     202                 :            : 
     203 [ +  - ][ +  - ]:          4 : }  // namespace MBMesquite

Generated by: LCOV version 1.11