Quinoa all test code coverage report
Current view: top level - PDE/Integrate - MultiMatTerms.cpp (source / functions) Hit Total Coverage
Commit: -128-NOTFOUND Lines: 238 362 65.7 %
Date: 2025-09-04 12:53:51 Functions: 7 9 77.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 147 346 42.5 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/PDE/Integrate/MultiMatTerms.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     Functions for computing volume integrals of multi-material terms
       9                 :            :      using DG methods
      10                 :            :   \details   This file contains functionality for computing volume integrals of
      11                 :            :      non-conservative and pressure relaxation terms that appear in the
      12                 :            :      multi-material hydrodynamic equations, using the discontinuous Galerkin
      13                 :            :      method for various orders of numerical representation.
      14                 :            : */
      15                 :            : // *****************************************************************************
      16                 :            : 
      17                 :            : #include "QuinoaConfig.hpp"
      18                 :            : 
      19                 :            : #include "MultiMatTerms.hpp"
      20                 :            : #include "Vector.hpp"
      21                 :            : #include "Quadrature.hpp"
      22                 :            : #include "MultiMat/MultiMatIndexing.hpp"
      23                 :            : #include "Reconstruction.hpp"
      24                 :            : #include "Inciter/InputDeck/InputDeck.hpp"
      25                 :            : #include "EoS/GetMatProp.hpp"
      26                 :            : 
      27                 :            : namespace inciter {
      28                 :            : extern ctr::InputDeck g_inputdeck;
      29                 :            : }
      30                 :            : 
      31                 :            : // Lapacke forward declarations
      32                 :            : extern "C" {
      33                 :            : 
      34                 :            : using lapack_int = long;
      35                 :            : 
      36                 :            : #define LAPACK_ROW_MAJOR 101
      37                 :            : 
      38                 :            : lapack_int LAPACKE_dsysv( int, char, lapack_int, lapack_int, double*,
      39                 :            :     lapack_int, lapack_int*, double*, lapack_int );
      40                 :            : 
      41                 :            : }
      42                 :            : 
      43                 :            : namespace tk {
      44                 :            : 
      45                 :            : void
      46                 :       6705 : nonConservativeInt( const bool pref,
      47                 :            :                     std::size_t nmat,
      48                 :            :                     const std::vector< inciter::EOS >& mat_blk,
      49                 :            :                     const std::size_t ndof,
      50                 :            :                     const std::size_t rdof,
      51                 :            :                     const std::size_t nelem,
      52                 :            :                     const std::vector< std::size_t >& inpoel,
      53                 :            :                     const UnsMesh::Coords& coord,
      54                 :            :                     const Fields& geoElem,
      55                 :            :                     const Fields& U,
      56                 :            :                     const Fields& P,
      57                 :            :                     const std::vector< std::vector< tk::real > >& riemannDeriv,
      58                 :            :                     const std::vector< std::size_t >& ndofel,
      59                 :            :                     Fields& R,
      60                 :            :                     int intsharp )
      61                 :            : // *****************************************************************************
      62                 :            : //  Compute volume integrals for multi-material DG
      63                 :            : //! \details This is called for multi-material DG, computing volume integrals of
      64                 :            : //!   terms in the volume fraction and energy equations, which do not exist in
      65                 :            : //!   the single-material flow formulation (for `CompFlow` DG). For further
      66                 :            : //!   details see Pelanti, M., & Shyue, K. M. (2019). A numerical model for
      67                 :            : //!   multiphase liquid–vapor–gas flows with interfaces and cavitation.
      68                 :            : //!   International Journal of Multiphase Flow, 113, 208-230.
      69                 :            : //! \param[in] pref Indicator for p-adaptive algorithm
      70                 :            : //! \param[in] nmat Number of materials in this PDE system
      71                 :            : //! \param[in] mat_blk EOS material block
      72                 :            : //! \param[in] ndof Maximum number of degrees of freedom
      73                 :            : //! \param[in] rdof Maximum number of reconstructed degrees of freedom
      74                 :            : //! \param[in] nelem Total number of elements
      75                 :            : //! \param[in] inpoel Element-node connectivity
      76                 :            : //! \param[in] coord Array of nodal coordinates
      77                 :            : //! \param[in] geoElem Element geometry array
      78                 :            : //! \param[in] U Solution vector at recent time step
      79                 :            : //! \param[in] P Vector of primitive quantities at recent time step
      80                 :            : //! \param[in] riemannDeriv Derivatives of partial-pressures and velocities
      81                 :            : //!   computed from the Riemann solver for use in the non-conservative terms
      82                 :            : //! \param[in] ndofel Vector of local number of degrees of freedome
      83                 :            : //! \param[in,out] R Right-hand side vector added to
      84                 :            : //! \param[in] intsharp Interface reconstruction indicator
      85                 :            : // *****************************************************************************
      86                 :            : {
      87                 :            :   using inciter::volfracIdx;
      88                 :            :   using inciter::densityIdx;
      89                 :            :   using inciter::momentumIdx;
      90                 :            :   using inciter::energyIdx;
      91                 :            :   using inciter::velocityIdx;
      92                 :            :   using inciter::deformIdx;
      93                 :            :   using inciter::newSolidsAccFn;
      94                 :            : 
      95                 :            :   const auto& solidx =
      96                 :       6705 :     inciter::g_inputdeck.get< tag::matidxmap, tag::solidx >();
      97                 :            : 
      98                 :       6705 :   const auto& cx = coord[0];
      99                 :       6705 :   const auto& cy = coord[1];
     100                 :       6705 :   const auto& cz = coord[2];
     101                 :            : 
     102                 :       6705 :   auto ncomp = U.nprop()/rdof;
     103                 :       6705 :   auto nprim = P.nprop()/rdof;
     104                 :            : 
     105                 :            :   // compute volume integrals
     106         [ +  + ]:    2504385 :   for (std::size_t e=0; e<nelem; ++e)
     107                 :            :   {
     108         [ +  - ]:    2497680 :     auto ng = tk::NGvol(ndofel[e]);
     109                 :            : 
     110                 :            :     // arrays for quadrature points
     111                 :    4995360 :     std::array< std::vector< real >, 3 > coordgp;
     112                 :    4995360 :     std::vector< real > wgp;
     113                 :            : 
     114         [ +  - ]:    2497680 :     coordgp[0].resize( ng );
     115         [ +  - ]:    2497680 :     coordgp[1].resize( ng );
     116         [ +  - ]:    2497680 :     coordgp[2].resize( ng );
     117         [ +  - ]:    2497680 :     wgp.resize( ng );
     118                 :            : 
     119         [ +  - ]:    2497680 :     GaussQuadratureTet( ng, coordgp, wgp );
     120                 :            : 
     121                 :            :     // Extract the element coordinates
     122                 :            :     std::array< std::array< real, 3>, 4 > coordel {{
     123                 :    7493040 :       {{ cx[ inpoel[4*e  ] ], cy[ inpoel[4*e  ] ], cz[ inpoel[4*e  ] ] }},
     124                 :    7493040 :       {{ cx[ inpoel[4*e+1] ], cy[ inpoel[4*e+1] ], cz[ inpoel[4*e+1] ] }},
     125                 :    7493040 :       {{ cx[ inpoel[4*e+2] ], cy[ inpoel[4*e+2] ], cz[ inpoel[4*e+2] ] }},
     126                 :    7493040 :       {{ cx[ inpoel[4*e+3] ], cy[ inpoel[4*e+3] ], cz[ inpoel[4*e+3] ] }}
     127                 :   27474480 :     }};
     128                 :            : 
     129                 :            :     auto jacInv =
     130                 :    2497680 :             inverseJacobian( coordel[0], coordel[1], coordel[2], coordel[3] );
     131                 :            : 
     132                 :            :     // If an rDG method is set up (P0P1), then, currently we compute the P1
     133                 :            :     // basis functions and solutions by default. This implies that P0P1 is
     134                 :            :     // unsupported in the p-adaptive DG (PDG).
     135                 :            :     std::size_t dof_el;
     136         [ +  + ]:    2497680 :     if (rdof > ndof)
     137                 :            :     {
     138                 :     341100 :       dof_el = rdof;
     139                 :            :     }
     140                 :            :     else
     141                 :            :     {
     142                 :    2156580 :       dof_el = ndofel[e];
     143                 :            :     }
     144                 :            : 
     145                 :            :     // For multi-material p-adaptive simulation, when dofel = 1, p0p1 is
     146                 :            :     // applied and ndof for solution evaluation should be 4
     147 [ +  + ][ -  + ]:    2497680 :     if(dof_el == 1 && pref)
     148                 :          0 :       dof_el = 4;
     149                 :            : 
     150                 :            :     // Compute the derivatives of basis function for second order terms
     151                 :    4995360 :     std::array< std::vector<tk::real>, 3 > dBdx;
     152         [ +  + ]:    2497680 :     if (ndofel[e] > 1)
     153         [ +  - ]:     500280 :       dBdx = eval_dBdx_p1( ndofel[e], jacInv );
     154                 :            : 
     155                 :            :     // Gaussian quadrature
     156         [ +  + ]:    6996480 :     for (std::size_t igp=0; igp<ng; ++igp)
     157                 :            :     {
     158         [ -  + ]:    4498800 :       if (ndofel[e] > 4)
     159         [ -  - ]:          0 :         eval_dBdx_p2( igp, coordgp, jacInv, dBdx );
     160                 :            : 
     161                 :            :       // Compute the basis function
     162                 :            :       auto B =
     163         [ +  - ]:    8997600 :         eval_basis( dof_el, coordgp[0][igp], coordgp[1][igp], coordgp[2][igp] );
     164                 :            : 
     165         [ +  - ]:    4498800 :       auto wt = wgp[igp] * geoElem(e, 0);
     166                 :            : 
     167                 :            :       auto state = evalPolynomialSol(mat_blk, intsharp, ncomp, nprim,
     168                 :            :         rdof, nmat, e, dof_el, inpoel, coord, geoElem,
     169         [ +  - ]:    8997600 :         {{coordgp[0][igp], coordgp[1][igp], coordgp[2][igp]}}, B, U, P);
     170                 :            : 
     171                 :            :       // get bulk properties
     172                 :    4498800 :       tk::real rhob(0.0);
     173         [ +  + ]:   14589300 :       for (std::size_t k=0; k<nmat; ++k)
     174                 :   10090500 :           rhob += state[densityIdx(nmat, k)];
     175                 :            : 
     176                 :            :       // get the velocity vector
     177                 :    4498800 :       std::array< tk::real, 3 > vel{{ state[ncomp+velocityIdx(nmat, 0)],
     178                 :    4498800 :                                       state[ncomp+velocityIdx(nmat, 1)],
     179                 :    8997600 :                                       state[ncomp+velocityIdx(nmat, 2)] }};
     180                 :            : 
     181         [ +  - ]:    8997600 :       std::vector< tk::real > ymat(nmat, 0.0);
     182                 :    4498800 :       std::array< tk::real, 3 > dap{{0.0, 0.0, 0.0}};
     183         [ +  + ]:   14589300 :       for (std::size_t k=0; k<nmat; ++k)
     184                 :            :       {
     185                 :   10090500 :         ymat[k] = state[densityIdx(nmat, k)]/rhob;
     186                 :            : 
     187                 :   10090500 :         std::size_t mark(3*k);
     188         [ -  + ]:   10090500 :         if (solidx[k] > 0) mark = 3*nmat+ndof+3*(solidx[k]-1);
     189                 :            : 
     190         [ +  + ]:   40362000 :         for (std::size_t idir=0; idir<3; ++idir)
     191                 :   30271500 :           dap[idir] += riemannDeriv[mark+idir][e];
     192                 :            :       }
     193                 :            : 
     194                 :            :       // compute non-conservative terms
     195                 :            :       std::vector< std::vector< tk::real > > ncf
     196 [ +  - ][ +  - ]:   13496400 :         (ncomp, std::vector<tk::real>(ndofel[e],0.0));
     197                 :            : 
     198         [ +  + ]:   17995200 :       for (std::size_t idir=0; idir<3; ++idir)
     199         [ +  + ]:   49505400 :         for(std::size_t idof=0; idof<ndofel[e]; ++idof)
     200                 :   36009000 :           ncf[momentumIdx(nmat, idir)][idof] = 0.0;
     201                 :            : 
     202         [ +  + ]:   14589300 :       for (std::size_t k=0; k<nmat; ++k)
     203                 :            :       {
     204                 :            :         // evaluate non-conservative term for energy equation
     205                 :   10090500 :         std::size_t mark(3*k);
     206         [ -  + ]:   10090500 :         if (solidx[k] > 0) mark = 3*nmat+ndof+3*(solidx[k]-1);
     207                 :            : 
     208         [ +  + ]:   35189400 :         for(std::size_t idof=0; idof<ndofel[e]; ++idof)
     209                 :            :         {
     210                 :   25098900 :           ncf[densityIdx(nmat, k)][idof] = 0.0;
     211                 :            : 
     212         [ +  + ]:  100395600 :           for (std::size_t idir=0; idir<3; ++idir)
     213                 :  150593400 :             ncf[energyIdx(nmat, k)][idof] -= vel[idir] * ( ymat[k]*dap[idir]
     214                 :   75296700 :                                                   - riemannDeriv[mark+idir][e] );
     215                 :            :         }
     216                 :            : 
     217                 :            :         // evaluate non-conservative terms for g equation
     218         [ -  + ]:   10090500 :         if (solidx[k] > 0) {
     219         [ -  - ]:          0 :           std::size_t nsld = inciter::numSolids(nmat, solidx);
     220         [ -  - ]:          0 :           for (std::size_t idof=0; idof<ndofel[e]; ++idof)
     221         [ -  - ]:          0 :             for (std::size_t i=0; i<3; ++i)
     222         [ -  - ]:          0 :               for (std::size_t j=0; j<3; ++j)
     223         [ -  - ]:          0 :                 for (std::size_t l=0; l<3; ++l)
     224                 :            :                 {
     225                 :          0 :                   mark = 3*nmat+ndof+3*nsld+inciter::newSolidsAccFn(k,i,j,l);
     226                 :          0 :                   ncf[deformIdx(nmat, solidx[k], i, j)][idof] -=
     227                 :          0 :                     vel[l] * riemannDeriv[mark][e];
     228                 :            :                 }
     229                 :            :         }
     230                 :            : 
     231                 :            :         // Evaluate non-conservative term for volume fraction equation:
     232                 :            :         // Here we make an assumption that the derivative of Riemann velocity
     233                 :            :         // times the basis function is constant. Therefore, when P0P1/DGP1/DGP2
     234                 :            :         // are used for constant velocity problems, the discretization is
     235                 :            :         // consistent. However, for a general problem with varying velocity,
     236                 :            :         // there will be errors since the said derivative is not constant.
     237                 :            :         // A discretization that solves this issue has not been implemented yet.
     238                 :            :         // Nevertheless, this does not affect high-order accuracy in
     239                 :            :         // single material regions for problems with sharp interfaces. Since
     240                 :            :         // volume fractions are nearly constant in such regions, using
     241                 :            :         // high-order for volume fractions does not show any benefits over
     242                 :            :         // THINC. Therefore, for such problems, we only use FV for the volume
     243                 :            :         // fractions, and these non-conservative high-order terms do not need
     244                 :            :         // to be computed.
     245                 :            :         // In summary, high-order discretization for non-conservative terms in
     246                 :            :         // volume fraction equations is avoided for sharp interface problems.
     247 [ -  + ][ -  - ]:   10090500 :         if (ndof <= 4 || intsharp == 1) {
     248         [ +  + ]:   35189400 :           for(std::size_t idof=0; idof<ndofel[e]; ++idof)
     249                 :   50197800 :             ncf[volfracIdx(nmat, k)][idof] = state[volfracIdx(nmat, k)]
     250                 :   35189400 :                                            * riemannDeriv[3*nmat+idof][e];
     251         [ -  - ]:          0 :         } else if (intsharp == 0) {     // If DGP2 without THINC
     252                 :            :           // DGP2 is discretized differently than DGP1/FV to guarantee 3rd order
     253                 :            :           // convergence for the testcases with uniform and constant velocity.
     254                 :            : 
     255                 :            :           // P0 contributions for all equations
     256         [ -  - ]:          0 :           for(std::size_t idof=0; idof<ndof; ++idof)
     257                 :          0 :           ncf[volfracIdx(nmat, k)][idof] = state[volfracIdx(nmat, k)]
     258                 :          0 :                                          * riemannDeriv[3*nmat][e] * B[idof];
     259                 :            :           // High order contributions
     260         [ -  - ]:          0 :           for(std::size_t idof=1; idof<ndof; ++idof)
     261         [ -  - ]:          0 :             for(std::size_t idir=0; idir<3; ++idir)
     262                 :          0 :             ncf[volfracIdx(nmat, k)][idof] += state[volfracIdx(nmat, k)]
     263                 :          0 :                                             * vel[idir] * dBdx[idir][idof];
     264                 :            :         }
     265                 :            :       }
     266                 :            : 
     267         [ +  - ]:    4498800 :       updateRhsNonCons( ncomp, nmat, ndof, ndofel[e], wt, e, B, dBdx, ncf, R );
     268                 :            :     }
     269                 :            :   }
     270                 :       6705 : }
     271                 :            : 
     272                 :            : void
     273                 :    4498800 : updateRhsNonCons(
     274                 :            :   ncomp_t ncomp,
     275                 :            :   const std::size_t nmat,
     276                 :            :   const std::size_t ndof,
     277                 :            :   [[maybe_unused]] const std::size_t ndof_el,
     278                 :            :   const tk::real wt,
     279                 :            :   const std::size_t e,
     280                 :            :   const std::vector<tk::real>& B,
     281                 :            :   [[maybe_unused]] const std::array< std::vector<tk::real>, 3 >& dBdx,
     282                 :            :   const std::vector< std::vector< tk::real > >& ncf,
     283                 :            :   Fields& R )
     284                 :            : // *****************************************************************************
     285                 :            : //  Update the rhs by adding the non-conservative term integrals
     286                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     287                 :            : //! \param[in] nmat Number of materials
     288                 :            : //! \param[in] ndof Maximum number of degrees of freedom
     289                 :            : //! \param[in] ndof_el Number of degrees of freedom for local element
     290                 :            : //! \param[in] wt Weight of gauss quadrature point
     291                 :            : //! \param[in] e Element index
     292                 :            : //! \param[in] B Basis function evaluated at local quadrature point
     293                 :            : //! \param[in] dBdx Vector of basis function derivatives
     294                 :            : //! \param[in] ncf Vector of non-conservative terms
     295                 :            : //! \param[in,out] R Right-hand side vector computed
     296                 :            : // *****************************************************************************
     297                 :            : {
     298                 :            :   using inciter::volfracIdx;
     299                 :            :   using inciter::energyIdx;
     300                 :            :   using inciter::deformIdx;
     301                 :            :   using inciter::volfracDofIdx;
     302                 :            :   using inciter::energyDofIdx;
     303                 :            :   using inciter::deformDofIdx;
     304                 :            : 
     305                 :            :   //Assert( dBdx[0].size() == ndof_el,
     306                 :            :   //        "Size mismatch for basis function derivatives" );
     307                 :            :   //Assert( dBdx[1].size() == ndof_el,
     308                 :            :   //        "Size mismatch for basis function derivatives" );
     309                 :            :   //Assert( dBdx[2].size() == ndof_el,
     310                 :            :   //        "Size mismatch for basis function derivatives" );
     311                 :            :   //Assert( ncf.size() == ncomp,
     312                 :            :   //        "Size mismatch for non-conservative term" );
     313 [ -  + ][ -  - ]:    4498800 :   Assert( ncf.size() == ncomp, "Size mismatch for non-conservative term" );
         [ -  - ][ -  - ]
     314                 :            : 
     315         [ +  + ]:   48266700 :   for (ncomp_t c=0; c<ncomp; ++c)
     316                 :            :   {
     317                 :   43767900 :     auto mark = c*ndof;
     318                 :   43767900 :     R(e, mark) += wt * ncf[c][0];
     319                 :            :   }
     320                 :            : 
     321         [ +  + ]:    4498800 :   if( ndof_el > 1)
     322                 :            :   {
     323                 :            :     // Update rhs with distributions from volume fraction and energy equations
     324         [ +  + ]:    7504200 :     for (std::size_t k=0; k<nmat; ++k)
     325                 :            :     {
     326         [ +  + ]:   20011200 :       for(std::size_t idof = 1; idof < ndof_el; idof++)
     327                 :            :       {
     328                 :   15008400 :         R(e, volfracDofIdx(nmat,k,ndof,idof)) +=
     329                 :   15008400 :           wt * ncf[volfracIdx(nmat,k)][idof];
     330                 :   15008400 :         R(e, energyDofIdx(nmat,k,ndof,idof)) +=
     331                 :   15008400 :           wt * ncf[energyIdx(nmat,k)][idof] * B[idof];
     332                 :            :         // Note: High order non-conservative g terms not implemented yet!
     333                 :            :       }
     334                 :            :     }
     335                 :            :   }
     336                 :    4498800 : }
     337                 :            : 
     338                 :            : std::vector< tk::real >
     339                 :    1091856 : nonConservativeIntFV(
     340                 :            :   std::size_t nmat,
     341                 :            :   const std::size_t rdof,
     342                 :            :   const std::size_t e,
     343                 :            :   const std::array< tk::real, 3 >& fn,
     344                 :            :   const Fields& U,
     345                 :            :   const Fields& P,
     346                 :            :   const std::vector< tk::real >& var_riemann )
     347                 :            : // *****************************************************************************
     348                 :            : //  Compute integrals of non-conservative terms for multi-material FV
     349                 :            : //! \details This is called for multi-material FV, computing integrals of
     350                 :            : //!   terms in the volume fraction and energy equations, which do not exist in
     351                 :            : //!   the single-material flow formulation (for `CompFlow`). For further
     352                 :            : //!   details see Pelanti, M., & Shyue, K. M. (2019). A numerical model for
     353                 :            : //!   multiphase liquid–vapor–gas flows with interfaces and cavitation.
     354                 :            : //!   International Journal of Multiphase Flow, 113, 208-230.
     355                 :            : //! \param[in] nmat Number of materials in this PDE system
     356                 :            : //! \param[in] rdof Maximum number of reconstructed degrees of freedom
     357                 :            : //! \param[in] e Element for which contribution is to be calculated
     358                 :            : //! \param[in] fn Face normal
     359                 :            : //! \param[in] U Solution vector at recent time step
     360                 :            : //! \param[in] P Vector of primitive quantities at recent time step
     361                 :            : //! \param[in] var_riemann Riemann-values of partial-pressures and velocities
     362                 :            : //!   computed from the Riemann solver for use in the non-conservative terms
     363                 :            : // *****************************************************************************
     364                 :            : {
     365                 :            :   using inciter::volfracIdx;
     366                 :            :   using inciter::densityIdx;
     367                 :            :   using inciter::momentumIdx;
     368                 :            :   using inciter::energyIdx;
     369                 :            :   using inciter::velocityIdx;
     370                 :            :   using inciter::volfracDofIdx;
     371                 :            :   using inciter::densityDofIdx;
     372                 :            :   using inciter::velocityDofIdx;
     373                 :            : 
     374                 :    1091856 :   auto ncomp = U.nprop()/rdof;
     375                 :            : 
     376                 :            :   // get bulk properties
     377                 :    1091856 :   tk::real rhob(0.0), p_face(0.0);
     378         [ +  + ]:    3512624 :   for (std::size_t k=0; k<nmat; ++k)
     379                 :            :   {
     380         [ +  - ]:    2420768 :     rhob += U(e, densityDofIdx(nmat,k,rdof,0));
     381                 :    2420768 :     p_face += var_riemann[k];
     382                 :            :   }
     383                 :            : 
     384         [ +  - ]:    1091856 :   std::array< tk::real, 3 > vel{{ P(e, velocityDofIdx(nmat,0,rdof,0)),
     385         [ +  - ]:    1091856 :                                   P(e, velocityDofIdx(nmat,1,rdof,0)),
     386         [ +  - ]:    2183712 :                                   P(e, velocityDofIdx(nmat,2,rdof,0)) }};
     387                 :            : 
     388                 :            :   // compute non-conservative terms
     389         [ +  - ]:    1091856 :   std::vector< tk::real > ncf(ncomp, 0.0);
     390         [ +  - ]:    2183712 :   std::vector< tk::real > ymat(nmat, 0.0);
     391         [ +  + ]:    3512624 :   for (std::size_t k=0; k<nmat; ++k)
     392                 :            :   {
     393         [ +  - ]:    2420768 :     ymat[k] = U(e, densityDofIdx(nmat,k,rdof,0))/rhob;
     394                 :            : 
     395                 :            :     // evaluate non-conservative term for energy equation
     396         [ +  + ]:    9683072 :     for (std::size_t idir=0; idir<3; ++idir)
     397                 :   14524608 :       ncf[energyIdx(nmat, k)] -= vel[idir] * ( ymat[k]*p_face*fn[idir]
     398                 :    7262304 :                                             - var_riemann[k]*fn[idir] );
     399                 :            : 
     400                 :            :     // evaluate non-conservative term for volume fraction equation
     401         [ +  - ]:    4841536 :     ncf[volfracIdx(nmat, k)] = U(e, volfracDofIdx(nmat,k,rdof,0))
     402                 :    2420768 :       * var_riemann[nmat];
     403                 :            :   }
     404                 :            : 
     405                 :    2183712 :   return ncf;
     406                 :            : }
     407                 :            : 
     408                 :            : void
     409                 :        375 : pressureRelaxationInt( const bool pref,
     410                 :            :                        std::size_t nmat,
     411                 :            :                        const std::vector< inciter::EOS >& mat_blk,
     412                 :            :                        const std::size_t ndof,
     413                 :            :                        const std::size_t rdof,
     414                 :            :                        const std::size_t nelem,
     415                 :            :                        const std::vector< std::size_t >& inpoel,
     416                 :            :                        const UnsMesh::Coords& coord,
     417                 :            :                        const Fields& geoElem,
     418                 :            :                        const Fields& U,
     419                 :            :                        const Fields& P,
     420                 :            :                        const std::vector< std::size_t >& ndofel,
     421                 :            :                        const tk::real ct,
     422                 :            :                        Fields& R,
     423                 :            :                        int intsharp )
     424                 :            : // *****************************************************************************
     425                 :            : //  Compute volume integrals of pressure relaxation terms in multi-material DG
     426                 :            : //! \details This is called for multi-material DG to compute volume integrals of
     427                 :            : //!   finite pressure relaxation terms in the volume fraction and energy
     428                 :            : //!   equations, which do not exist in the single-material flow formulation (for
     429                 :            : //!   `CompFlow` DG). For further details see Dobrev, V. A., Kolev, T. V.,
     430                 :            : //!   Rieben, R. N., & Tomov, V. Z. (2016). Multi‐material closure model for
     431                 :            : //!   high‐order finite element Lagrangian hydrodynamics. International Journal
     432                 :            : //!   for Numerical Methods in Fluids, 82(10), 689-706.
     433                 :            : //! \param[in] pref Indicator for p-adaptive algorithm
     434                 :            : //! \param[in] nmat Number of materials in this PDE system
     435                 :            : //! \param[in] mat_blk EOS material block
     436                 :            : //! \param[in] ndof Maximum number of degrees of freedom
     437                 :            : //! \param[in] rdof Maximum number of reconstructed degrees of freedom
     438                 :            : //! \param[in] nelem Total number of elements
     439                 :            : //! \param[in] inpoel Element-node connectivity
     440                 :            : //! \param[in] coord Array of nodal coordinates
     441                 :            : //! \param[in] geoElem Element geometry array
     442                 :            : //! \param[in] U Solution vector at recent time step
     443                 :            : //! \param[in] P Vector of primitive quantities at recent time step
     444                 :            : //! \param[in] ndofel Vector of local number of degrees of freedome
     445                 :            : //! \param[in] ct Pressure relaxation time-scale for this system
     446                 :            : //! \param[in,out] R Right-hand side vector added to
     447                 :            : //! \param[in] intsharp Interface reconstruction indicator
     448                 :            : // *****************************************************************************
     449                 :            : {
     450                 :            :   using inciter::volfracIdx;
     451                 :            :   using inciter::densityIdx;
     452                 :            :   using inciter::momentumIdx;
     453                 :            :   using inciter::energyIdx;
     454                 :            :   using inciter::pressureIdx;
     455                 :            :   using inciter::velocityIdx;
     456                 :            :   using inciter::deformIdx;
     457                 :            : 
     458                 :            :   const auto& solidx =
     459                 :        375 :     inciter::g_inputdeck.get< tag::matidxmap, tag::solidx >();
     460                 :            : 
     461                 :        375 :   auto ncomp = U.nprop()/rdof;
     462                 :        375 :   auto nprim = P.nprop()/rdof;
     463                 :            : 
     464                 :            :   // compute volume integrals
     465         [ +  + ]:     227775 :   for (std::size_t e=0; e<nelem; ++e)
     466                 :            :   {
     467         [ +  - ]:     227400 :     auto dx = geoElem(e,4)/2.0;
     468         [ +  - ]:     227400 :     auto ng = NGvol(ndofel[e]);
     469                 :            : 
     470                 :            :     // arrays for quadrature points
     471                 :     454800 :     std::array< std::vector< real >, 3 > coordgp;
     472                 :     454800 :     std::vector< real > wgp;
     473                 :            : 
     474         [ +  - ]:     227400 :     coordgp[0].resize( ng );
     475         [ +  - ]:     227400 :     coordgp[1].resize( ng );
     476         [ +  - ]:     227400 :     coordgp[2].resize( ng );
     477         [ +  - ]:     227400 :     wgp.resize( ng );
     478                 :            : 
     479         [ +  - ]:     227400 :     GaussQuadratureTet( ng, coordgp, wgp );
     480                 :            : 
     481                 :            :     // Compute the derivatives of basis function for DG(P1)
     482                 :     454800 :     std::array< std::vector<real>, 3 > dBdx;
     483                 :            : 
     484                 :            :     // If an rDG method is set up (P0P1), then, currently we compute the P1
     485                 :            :     // basis functions and solutions by default. This implies that P0P1 is
     486                 :            :     // unsupported in the p-adaptive DG (PDG).
     487                 :            :     std::size_t dof_el;
     488         [ -  + ]:     227400 :     if (rdof > ndof)
     489                 :            :     {
     490                 :          0 :       dof_el = rdof;
     491                 :            :     }
     492                 :            :     else
     493                 :            :     {
     494                 :     227400 :       dof_el = ndofel[e];
     495                 :            :     }
     496                 :            : 
     497                 :            :     // For multi-material p-adaptive simulation, when dofel = 1, p0p1 is applied
     498                 :            :     // and ndof for solution evaluation should be 4
     499 [ -  + ][ -  - ]:     227400 :     if(dof_el == 1 && pref)
     500                 :          0 :       dof_el = 4;
     501                 :            : 
     502                 :            :     // Gaussian quadrature
     503         [ +  + ]:    1364400 :     for (std::size_t igp=0; igp<ng; ++igp)
     504                 :            :     {
     505                 :            :       // Compute the basis function
     506                 :            :       auto B =
     507         [ +  - ]:    2274000 :         eval_basis( dof_el, coordgp[0][igp], coordgp[1][igp], coordgp[2][igp] );
     508                 :            : 
     509         [ +  - ]:    1137000 :       auto wt = wgp[igp] * geoElem(e, 0);
     510                 :            : 
     511                 :            :       auto state = evalPolynomialSol(mat_blk, intsharp, ncomp, nprim,
     512                 :            :         rdof, nmat, e, dof_el, inpoel, coord, geoElem,
     513         [ +  - ]:    2274000 :         {{coordgp[0][igp], coordgp[1][igp], coordgp[2][igp]}}, B, U, P);
     514                 :            : 
     515                 :            :       // get bulk properties
     516                 :    1137000 :       real rhob(0.0);
     517         [ +  + ]:    3411000 :       for (std::size_t k=0; k<nmat; ++k)
     518                 :    2274000 :         rhob += state[densityIdx(nmat, k)];
     519                 :            : 
     520                 :            :       // get pressures and bulk modulii
     521                 :    1137000 :       real pb(0.0), nume(0.0), deno(0.0), trelax(0.0);
     522 [ +  - ][ +  - ]:    2274000 :       std::vector< real > apmat(nmat, 0.0), kmat(nmat, 0.0);
     523         [ +  - ]:    2274000 :       std::vector< int > do_relax(nmat, 1);
     524                 :    1137000 :       bool is_relax(false);
     525         [ +  + ]:    3411000 :       for (std::size_t k=0; k<nmat; ++k)
     526                 :            :       {
     527                 :    2274000 :         real arhomat = state[densityIdx(nmat, k)];
     528                 :    2274000 :         real alphamat = state[volfracIdx(nmat, k)];
     529                 :    2274000 :         apmat[k] = state[ncomp+pressureIdx(nmat, k)];
     530                 :    2274000 :         real amat = 0.0;
     531 [ +  - ][ +  + ]:    2274000 :         if (solidx[k] == 0 && alphamat >= inciter::volfracPRelaxLim()) {
                 [ +  + ]
     532         [ +  - ]:    2337396 :             amat = mat_blk[k].compute< inciter::EOS::soundspeed >( arhomat,
     533                 :    1168698 :               apmat[k], alphamat, k );
     534                 :    1168698 :           kmat[k] = arhomat * amat * amat;
     535                 :    1168698 :           pb += apmat[k];
     536                 :            : 
     537                 :            :           // relaxation parameters
     538                 :    1168698 :           trelax = std::max(trelax, ct*dx/amat);
     539                 :    1168698 :           nume += alphamat * apmat[k] / kmat[k];
     540                 :    1168698 :           deno += alphamat * alphamat / kmat[k];
     541                 :            : 
     542                 :    1168698 :           is_relax = true;
     543                 :            :         }
     544                 :    1105302 :         else do_relax[k] = 0;
     545                 :            :       }
     546                 :    1137000 :       real p_relax(0.0);
     547         [ +  - ]:    1137000 :       if (is_relax) p_relax = nume/deno;
     548                 :            : 
     549                 :            :       // compute pressure relaxation terms
     550         [ +  - ]:    2274000 :       std::vector< real > s_prelax(ncomp, 0.0);
     551         [ +  + ]:    3411000 :       for (std::size_t k=0; k<nmat; ++k)
     552                 :            :       {
     553                 :            :         // only perform prelax on existing quantities
     554         [ +  + ]:    2274000 :         if (do_relax[k] == 1) {
     555                 :    1168698 :           auto s_alpha = (apmat[k]-p_relax*state[volfracIdx(nmat, k)])
     556                 :    1168698 :             * (state[volfracIdx(nmat, k)]/kmat[k]) / trelax;
     557                 :    1168698 :           s_prelax[volfracIdx(nmat, k)] = s_alpha;
     558                 :    1168698 :           s_prelax[energyIdx(nmat, k)] = - pb*s_alpha;
     559                 :            :         }
     560                 :            :       }
     561                 :            : 
     562         [ +  - ]:    1137000 :       updateRhsPre( ncomp, ndof, ndofel[e], wt, e, B, s_prelax, R );
     563                 :            :     }
     564                 :            :   }
     565                 :        375 : }
     566                 :            : 
     567                 :            : void
     568                 :    1137000 : updateRhsPre(
     569                 :            :   ncomp_t ncomp,
     570                 :            :   const std::size_t ndof,
     571                 :            :   [[maybe_unused]] const std::size_t ndof_el,
     572                 :            :   const tk::real wt,
     573                 :            :   const std::size_t e,
     574                 :            :   const std::vector< tk::real >& B,
     575                 :            :   std::vector< tk::real >& ncf,
     576                 :            :   Fields& R )
     577                 :            : // *****************************************************************************
     578                 :            : //  Update the rhs by adding the pressure relaxation integrals
     579                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     580                 :            : //! \param[in] ndof Maximum number of degrees of freedom
     581                 :            : //! \param[in] ndof_el Number of degrees of freedom for local element
     582                 :            : //! \param[in] wt Weight of gauss quadrature point
     583                 :            : //! \param[in] e Element index
     584                 :            : //! \param[in] B Basis function evaluated at local quadrature point
     585                 :            : //! \param[in] ncf Vector of non-conservative terms
     586                 :            : //! \param[in,out] R Right-hand side vector computed
     587                 :            : // *****************************************************************************
     588                 :            : {
     589                 :            :   //Assert( dBdx[0].size() == ndof_el,
     590                 :            :   //        "Size mismatch for basis function derivatives" );
     591                 :            :   //Assert( dBdx[1].size() == ndof_el,
     592                 :            :   //        "Size mismatch for basis function derivatives" );
     593                 :            :   //Assert( dBdx[2].size() == ndof_el,
     594                 :            :   //        "Size mismatch for basis function derivatives" );
     595                 :            :   //Assert( ncf.size() == ncomp,
     596                 :            :   //        "Size mismatch for non-conservative term" );
     597 [ -  + ][ -  - ]:    1137000 :   Assert( ncf.size() == ncomp, "Size mismatch for non-conservative term" );
         [ -  - ][ -  - ]
     598                 :            : 
     599         [ +  + ]:   11370000 :   for (ncomp_t c=0; c<ncomp; ++c)
     600                 :            :   {
     601                 :   10233000 :     auto mark = c*ndof;
     602         [ +  + ]:   51165000 :     for(std::size_t idof = 0; idof < ndof; idof++)
     603                 :   40932000 :       R(e, mark+idof) += wt * ncf[c] * B[idof];
     604                 :            :   }
     605                 :    1137000 : }
     606                 :            : 
     607                 :            : void
     608                 :       1218 : pressureRelaxationIntFV(
     609                 :            :   std::size_t nmat,
     610                 :            :   const std::vector< inciter::EOS >& mat_blk,
     611                 :            :   const std::size_t rdof,
     612                 :            :   const std::size_t nelem,
     613                 :            :   const std::vector< std::size_t >& inpoel,
     614                 :            :   const UnsMesh::Coords& coord,
     615                 :            :   const Fields& geoElem,
     616                 :            :   const Fields& U,
     617                 :            :   const Fields& P,
     618                 :            :   const tk::real ct,
     619                 :            :   Fields& R )
     620                 :            : // *****************************************************************************
     621                 :            : //  Compute volume integrals of pressure relaxation terms in multi-material FV
     622                 :            : //! \details This is called for multi-material FV to compute volume integrals of
     623                 :            : //!   finite pressure relaxation terms in the volume fraction and energy
     624                 :            : //!   equations, which do not exist in the single-material flow formulation (for
     625                 :            : //!   `CompFlow`). For further details see Dobrev, V. A., Kolev, T. V.,
     626                 :            : //!   Rieben, R. N., & Tomov, V. Z. (2016). Multi‐material closure model for
     627                 :            : //!   high‐order finite element Lagrangian hydrodynamics. International Journal
     628                 :            : //!   for Numerical Methods in Fluids, 82(10), 689-706.
     629                 :            : //! \param[in] nmat Number of materials in this PDE system
     630                 :            : //! \param[in] mat_blk EOS material block
     631                 :            : //! \param[in] rdof Maximum number of reconstructed degrees of freedom
     632                 :            : //! \param[in] nelem Total number of elements
     633                 :            : //! \param[in] geoElem Element geometry array
     634                 :            : //! \param[in] U Solution vector at recent time step
     635                 :            : //! \param[in] P Vector of primitive quantities at recent time step
     636                 :            : //! \param[in] ct Pressure relaxation time-scale for this system
     637                 :            : //! \param[in,out] R Right-hand side vector added to
     638                 :            : // *****************************************************************************
     639                 :            : {
     640                 :            :   using inciter::volfracIdx;
     641                 :            :   using inciter::energyIdx;
     642                 :            :   using inciter::pressureIdx;
     643                 :            :   using inciter::velocityIdx;
     644                 :            :   using inciter::densityIdx;
     645                 :            : 
     646                 :       1218 :   auto ncomp = U.nprop()/rdof;
     647                 :       1218 :   auto nprim = P.nprop()/rdof;
     648                 :            : 
     649                 :            :   // compute volume integrals
     650         [ +  + ]:     129578 :   for (std::size_t e=0; e<nelem; ++e)
     651                 :            :   {
     652         [ +  - ]:     128360 :     auto dx = geoElem(e,4)/2.0;
     653                 :            : 
     654                 :            :     // Compute the basis function
     655         [ +  - ]:     256720 :     std::vector< tk::real > B(rdof, 0.0);
     656                 :     128360 :     B[0] = 1.0;
     657                 :            : 
     658                 :            :     auto state = evalPolynomialSol(mat_blk, 0, ncomp, nprim,
     659                 :            :       rdof, nmat, e, rdof, inpoel, coord, geoElem,
     660         [ +  - ]:     256720 :       {{0.25, 0.25, 0.25}}, B, U, P);
     661                 :            : 
     662                 :            :     // get bulk properties
     663                 :     128360 :     real rhob(0.0);
     664         [ +  + ]:     437640 :     for (std::size_t k=0; k<nmat; ++k)
     665                 :     309280 :       rhob += state[densityIdx(nmat, k)];
     666                 :            : 
     667                 :            :     // get pressures and bulk modulii
     668                 :     128360 :     real pb(0.0), nume(0.0), deno(0.0), trelax(0.0);
     669 [ +  - ][ +  - ]:     256720 :     std::vector< real > apmat(nmat, 0.0), kmat(nmat, 0.0);
     670         [ +  - ]:     256720 :     std::vector< int > do_relax(nmat, 1);
     671                 :     128360 :     bool is_relax(false);
     672         [ +  + ]:     437640 :     for (std::size_t k=0; k<nmat; ++k)
     673                 :            :     {
     674                 :     309280 :       real arhomat = state[densityIdx(nmat, k)];
     675                 :     309280 :       real alphamat = state[volfracIdx(nmat, k)];
     676         [ +  + ]:     309280 :       if (alphamat >= inciter::volfracPRelaxLim()) {
     677                 :     128874 :         apmat[k] = state[ncomp+pressureIdx(nmat, k)];
     678         [ +  - ]:     257748 :         real amat = mat_blk[k].compute< inciter::EOS::soundspeed >( arhomat,
     679                 :     128874 :           apmat[k], alphamat, k );
     680                 :     128874 :         kmat[k] = arhomat * amat * amat;
     681                 :     128874 :         pb += apmat[k];
     682                 :            : 
     683                 :            :         // relaxation parameters
     684                 :     128874 :         trelax = std::max(trelax, ct*dx/amat);
     685                 :     128874 :         nume += alphamat * apmat[k] / kmat[k];
     686                 :     128874 :         deno += alphamat * alphamat / kmat[k];
     687                 :            : 
     688                 :     128874 :         is_relax = true;
     689                 :            :       }
     690                 :     180406 :       else do_relax[k] = 0;
     691                 :            :     }
     692                 :     128360 :     real p_relax(0.0);
     693         [ +  - ]:     128360 :     if (is_relax) p_relax = nume/deno;
     694                 :            : 
     695                 :            :     // compute pressure relaxation terms
     696         [ +  - ]:     256720 :     std::vector< real > s_prelax(ncomp, 0.0);
     697                 :            : 
     698         [ +  + ]:     437640 :     for (std::size_t k=0; k<nmat; ++k)
     699                 :            :     {
     700                 :            :       // only perform prelax on existing quantities
     701         [ +  + ]:     309280 :       if (do_relax[k] == 1) {
     702                 :     128874 :         auto s_alpha = (apmat[k]-p_relax*state[volfracIdx(nmat, k)])
     703                 :     128874 :           * (state[volfracIdx(nmat, k)]/kmat[k]) / trelax;
     704                 :     128874 :         s_prelax[volfracIdx(nmat, k)] = s_alpha;
     705                 :     128874 :         s_prelax[energyIdx(nmat, k)] = - pb*s_alpha;
     706                 :            :       }
     707                 :            :     }
     708                 :            : 
     709         [ +  + ]:    1441280 :     for (ncomp_t c=0; c<ncomp; ++c)
     710                 :            :     {
     711 [ +  - ][ +  - ]:    1312920 :       R(e, c) += geoElem(e,0) * s_prelax[c];
     712                 :            :     }
     713                 :            :   }
     714                 :       1218 : }
     715                 :            : 
     716                 :            : std::vector< std::vector< tk::real > >
     717                 :          0 : solvevriem( std::size_t nelem,
     718                 :            :             const std::vector< std::vector< tk::real > >& vriem,
     719                 :            :             const std::vector< std::vector< tk::real > >& riemannLoc )
     720                 :            : // *****************************************************************************
     721                 :            : //  Solve the reconstruct velocity used for volume fraction equation by
     722                 :            : //  Least square method
     723                 :            : //! \param[in] nelem Numer of elements
     724                 :            : //! \param[in,out] vriem Vector of the riemann velocity
     725                 :            : //! \param[in,out] riemannLoc Vector of coordinates where Riemann velocity data
     726                 :            : //!   is available
     727                 :            : //! \return Vector of Riemann velocity polynomial solution
     728                 :            : // *****************************************************************************
     729                 :            : {
     730                 :            :   std::vector< std::vector< tk::real > >
     731 [ -  - ][ -  - ]:          0 :     vriempoly( nelem, std::vector<tk::real>(12,0.0) );
     732                 :            : 
     733         [ -  - ]:          0 :   for (std::size_t e=0; e<nelem; ++e)
     734                 :            :   {
     735                 :            :     // Use the normal method to construct the linear system A^T * A * x = u
     736                 :          0 :     auto numgp = riemannLoc[e].size()/3;
     737                 :            :     std::vector< std::vector< tk::real > > A(numgp,
     738 [ -  - ][ -  - ]:          0 :                                              std::vector<tk::real>(4, 1.0));
     739                 :            : 
     740         [ -  - ]:          0 :     for(std::size_t k = 0; k < numgp; k++)
     741                 :            :     {
     742                 :          0 :       auto mark = k * 3;
     743                 :          0 :       A[k][1] = riemannLoc[e][mark];
     744                 :          0 :       A[k][2] = riemannLoc[e][mark+1];
     745                 :          0 :       A[k][3] = riemannLoc[e][mark+2];
     746                 :            :     }
     747                 :            : 
     748         [ -  - ]:          0 :     for(std::size_t idir = 0; idir < 3; idir++)
     749                 :            :     {
     750                 :            :       double AA_T[4*4], u[4];
     751                 :            : 
     752         [ -  - ]:          0 :       for(std::size_t i = 0; i < 4; i++)
     753         [ -  - ]:          0 :         for(std::size_t j = 0; j < 4; j++)
     754                 :            :         {
     755                 :          0 :           auto id = 4 * i + j;
     756                 :          0 :           AA_T[id] = 0;
     757         [ -  - ]:          0 :           for(std::size_t k = 0; k < numgp; k++)
     758                 :          0 :             AA_T[id] += A[k][i] * A[k][j];
     759                 :            :         }
     760                 :            : 
     761         [ -  - ]:          0 :       std::vector<tk::real> vel(numgp, 1.0);
     762         [ -  - ]:          0 :       for(std::size_t k = 0; k < numgp; k++)
     763                 :            :       {
     764                 :          0 :         auto mark = k * 3 + idir;
     765                 :          0 :         vel[k] = vriem[e][mark];
     766                 :            :       }
     767         [ -  - ]:          0 :       for(std::size_t k = 0; k < 4; k++)
     768                 :            :       {
     769                 :          0 :         u[k] = 0;
     770         [ -  - ]:          0 :         for(std::size_t i = 0; i < numgp; i++)
     771                 :          0 :           u[k] += A[i][k] * vel[i];
     772                 :            :       }
     773                 :            :  
     774                 :            :       lapack_int IPIV[4];
     775                 :            :       #ifndef NDEBUG
     776                 :            :       lapack_int info =
     777                 :            :       #endif
     778         [ -  - ]:          0 :         LAPACKE_dsysv( LAPACK_ROW_MAJOR, 'U', 4, 1, AA_T, 4, IPIV, u, 1 );
     779 [ -  - ][ -  - ]:          0 :       Assert( info == 0, "Error in linear system solver" );
         [ -  - ][ -  - ]
     780                 :            : 
     781                 :          0 :       auto idirmark = idir * 4;
     782         [ -  - ]:          0 :       for(std::size_t k = 0; k < 4; k++)
     783                 :          0 :         vriempoly[e][idirmark+k] = u[k];
     784                 :            :     }
     785                 :            :   }
     786                 :          0 :   return vriempoly;
     787                 :            : }
     788                 :            : 
     789                 :          0 : void evaluRiemann( ncomp_t ncomp,
     790                 :            :                    const int e_left,
     791                 :            :                    const int e_right,
     792                 :            :                    const std::size_t nmat,
     793                 :            :                    const std::vector< tk::real >& fl,
     794                 :            :                    const std::array< tk::real, 3 >& fn,
     795                 :            :                    const std::array< tk::real, 3 >& gp,
     796                 :            :                    const std::array< std::vector< tk::real >, 2 >& state,
     797                 :            :                    std::vector< std::vector< tk::real > >& vriem,
     798                 :            :                    std::vector< std::vector< tk::real > >& riemannLoc )
     799                 :            : // *****************************************************************************
     800                 :            : //  Compute the riemann velocity at the interface
     801                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     802                 :            : //! \param[in] e_left Index for the left element
     803                 :            : //! \param[in] e_right Index for the right element
     804                 :            : //! \param[in] nmat Number of materials in this PDE system
     805                 :            : //! \param[in] fn Face/Surface normal
     806                 :            : //! \param[in] gp Gauss points coordinates
     807                 :            : //! \param[in] fl Surface flux
     808                 :            : //! \param[in] state Vector of state variables for left and right side
     809                 :            : //! \param[in,out] vriem Vector of the riemann velocity
     810                 :            : //! \param[in,out] riemannLoc Vector of coordinates where Riemann velocity data
     811                 :            : //!   is available
     812                 :            : // *****************************************************************************
     813                 :            : {
     814                 :            :   using inciter::densityIdx;
     815                 :            :   using inciter::momentumIdx;
     816                 :            : 
     817                 :          0 :   std::size_t el(0), er(0);
     818                 :          0 :   el = static_cast< std::size_t >(e_left);
     819         [ -  - ]:          0 :   if(e_right != -1)
     820                 :          0 :     er = static_cast< std::size_t >(e_right);
     821                 :            : 
     822         [ -  - ]:          0 :   riemannLoc[el].push_back( gp[0] );
     823         [ -  - ]:          0 :   riemannLoc[el].push_back( gp[1] );
     824         [ -  - ]:          0 :   riemannLoc[el].push_back( gp[2] );
     825                 :            : 
     826         [ -  - ]:          0 :   if(e_right != -1)
     827                 :            :   {
     828         [ -  - ]:          0 :     riemannLoc[er].push_back( gp[0] );
     829         [ -  - ]:          0 :     riemannLoc[er].push_back( gp[1] );
     830         [ -  - ]:          0 :     riemannLoc[er].push_back( gp[2] );
     831                 :            :   }
     832                 :            : 
     833                 :          0 :   tk::real rhobl(0.0), rhobr(0.0);
     834         [ -  - ]:          0 :   for (std::size_t k=0; k<nmat; ++k)
     835                 :            :   {
     836                 :          0 :     rhobl += state[0][densityIdx(nmat, k)];
     837                 :          0 :     rhobr += state[1][densityIdx(nmat, k)];
     838                 :            :   }
     839                 :            : 
     840                 :          0 :   auto ul = state[0][momentumIdx(nmat, 0)] / rhobl;
     841                 :          0 :   auto vl = state[0][momentumIdx(nmat, 1)] / rhobl;
     842                 :          0 :   auto wl = state[0][momentumIdx(nmat, 2)] / rhobl;
     843                 :            : 
     844                 :          0 :   auto ur = state[1][momentumIdx(nmat, 0)] / rhobr;
     845                 :          0 :   auto vr = state[1][momentumIdx(nmat, 1)] / rhobr;
     846                 :          0 :   auto wr = state[1][momentumIdx(nmat, 2)] / rhobr;
     847                 :            : 
     848                 :            :   // Compute the normal velocities from left and right cells
     849                 :          0 :   auto vnl = ul * fn[0] + vl * fn[1] + wl * fn[2];
     850                 :          0 :   auto vnr = ur * fn[0] + vr * fn[1] + wr * fn[2];
     851                 :            : 
     852                 :            :   // The interface velocity is evaluated by adding the normal velocity which
     853                 :            :   // is taken from the Riemann solver and the tangential velocity which is
     854                 :            :   // evaluated as an average of the left and right cells
     855                 :          0 :   auto urie = 0.5 * ((ul + ur) - fn[0] * (vnl + vnr)) + fl[ncomp+nmat] * fn[0];
     856                 :          0 :   auto vrie = 0.5 * ((vl + vr) - fn[1] * (vnl + vnr)) + fl[ncomp+nmat] * fn[1];
     857                 :          0 :   auto wrie = 0.5 * ((wl + wr) - fn[2] * (vnl + vnr)) + fl[ncomp+nmat] * fn[2];
     858                 :            : 
     859         [ -  - ]:          0 :   vriem[el].push_back(urie);
     860         [ -  - ]:          0 :   vriem[el].push_back(vrie);
     861         [ -  - ]:          0 :   vriem[el].push_back(wrie);
     862                 :            : 
     863         [ -  - ]:          0 :   if(e_right != -1)
     864                 :            :   {
     865         [ -  - ]:          0 :     vriem[er].push_back(urie);
     866         [ -  - ]:          0 :     vriem[er].push_back(vrie);
     867         [ -  - ]:          0 :     vriem[er].push_back(wrie);
     868                 :            :   }
     869                 :          0 : }
     870                 :            : 
     871                 :            : std::vector< std::array< tk::real, 3 > >
     872                 :    7374000 : fluxTerms(
     873                 :            :   std::size_t ncomp,
     874                 :            :   std::size_t nmat,
     875                 :            :   const std::vector< inciter::EOS >& /*mat_blk*/,
     876                 :            :   const std::vector< tk::real >& ugp )
     877                 :            : // *****************************************************************************
     878                 :            : //  Compute the flux-function for the multimaterial PDEs
     879                 :            : //! \param[in] ncomp Number of components in this PDE system
     880                 :            : //! \param[in] nmat Number of materials in this PDE system
     881                 :            : // //! \param[in] mat_blk EOS material block
     882                 :            : //! \param[in] ugp State vector at the Gauss point at which flux is required
     883                 :            : //! \return Flux vectors for all components in multi-material PDE system
     884                 :            : // *****************************************************************************
     885                 :            : {
     886                 :            :   using inciter::volfracIdx;
     887                 :            :   using inciter::densityIdx;
     888                 :            :   using inciter::momentumIdx;
     889                 :            :   using inciter::energyIdx;
     890                 :            :   using inciter::velocityIdx;
     891                 :            :   using inciter::pressureIdx;
     892                 :            :   using inciter::deformIdx;
     893                 :            : 
     894                 :            :   const auto& solidx =
     895                 :    7374000 :     inciter::g_inputdeck.get< tag::matidxmap, tag::solidx >();
     896                 :            : 
     897         [ +  - ]:    7374000 :   std::vector< std::array< tk::real, 3 > > fl( ncomp, {{0, 0, 0}} );
     898                 :            : 
     899                 :    7374000 :   tk::real rho(0.0);
     900         [ +  + ]:   22122000 :   for (std::size_t k=0; k<nmat; ++k)
     901                 :   14748000 :     rho += ugp[densityIdx(nmat, k)];
     902                 :            : 
     903                 :    7374000 :   auto u = ugp[ncomp+velocityIdx(nmat,0)];
     904                 :    7374000 :   auto v = ugp[ncomp+velocityIdx(nmat,1)];
     905                 :    7374000 :   auto w = ugp[ncomp+velocityIdx(nmat,2)];
     906                 :            : 
     907 [ +  - ][ -  + ]:    7374000 :   if (inciter::haveSolid(nmat, solidx))
     908                 :            :   {
     909         [ -  - ]:          0 :     std::vector< tk::real > al(nmat, 0.0);
     910                 :          0 :     std::vector< std::array< std::array< tk::real, 3 >, 3 > > g, asig;
     911                 :            :     std::array< std::array< tk::real, 3 >, 3 >
     912                 :          0 :       sig {{ {{0, 0, 0}}, {{0, 0, 0}}, {{0, 0, 0}} }};
     913         [ -  - ]:          0 :     for (std::size_t k=0; k<nmat; ++k)
     914                 :            :     {
     915                 :          0 :       al[k] = ugp[volfracIdx(nmat, k)];
     916                 :            :       // inv deformation gradient and Cauchy stress tensors
     917 [ -  - ][ -  - ]:          0 :       g.push_back(inciter::getDeformGrad(nmat, k, ugp));
     918 [ -  - ][ -  - ]:          0 :       asig.push_back(inciter::getCauchyStress(nmat, k, ncomp, ugp));
     919         [ -  - ]:          0 :       for (std::size_t i=0; i<3; ++i) asig[k][i][i] -= ugp[ncomp+pressureIdx(nmat,k)];
     920                 :            : 
     921         [ -  - ]:          0 :       for (size_t i=0; i<3; ++i)
     922         [ -  - ]:          0 :         for (size_t j=0; j<3; ++j)
     923                 :          0 :           sig[i][j] += asig[k][i][j];
     924                 :            :     }
     925                 :            : 
     926                 :            :     // conservative part of momentum flux
     927                 :          0 :     fl[momentumIdx(nmat, 0)][0] = ugp[momentumIdx(nmat, 0)] * u - sig[0][0];
     928                 :          0 :     fl[momentumIdx(nmat, 1)][0] = ugp[momentumIdx(nmat, 1)] * u - sig[0][1];
     929                 :          0 :     fl[momentumIdx(nmat, 2)][0] = ugp[momentumIdx(nmat, 2)] * u - sig[0][2];
     930                 :            : 
     931                 :          0 :     fl[momentumIdx(nmat, 0)][1] = ugp[momentumIdx(nmat, 0)] * v - sig[1][0];
     932                 :          0 :     fl[momentumIdx(nmat, 1)][1] = ugp[momentumIdx(nmat, 1)] * v - sig[1][1];
     933                 :          0 :     fl[momentumIdx(nmat, 2)][1] = ugp[momentumIdx(nmat, 2)] * v - sig[1][2];
     934                 :            : 
     935                 :          0 :     fl[momentumIdx(nmat, 0)][2] = ugp[momentumIdx(nmat, 0)] * w - sig[2][0];
     936                 :          0 :     fl[momentumIdx(nmat, 1)][2] = ugp[momentumIdx(nmat, 1)] * w - sig[2][1];
     937                 :          0 :     fl[momentumIdx(nmat, 2)][2] = ugp[momentumIdx(nmat, 2)] * w - sig[2][2];
     938                 :            : 
     939         [ -  - ]:          0 :     for (std::size_t k=0; k<nmat; ++k)
     940                 :            :     {
     941                 :            :       // conservative part of volume-fraction flux
     942                 :          0 :       fl[volfracIdx(nmat, k)][0] = 0.0;
     943                 :          0 :       fl[volfracIdx(nmat, k)][1] = 0.0;
     944                 :          0 :       fl[volfracIdx(nmat, k)][2] = 0.0;
     945                 :            : 
     946                 :            :       // conservative part of material continuity flux
     947                 :          0 :       fl[densityIdx(nmat, k)][0] = u * ugp[densityIdx(nmat, k)];
     948                 :          0 :       fl[densityIdx(nmat, k)][1] = v * ugp[densityIdx(nmat, k)];
     949                 :          0 :       fl[densityIdx(nmat, k)][2] = w * ugp[densityIdx(nmat, k)];
     950                 :            : 
     951                 :            :       // conservative part of material total-energy flux
     952                 :          0 :       fl[energyIdx(nmat, k)][0] = u * ugp[energyIdx(nmat, k)]
     953                 :          0 :         - u * asig[k][0][0] - v * asig[k][1][0] - w * asig[k][2][0];
     954                 :          0 :       fl[energyIdx(nmat, k)][1] = v * ugp[energyIdx(nmat, k)]
     955                 :          0 :         - u * asig[k][0][1] - v * asig[k][1][1] - w * asig[k][2][1];
     956                 :          0 :       fl[energyIdx(nmat, k)][2] = w * ugp[energyIdx(nmat, k)]
     957                 :          0 :         - u * asig[k][0][2] - v * asig[k][1][2] - w * asig[k][2][2];
     958                 :            : 
     959                 :            :       // conservative part of material inverse deformation gradient
     960                 :            :       // g_ij: \partial (g_il u_l) / \partial (x_j)
     961         [ -  - ]:          0 :       if (solidx[k] > 0)
     962                 :            :       {
     963         [ -  - ]:          0 :         for (std::size_t i=0; i<3; ++i)
     964                 :            :         {
     965         [ -  - ]:          0 :           for (std::size_t j=0; j<3; ++j)
     966                 :            :           {
     967                 :          0 :             fl[deformIdx(nmat,solidx[k],i,j)][j] =
     968                 :          0 :               u*g[k][i][0] + v*g[k][i][1] + w*g[k][i][2];
     969                 :            :           }
     970                 :            :           // other components are zero
     971                 :            :         }
     972                 :            :       }
     973                 :            :     }
     974                 :            :   }
     975                 :            :   else
     976                 :            :   {
     977                 :    7374000 :     tk::real p(0.0);
     978         [ +  - ]:   14748000 :     std::vector< tk::real > apk( nmat, 0.0 );
     979         [ +  + ]:   22122000 :     for (std::size_t k=0; k<nmat; ++k)
     980                 :            :     {
     981                 :   14748000 :       apk[k] = ugp[ncomp+pressureIdx(nmat,k)];
     982                 :   14748000 :       p += apk[k];
     983                 :            :     }
     984                 :            : 
     985                 :            :     // conservative part of momentum flux
     986                 :    7374000 :     fl[momentumIdx(nmat, 0)][0] = ugp[momentumIdx(nmat, 0)] * u + p;
     987                 :    7374000 :     fl[momentumIdx(nmat, 1)][0] = ugp[momentumIdx(nmat, 1)] * u;
     988                 :    7374000 :     fl[momentumIdx(nmat, 2)][0] = ugp[momentumIdx(nmat, 2)] * u;
     989                 :            : 
     990                 :    7374000 :     fl[momentumIdx(nmat, 0)][1] = ugp[momentumIdx(nmat, 0)] * v;
     991                 :    7374000 :     fl[momentumIdx(nmat, 1)][1] = ugp[momentumIdx(nmat, 1)] * v + p;
     992                 :    7374000 :     fl[momentumIdx(nmat, 2)][1] = ugp[momentumIdx(nmat, 2)] * v;
     993                 :            : 
     994                 :    7374000 :     fl[momentumIdx(nmat, 0)][2] = ugp[momentumIdx(nmat, 0)] * w;
     995                 :    7374000 :     fl[momentumIdx(nmat, 1)][2] = ugp[momentumIdx(nmat, 1)] * w;
     996                 :    7374000 :     fl[momentumIdx(nmat, 2)][2] = ugp[momentumIdx(nmat, 2)] * w + p;
     997                 :            : 
     998         [ +  + ]:   22122000 :     for (std::size_t k=0; k<nmat; ++k)
     999                 :            :     {
    1000                 :            :       // conservative part of volume-fraction flux
    1001                 :   14748000 :       fl[volfracIdx(nmat, k)][0] = 0.0;
    1002                 :   14748000 :       fl[volfracIdx(nmat, k)][1] = 0.0;
    1003                 :   14748000 :       fl[volfracIdx(nmat, k)][2] = 0.0;
    1004                 :            : 
    1005                 :            :       // conservative part of material continuity flux
    1006                 :   14748000 :       fl[densityIdx(nmat, k)][0] = u * ugp[densityIdx(nmat, k)];
    1007                 :   14748000 :       fl[densityIdx(nmat, k)][1] = v * ugp[densityIdx(nmat, k)];
    1008                 :   14748000 :       fl[densityIdx(nmat, k)][2] = w * ugp[densityIdx(nmat, k)];
    1009                 :            : 
    1010                 :            :       // conservative part of material total-energy flux
    1011                 :   14748000 :       auto hmat = ugp[energyIdx(nmat, k)] + apk[k];
    1012                 :   14748000 :       fl[energyIdx(nmat, k)][0] = u * hmat;
    1013                 :   14748000 :       fl[energyIdx(nmat, k)][1] = v * hmat;
    1014                 :   14748000 :       fl[energyIdx(nmat, k)][2] = w * hmat;
    1015                 :            :     }
    1016                 :            :   }
    1017                 :            : 
    1018                 :    7374000 :   return fl;
    1019                 :            : }
    1020                 :            : 
    1021                 :            : }// tk::

Generated by: LCOV version 1.14