Xyst test code coverage report
Current view: top level - Physics - Riemann.cpp (source / functions) Hit Total Coverage
Commit: 5689ba12dc66a776d3d75f1ee48cc7d78eaa18dc Lines: 392 405 96.8 %
Date: 2024-11-22 19:02:53 Functions: 11 11 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 128 156 82.1 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/Physics/Riemann.cpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.,
       7                 :            :              2022-2024 J. Bakosi
       8                 :            :              All rights reserved. See the LICENSE file for details.
       9                 :            :   \brief     Riemann, MUSCL, limiting for edge-based continuous Galerkin
      10                 :            : */
      11                 :            : // *****************************************************************************
      12                 :            : 
      13                 :            : #include "Vector.hpp"
      14                 :            : #include "Around.hpp"
      15                 :            : #include "DerivedData.hpp"
      16                 :            : #include "EOS.hpp"
      17                 :            : #include "Riemann.hpp"
      18                 :            : #include "Problems.hpp"
      19                 :            : #include "InciterConfig.hpp"
      20                 :            : 
      21                 :            : namespace inciter {
      22                 :            : 
      23                 :            : extern ctr::Config g_cfg;
      24                 :            : 
      25                 :            : } // ::inciter
      26                 :            : 
      27                 :            : namespace riemann {
      28                 :            : 
      29                 :            : static const tk::real muscl_eps = 1.0e-9;
      30                 :            : static const tk::real muscl_const = 1.0/3.0;
      31                 :            : 
      32                 :            : using inciter::g_cfg;
      33                 :            : 
      34                 :            : static void
      35                 :   17200140 : muscl( std::size_t p,
      36                 :            :        std::size_t q,
      37                 :            :        const tk::UnsMesh::Coords& coord,
      38                 :            :        const tk::Fields& G,
      39                 :            :        tk::real& rL, tk::real& uL, tk::real& vL, tk::real& wL, tk::real& eL,
      40                 :            :        tk::real& rR, tk::real& uR, tk::real& vR, tk::real& wR, tk::real& eR )
      41                 :            : // *****************************************************************************
      42                 :            : //! Compute MUSCL reconstruction in edge-end points for the flow variables
      43                 :            : //! \param[in] p Left node id of edge-end
      44                 :            : //! \param[in] q Right node id of edge-end
      45                 :            : //! \param[in] coord Array of nodal coordinates
      46                 :            : //! \param[in] G Gradient of all unknowns in mesh points
      47                 :            : //! \param[in,out] rL Left density
      48                 :            : //! \param[in,out] uL Left X velocity
      49                 :            : //! \param[in,out] vL Left Y velocity
      50                 :            : //! \param[in,out] wL Left Z velocity
      51                 :            : //! \param[in,out] eL Left internal energy
      52                 :            : //! \param[in,out] rR Right density
      53                 :            : //! \param[in,out] uR Right X velocity
      54                 :            : //! \param[in,out] vR Right Y velocity
      55                 :            : //! \param[in,out] wR Right Z velocity
      56                 :            : //! \param[in,out] eR Right internal energy
      57                 :            : // *****************************************************************************
      58                 :            : {
      59                 :            :   // access node coordinates
      60                 :            :   const auto& x = coord[0];
      61                 :            :   const auto& y = coord[1];
      62                 :            :   const auto& z = coord[2];
      63                 :            : 
      64                 :            :   // edge vector
      65                 :   17200140 :   tk::real vw[3] = { x[q]-x[p], y[q]-y[p], z[q]-z[p] };
      66                 :            : 
      67                 :            :   tk::real delta1[5], delta2[5], delta3[5];
      68                 :   17200140 :   tk::real ls[5] = { rL, uL, vL, wL, eL },
      69                 :   17200140 :            rs[5] = { rR, uR, vR, wR, eR },
      70                 :            :            url[5], urr[5];
      71                 :   17200140 :   memcpy( url, ls, sizeof ls );
      72                 :   17200140 :   memcpy( urr, rs, sizeof rs );
      73                 :            : 
      74                 :            :   // MUSCL reconstruction of edge-end-point primitive variables
      75         [ +  + ]:  103200840 :   for (std::size_t c=0; c<5; ++c) {
      76                 :            : 
      77                 :   86000700 :     auto g1 = G(p,c*3+0)*vw[0] + G(p,c*3+1)*vw[1] + G(p,c*3+2)*vw[2];
      78                 :   86000700 :     auto g2 = G(q,c*3+0)*vw[0] + G(q,c*3+1)*vw[1] + G(q,c*3+2)*vw[2];
      79                 :            : 
      80                 :   86000700 :     delta2[c] = rs[c] - ls[c];
      81                 :   86000700 :     delta1[c] = 2.0 * g1 - delta2[c];
      82                 :   86000700 :     delta3[c] = 2.0 * g2 - delta2[c];
      83                 :            : 
      84                 :            :     // MUSCL extrapolation option 1:
      85                 :            :     // ---------------------------------------------------------------------
      86                 :            :     // See Waltz, J., Morgan, N. R., Canfield, T. R., Charest, M. R., Risinger,
      87                 :            :     // L. D., & Wohlbier, J. G. (2014). A three-dimensional finite element
      88                 :            :     // arbitrary Lagrangian–Eulerian method for shock hydrodynamics on
      89                 :            :     // unstructured grids. Computers & Fluids, 92, 172-187.
      90                 :            : 
      91                 :            :     // van Leer limiter
      92                 :   86000700 :     auto rcL = (delta2[c] + muscl_eps) / (delta1[c] + muscl_eps);
      93                 :   86000700 :     auto rcR = (delta2[c] + muscl_eps) / (delta3[c] + muscl_eps);
      94                 :   86000700 :     auto rLinv = (delta1[c] + muscl_eps) / (delta2[c] + muscl_eps);
      95                 :   86000700 :     auto rRinv = (delta3[c] + muscl_eps) / (delta2[c] + muscl_eps);
      96                 :   86000700 :     auto phiL = (std::abs(rcL) + rcL) / (std::abs(rcL) + 1.0);
      97                 :   86000700 :     auto phiR = (std::abs(rcR) + rcR) / (std::abs(rcR) + 1.0);
      98                 :   86000700 :     auto phi_L_inv = (std::abs(rLinv) + rLinv) / (std::abs(rLinv) + 1.0);
      99                 :   86000700 :     auto phi_R_inv = (std::abs(rRinv) + rRinv) / (std::abs(rRinv) + 1.0);
     100                 :            :     // update unknowns with reconstructed unknowns
     101                 :   86000700 :     url[c] += 0.25*(delta1[c]*(1.0-muscl_const)*phiL +
     102                 :   86000700 :                     delta2[c]*(1.0+muscl_const)*phi_L_inv);
     103                 :   86000700 :     urr[c] -= 0.25*(delta3[c]*(1.0-muscl_const)*phiR +
     104                 :   86000700 :                     delta2[c]*(1.0+muscl_const)*phi_R_inv);
     105                 :            : 
     106                 :            :     // MUSCL extrapolation option 2:
     107                 :            :     // ---------------------------------------------------------------------
     108                 :            :     // See Luo, H., Baum, J. D., & Lohner, R. (1994). Edge-based finite element
     109                 :            :     // scheme for the Euler equations. AIAA journal, 32(6), 1183-1190.
     110                 :            :     // van Leer, B. (1974). Towards the ultimate conservative difference
     111                 :            :     // scheme. II. Monotonicity and conservation combined in a second-order
     112                 :            :     // scheme. Journal of computational physics, 14(4), 361-370.
     113                 :            :     // Derived from the flux limiter phi as: s = phi_inv - (1 - phi)
     114                 :            : 
     115                 :            :     // van Albada limiter
     116                 :            :     //auto sL = std::max(0.0, (2.0*delta1[c]*delta2[c] + muscl_eps)
     117                 :            :     //  /(delta1[c]*delta1[c] + delta2[c]*delta2[c] + muscl_eps));
     118                 :            :     //auto sR = std::max(0.0, (2.0*delta3[c]*delta2[c] + muscl_eps)
     119                 :            :     //  /(delta3[c]*delta3[c] + delta2[c]*delta2[c] + muscl_eps));
     120                 :            :     //// update unknowns with reconstructed unknowns
     121                 :            :     //url[c] += 0.25*sL*(delta1[c]*(1.0 - muscl_const*sL)
     122                 :            :     //                 + delta2[c]*(1.0 + muscl_const*sL));
     123                 :            :     //urr[c] -= 0.25*sR*(delta3[c]*(1.0 - muscl_const*sR)
     124                 :            :     //                 + delta2[c]*(1.0 + muscl_const*sR));
     125                 :            :   }
     126                 :            : 
     127                 :            :   // force first order if the reconstructions for density or internal energy
     128                 :            :   // would have allowed negative values
     129 [ +  + ][ +  + ]:   17200140 :   if (ls[0] < delta1[0] || ls[4] < delta1[4]) memcpy( url, ls, sizeof ls );
     130 [ +  + ][ +  + ]:   17200140 :   if (rs[0] < -delta3[0] || rs[4] < -delta3[4]) memcpy( urr, rs, sizeof rs );
     131                 :            : 
     132                 :   17200140 :   rL = url[0];
     133                 :   17200140 :   uL = url[1];
     134                 :   17200140 :   vL = url[2];
     135                 :   17200140 :   wL = url[3];
     136                 :   17200140 :   eL = url[4];
     137                 :            : 
     138                 :   17200140 :   rR = urr[0];
     139                 :   17200140 :   uR = urr[1];
     140                 :   17200140 :   vR = urr[2];
     141                 :   17200140 :   wR = urr[3];
     142                 :   17200140 :   eR = urr[4];
     143                 :   17200140 : }
     144                 :            : 
     145                 :            : static void
     146                 :    4668948 : muscl( std::size_t p, std::size_t q, const tk::UnsMesh::Coords& coord,
     147                 :            :        const tk::Fields& G, tk::real uL[], tk::real uR[] )
     148                 :            : // *****************************************************************************
     149                 :            : //! Compute MUSCL reconstruction in edge-end points for transported scalars
     150                 :            : //! \param[in] p Left node id of edge-end
     151                 :            : //! \param[in] q Right node id of edge-end
     152                 :            : //! \param[in] coord Array of nodal coordinates
     153                 :            : //! \param[in] G Gradient of all unknowns in mesh points
     154                 :            : //! \param[in,out] uL Primitive variables at left edge-end point
     155                 :            : //! \param[in,out] uR Primitive variables at right edge-end point
     156                 :            : // *****************************************************************************
     157                 :            : {
     158                 :            :   #if defined(__clang__)
     159                 :            :     #pragma clang diagnostic push
     160                 :            :     #pragma clang diagnostic ignored "-Wvla"
     161                 :            :     #pragma clang diagnostic ignored "-Wvla-extension"
     162                 :            :   #elif defined(STRICT_GNUC)
     163                 :            :     #pragma GCC diagnostic push
     164                 :            :     #pragma GCC diagnostic ignored "-Wvla"
     165                 :            :   #endif
     166                 :            : 
     167                 :    4668948 :   auto ns = G.nprop() / 3 - 5;
     168                 :            : 
     169                 :            :   const auto& x = coord[0];
     170                 :            :   const auto& y = coord[1];
     171                 :            :   const auto& z = coord[2];
     172                 :            : 
     173                 :            :   // edge vector
     174                 :    4668948 :   tk::real vw[3] = { x[q]-x[p], y[q]-y[p], z[q]-z[p] };
     175                 :            : 
     176                 :    4668948 :   tk::real delta1[ns], delta2[ns], delta3[ns];
     177                 :            : 
     178                 :            :   // MUSCL reconstruction of edge-end-point of primitive variables
     179         [ +  + ]:    9337896 :   for (std::size_t c=0; c<ns; ++c) {
     180                 :    4668948 :     auto g = (5+c)*3;
     181                 :    4668948 :     auto g1 = G(p,g+0)*vw[0] + G(p,g+1)*vw[1] + G(p,g+2)*vw[2];
     182                 :    4668948 :     auto g2 = G(q,g+0)*vw[0] + G(q,g+1)*vw[1] + G(q,g+2)*vw[2];
     183                 :            : 
     184                 :    4668948 :     delta2[c] = uR[5+c] - uL[5+c];
     185                 :    4668948 :     delta1[c] = 2.0 * g1 - delta2[c];
     186                 :    4668948 :     delta3[c] = 2.0 * g2 - delta2[c];
     187                 :            : 
     188                 :            :     // van Leer limiter
     189                 :    4668948 :     auto rL = (delta2[c] + muscl_eps) / (delta1[c] + muscl_eps);
     190                 :    4668948 :     auto rR = (delta2[c] + muscl_eps) / (delta3[c] + muscl_eps);
     191                 :    4668948 :     auto rLinv = (delta1[c] + muscl_eps) / (delta2[c] + muscl_eps);
     192                 :    4668948 :     auto rRinv = (delta3[c] + muscl_eps) / (delta2[c] + muscl_eps);
     193                 :    4668948 :     auto phiL = (std::abs(rL) + rL) / (std::abs(rL) + 1.0);
     194                 :    4668948 :     auto phiR = (std::abs(rR) + rR) / (std::abs(rR) + 1.0);
     195                 :    4668948 :     auto phi_L_inv = (std::abs(rLinv) + rLinv) / (std::abs(rLinv) + 1.0);
     196                 :    4668948 :     auto phi_R_inv = (std::abs(rRinv) + rRinv) / (std::abs(rRinv) + 1.0);
     197                 :            :     // update unknowns with reconstructed unknowns
     198                 :    4668948 :     uL[5+c] += 0.25*(delta1[c]*(1.0-muscl_const)*phiL +
     199                 :    4668948 :                      delta2[c]*(1.0+muscl_const)*phi_L_inv);
     200                 :    4668948 :     uR[5+c] -= 0.25*(delta3[c]*(1.0-muscl_const)*phiR +
     201                 :    4668948 :                      delta2[c]*(1.0+muscl_const)*phi_R_inv);
     202                 :            :   }
     203                 :            : 
     204                 :            :   #if defined(__clang__)
     205                 :            :     #pragma clang diagnostic pop
     206                 :            :   #elif defined(STRICT_GNUC)
     207                 :            :     #pragma GCC diagnostic pop
     208                 :            :   #endif
     209                 :    4668948 : }
     210                 :            : 
     211                 :            : static void
     212                 :   48967650 : primitive( std::size_t ncomp, std::size_t i, const tk::Fields& U, tk::real u[] )
     213                 :            : // *****************************************************************************
     214                 :            : //! Compute primitive flow variables from conserved ones
     215                 :            : //! \param[in] ncomp Number of scalar components: 5 + scalars
     216                 :            : //! \param[in] i Index to read conserved variables from
     217                 :            : //! \param[in] U Solution vector to read conserved variables from
     218                 :            : //! \param[in,out] u Computed primitive variables
     219                 :            : // *****************************************************************************
     220                 :            : {
     221                 :   48967650 :   u[0] = U(i,0);
     222                 :   48967650 :   u[1] = U(i,1) / u[0];
     223                 :   48967650 :   u[2] = U(i,2) / u[0];
     224                 :   48967650 :   u[3] = U(i,3) / u[0];
     225                 :   48967650 :   u[4] = U(i,4) / u[0] - 0.5*(u[1]*u[1] + u[2]*u[2] + u[3]*u[3]);
     226         [ +  + ]:   63006834 :   for (std::size_t c=5; c<ncomp; ++c) u[c] = U(i,c);
     227                 :   48967650 : }
     228                 :            : 
     229                 :            : void
     230                 :      38040 : grad( const std::array< std::vector< std::size_t >, 3 >& dsupedge,
     231                 :            :       const std::array< std::vector< tk::real >, 3 >& dsupint,
     232                 :            :       const std::array< std::vector< tk::real >, 3 >& coord,
     233                 :            :       const std::vector< std::size_t >& triinpoel,
     234                 :            :       const tk::Fields& U,
     235                 :            :       tk::Fields& G )
     236                 :            : // *****************************************************************************
     237                 :            : //  Compute nodal gradients of primitive variables in all points
     238                 :            : //! \param[in] dsupedge Domain superedges
     239                 :            : //! \param[in] dsupint Domain superedge integrals
     240                 :            : //! \param[in] coord Mesh node coordinates
     241                 :            : //! \param[in] triinpoel Boundary face connectivity
     242                 :            : //! \param[in] U Solution vector at recent time step
     243                 :            : //! \param[in,out] G Nodal gradients
     244                 :            : //! \return Gradients of primitive variables in all mesh points
     245                 :            : // *****************************************************************************
     246                 :            : {
     247                 :            :   #if defined(__clang__)
     248                 :            :     #pragma clang diagnostic push
     249                 :            :     #pragma clang diagnostic ignored "-Wvla"
     250                 :            :     #pragma clang diagnostic ignored "-Wvla-extension"
     251                 :            :   #elif defined(STRICT_GNUC)
     252                 :            :     #pragma GCC diagnostic push
     253                 :            :     #pragma GCC diagnostic ignored "-Wvla"
     254                 :            :   #endif
     255                 :            : 
     256                 :            :   // cppcheck-suppress unreadVariable
     257                 :            :   auto ncomp = U.nprop();
     258                 :            : 
     259                 :            :   Assert( G.nunk() == U.nunk(), "Size mismatch" );
     260                 :            :   Assert( G.nprop() == ncomp*3, "Size mismatch" );
     261                 :            :   G.fill( 0.0 );
     262                 :            : 
     263                 :            :   // domain integral
     264                 :            : 
     265                 :            :   // domain edge contributions: tetrahedron superedges
     266         [ +  + ]:    1572384 :   for (std::size_t e=0; e<dsupedge[0].size()/4; ++e) {
     267                 :    1534344 :     const auto N = dsupedge[0].data() + e*4;
     268                 :    1534344 :     tk::real u[4][ncomp];
     269                 :    1534344 :     primitive( ncomp, N[0], U, u[0] );
     270                 :    1534344 :     primitive( ncomp, N[1], U, u[1] );
     271                 :    1534344 :     primitive( ncomp, N[2], U, u[2] );
     272                 :    1534344 :     primitive( ncomp, N[3], U, u[3] );
     273         [ +  + ]:    9623607 :     for (std::size_t c=0; c<ncomp; ++c) {
     274         [ +  + ]:   32357052 :       for (std::size_t j=0; j<3; ++j) {
     275                 :            :         tk::real f[6];
     276                 :            :         const auto d = dsupint[0].data();
     277                 :   24267789 :         f[0] = d[(e*6+0)*3+j] * (u[1][c] + u[0][c]);
     278                 :   24267789 :         f[1] = d[(e*6+1)*3+j] * (u[2][c] + u[1][c]);
     279                 :   24267789 :         f[2] = d[(e*6+2)*3+j] * (u[0][c] + u[2][c]);
     280                 :   24267789 :         f[3] = d[(e*6+3)*3+j] * (u[3][c] + u[0][c]);
     281                 :   24267789 :         f[4] = d[(e*6+4)*3+j] * (u[3][c] + u[1][c]);
     282                 :   24267789 :         f[5] = d[(e*6+5)*3+j] * (u[3][c] + u[2][c]);
     283                 :   24267789 :         G(N[0],c*3+j) = G(N[0],c*3+j) - f[0] + f[2] - f[3];
     284                 :   24267789 :         G(N[1],c*3+j) = G(N[1],c*3+j) + f[0] - f[1] - f[4];
     285                 :   24267789 :         G(N[2],c*3+j) = G(N[2],c*3+j) + f[1] - f[2] - f[5];
     286                 :   24267789 :         G(N[3],c*3+j) = G(N[3],c*3+j) + f[3] + f[4] + f[5];
     287                 :            :       }
     288                 :            :     }
     289                 :    1534344 :   }
     290                 :            : 
     291                 :            :   // domain edge contributions: triangle superedges
     292         [ +  + ]:    1286139 :   for (std::size_t e=0; e<dsupedge[1].size()/3; ++e) {
     293                 :    1248099 :     const auto N = dsupedge[1].data() + e*3;
     294                 :    1248099 :     tk::real u[3][ncomp];
     295                 :    1248099 :     primitive( ncomp, N[0], U, u[0] );
     296                 :    1248099 :     primitive( ncomp, N[1], U, u[1] );
     297                 :    1248099 :     primitive( ncomp, N[2], U, u[2] );
     298         [ +  + ]:    7821330 :     for (std::size_t c=0; c<ncomp; ++c) {
     299         [ +  + ]:   26292924 :       for (std::size_t j=0; j<3; ++j) {
     300                 :            :         tk::real f[3];
     301                 :            :         const auto d = dsupint[1].data();
     302                 :   19719693 :         f[0] = d[(e*3+0)*3+j] * (u[1][c] + u[0][c]);
     303                 :   19719693 :         f[1] = d[(e*3+1)*3+j] * (u[2][c] + u[1][c]);
     304                 :   19719693 :         f[2] = d[(e*3+2)*3+j] * (u[0][c] + u[2][c]);
     305                 :   19719693 :         G(N[0],c*3+j) = G(N[0],c*3+j) - f[0] + f[2];
     306                 :   19719693 :         G(N[1],c*3+j) = G(N[1],c*3+j) + f[0] - f[1];
     307                 :   19719693 :         G(N[2],c*3+j) = G(N[2],c*3+j) + f[1] - f[2];
     308                 :            :       }
     309                 :            :     }
     310                 :    1248099 :   }
     311                 :            : 
     312                 :            :   // domain edge contributions: edges
     313         [ +  + ]:    4287819 :   for (std::size_t e=0; e<dsupedge[2].size()/2; ++e) {
     314                 :    4249779 :     const auto N = dsupedge[2].data() + e*2;
     315                 :    4249779 :     tk::real u[2][ncomp];
     316                 :    4249779 :     primitive( ncomp, N[0], U, u[0] );
     317                 :    4249779 :     primitive( ncomp, N[1], U, u[1] );
     318                 :    4249779 :     const auto d = dsupint[2].data() + e*3;
     319         [ +  + ]:   26664156 :     for (std::size_t c=0; c<ncomp; ++c) {
     320         [ +  + ]:   89657508 :       for (std::size_t j=0; j<3; ++j) {
     321                 :   67243131 :         tk::real f = d[j] * (u[1][c] + u[0][c]);
     322                 :   67243131 :         G(N[0],c*3+j) -= f;
     323                 :   67243131 :         G(N[1],c*3+j) += f;
     324                 :            :       }
     325                 :            :     }
     326                 :    4249779 :   }
     327                 :            : 
     328                 :            :   // boundary integral
     329                 :            : 
     330                 :            :   const auto& x = coord[0];
     331                 :            :   const auto& y = coord[1];
     332                 :            :   const auto& z = coord[2];
     333                 :            : 
     334         [ +  + ]:    4106436 :   for (std::size_t e=0; e<triinpoel.size()/3; ++e) {
     335                 :    4068396 :     const auto N = triinpoel.data() + e*3;
     336                 :    4068396 :     tk::real u[3][ncomp];
     337                 :    4068396 :     primitive( ncomp, N[0], U, u[0] );
     338                 :    4068396 :     primitive( ncomp, N[1], U, u[1] );
     339                 :    4068396 :     primitive( ncomp, N[2], U, u[2] );
     340                 :            :     const std::array< tk::real, 3 >
     341                 :    4068396 :       ba{ x[N[1]]-x[N[0]], y[N[1]]-y[N[0]], z[N[1]]-z[N[0]] },
     342                 :    4068396 :       ca{ x[N[2]]-x[N[0]], y[N[2]]-y[N[0]], z[N[2]]-z[N[0]] };
     343                 :            :     auto n = tk::cross( ba, ca );
     344                 :    4068396 :     n[0] /= 12.0;
     345                 :    4068396 :     n[1] /= 12.0;
     346                 :    4068396 :     n[2] /= 12.0;
     347         [ +  + ]:   25757208 :     for (std::size_t c=0; c<ncomp; ++c) {
     348                 :   21688812 :       auto uab = (u[0][c] + u[1][c])/4.0;
     349                 :   21688812 :       auto ubc = (u[1][c] + u[2][c])/4.0;
     350                 :   21688812 :       auto uca = (u[2][c] + u[0][c])/4.0;
     351                 :   21688812 :       tk::real g[] = { uab + uca + u[0][c],
     352                 :   21688812 :                        uab + ubc + u[1][c],
     353                 :   21688812 :                        ubc + uca + u[2][c] };
     354         [ +  + ]:   86755248 :       for (std::size_t j=0; j<3; ++j) {
     355                 :   65066436 :         G(N[0],c*3+j) += g[j] * n[j];
     356                 :   65066436 :         G(N[1],c*3+j) += g[j] * n[j];
     357                 :   65066436 :         G(N[2],c*3+j) += g[j] * n[j];
     358                 :            :       }
     359                 :            :     }
     360                 :    4068396 :   }
     361                 :            : 
     362                 :            :   #if defined(__clang__)
     363                 :            :     #pragma clang diagnostic pop
     364                 :            :   #elif defined(STRICT_GNUC)
     365                 :            :     #pragma GCC diagnostic pop
     366                 :            :   #endif
     367                 :      38040 : }
     368                 :            : 
     369                 :            : static void
     370                 :   16246428 : rusanov( const tk::UnsMesh::Coords& coord,
     371                 :            :          const tk::Fields& G,
     372                 :            :          const tk::real dsupint[],
     373                 :            :          std::size_t p,
     374                 :            :          std::size_t q,
     375                 :            :          const tk::real L[],
     376                 :            :          const tk::real R[],
     377                 :            :          tk::real f[],
     378                 :            :          std::size_t symL,
     379                 :            :          std::size_t symR )
     380                 :            : // *****************************************************************************
     381                 :            : //! Compute advection fluxes on a single edge with Rusanov's flux
     382                 :            : //! \param[in] coord Mesh node coordinates
     383                 :            : //! \param[in] G Nodal gradients
     384                 :            : //! \param[in] dsupint Domain superedge integral for this edge
     385                 :            : //! \param[in] p Left node index of edge
     386                 :            : //! \param[in] q Right node index of edge
     387                 :            : //! \param[in,out] L Left physics state variables
     388                 :            : //! \param[in,out] R Rigth physics state variables
     389                 :            : //! \param[in,out] f Flux computed
     390                 :            : //! \param[in] symL Non-zero if left edge end-point is on a symmetry boundary
     391                 :            : //! \param[in] symR Non-zero if right edge end-point is on a symmetry boundary
     392                 :            : // *****************************************************************************
     393                 :            : {
     394                 :            :   #if defined(__clang__)
     395                 :            :     #pragma clang diagnostic push
     396                 :            :     #pragma clang diagnostic ignored "-Wvla"
     397                 :            :     #pragma clang diagnostic ignored "-Wvla-extension"
     398                 :            :   #elif defined(STRICT_GNUC)
     399                 :            :     #pragma GCC diagnostic push
     400                 :            :     #pragma GCC diagnostic ignored "-Wvla"
     401                 :            :   #endif
     402                 :            : 
     403                 :   16246428 :   auto ncomp = G.nprop() / 3;
     404                 :            : 
     405                 :            :   // will work on copies of physics variables
     406                 :   16246428 :   tk::real l[ncomp], r[ncomp];
     407                 :   16246428 :   memcpy( l, L, sizeof l );
     408                 :   16246428 :   memcpy( r, R, sizeof r );
     409                 :            : 
     410                 :            :   // MUSCL reconstruction in edge-end points for flow variables
     411                 :   16246428 :   muscl( p, q, coord, G, l[0], l[1], l[2], l[3], l[4],
     412                 :   16246428 :                          r[0], r[1], r[2], r[3], r[4] );
     413                 :            : 
     414                 :            :   // pressure
     415         [ +  - ]:   16246428 :   auto pL = eos::pressure( l[0]*l[4] );
     416                 :   16246428 :   auto pR = eos::pressure( r[0]*r[4] );
     417                 :            : 
     418                 :            :   // dualface-normal velocities
     419                 :   16246428 :   auto nx = dsupint[0];
     420                 :   16246428 :   auto ny = dsupint[1];
     421                 :   16246428 :   auto nz = dsupint[2];
     422         [ +  - ]:   16246428 :   auto vnL = symL ? 0.0 : (l[1]*nx + l[2]*ny + l[3]*nz);
     423         [ +  - ]:   16246428 :   auto vnR = symR ? 0.0 : (r[1]*nx + r[2]*ny + r[3]*nz);
     424                 :            : 
     425                 :            :   // back to conserved variables
     426                 :   16246428 :   l[4] = (l[4] + 0.5*(l[1]*l[1] + l[2]*l[2] + l[3]*l[3])) * l[0];
     427                 :   16246428 :   l[1] *= l[0];
     428                 :   16246428 :   l[2] *= l[0];
     429                 :   16246428 :   l[3] *= l[0];
     430                 :   16246428 :   r[4] = (r[4] + 0.5*(r[1]*r[1] + r[2]*r[2] + r[3]*r[3])) * r[0];
     431                 :   16246428 :   r[1] *= r[0];
     432                 :   16246428 :   r[2] *= r[0];
     433         [ +  + ]:   16246428 :   r[3] *= r[0];
     434                 :            : 
     435                 :            :   // dissipation
     436                 :            :   auto len = tk::length( nx, ny, nz );
     437                 :   16246428 :   auto sl = std::abs(vnL) + eos::soundspeed(l[0],pL)*len;
     438         [ +  + ]:   16246428 :   auto sr = std::abs(vnR) + eos::soundspeed(r[0],pR)*len;
     439                 :   16246428 :   auto fw = std::max( sl, sr );
     440                 :            : 
     441                 :            :   // flow fluxes
     442                 :   16246428 :   f[0] = l[0]*vnL + r[0]*vnR + fw*(r[0] - l[0]);
     443                 :   16246428 :   f[1] = l[1]*vnL + r[1]*vnR + (pL + pR)*nx + fw*(r[1] - l[1]);
     444                 :   16246428 :   f[2] = l[2]*vnL + r[2]*vnR + (pL + pR)*ny + fw*(r[2] - l[2]);
     445                 :   16246428 :   f[3] = l[3]*vnL + r[3]*vnR + (pL + pR)*nz + fw*(r[3] - l[3]);
     446                 :   16246428 :   f[4] = (l[4] + pL)*vnL + (r[4] + pR)*vnR + fw*(r[4] - l[4]);
     447                 :            : 
     448                 :            :   // artificial viscosity
     449                 :   16246428 :   const auto stab2 = g_cfg.get< tag::stab2 >();
     450         [ +  + ]:   16246428 :   if (stab2) {
     451                 :     242604 :     auto stab2coef = g_cfg.get< tag::stab2coef >();
     452                 :     242604 :     auto fws = stab2coef * fw;
     453                 :     242604 :     f[0] -= fws*(l[0] - r[0]);
     454                 :     242604 :     f[1] -= fws*(l[1] - r[1]);
     455                 :     242604 :     f[2] -= fws*(l[2] - r[2]);
     456                 :     242604 :     f[3] -= fws*(l[3] - r[3]);
     457                 :     242604 :     f[4] -= fws*(l[4] - r[4]);
     458                 :            :   }
     459                 :            : 
     460         [ +  + ]:   16246428 :   if (ncomp == 5) return;
     461                 :            : 
     462                 :            :   // MUSCL reconstruction in edge-end points for scalars
     463                 :    4306428 :   muscl( p, q, coord, G, l, r );
     464                 :            : 
     465                 :            :   // scalar dissipation
     466         [ +  + ]:    4306428 :   auto sw = std::max( std::abs(vnL), std::abs(vnR) );
     467                 :            : 
     468                 :            :   // scalar fluxes
     469         [ +  + ]:    8612856 :   for (std::size_t c=5; c<ncomp; ++c) {
     470                 :    4306428 :     f[c] = l[c]*vnL + r[c]*vnR + sw*(r[c] - l[c]);
     471                 :            :   }
     472                 :            : 
     473                 :            :   #if defined(__clang__)
     474                 :            :     #pragma clang diagnostic pop
     475                 :            :   #elif defined(STRICT_GNUC)
     476                 :            :     #pragma GCC diagnostic pop
     477                 :            :   #endif
     478                 :   16246428 : }
     479                 :            : 
     480                 :            : static void
     481                 :     953712 : hllc( const tk::UnsMesh::Coords& coord,
     482                 :            :       const tk::Fields& G,
     483                 :            :       const tk::real dsupint[],
     484                 :            :       std::size_t p,
     485                 :            :       std::size_t q,
     486                 :            :       const tk::real L[],
     487                 :            :       const tk::real R[],
     488                 :            :       tk::real f[],
     489                 :            :       std::size_t symL,
     490                 :            :       std::size_t symR )
     491                 :            : // *****************************************************************************
     492                 :            : //! Compute advection fluxes on a single edge with Harten-Lax-vanLeer-Contact
     493                 :            : //! \param[in] coord Mesh node coordinates
     494                 :            : //! \param[in] G Nodal gradients
     495                 :            : //! \param[in] dsupint Domain superedge integral for this edge
     496                 :            : //! \param[in] p Left node index of edge
     497                 :            : //! \param[in] q Right node index of edge
     498                 :            : //! \param[in,out] L Left physics state variables
     499                 :            : //! \param[in,out] R Rigth physics state variables
     500                 :            : //! \param[in,out] f Flux computed
     501                 :            : //! \param[in] symL Non-zero if left edge end-point is on a symmetry boundary
     502                 :            : //! \param[in] symR Non-zero if right edge end-point is on a symmetry boundary
     503                 :            : // *****************************************************************************
     504                 :            : {
     505                 :            :   #if defined(__clang__)
     506                 :            :     #pragma clang diagnostic push
     507                 :            :     #pragma clang diagnostic ignored "-Wvla"
     508                 :            :     #pragma clang diagnostic ignored "-Wvla-extension"
     509                 :            :   #elif defined(STRICT_GNUC)
     510                 :            :     #pragma GCC diagnostic push
     511                 :            :     #pragma GCC diagnostic ignored "-Wvla"
     512                 :            :   #endif
     513                 :            : 
     514                 :     953712 :   auto ncomp = G.nprop() / 3;
     515                 :            : 
     516                 :            :   // will work on copies of physics variables
     517                 :     953712 :   tk::real l[ncomp], r[ncomp];
     518                 :     953712 :   memcpy( l, L, sizeof l );
     519                 :     953712 :   memcpy( r, R, sizeof r );
     520                 :            : 
     521                 :            :   // MUSCL reconstruction in edge-end points for flow variables
     522                 :     953712 :   muscl( p, q, coord, G, l[0], l[1], l[2], l[3], l[4],
     523                 :     953712 :                          r[0], r[1], r[2], r[3], r[4] );
     524                 :            : 
     525                 :            :   // dualface-normal velocities
     526                 :     953712 :   auto nx = -dsupint[0];
     527                 :     953712 :   auto ny = -dsupint[1];
     528         [ +  - ]:     953712 :   auto nz = -dsupint[2];
     529                 :            :   auto len = tk::length( nx, ny, nz );
     530                 :     953712 :   nx /= len;
     531                 :     953712 :   ny /= len;
     532                 :     953712 :   nz /= len;
     533         [ +  - ]:     953712 :   auto qL = symL ? 0.0 : (l[1]*nx + l[2]*ny + l[3]*nz);
     534         [ +  - ]:     953712 :   auto qR = symR ? 0.0 : (r[1]*nx + r[2]*ny + r[3]*nz);
     535                 :            : 
     536                 :            :   // pressure
     537         [ -  + ]:     953712 :   auto pL = eos::pressure( l[0]*l[4] );
     538                 :     953712 :   auto pR = eos::pressure( r[0]*r[4] );
     539                 :            : 
     540                 :            :   // back to conserved variables
     541                 :     953712 :   l[4] = (l[4] + 0.5*(l[1]*l[1] + l[2]*l[2] + l[3]*l[3])) * l[0];
     542                 :     953712 :   l[1] *= l[0];
     543                 :     953712 :   l[2] *= l[0];
     544                 :     953712 :   l[3] *= l[0];
     545                 :     953712 :   r[4] = (r[4] + 0.5*(r[1]*r[1] + r[2]*r[2] + r[3]*r[3])) * r[0];
     546                 :     953712 :   r[1] *= r[0];
     547                 :     953712 :   r[2] *= r[0];
     548         [ -  + ]:     953712 :   r[3] *= r[0];
     549                 :            : 
     550                 :            :   // sound speed
     551                 :            :   auto cL = eos::soundspeed(l[0],pL);
     552                 :            :   auto cR = eos::soundspeed(r[0],pR);
     553                 :            : 
     554                 :            :   // left and right wave speeds
     555                 :     953712 :   auto sL = fmin( qL - cL, qR - cR );
     556                 :     953712 :   auto sR = fmax( qL + cL, qR + cR );
     557                 :            : 
     558                 :            :   // contact wave speed and pressure
     559                 :     953712 :   auto tL = sL - qL;
     560                 :     953712 :   auto tR = sR - qR;
     561                 :     953712 :   auto sM = (r[0]*qR*tR - l[0]*qL*tL + pL - pR) / (r[0]*tR - l[0]*tL);
     562                 :     953712 :   auto pS = pL - l[0]*tL*(qL - sM);
     563                 :            : 
     564                 :            :   // intermediate left-, and right-state conserved unknowns
     565                 :     953712 :   tk::real uL[ncomp], uR[ncomp];
     566                 :     953712 :   auto s = sL - sM;
     567                 :     953712 :   uL[0] = tL*l[0]/s;
     568                 :     953712 :   uL[1] = (tL*l[1] + (pS-pL)*nx)/s;
     569                 :     953712 :   uL[2] = (tL*l[2] + (pS-pL)*ny)/s;
     570                 :     953712 :   uL[3] = (tL*l[3] + (pS-pL)*nz)/s;
     571                 :     953712 :   uL[4] = (tL*l[4] - pL*qL + pS*sM)/s;
     572                 :     953712 :   s = sR - sM;
     573                 :     953712 :   uR[0] = tR*r[0]/s;
     574                 :     953712 :   uR[1] = (tR*r[1] + (pS-pR)*nx)/s;
     575                 :     953712 :   uR[2] = (tR*r[2] + (pS-pR)*ny)/s;
     576                 :     953712 :   uR[3] = (tR*r[3] + (pS-pR)*nz)/s;
     577                 :     953712 :   uR[4] = (tR*r[4] - pR*qR + pS*sM)/s;
     578                 :            : 
     579                 :     953712 :   auto L2 = -2.0*len;
     580                 :     953712 :   nx *= L2;
     581                 :     953712 :   ny *= L2;
     582                 :     953712 :   nz *= L2;
     583                 :            : 
     584                 :            :   // flow fluxes
     585         [ -  + ]:     953712 :   if (sL > 0.0) {
     586                 :          0 :     auto qL2 = qL * L2;
     587                 :          0 :     f[0] = l[0]*qL2;
     588                 :          0 :     f[1] = l[1]*qL2 + pL*nx;
     589                 :          0 :     f[2] = l[2]*qL2 + pL*ny;
     590                 :          0 :     f[3] = l[3]*qL2 + pL*nz;
     591                 :          0 :     f[4] = (l[4] + pL)*qL2;
     592                 :            :   }
     593 [ +  - ][ +  + ]:     953712 :   else if (sL <= 0.0 && sM > 0.0) {
     594                 :     477426 :     auto qL2 = qL * L2;
     595                 :     477426 :     auto sL2 = sL * L2;
     596                 :     477426 :     f[0] = l[0]*qL2 + sL2*(uL[0] - l[0]);
     597                 :     477426 :     f[1] = l[1]*qL2 + pL*nx + sL2*(uL[1] - l[1]);
     598                 :     477426 :     f[2] = l[2]*qL2 + pL*ny + sL2*(uL[2] - l[2]);
     599                 :     477426 :     f[3] = l[3]*qL2 + pL*nz + sL2*(uL[3] - l[3]);
     600                 :     477426 :     f[4] = (l[4] + pL)*qL2 + sL2*(uL[4] - l[4]);
     601                 :     477426 :   }
     602 [ +  - ][ +  - ]:     476286 :   else if (sM <= 0.0 && sR >= 0.0) {
     603                 :     476286 :     auto qR2 = qR * L2;
     604                 :     476286 :     auto sR2 = sR * L2;
     605                 :     476286 :     f[0] = r[0]*qR2 + sR2*(uR[0] - r[0]);
     606                 :     476286 :     f[1] = r[1]*qR2 + pR*nx + sR2*(uR[1] - r[1]);
     607                 :     476286 :     f[2] = r[2]*qR2 + pR*ny + sR2*(uR[2] - r[2]);
     608                 :     476286 :     f[3] = r[3]*qR2 + pR*nz + sR2*(uR[3] - r[3]);
     609                 :     476286 :     f[4] = (r[4] + pR)*qR2 + sR2*(uR[4] - r[4]);
     610                 :     476286 :   }
     611                 :            :   else {
     612                 :          0 :     auto qR2 = qR * L2;
     613                 :          0 :     f[0] = r[0]*qR2;
     614                 :          0 :     f[1] = r[1]*qR2 + pR*nx;
     615                 :          0 :     f[2] = r[2]*qR2 + pR*ny;
     616                 :          0 :     f[3] = r[3]*qR2 + pR*nz;
     617                 :          0 :     f[4] = (r[4] + pR)*qR2;
     618                 :            :   }
     619                 :            : 
     620                 :            :   // artificial viscosity
     621                 :     953712 :   const auto stab2 = g_cfg.get< tag::stab2 >();
     622         [ +  + ]:     953712 :   if (stab2) {
     623         [ +  + ]:     295596 :     auto stab2coef = g_cfg.get< tag::stab2coef >();
     624                 :     295596 :     auto sl = std::abs(qL) + cL;
     625         [ +  + ]:     295596 :     auto sr = std::abs(qR) + cR;
     626                 :     295596 :     auto fws = stab2coef * std::max(sl,sr) * len;
     627                 :     295596 :     f[0] -= fws * (l[0] - r[0]);
     628                 :     295596 :     f[1] -= fws * (l[1] - r[1]);
     629                 :     295596 :     f[2] -= fws * (l[2] - r[2]);
     630                 :     295596 :     f[3] -= fws * (l[3] - r[3]);
     631                 :     295596 :     f[4] -= fws * (l[4] - r[4]);
     632                 :            :   }
     633                 :            : 
     634         [ +  + ]:     953712 :   if (ncomp == 5) return;
     635                 :            : 
     636                 :            :   // MUSCL reconstruction in edge-end points for scalars
     637                 :     362520 :   muscl( p, q, coord, G, l, r );
     638                 :            : 
     639                 :            :   // scalar
     640         [ +  + ]:     362520 :   auto sw = std::max( std::abs(qL), std::abs(qR) ) * len;
     641         [ +  + ]:     725040 :   for (std::size_t c=5; c<ncomp; ++c) {
     642                 :     362520 :     f[c] = (l[c]*qL + r[c]*qR)*len + sw*(r[c] - l[c]);
     643                 :            :   }
     644                 :            : 
     645                 :            :   #if defined(__clang__)
     646                 :            :     #pragma clang diagnostic pop
     647                 :            :   #elif defined(STRICT_GNUC)
     648                 :            :     #pragma GCC diagnostic pop
     649                 :            :   #endif
     650                 :     953712 : }
     651                 :            : 
     652                 :            : static void
     653                 :      38040 : advdom( const tk::UnsMesh::Coords& coord,
     654                 :            :         const std::array< std::vector< std::size_t >, 3 >& dsupedge,
     655                 :            :         const std::array< std::vector< tk::real >, 3 >& dsupint,
     656                 :            :         const tk::Fields& G,
     657                 :            :         const tk::Fields& U,
     658                 :            :         // cppcheck-suppress constParameter
     659                 :            :         tk::Fields& R )
     660                 :            : // *****************************************************************************
     661                 :            : //! Compute domain integral for advection
     662                 :            : //! \param[in] coord Mesh node coordinates
     663                 :            : //! \param[in] dsupedge Domain superedges
     664                 :            : //! \param[in] dsupint Domain superedge integrals
     665                 :            : //! \param[in] G Nodal gradients
     666                 :            : //! \param[in] U Solution vector at recent time step
     667                 :            : //! \param[in,out] R Right-hand side vector computed
     668                 :            : // *****************************************************************************
     669                 :            : {
     670                 :            :   // number of transported scalars
     671                 :            :   auto ncomp = U.nprop();
     672                 :            : 
     673                 :            :   // configure flux function
     674                 :      38040 :   auto cfgflux = [](){
     675                 :            :     const auto& cfg = g_cfg.get< tag::flux >();
     676         [ +  + ]:      38040 :     if (cfg == "rusanov")
     677                 :            :       return rusanov;
     678         [ -  + ]:       3372 :     else if (cfg == "hllc")
     679                 :            :       return hllc;
     680                 :            :     else
     681 [ -  - ][ -  - ]:          0 :       Throw( "Flux not configured" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     682                 :            :   };
     683                 :            : 
     684                 :      38040 :   auto flux = cfgflux();
     685                 :            : 
     686                 :            :   #if defined(__clang__)
     687                 :            :     #pragma clang diagnostic push
     688                 :            :     #pragma clang diagnostic ignored "-Wvla"
     689                 :            :     #pragma clang diagnostic ignored "-Wvla-extension"
     690                 :            :   #elif defined(STRICT_GNUC)
     691                 :            :     #pragma GCC diagnostic push
     692                 :            :     #pragma GCC diagnostic ignored "-Wvla"
     693                 :            :   #endif
     694                 :            : 
     695                 :            :   // domain edge contributions: tetrahedron superedges
     696         [ +  + ]:    1572384 :   for (std::size_t e=0; e<dsupedge[0].size()/4; ++e) {
     697                 :    1534344 :     const auto N = dsupedge[0].data() + e*4;
     698                 :            :     // primitive variables
     699                 :    1534344 :     tk::real u[4][ncomp];
     700                 :    1534344 :     primitive( ncomp, N[0], U, u[0] );
     701                 :    1534344 :     primitive( ncomp, N[1], U, u[1] );
     702                 :    1534344 :     primitive( ncomp, N[2], U, u[2] );
     703                 :    1534344 :     primitive( ncomp, N[3], U, u[3] );
     704                 :            :     // edge fluxes
     705                 :    1534344 :     tk::real f[6][ncomp];
     706                 :            :     const auto d = dsupint[0].data();
     707                 :    1534344 :     flux( coord, G, d+(e*6+0)*3, N[0], N[1], u[0], u[1], f[0], 0, 0 );
     708                 :    1534344 :     flux( coord, G, d+(e*6+1)*3, N[1], N[2], u[1], u[2], f[1], 0, 0 );
     709                 :    1534344 :     flux( coord, G, d+(e*6+2)*3, N[2], N[0], u[2], u[0], f[2], 0, 0 );
     710                 :    1534344 :     flux( coord, G, d+(e*6+3)*3, N[0], N[3], u[0], u[3], f[3], 0, 0 );
     711                 :    1534344 :     flux( coord, G, d+(e*6+4)*3, N[1], N[3], u[1], u[3], f[4], 0, 0 );
     712                 :    1534344 :     flux( coord, G, d+(e*6+5)*3, N[2], N[3], u[2], u[3], f[5], 0, 0 );
     713                 :            :     // edge flux contributions
     714         [ +  + ]:    9623607 :     for (std::size_t c=0; c<ncomp; ++c) {
     715                 :    8089263 :       R(N[0],c) = R(N[0],c) - f[0][c] + f[2][c] - f[3][c];
     716                 :    8089263 :       R(N[1],c) = R(N[1],c) + f[0][c] - f[1][c] - f[4][c];
     717                 :    8089263 :       R(N[2],c) = R(N[2],c) + f[1][c] - f[2][c] - f[5][c];
     718                 :    8089263 :       R(N[3],c) = R(N[3],c) + f[3][c] + f[4][c] + f[5][c];
     719                 :            :     }
     720                 :    1534344 :   }
     721                 :            : 
     722                 :            :   // domain edge contributions: triangle superedges
     723         [ +  + ]:    1286139 :   for (std::size_t e=0; e<dsupedge[1].size()/3; ++e) {
     724                 :    1248099 :     const auto N = dsupedge[1].data() + e*3;
     725                 :            :     // primitive variables
     726                 :    1248099 :     tk::real u[3][ncomp];
     727                 :    1248099 :     primitive( ncomp, N[0], U, u[0] );
     728                 :    1248099 :     primitive( ncomp, N[1], U, u[1] );
     729                 :    1248099 :     primitive( ncomp, N[2], U, u[2] );
     730                 :            :     // edge fluxes
     731                 :    1248099 :     tk::real f[3][ncomp];
     732                 :            :     const auto d = dsupint[1].data();
     733                 :    1248099 :     flux( coord, G, d+(e*3+0)*3, N[0], N[1], u[0], u[1], f[0], 0, 0 );
     734                 :    1248099 :     flux( coord, G, d+(e*3+1)*3, N[1], N[2], u[1], u[2], f[1], 0, 0 );
     735                 :    1248099 :     flux( coord, G, d+(e*3+2)*3, N[2], N[0], u[2], u[0], f[2], 0, 0 );
     736                 :            :     // edge flux contributions
     737         [ +  + ]:    7821330 :     for (std::size_t c=0; c<ncomp; ++c) {
     738                 :    6573231 :       R(N[0],c) = R(N[0],c) - f[0][c] + f[2][c];
     739                 :    6573231 :       R(N[1],c) = R(N[1],c) + f[0][c] - f[1][c];
     740                 :    6573231 :       R(N[2],c) = R(N[2],c) + f[1][c] - f[2][c];
     741                 :            :     }
     742                 :    1248099 :   }
     743                 :            : 
     744                 :            :   // domain edge contributions: edges
     745         [ +  + ]:    4287819 :   for (std::size_t e=0; e<dsupedge[2].size()/2; ++e) {
     746                 :    4249779 :     const auto N = dsupedge[2].data() + e*2;
     747                 :    4249779 :     tk::real u[2][ncomp];
     748                 :    4249779 :     primitive( ncomp, N[0], U, u[0] );
     749                 :    4249779 :     primitive( ncomp, N[1], U, u[1] );
     750                 :            :     // edge fluxes
     751                 :    4249779 :     tk::real f[ncomp];
     752                 :            :     const auto d = dsupint[2].data();
     753                 :    4249779 :     flux( coord, G, d+e*3, N[0], N[1], u[0], u[1], f, 0, 0 );
     754                 :            :     // edge flux contributions
     755         [ +  + ]:   26664156 :     for (std::size_t c=0; c<ncomp; ++c) {
     756                 :   22414377 :       R(N[0],c) -= f[c];
     757                 :   22414377 :       R(N[1],c) += f[c];
     758                 :            :     }
     759                 :    4249779 :   }
     760                 :            : 
     761                 :            :   #if defined(__clang__)
     762                 :            :     #pragma clang diagnostic pop
     763                 :            :   #elif defined(STRICT_GNUC)
     764                 :            :     #pragma GCC diagnostic pop
     765                 :            :   #endif
     766                 :      38040 : }
     767                 :            : 
     768                 :            : static void
     769                 :      38040 : advbnd( const std::vector< std::size_t >& triinpoel,
     770                 :            :         const std::array< std::vector< tk::real >, 3 >& coord,
     771                 :            :         const std::vector< std::uint8_t >& besym,
     772                 :            :         const tk::Fields& U,
     773                 :            :         tk::Fields& R )
     774                 :            : // *****************************************************************************
     775                 :            : //! Compute boundary integral for advection
     776                 :            : //! \param[in] triinpoel Boundary face connectivity
     777                 :            : //! \param[in] coord Mesh node coordinates
     778                 :            : //! \param[in] besym Boundary element symmetry BC flags
     779                 :            : //! \param[in] U Solution vector at recent time step
     780                 :            : //! \param[in,out] R Right-hand side vector
     781                 :            : // *****************************************************************************
     782                 :            : {
     783                 :            :   auto ncomp = U.nprop();
     784                 :            : 
     785                 :            :   const auto& x = coord[0];
     786                 :            :   const auto& y = coord[1];
     787                 :            :   const auto& z = coord[2];
     788                 :            : 
     789                 :            :   #if defined(__clang__)
     790                 :            :     #pragma clang diagnostic push
     791                 :            :     #pragma clang diagnostic ignored "-Wvla"
     792                 :            :     #pragma clang diagnostic ignored "-Wvla-extension"
     793                 :            :   #elif defined(STRICT_GNUC)
     794                 :            :     #pragma GCC diagnostic push
     795                 :            :     #pragma GCC diagnostic ignored "-Wvla"
     796                 :            :   #endif
     797                 :            : 
     798         [ +  + ]:    4106436 :   for (std::size_t e=0; e<triinpoel.size()/3; ++e) {
     799                 :    4068396 :     const auto N = triinpoel.data() + e*3;
     800                 :            : 
     801                 :    4068396 :     auto rA  = U(N[0],0);
     802                 :    4068396 :     auto ruA = U(N[0],1);
     803                 :    4068396 :     auto rvA = U(N[0],2);
     804                 :    4068396 :     auto rwA = U(N[0],3);
     805                 :    4068396 :     auto reA = U(N[0],4);
     806                 :            : 
     807                 :    4068396 :     auto rB  = U(N[1],0);
     808                 :    4068396 :     auto ruB = U(N[1],1);
     809                 :    4068396 :     auto rvB = U(N[1],2);
     810                 :    4068396 :     auto rwB = U(N[1],3);
     811                 :    4068396 :     auto reB = U(N[1],4);
     812                 :            : 
     813                 :    4068396 :     auto rC  = U(N[2],0);
     814                 :    4068396 :     auto ruC = U(N[2],1);
     815                 :    4068396 :     auto rvC = U(N[2],2);
     816                 :    4068396 :     auto rwC = U(N[2],3);
     817                 :    4068396 :     auto reC = U(N[2],4);
     818                 :            : 
     819                 :            :     const std::array< tk::real, 3 >
     820                 :    4068396 :       ba{ x[N[1]]-x[N[0]], y[N[1]]-y[N[0]], z[N[1]]-z[N[0]] },
     821         [ +  + ]:    4068396 :       ca{ x[N[2]]-x[N[0]], y[N[2]]-y[N[0]], z[N[2]]-z[N[0]] };
     822                 :            :     auto [nx,ny,nz] = tk::cross( ba, ca );      // 2A
     823                 :    4068396 :     nx /= 12.0;
     824                 :    4068396 :     ny /= 12.0;
     825                 :    4068396 :     nz /= 12.0;
     826                 :            : 
     827         [ +  + ]:    4068396 :     tk::real p, vn, f[ncomp][3];
     828                 :    4068396 :     const auto sym = besym.data() + e*3;
     829                 :            : 
     830         [ +  + ]:    4068396 :     p = eos::pressure( reA - 0.5*(ruA*ruA + rvA*rvA + rwA*rwA)/rA );
     831         [ +  + ]:    4068396 :     vn = sym[0] ? 0.0 : (nx*ruA + ny*rvA + nz*rwA)/rA;
     832                 :            :     // flow
     833                 :    4068396 :     f[0][0] = rA*vn;
     834                 :    4068396 :     f[1][0] = ruA*vn + p*nx;
     835                 :    4068396 :     f[2][0] = rvA*vn + p*ny;
     836                 :    4068396 :     f[3][0] = rwA*vn + p*nz;
     837                 :    4068396 :     f[4][0] = (reA + p)*vn;
     838                 :            :     // scalar
     839         [ +  + ]:    5415228 :     for (std::size_t c=5; c<ncomp; ++c) f[c][0] = U(N[0],c)*vn;
     840                 :            : 
     841         [ +  + ]:    4068396 :     p = eos::pressure( reB - 0.5*(ruB*ruB + rvB*rvB + rwB*rwB)/rB );
     842         [ +  + ]:    4068396 :     vn = sym[1] ? 0.0 : (nx*ruB + ny*rvB + nz*rwB)/rB;
     843                 :            :     // flow
     844                 :    4068396 :     f[0][1] = rB*vn;
     845                 :    4068396 :     f[1][1] = ruB*vn + p*nx;
     846                 :    4068396 :     f[2][1] = rvB*vn + p*ny;
     847                 :    4068396 :     f[3][1] = rwB*vn + p*nz;
     848                 :    4068396 :     f[4][1] = (reB + p)*vn;
     849                 :            :     // scalar
     850         [ +  + ]:    5415228 :     for (std::size_t c=5; c<ncomp; ++c) f[c][1] = U(N[1],c)*vn;
     851                 :            : 
     852         [ +  + ]:    4068396 :     p = eos::pressure( reC - 0.5*(ruC*ruC + rvC*rvC + rwC*rwC)/rC );
     853         [ +  + ]:    4068396 :     vn = sym[2] ? 0.0 : (nx*ruC + ny*rvC + nz*rwC)/rC;
     854                 :            :     // flow
     855                 :    4068396 :     f[0][2] = rC*vn;
     856                 :    4068396 :     f[1][2] = ruC*vn + p*nx;
     857                 :    4068396 :     f[2][2] = rvC*vn + p*ny;
     858                 :    4068396 :     f[3][2] = rwC*vn + p*nz;
     859                 :    4068396 :     f[4][2] = (reC + p)*vn;
     860                 :            :     // scalar
     861         [ +  + ]:    5415228 :     for (std::size_t c=5; c<ncomp; ++c) f[c][2] = U(N[2],c)*vn;
     862                 :            : 
     863         [ +  + ]:   25757208 :     for (std::size_t c=0; c<ncomp; ++c) {
     864                 :   21688812 :       auto fab = (f[c][0] + f[c][1])/4.0;
     865                 :   21688812 :       auto fbc = (f[c][1] + f[c][2])/4.0;
     866                 :   21688812 :       auto fca = (f[c][2] + f[c][0])/4.0;
     867                 :   21688812 :       R(N[0],c) += fab + fca + f[c][0];
     868                 :   21688812 :       R(N[1],c) += fab + fbc + f[c][1];
     869                 :   21688812 :       R(N[2],c) += fbc + fca + f[c][2];
     870                 :            :     }
     871         [ +  + ]:    4068396 :   }
     872                 :            : 
     873                 :            :   #if defined(__clang__)
     874                 :            :     #pragma clang diagnostic pop
     875                 :            :   #elif defined(STRICT_GNUC)
     876                 :            :     #pragma GCC diagnostic pop
     877                 :            :   #endif
     878                 :      38040 : }
     879                 :            : 
     880                 :            : static void
     881                 :      38040 : src( const std::array< std::vector< tk::real >, 3 >& coord,
     882                 :            :      const std::vector< tk::real >& v,
     883                 :            :      tk::real t,
     884                 :            :      const std::vector< tk::real >& tp,
     885                 :            :      tk::Fields& R )
     886                 :            : // *****************************************************************************
     887                 :            : //  Compute source integral
     888                 :            : //! \param[in] coord Mesh node coordinates
     889                 :            : //! \param[in] v Nodal mesh volumes without contributions from other chares
     890                 :            : //! \param[in] t Physical time
     891                 :            : //! \param[in] tp Physical time for each mesh node
     892                 :            : //! \param[in,out] R Right-hand side vector computed
     893                 :            : // *****************************************************************************
     894                 :            : {
     895                 :      38040 :   auto src = problems::SRC();
     896         [ +  + ]:      38040 :   if (!src) return;
     897                 :            : 
     898                 :            :   const auto& x = coord[0];
     899                 :            :   const auto& y = coord[1];
     900                 :            :   const auto& z = coord[2];
     901                 :            : 
     902         [ +  + ]:    1622535 :   for (std::size_t p=0; p<R.nunk(); ++p) {
     903         [ +  + ]:    1599135 :     if (g_cfg.get< tag::steady >()) t = tp[p];
     904         [ -  + ]:    1599135 :     auto s = src( x[p], y[p], z[p], t );
     905         [ +  + ]:   10250940 :     for (std::size_t c=0; c<s.size(); ++c) R(p,c) -= s[c] * v[p];
     906                 :            :   }
     907                 :            : }
     908                 :            : 
     909                 :            : void
     910                 :      38040 : rhs( const std::array< std::vector< std::size_t >, 3 >& dsupedge,
     911                 :            :      const std::array< std::vector< tk::real >, 3 >& dsupint,
     912                 :            :      const std::array< std::vector< tk::real >, 3 >& coord,
     913                 :            :      const std::vector< std::size_t >& triinpoel,
     914                 :            :      const std::vector< std::uint8_t >& besym,
     915                 :            :      const tk::Fields& G,
     916                 :            :      const tk::Fields& U,
     917                 :            :      const std::vector< tk::real >& v,
     918                 :            :      tk::real t,
     919                 :            :      const std::vector< tk::real >& tp,
     920                 :            :      tk::Fields& R )
     921                 :            : // *****************************************************************************
     922                 :            : //  Compute right hand side
     923                 :            : //! \param[in] dsupedge Domain superedges
     924                 :            : //! \param[in] dsupint Domain superedge integrals
     925                 :            : //! \param[in] coord Mesh node coordinates
     926                 :            : //! \param[in] triinpoel Boundary face connectivity
     927                 :            : //! \param[in] besym Boundary element symmetry BC flags
     928                 :            : //! \param[in] G Gradients in mesh nodes
     929                 :            : //! \param[in] U Unknowns/solution vector in mesh nodes
     930                 :            : //! \param[in] v Nodal mesh volumes without contributions from other chares
     931                 :            : //! \param[in] t Physical time
     932                 :            : //! \param[in] tp Physical time for each mesh node
     933                 :            : //! \param[in,out] R Right-hand side vector computed
     934                 :            : // *****************************************************************************
     935                 :            : {
     936                 :            :   Assert( U.nunk() == coord[0].size(), "Number of unknowns in solution "
     937                 :            :           "vector at recent time step incorrect" );
     938                 :            :   Assert( R.nunk() == coord[0].size(),
     939                 :            :           "Number of unknowns and/or number of components in right-hand "
     940                 :            :           "side vector incorrect" );
     941                 :            : 
     942                 :            :   R.fill( 0.0 );
     943                 :      38040 :   advdom( coord, dsupedge, dsupint, G, U, R );
     944                 :      38040 :   advbnd( triinpoel, coord, besym, U, R );
     945                 :      38040 :   src( coord, v, t, tp, R );
     946                 :      38040 : }
     947                 :            : 
     948                 :            : } // riemann::

Generated by: LCOV version 1.16