Quinoa all test code coverage report
Current view: top level - PDE - PrefIndicator.cpp (source / functions) Hit Total Coverage
Commit: -128-NOTFOUND Lines: 47 145 32.4 %
Date: 2024-11-22 08:51:48 Functions: 2 4 50.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 42 184 22.8 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/PDE/PrefIndicator.cpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.
       7                 :            :              All rights reserved. See the LICENSE file for details.
       8                 :            :   \brief     Adaptive indicators for p-adaptive discontiunous Galerkin methods
       9                 :            :   \details   This file contains functions that provide adaptive indicator
      10                 :            :     function calculations for marking the number of degree of freedom of each
      11                 :            :     element.
      12                 :            : */
      13                 :            : // *****************************************************************************
      14                 :            : 
      15                 :            : #include "PrefIndicator.hpp"
      16                 :            : 
      17                 :            : #include "Tags.hpp"
      18                 :            : #include "Vector.hpp"
      19                 :            : #include "Integrate/Basis.hpp"
      20                 :            : #include "Integrate/Quadrature.hpp"
      21                 :            : 
      22                 :            : namespace inciter {
      23                 :            : 
      24                 :       1636 : void spectral_decay( std::size_t nmat,
      25                 :            :                      std::size_t nunk,
      26                 :            :                      const std::vector< int >& esuel,
      27                 :            :                      const tk::Fields& unk,
      28                 :            :                      std::size_t ndof,
      29                 :            :                      std::size_t ndofmax,
      30                 :            :                      tk::real tolref,
      31                 :            :                      std::vector< std::size_t >& ndofel )
      32                 :            : // *****************************************************************************
      33                 :            : //! Evaluate the spectral-decay indicator and mark the ndof for each element
      34                 :            : //! \param[in] nmat Number of materials in this PDE system
      35                 :            : //! \param[in] nunk Number of unknowns
      36                 :            : //! \param[in] esuel Elements surrounding elements
      37                 :            : //! \param[in] unk Array of unknowns
      38                 :            : //! \param[in] ndof Number of degrees of freedom in the solution
      39                 :            : //! \param[in] ndofmax Max number of degrees of freedom for p-refinement
      40                 :            : //! \param[in] tolref Tolerance for p-refinement
      41                 :            : //! \param[in,out] ndofel Vector of local number of degrees of freedome
      42                 :            : //! \details The spectral decay indicator, implemented in this functiopn,
      43                 :            : //!   calculates the difference between the projections of the numerical
      44                 :            : //!   solutions on finite element space of order p and p-1.
      45                 :            : //! \see F. Naddei, et. al., "A comparison of refinement indicators for the
      46                 :            : //!    p-adaptive simulation of steady and unsteady flows with discontinuous
      47                 :            : //!    Galerkin methods" at https://doi.org/10.1016/j.jcp.2018.09.045, and G.
      48                 :            : //!    Gassner, et al., "Explicit discontinuous Galerkin schemes with adaptation
      49                 :            : //!    in space and time"
      50                 :            : // *****************************************************************************
      51                 :            : {
      52                 :       1636 :   const auto ncomp = unk.nprop() / ndof;
      53                 :            : 
      54                 :            :   // The array storing the adaptive indicator for each elements
      55         [ +  - ]:       3272 :   std::vector< tk::real > Ind(nunk, 0);
      56                 :            : 
      57         [ +  + ]:     379148 :   for (std::size_t e=0; e<esuel.size()/4; ++e) {
      58         [ +  + ]:     377512 :     if(ndofel[e] > 1) {
      59         [ +  - ]:     125871 :       if(nmat == 1)
      60                 :     125871 :         Ind[e] =
      61         [ +  - ]:     125871 :           evalDiscIndicator_CompFlow(e, ncomp, ndof, ndofel[e], unk);
      62         [ -  - ]:          0 :       else if(nmat > 1)
      63                 :          0 :         Ind[e] =
      64         [ -  - ]:          0 :           evalDiscIndicator_MultiMat(e, nmat, ncomp, ndof, ndofel[e], unk);
      65                 :            :     }
      66                 :            :   }
      67                 :            : 
      68                 :            :   // As for spectral-decay indicator, rho_p - rho_(p-1) actually is the leading
      69                 :            :   // term of discretization error for the numerical solution of p-1. Therefore,
      70                 :            :   // this function represents the qualitative behavior of the discretization
      71                 :            :   // error. If the value is less than epsL which means the discretization error
      72                 :            :   // is already a really small number, then the element should be de-refined. On
      73                 :            :   // the other hand, if the value is larger than epsH which means the
      74                 :            :   // discretization error is relatively large, then it should be refined.
      75                 :            : 
      76                 :            :   // Note: Spectral-decay indicator is a measurement of the continuity of the
      77                 :            :   // numerical solution inside this element. So when this indicator appears
      78                 :            :   // to be relatively large, there might be a shock inside this element and a
      79                 :            :   // derefinement or h-refinement should be applied. This condition will be
      80                 :            :   // implemented later.
      81                 :            : 
      82                 :            :   // As for the discretiazation-error based indicator, like spectral-decay
      83                 :            :   // indicator, the choices for epsH and epsL are based on the data from
      84                 :            :   // numerical experiments. Empirically, we found that when the epsH belongs
      85                 :            :   // to [-4, -8] and epsL belongs to [-6, -14], decent results could be
      86                 :            :   // observed. And then a linear projection is performed to map epsL and espH
      87                 :            :   // to the range of [0, 1] so that it could be controlled by tolref.
      88                 :            : 
      89                 :       1636 :   auto epsH = std::pow(10, -4 - tolref * 4.0);
      90                 :       1636 :   auto epsL = std::pow(10, -6 - tolref * 8.0);
      91                 :            :   // The epsL_p2 as well as the 'else if' code below are kept, since sometimes
      92                 :            :   // just using a common epsL for both DGP2 and DGP1 might not produce good ndof
      93                 :            :   // distributions. Further testing required by manupulating these 3 thresholds.
      94                 :            :   //auto epsL_p2 = std::pow(10, -7 - tolref * 8.0);
      95                 :            : 
      96                 :            :   // Marke the ndof according to the adaptive indicator
      97         [ +  + ]:     379148 :   for (std::size_t e=0; e<esuel.size()/4; ++e)
      98                 :            :   {
      99         [ +  + ]:     377512 :     if(Ind[e] < epsL)                          // Derefinement
     100                 :            :     {
     101         [ +  + ]:     329584 :       if(ndofel[e] == 4)
     102                 :      43049 :         ndofel[e] = 1;
     103         [ +  + ]:     286535 :       else if(ndofel[e] == 10)
     104                 :      34894 :         ndofel[e] = 4;
     105                 :            :     }
     106                 :            :     //else if (Ind[e] < epsL_p2 && ndofel[e] == 10) {
     107                 :            :     //  ndofel[e] = 4;
     108                 :            :     //}
     109         [ +  + ]:      47928 :     else if(Ind[e] > epsH)                     // Refinement
     110                 :            :     {
     111 [ +  + ][ -  + ]:      18590 :       if(ndofel[e] == 4 && ndofmax > 4)
                 [ -  + ]
     112                 :          0 :         ndofel[e] = 10;
     113                 :            :     }
     114                 :            :   }
     115                 :       1636 : }
     116                 :            : 
     117                 :          0 : void non_conformity( std::size_t nunk,
     118                 :            :                      std::size_t Nbfac,
     119                 :            :                      const std::vector< std::size_t >& inpoel,
     120                 :            :                      const tk::UnsMesh::Coords& coord,
     121                 :            :                      const std::vector< int >& esuel,
     122                 :            :                      const std::vector< int >& esuf,
     123                 :            :                      const std::vector< std::size_t >& inpofa,
     124                 :            :                      const tk::Fields& unk,
     125                 :            :                      std::size_t ndof,
     126                 :            :                      std::size_t ndofmax,
     127                 :            :                      std::vector< std::size_t >& ndofel )
     128                 :            : // *****************************************************************************
     129                 :            : //! Evaluate the non-conformity indicator and mark the ndof for each element
     130                 :            : //! \param[in] nunk Number of unknowns
     131                 :            : //! \param[in] Nbfac Number of internal faces
     132                 :            : //! \param[in] inpoel Element-node connectivity
     133                 :            : //! \param[in] coord Array of nodal coordinates
     134                 :            : //! \param[in] esuel Elements surrounding elements
     135                 :            : //! \param[in] esuf Elements surrounding faces
     136                 :            : //! \param[in] inpofa Face-node connectivity
     137                 :            : //! \param[in] unk Array of unknowns
     138                 :            : //! \param[in] ndof Number of degrees of freedom in the solution
     139                 :            : //! \param[in] ndofmax Max number of degrees of freedom for p-refinement
     140                 :            : //! \param[in,out] ndofel Vector of local number of degrees of freedome
     141                 :            : //! \details The non-conformity indicator, this function implements, evaluates
     142                 :            : //!   the jump in the numerical solutions as a measure of the numerical error.
     143                 :            : //! \see F. Naddei, et. al., "A comparison of refinement indicators for the
     144                 :            : //!   p-adaptive simulation of steady and unsteady flows with discontinuous
     145                 :            : //!   Galerkin methods at https://doi.org/10.1016/j.jcp.2018.09.045.
     146                 :            : //! \warning This indicator can only be applied in serial, i.e., single CPU, for
     147                 :            : //!    now because the solution communication happens before eval_ndof() in DG,
     148                 :            : //!    which will lead to incorrect evaluation of the numerical solution at the
     149                 :            : //!    neighboring cells.
     150                 :            : // *****************************************************************************
     151                 :            : {
     152                 :          0 :   const auto ncomp = unk.nprop() / ndof;
     153                 :            : 
     154                 :          0 :   const auto& cx = coord[0];
     155                 :          0 :   const auto& cy = coord[1];
     156                 :          0 :   const auto& cz = coord[2];
     157                 :            : 
     158                 :            :   // The array storing the adaptive indicator for each elements
     159         [ -  - ]:          0 :   std::vector< tk::real > Ind(nunk, 0);
     160                 :            : 
     161                 :            :   // compute error indicator for each face
     162         [ -  - ]:          0 :   for (auto f=Nbfac; f<esuf.size()/2; ++f)
     163                 :            :   {
     164 [ -  - ][ -  - ]:          0 :     Assert( esuf[2*f] > -1 && esuf[2*f+1] > -1, "Interior element detected "
         [ -  - ][ -  - ]
                 [ -  - ]
     165                 :            :             "as -1" );
     166                 :            : 
     167                 :          0 :     std::size_t el = static_cast< std::size_t >(esuf[2*f]);
     168                 :          0 :     std::size_t er = static_cast< std::size_t >(esuf[2*f+1]);
     169                 :            : 
     170         [ -  - ]:          0 :     auto ng_l = tk::NGfa(ndofel[el]);
     171         [ -  - ]:          0 :     auto ng_r = tk::NGfa(ndofel[er]);
     172                 :            : 
     173                 :            :     // When the number of gauss points for the left and right element are
     174                 :            :     // different, choose the larger ng
     175                 :          0 :     auto ng = std::max( ng_l, ng_r );
     176                 :            : 
     177                 :            :     // arrays for quadrature points
     178                 :          0 :     std::array< std::vector< tk::real >, 2 > coordgp;
     179                 :          0 :     std::vector< tk::real > wgp;
     180                 :            : 
     181         [ -  - ]:          0 :     coordgp[0].resize( ng );
     182         [ -  - ]:          0 :     coordgp[1].resize( ng );
     183         [ -  - ]:          0 :     wgp.resize( ng );
     184                 :            : 
     185                 :            :     // get quadrature point weights and coordinates for triangle
     186         [ -  - ]:          0 :     tk::GaussQuadratureTri( ng, coordgp, wgp );
     187                 :            : 
     188                 :            :     // Extract the element coordinates
     189                 :            :     std::array< std::array< tk::real, 3>, 4 > coordel_l {{
     190                 :          0 :       {{ cx[ inpoel[4*el  ] ], cy[ inpoel[4*el  ] ], cz[ inpoel[4*el  ] ] }},
     191                 :          0 :       {{ cx[ inpoel[4*el+1] ], cy[ inpoel[4*el+1] ], cz[ inpoel[4*el+1] ] }},
     192                 :          0 :       {{ cx[ inpoel[4*el+2] ], cy[ inpoel[4*el+2] ], cz[ inpoel[4*el+2] ] }},
     193                 :          0 :       {{ cx[ inpoel[4*el+3] ], cy[ inpoel[4*el+3] ], cz[ inpoel[4*el+3] ] }} }};
     194                 :            : 
     195                 :            :     std::array< std::array< tk::real, 3>, 4 > coordel_r {{
     196                 :          0 :       {{ cx[ inpoel[4*er  ] ], cy[ inpoel[4*er  ] ], cz[ inpoel[4*er  ] ] }},
     197                 :          0 :       {{ cx[ inpoel[4*er+1] ], cy[ inpoel[4*er+1] ], cz[ inpoel[4*er+1] ] }},
     198                 :          0 :       {{ cx[ inpoel[4*er+2] ], cy[ inpoel[4*er+2] ], cz[ inpoel[4*er+2] ] }},
     199                 :          0 :       {{ cx[ inpoel[4*er+3] ], cy[ inpoel[4*er+3] ], cz[ inpoel[4*er+3] ] }} }};
     200                 :            : 
     201                 :            :     // Compute the determinant of Jacobian matrix
     202                 :            :     auto detT_l =
     203                 :          0 :       tk::Jacobian( coordel_l[0], coordel_l[1], coordel_l[2], coordel_l[3] );
     204                 :            :     auto detT_r =
     205                 :          0 :       tk::Jacobian( coordel_r[0], coordel_r[1], coordel_r[2], coordel_r[3] );
     206                 :            : 
     207                 :            :     // Extract the face coordinates
     208                 :            :     std::array< std::array< tk::real, 3>, 3 > coordfa {{
     209                 :          0 :       {{ cx[ inpofa[3*f  ] ], cy[ inpofa[3*f  ] ], cz[ inpofa[3*f  ] ] }},
     210                 :          0 :       {{ cx[ inpofa[3*f+1] ], cy[ inpofa[3*f+1] ], cz[ inpofa[3*f+1] ] }},
     211                 :          0 :       {{ cx[ inpofa[3*f+2] ], cy[ inpofa[3*f+2] ], cz[ inpofa[3*f+2] ] }} }};
     212                 :            : 
     213                 :            :     // Gaussian quadrature
     214         [ -  - ]:          0 :     for (std::size_t igp=0; igp<ng; ++igp)
     215                 :            :     {
     216                 :            :       // Compute the coordinates of quadrature point at physical domain
     217         [ -  - ]:          0 :       auto gp = tk::eval_gp( igp, coordfa, coordgp );
     218                 :            : 
     219                 :            :       //Compute the basis functions
     220                 :          0 :       auto B_l = tk::eval_basis( ndofel[el],
     221                 :          0 :         tk::Jacobian( coordel_l[0], gp, coordel_l[2], coordel_l[3] ) / detT_l,
     222                 :          0 :         tk::Jacobian( coordel_l[0], coordel_l[1], gp, coordel_l[3] ) / detT_l,
     223         [ -  - ]:          0 :         tk::Jacobian( coordel_l[0], coordel_l[1], coordel_l[2], gp ) / detT_l );
     224                 :          0 :       auto B_r = tk::eval_basis( ndofel[er],
     225                 :          0 :         tk::Jacobian( coordel_r[0], gp, coordel_r[2], coordel_r[3] ) / detT_r,
     226                 :          0 :         tk::Jacobian( coordel_r[0], coordel_r[1], gp, coordel_r[3] ) / detT_r,
     227         [ -  - ]:          0 :         tk::Jacobian( coordel_r[0], coordel_r[1], coordel_r[2], gp ) / detT_r );
     228                 :            : 
     229                 :          0 :       std::array< std::vector< tk::real >, 2 > state;
     230                 :            : 
     231         [ -  - ]:          0 :       state[0] = tk::eval_state( ncomp, ndof, ndofel[el], el, unk, B_l );
     232         [ -  - ]:          0 :       state[1] = tk::eval_state( ncomp, ndof, ndofel[er], er, unk, B_r );
     233                 :            : 
     234 [ -  - ][ -  - ]:          0 :       Assert( unk[0].size() == ncomp, "Size mismatch" );
         [ -  - ][ -  - ]
                 [ -  - ]
     235 [ -  - ][ -  - ]:          0 :       Assert( unk[1].size() == ncomp, "Size mismatch" );
         [ -  - ][ -  - ]
                 [ -  - ]
     236                 :            : 
     237                 :          0 :       auto rhoL = state[0][0];
     238                 :          0 :       auto rhoR = state[1][0];
     239                 :            : 
     240                 :          0 :       auto ind = fabs( rhoL - rhoR ) / 2.0 * ( rhoL + rhoR );
     241                 :          0 :       Ind[el] = std::max( ind, Ind[el] );
     242                 :          0 :       Ind[er] = std::max( ind, Ind[er] );
     243                 :            :     }
     244                 :            :   }
     245                 :            : 
     246                 :            :   // By assuming a smooth solution, we use the non-conformity indicator to
     247                 :            :   // represent the error for the numerical solution qualitatively. If the value
     248                 :            :   // is less than epsL which means the error is already a really small number,
     249                 :            :   // then the element should be de-refined. On the other hand, if the value is
     250                 :            :   // larger than epsH which means the error is relatively large, then it should
     251                 :            :   // be refined.
     252                 :            : 
     253                 :            :   // Marke the ndof according to the adaptive indicator
     254         [ -  - ]:          0 :   for (std::size_t e=0; e<esuel.size()/4; ++e)
     255                 :            :   {
     256         [ -  - ]:          0 :     if(Ind[e] < 1e-4)                         // Derefinement
     257                 :            :     {
     258         [ -  - ]:          0 :       if(ndofel[e] == 10)
     259                 :          0 :         ndofel[e] = 4;
     260         [ -  - ]:          0 :       else if(ndofel[e] == 4)
     261                 :          0 :         ndofel[e] = 1;
     262                 :            :     }
     263         [ -  - ]:          0 :     else if(Ind[e] > 1e-3)                    // Refinement
     264                 :            :     {
     265 [ -  - ][ -  - ]:          0 :       if(ndofel[e] == 4 && ndofmax > 4)
                 [ -  - ]
     266                 :          0 :         ndofel[e] = 10;
     267         [ -  - ]:          0 :       else if(ndofel[e] == 1)
     268                 :          0 :         ndofel[e] = 4;
     269                 :            :     }
     270                 :            :   }
     271                 :          0 : }
     272                 :            : 
     273                 :     125871 : tk::real evalDiscIndicator_CompFlow( std::size_t e,
     274                 :            :                                      ncomp_t ncomp,
     275                 :            :                                      const std::size_t ndof,
     276                 :            :                                      const std::size_t ndofel,
     277                 :            :                                      const tk::Fields& unk )
     278                 :            : // *****************************************************************************
     279                 :            : //! Evaluate the spectral decay indicator
     280                 :            : //! \param[in] e Index for the tetrahedron element
     281                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     282                 :            : //! \param[in] ndof Number of degrees of freedom in the solution
     283                 :            : //! \param[in] ndofel Local number of degrees of freedom
     284                 :            : //! \param[in] unk Array of unknowns
     285                 :            : //! \return The value of spectral indicator for the element
     286                 :            : //! \detail The spectral indicator evaluates the density differences between
     287                 :            : //!   the numerical solutions at different polynomial space
     288                 :            : // *****************************************************************************
     289                 :            : {
     290         [ +  - ]:     125871 :   auto ng = tk::NGvol(ndofel);
     291                 :            : 
     292                 :            :   // arrays for quadrature points
     293                 :     251742 :   std::array< std::vector< tk::real >, 3 > coordgp;
     294         [ +  - ]:     125871 :   std::vector< tk::real > wgp( ng );
     295                 :            : 
     296         [ +  - ]:     125871 :   coordgp[0].resize( ng );
     297         [ +  - ]:     125871 :   coordgp[1].resize( ng );
     298         [ +  - ]:     125871 :   coordgp[2].resize( ng );
     299                 :            : 
     300         [ +  - ]:     125871 :   tk::GaussQuadratureTet( ng, coordgp, wgp );
     301                 :            : 
     302                 :     125871 :   tk::real dU(0.0), U(0.0), Ind(0.0);
     303                 :            : 
     304                 :            :   // Gaussian quadrature
     305         [ +  + ]:    1245876 :   for (std::size_t igp=0; igp<ng; ++igp)
     306                 :            :   {
     307                 :            :     // Compute the basis function
     308                 :    2240010 :     auto B = tk::eval_basis( ndofel, coordgp[0][igp], coordgp[1][igp],
     309         [ +  - ]:    4480020 :                              coordgp[2][igp] );
     310                 :            : 
     311         [ +  - ]:    2240010 :     auto state = tk::eval_state( ncomp, ndof, ndofel, e, unk, B );
     312                 :            : 
     313                 :    1120005 :     U += wgp[igp] * state[0] * state[0];
     314                 :            : 
     315         [ +  + ]:    1120005 :     if(ndofel > 4)
     316                 :            :     {
     317         [ +  - ]:     899525 :        auto dU_p2 = unk(e, 4) * B[4]
     318         [ +  - ]:     899525 :                   + unk(e, 5) * B[5]
     319         [ +  - ]:     899525 :                   + unk(e, 6) * B[6]
     320         [ +  - ]:     899525 :                   + unk(e, 7) * B[7]
     321         [ +  - ]:     899525 :                   + unk(e, 8) * B[8]
     322         [ +  - ]:     899525 :                   + unk(e, 9) * B[9];
     323                 :            : 
     324                 :     899525 :        dU += wgp[igp] * dU_p2 * dU_p2;
     325                 :            :     }
     326                 :            :     else
     327                 :            :     {
     328         [ +  - ]:     220480 :        auto dU_p1 = unk(e, 1) * B[1]
     329         [ +  - ]:     220480 :                   + unk(e, 2) * B[2]
     330         [ +  - ]:     220480 :                   + unk(e, 3) * B[3];
     331                 :            : 
     332                 :     220480 :        dU += wgp[igp] * dU_p1 * dU_p1;
     333                 :            :     }
     334                 :            :   }
     335                 :            : 
     336                 :     125871 :   Ind = dU / U;
     337                 :            : 
     338                 :     251742 :   return Ind;
     339                 :            : }
     340                 :            : 
     341                 :          0 : tk::real evalDiscIndicator_MultiMat( std::size_t e,
     342                 :            :                                      std::size_t nmat,
     343                 :            :                                      ncomp_t ncomp,
     344                 :            :                                      const std::size_t ndof,
     345                 :            :                                      const std::size_t ndofel,
     346                 :            :                                      const tk::Fields& unk )
     347                 :            : // *****************************************************************************
     348                 :            : //! Evaluate the spectral decay indicator
     349                 :            : //! \param[in] e Index for the tetrahedron element
     350                 :            : //! \param[in] nmat Number of materials in this PDE system
     351                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     352                 :            : //! \param[in] ndof Number of degrees of freedom in the solution
     353                 :            : //! \param[in] ndofel Local number of degrees of freedom
     354                 :            : //! \param[in] unk Array of unknowns
     355                 :            : //! \return The value of spectral indicator for the element
     356                 :            : //! \detail The spectral indicator evaluates the bulk density differences
     357                 :            : //!   between the numerical solutions at different polynomial space
     358                 :            : // *****************************************************************************
     359                 :            : {
     360         [ -  - ]:          0 :   auto ng = tk::NGvol(ndof);
     361                 :            : 
     362                 :            :   // arrays for quadrature points
     363                 :          0 :   std::array< std::vector< tk::real >, 3 > coordgp;
     364         [ -  - ]:          0 :   std::vector< tk::real > wgp( ng );
     365                 :            : 
     366         [ -  - ]:          0 :   coordgp[0].resize( ng );
     367         [ -  - ]:          0 :   coordgp[1].resize( ng );
     368         [ -  - ]:          0 :   coordgp[2].resize( ng );
     369                 :            : 
     370         [ -  - ]:          0 :   tk::GaussQuadratureTet( ng, coordgp, wgp );
     371                 :            : 
     372                 :          0 :   tk::real dU(0.0), U(0.0), Ind(0.0);
     373                 :            : 
     374                 :            :   // Gaussian quadrature
     375         [ -  - ]:          0 :   for (std::size_t igp=0; igp<ng; ++igp)
     376                 :            :   {
     377                 :            :     // Compute the basis function
     378                 :          0 :     auto B = tk::eval_basis( ndof, coordgp[0][igp], coordgp[1][igp],
     379         [ -  - ]:          0 :                              coordgp[2][igp] );
     380                 :            : 
     381         [ -  - ]:          0 :     auto state = tk::eval_state( ncomp, ndof, ndofel, e, unk, B );
     382                 :            : 
     383                 :          0 :     tk::real denom(0.0), numer(0.0);
     384         [ -  - ]:          0 :     for(std::size_t k = 0; k < nmat; k++) {
     385                 :          0 :       denom += state[densityIdx(nmat, k)];
     386         [ -  - ]:          0 :       if(ndofel > 4) {
     387         [ -  - ]:          0 :         numer += ( unk(e, densityDofIdx(nmat, k, ndof, 4)) * B[4]
     388         [ -  - ]:          0 :                  + unk(e, densityDofIdx(nmat, k, ndof, 5)) * B[5]
     389         [ -  - ]:          0 :                  + unk(e, densityDofIdx(nmat, k, ndof, 6)) * B[6]
     390         [ -  - ]:          0 :                  + unk(e, densityDofIdx(nmat, k, ndof, 7)) * B[7]
     391         [ -  - ]:          0 :                  + unk(e, densityDofIdx(nmat, k, ndof, 8)) * B[8]
     392         [ -  - ]:          0 :                  + unk(e, densityDofIdx(nmat, k, ndof, 9)) * B[9] );
     393                 :            :       } else {
     394         [ -  - ]:          0 :         numer += ( unk(e, densityDofIdx(nmat, k, ndof, 1)) * B[1]
     395         [ -  - ]:          0 :                  + unk(e, densityDofIdx(nmat, k, ndof, 2)) * B[2]
     396         [ -  - ]:          0 :                  + unk(e, densityDofIdx(nmat, k, ndof, 3)) * B[3] );
     397                 :            :       }
     398                 :            :     }
     399                 :          0 :     dU += wgp[igp] * numer * numer;
     400                 :          0 :     U  += wgp[igp] * denom * denom;
     401                 :            :   }
     402                 :            : 
     403                 :          0 :   Ind = dU / U;
     404                 :            : 
     405                 :          0 :   return Ind;
     406                 :            : }
     407                 :            : 
     408                 :            : }
     409                 :            : // inciter::

Generated by: LCOV version 1.14