Quinoa all test code coverage report
Current view: top level - PDE - PrefIndicator.cpp (source / functions) Hit Total Coverage
Commit: -128-NOTFOUND Lines: 46 161 28.6 %
Date: 2024-04-29 14:42:33 Functions: 2 4 50.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 34 162 21.0 %

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

Generated by: LCOV version 1.14