Quinoa all test code coverage report
Current view: top level - PDE/Integrate - MultiMatTerms.cpp (source / functions) Hit Total Coverage
Commit: -128-NOTFOUND Lines: 235 359 65.5 %
Date: 2025-12-08 20:34:58 Functions: 7 9 77.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 143 342 41.8 %

           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                 :       6450 : 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                 :       6450 :     inciter::g_inputdeck.get< tag::matidxmap, tag::solidx >();
      97                 :            : 
      98                 :       6450 :   const auto& cx = coord[0];
      99                 :       6450 :   const auto& cy = coord[1];
     100                 :       6450 :   const auto& cz = coord[2];
     101                 :            : 
     102                 :       6450 :   auto ncomp = U.nprop()/rdof;
     103                 :       6450 :   auto nprim = P.nprop()/rdof;
     104                 :            : 
     105                 :            :   // compute volume integrals
     106         [ +  + ]:    2322210 :   for (std::size_t e=0; e<nelem; ++e)
     107                 :            :   {
     108         [ +  - ]:    2315760 :     auto ng = tk::NGvol(ndofel[e]);
     109                 :            : 
     110                 :            :     // arrays for quadrature points
     111                 :    4631520 :     std::array< std::vector< real >, 3 > coordgp;
     112                 :    4631520 :     std::vector< real > wgp;
     113                 :            : 
     114         [ +  - ]:    2315760 :     coordgp[0].resize( ng );
     115         [ +  - ]:    2315760 :     coordgp[1].resize( ng );
     116         [ +  - ]:    2315760 :     coordgp[2].resize( ng );
     117         [ +  - ]:    2315760 :     wgp.resize( ng );
     118                 :            : 
     119         [ +  - ]:    2315760 :     GaussQuadratureTet( ng, coordgp, wgp );
     120                 :            : 
     121                 :            :     // Extract the element coordinates
     122                 :            :     std::array< std::array< real, 3>, 4 > coordel {{
     123                 :    6947280 :       {{ cx[ inpoel[4*e  ] ], cy[ inpoel[4*e  ] ], cz[ inpoel[4*e  ] ] }},
     124                 :    6947280 :       {{ cx[ inpoel[4*e+1] ], cy[ inpoel[4*e+1] ], cz[ inpoel[4*e+1] ] }},
     125                 :    6947280 :       {{ cx[ inpoel[4*e+2] ], cy[ inpoel[4*e+2] ], cz[ inpoel[4*e+2] ] }},
     126                 :    6947280 :       {{ cx[ inpoel[4*e+3] ], cy[ inpoel[4*e+3] ], cz[ inpoel[4*e+3] ] }}
     127                 :   25473360 :     }};
     128                 :            : 
     129                 :            :     auto jacInv =
     130                 :    2315760 :             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         [ +  + ]:    2315760 :     if (rdof > ndof)
     137                 :            :     {
     138                 :     341100 :       dof_el = rdof;
     139                 :            :     }
     140                 :            :     else
     141                 :            :     {
     142                 :    1974660 :       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 [ +  + ][ -  + ]:    2315760 :     if(dof_el == 1 && pref)
     148                 :          0 :       dof_el = 4;
     149                 :            : 
     150                 :            :     // Compute the derivatives of basis function for second order terms
     151                 :    4631520 :     std::array< std::vector<tk::real>, 3 > dBdx;
     152         [ +  + ]:    2315760 :     if (ndofel[e] > 1)
     153         [ +  - ]:     318360 :       dBdx = eval_dBdx_p1( ndofel[e], jacInv );
     154                 :            : 
     155                 :            :     // Gaussian quadrature
     156         [ +  + ]:    5904960 :     for (std::size_t igp=0; igp<ng; ++igp)
     157                 :            :     {
     158         [ -  + ]:    3589200 :       if (ndofel[e] > 4)
     159         [ -  - ]:          0 :         eval_dBdx_p2( igp, coordgp, jacInv, dBdx );
     160                 :            : 
     161                 :            :       // Compute the basis function
     162                 :            :       auto B =
     163         [ +  - ]:    7178400 :         eval_basis( dof_el, coordgp[0][igp], coordgp[1][igp], coordgp[2][igp] );
     164                 :            : 
     165         [ +  - ]:    3589200 :       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         [ +  - ]:    7178400 :         {{coordgp[0][igp], coordgp[1][igp], coordgp[2][igp]}}, B, U, P);
     170                 :            : 
     171                 :            :       // get bulk properties
     172                 :    3589200 :       tk::real rhob(0.0);
     173         [ +  + ]:   11860500 :       for (std::size_t k=0; k<nmat; ++k)
     174                 :    8271300 :           rhob += state[densityIdx(nmat, k)];
     175                 :            : 
     176                 :            :       // get the velocity vector
     177                 :    3589200 :       std::array< tk::real, 3 > vel{{ state[ncomp+velocityIdx(nmat, 0)],
     178                 :    3589200 :                                       state[ncomp+velocityIdx(nmat, 1)],
     179                 :    7178400 :                                       state[ncomp+velocityIdx(nmat, 2)] }};
     180                 :            : 
     181         [ +  - ]:    7178400 :       std::vector< tk::real > ymat(nmat, 0.0);
     182                 :    3589200 :       std::array< tk::real, 3 > dap{{0.0, 0.0, 0.0}};
     183         [ +  + ]:   11860500 :       for (std::size_t k=0; k<nmat; ++k)
     184                 :            :       {
     185                 :    8271300 :         ymat[k] = state[densityIdx(nmat, k)]/rhob;
     186                 :            : 
     187                 :    8271300 :         std::size_t mark(3*k);
     188         [ -  + ]:    8271300 :         if (solidx[k] > 0) mark = 3*nmat+ndof+3*(solidx[k]-1);
     189                 :            : 
     190         [ +  + ]:   33085200 :         for (std::size_t idir=0; idir<3; ++idir)
     191                 :   24813900 :           dap[idir] += riemannDeriv[mark+idir][e];
     192                 :            :       }
     193                 :            : 
     194                 :            :       // compute non-conservative terms
     195                 :            :       std::vector< std::vector< tk::real > > ncf
     196 [ +  - ][ +  - ]:   10767600 :         (ncomp, std::vector<tk::real>(ndofel[e],0.0));
     197                 :            : 
     198         [ +  + ]:   14356800 :       for (std::size_t idir=0; idir<3; ++idir)
     199         [ +  + ]:   35861400 :         for(std::size_t idof=0; idof<ndofel[e]; ++idof)
     200                 :   25093800 :           ncf[momentumIdx(nmat, idir)][idof] = 0.0;
     201                 :            : 
     202         [ +  + ]:   11860500 :       for (std::size_t k=0; k<nmat; ++k)
     203                 :            :       {
     204                 :            :         // evaluate non-conservative term for energy equation
     205                 :    8271300 :         std::size_t mark(3*k);
     206         [ -  + ]:    8271300 :         if (solidx[k] > 0) mark = 3*nmat+ndof+3*(solidx[k]-1);
     207                 :            : 
     208         [ +  + ]:   26093400 :         for(std::size_t idof=0; idof<ndofel[e]; ++idof)
     209                 :            :         {
     210                 :   17822100 :           ncf[densityIdx(nmat, k)][idof] = 0.0;
     211                 :            : 
     212         [ +  + ]:   71288400 :           for (std::size_t idir=0; idir<3; ++idir)
     213                 :  106932600 :             ncf[energyIdx(nmat, k)][idof] -= vel[idir] * ( ymat[k]*dap[idir]
     214                 :   53466300 :                                                   - riemannDeriv[mark+idir][e] );
     215                 :            :         }
     216                 :            : 
     217                 :            :         // evaluate non-conservative terms for g equation
     218         [ -  + ]:    8271300 :         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 [ -  + ][ -  - ]:    8271300 :         if (ndof <= 4 || intsharp == 1) {
     248         [ +  + ]:   26093400 :           for(std::size_t idof=0; idof<ndofel[e]; ++idof)
     249                 :   35644200 :             ncf[volfracIdx(nmat, k)][idof] = state[volfracIdx(nmat, k)]
     250                 :   26093400 :                                            * 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         [ +  - ]:    3589200 :       updateRhsNonCons( ncomp, nmat, ndof, ndofel[e], wt, e, B, dBdx, ncf, R );
     268                 :            :     }
     269                 :            :   }
     270                 :       6450 : }
     271                 :            : 
     272                 :            : void
     273                 :    3589200 : 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 [ -  + ][ -  - ]:    3589200 :   Assert( ncf.size() == ncomp, "Size mismatch for non-conservative term" );
         [ -  - ][ -  - ]
     314                 :            : 
     315         [ +  + ]:   39170700 :   for (ncomp_t c=0; c<ncomp; ++c)
     316                 :            :   {
     317                 :   35581500 :     auto mark = c*ndof;
     318                 :   35581500 :     R(e, mark) += wt * ncf[c][0];
     319                 :            :   }
     320                 :            : 
     321         [ +  + ]:    3589200 :   if( ndof_el > 1)
     322                 :            :   {
     323                 :            :     // Update rhs with distributions from volume fraction and energy equations
     324         [ +  + ]:    4775400 :     for (std::size_t k=0; k<nmat; ++k)
     325                 :            :     {
     326         [ +  + ]:   12734400 :       for(std::size_t idof = 1; idof < ndof_el; idof++)
     327                 :            :       {
     328                 :    9550800 :         R(e, volfracDofIdx(nmat,k,ndof,idof)) +=
     329                 :    9550800 :           wt * ncf[volfracIdx(nmat,k)][idof];
     330                 :    9550800 :         R(e, energyDofIdx(nmat,k,ndof,idof)) +=
     331                 :    9550800 :           wt * ncf[energyIdx(nmat,k)][idof] * B[idof];
     332                 :            :         // Note: High order non-conservative g terms not implemented yet!
     333                 :            :       }
     334                 :            :     }
     335                 :            :   }
     336                 :    3589200 : }
     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                 :    1091856 :   auto v_dot_n = tk::dot(vel, fn);
     388                 :            : 
     389                 :            :   // compute non-conservative terms
     390                 :    1091856 :   auto v_riem = var_riemann[nmat];
     391         [ +  - ]:    1091856 :   std::vector< tk::real > ncf(ncomp, 0.0);
     392         [ +  + ]:    3512624 :   for (std::size_t k=0; k<nmat; ++k)
     393                 :            :   {
     394         [ +  - ]:    2420768 :     auto ymat = U(e, densityDofIdx(nmat,k,rdof,0))/rhob;
     395                 :            : 
     396                 :            :     // evaluate non-conservative term for energy equation
     397                 :    2420768 :     ncf[energyIdx(nmat, k)] -= v_dot_n * ( ymat*p_face - var_riemann[k] );
     398                 :            : 
     399                 :            :     // evaluate non-conservative term for volume fraction equation
     400         [ +  - ]:    4841536 :     ncf[volfracIdx(nmat, k)] = U(e, volfracDofIdx(nmat,k,rdof,0))
     401                 :    2420768 :       * v_riem;
     402                 :            :   }
     403                 :            : 
     404                 :    2183712 :   return ncf;
     405                 :            : }
     406                 :            : 
     407                 :            : void
     408                 :        375 : pressureRelaxationInt( const bool pref,
     409                 :            :                        std::size_t nmat,
     410                 :            :                        const std::vector< inciter::EOS >& mat_blk,
     411                 :            :                        const std::size_t ndof,
     412                 :            :                        const std::size_t rdof,
     413                 :            :                        const std::size_t nelem,
     414                 :            :                        const std::vector< std::size_t >& inpoel,
     415                 :            :                        const UnsMesh::Coords& coord,
     416                 :            :                        const Fields& geoElem,
     417                 :            :                        const Fields& U,
     418                 :            :                        const Fields& P,
     419                 :            :                        const std::vector< std::size_t >& ndofel,
     420                 :            :                        const tk::real ct,
     421                 :            :                        Fields& R,
     422                 :            :                        int intsharp )
     423                 :            : // *****************************************************************************
     424                 :            : //  Compute volume integrals of pressure relaxation terms in multi-material DG
     425                 :            : //! \details This is called for multi-material DG to compute volume integrals of
     426                 :            : //!   finite pressure relaxation terms in the volume fraction and energy
     427                 :            : //!   equations, which do not exist in the single-material flow formulation (for
     428                 :            : //!   `CompFlow` DG). For further details see Dobrev, V. A., Kolev, T. V.,
     429                 :            : //!   Rieben, R. N., & Tomov, V. Z. (2016). Multi‐material closure model for
     430                 :            : //!   high‐order finite element Lagrangian hydrodynamics. International Journal
     431                 :            : //!   for Numerical Methods in Fluids, 82(10), 689-706.
     432                 :            : //! \param[in] pref Indicator for p-adaptive algorithm
     433                 :            : //! \param[in] nmat Number of materials in this PDE system
     434                 :            : //! \param[in] mat_blk EOS material block
     435                 :            : //! \param[in] ndof Maximum number of degrees of freedom
     436                 :            : //! \param[in] rdof Maximum number of reconstructed degrees of freedom
     437                 :            : //! \param[in] nelem Total number of elements
     438                 :            : //! \param[in] inpoel Element-node connectivity
     439                 :            : //! \param[in] coord Array of nodal coordinates
     440                 :            : //! \param[in] geoElem Element geometry array
     441                 :            : //! \param[in] U Solution vector at recent time step
     442                 :            : //! \param[in] P Vector of primitive quantities at recent time step
     443                 :            : //! \param[in] ndofel Vector of local number of degrees of freedome
     444                 :            : //! \param[in] ct Pressure relaxation time-scale for this system
     445                 :            : //! \param[in,out] R Right-hand side vector added to
     446                 :            : //! \param[in] intsharp Interface reconstruction indicator
     447                 :            : // *****************************************************************************
     448                 :            : {
     449                 :            :   using inciter::volfracIdx;
     450                 :            :   using inciter::densityIdx;
     451                 :            :   using inciter::momentumIdx;
     452                 :            :   using inciter::energyIdx;
     453                 :            :   using inciter::pressureIdx;
     454                 :            :   using inciter::velocityIdx;
     455                 :            :   using inciter::deformIdx;
     456                 :            : 
     457                 :            :   const auto& solidx =
     458                 :        375 :     inciter::g_inputdeck.get< tag::matidxmap, tag::solidx >();
     459                 :            : 
     460                 :        375 :   auto ncomp = U.nprop()/rdof;
     461                 :        375 :   auto nprim = P.nprop()/rdof;
     462                 :            : 
     463                 :            :   // compute volume integrals
     464         [ +  + ]:     227775 :   for (std::size_t e=0; e<nelem; ++e)
     465                 :            :   {
     466         [ +  - ]:     227400 :     auto dx = geoElem(e,4)/2.0;
     467         [ +  - ]:     227400 :     auto ng = NGvol(ndofel[e]);
     468                 :            : 
     469                 :            :     // arrays for quadrature points
     470                 :     454800 :     std::array< std::vector< real >, 3 > coordgp;
     471                 :     454800 :     std::vector< real > wgp;
     472                 :            : 
     473         [ +  - ]:     227400 :     coordgp[0].resize( ng );
     474         [ +  - ]:     227400 :     coordgp[1].resize( ng );
     475         [ +  - ]:     227400 :     coordgp[2].resize( ng );
     476         [ +  - ]:     227400 :     wgp.resize( ng );
     477                 :            : 
     478         [ +  - ]:     227400 :     GaussQuadratureTet( ng, coordgp, wgp );
     479                 :            : 
     480                 :            :     // Compute the derivatives of basis function for DG(P1)
     481                 :     454800 :     std::array< std::vector<real>, 3 > dBdx;
     482                 :            : 
     483                 :            :     // If an rDG method is set up (P0P1), then, currently we compute the P1
     484                 :            :     // basis functions and solutions by default. This implies that P0P1 is
     485                 :            :     // unsupported in the p-adaptive DG (PDG).
     486                 :            :     std::size_t dof_el;
     487         [ -  + ]:     227400 :     if (rdof > ndof)
     488                 :            :     {
     489                 :          0 :       dof_el = rdof;
     490                 :            :     }
     491                 :            :     else
     492                 :            :     {
     493                 :     227400 :       dof_el = ndofel[e];
     494                 :            :     }
     495                 :            : 
     496                 :            :     // For multi-material p-adaptive simulation, when dofel = 1, p0p1 is applied
     497                 :            :     // and ndof for solution evaluation should be 4
     498 [ -  + ][ -  - ]:     227400 :     if(dof_el == 1 && pref)
     499                 :          0 :       dof_el = 4;
     500                 :            : 
     501                 :            :     // Gaussian quadrature
     502         [ +  + ]:    1364400 :     for (std::size_t igp=0; igp<ng; ++igp)
     503                 :            :     {
     504                 :            :       // Compute the basis function
     505                 :            :       auto B =
     506         [ +  - ]:    2274000 :         eval_basis( dof_el, coordgp[0][igp], coordgp[1][igp], coordgp[2][igp] );
     507                 :            : 
     508         [ +  - ]:    1137000 :       auto wt = wgp[igp] * geoElem(e, 0);
     509                 :            : 
     510                 :            :       auto state = evalPolynomialSol(mat_blk, intsharp, ncomp, nprim,
     511                 :            :         rdof, nmat, e, dof_el, inpoel, coord, geoElem,
     512         [ +  - ]:    2274000 :         {{coordgp[0][igp], coordgp[1][igp], coordgp[2][igp]}}, B, U, P);
     513                 :            : 
     514                 :            :       // get bulk properties
     515                 :    1137000 :       real rhob(0.0);
     516         [ +  + ]:    3411000 :       for (std::size_t k=0; k<nmat; ++k)
     517                 :    2274000 :         rhob += state[densityIdx(nmat, k)];
     518                 :            : 
     519                 :            :       // get pressures and bulk modulii
     520                 :    1137000 :       real pb(0.0), nume(0.0), deno(0.0), trelax(0.0);
     521 [ +  - ][ +  - ]:    2274000 :       std::vector< real > apmat(nmat, 0.0), kmat(nmat, 0.0);
     522         [ +  - ]:    2274000 :       std::vector< int > do_relax(nmat, 1);
     523                 :    1137000 :       bool is_relax(false);
     524         [ +  + ]:    3411000 :       for (std::size_t k=0; k<nmat; ++k)
     525                 :            :       {
     526                 :    2274000 :         real arhomat = state[densityIdx(nmat, k)];
     527                 :    2274000 :         real alphamat = state[volfracIdx(nmat, k)];
     528                 :    2274000 :         apmat[k] = state[ncomp+pressureIdx(nmat, k)];
     529                 :    2274000 :         real amat = 0.0;
     530 [ +  - ][ +  + ]:    2274000 :         if (solidx[k] == 0 && alphamat >= inciter::volfracPRelaxLim()) {
                 [ +  + ]
     531         [ +  - ]:    2300292 :             amat = mat_blk[k].compute< inciter::EOS::soundspeed >( arhomat,
     532                 :    1150146 :               apmat[k], alphamat, k );
     533                 :    1150146 :           kmat[k] = arhomat * amat * amat;
     534                 :    1150146 :           pb += apmat[k];
     535                 :            : 
     536                 :            :           // relaxation parameters
     537                 :    1150146 :           trelax = std::max(trelax, ct*dx/amat);
     538                 :    1150146 :           nume += alphamat * apmat[k] / kmat[k];
     539                 :    1150146 :           deno += alphamat * alphamat / kmat[k];
     540                 :            : 
     541                 :    1150146 :           is_relax = true;
     542                 :            :         }
     543                 :    1123854 :         else do_relax[k] = 0;
     544                 :            :       }
     545                 :    1137000 :       real p_relax(0.0);
     546         [ +  - ]:    1137000 :       if (is_relax) p_relax = nume/deno;
     547                 :            : 
     548                 :            :       // compute pressure relaxation terms
     549         [ +  - ]:    2274000 :       std::vector< real > s_prelax(ncomp, 0.0);
     550         [ +  + ]:    3411000 :       for (std::size_t k=0; k<nmat; ++k)
     551                 :            :       {
     552                 :            :         // only perform prelax on existing quantities
     553         [ +  + ]:    2274000 :         if (do_relax[k] == 1) {
     554                 :    1150146 :           auto s_alpha = (apmat[k]-p_relax*state[volfracIdx(nmat, k)])
     555                 :    1150146 :             * (state[volfracIdx(nmat, k)]/kmat[k]) / trelax;
     556                 :    1150146 :           s_prelax[volfracIdx(nmat, k)] = s_alpha;
     557                 :    1150146 :           s_prelax[energyIdx(nmat, k)] = - pb*s_alpha;
     558                 :            :         }
     559                 :            :       }
     560                 :            : 
     561         [ +  - ]:    1137000 :       updateRhsPre( ncomp, ndof, ndofel[e], wt, e, B, s_prelax, R );
     562                 :            :     }
     563                 :            :   }
     564                 :        375 : }
     565                 :            : 
     566                 :            : void
     567                 :    1137000 : updateRhsPre(
     568                 :            :   ncomp_t ncomp,
     569                 :            :   const std::size_t ndof,
     570                 :            :   [[maybe_unused]] const std::size_t ndof_el,
     571                 :            :   const tk::real wt,
     572                 :            :   const std::size_t e,
     573                 :            :   const std::vector< tk::real >& B,
     574                 :            :   std::vector< tk::real >& ncf,
     575                 :            :   Fields& R )
     576                 :            : // *****************************************************************************
     577                 :            : //  Update the rhs by adding the pressure relaxation integrals
     578                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     579                 :            : //! \param[in] ndof Maximum number of degrees of freedom
     580                 :            : //! \param[in] ndof_el Number of degrees of freedom for local element
     581                 :            : //! \param[in] wt Weight of gauss quadrature point
     582                 :            : //! \param[in] e Element index
     583                 :            : //! \param[in] B Basis function evaluated at local quadrature point
     584                 :            : //! \param[in] ncf Vector of non-conservative terms
     585                 :            : //! \param[in,out] R Right-hand side vector computed
     586                 :            : // *****************************************************************************
     587                 :            : {
     588                 :            :   //Assert( dBdx[0].size() == ndof_el,
     589                 :            :   //        "Size mismatch for basis function derivatives" );
     590                 :            :   //Assert( dBdx[1].size() == ndof_el,
     591                 :            :   //        "Size mismatch for basis function derivatives" );
     592                 :            :   //Assert( dBdx[2].size() == ndof_el,
     593                 :            :   //        "Size mismatch for basis function derivatives" );
     594                 :            :   //Assert( ncf.size() == ncomp,
     595                 :            :   //        "Size mismatch for non-conservative term" );
     596 [ -  + ][ -  - ]:    1137000 :   Assert( ncf.size() == ncomp, "Size mismatch for non-conservative term" );
         [ -  - ][ -  - ]
     597                 :            : 
     598         [ +  + ]:   11370000 :   for (ncomp_t c=0; c<ncomp; ++c)
     599                 :            :   {
     600                 :   10233000 :     auto mark = c*ndof;
     601         [ +  + ]:   51165000 :     for(std::size_t idof = 0; idof < ndof; idof++)
     602                 :   40932000 :       R(e, mark+idof) += wt * ncf[c] * B[idof];
     603                 :            :   }
     604                 :    1137000 : }
     605                 :            : 
     606                 :            : void
     607                 :       1218 : pressureRelaxationIntFV(
     608                 :            :   std::size_t nmat,
     609                 :            :   const std::vector< inciter::EOS >& mat_blk,
     610                 :            :   const std::size_t rdof,
     611                 :            :   const std::size_t nelem,
     612                 :            :   const std::vector< std::size_t >& inpoel,
     613                 :            :   const UnsMesh::Coords& coord,
     614                 :            :   const Fields& geoElem,
     615                 :            :   const Fields& U,
     616                 :            :   const Fields& P,
     617                 :            :   const tk::real ct,
     618                 :            :   Fields& R )
     619                 :            : // *****************************************************************************
     620                 :            : //  Compute volume integrals of pressure relaxation terms in multi-material FV
     621                 :            : //! \details This is called for multi-material FV to compute volume integrals of
     622                 :            : //!   finite pressure relaxation terms in the volume fraction and energy
     623                 :            : //!   equations, which do not exist in the single-material flow formulation (for
     624                 :            : //!   `CompFlow`). For further details see Dobrev, V. A., Kolev, T. V.,
     625                 :            : //!   Rieben, R. N., & Tomov, V. Z. (2016). Multi‐material closure model for
     626                 :            : //!   high‐order finite element Lagrangian hydrodynamics. International Journal
     627                 :            : //!   for Numerical Methods in Fluids, 82(10), 689-706.
     628                 :            : //! \param[in] nmat Number of materials in this PDE system
     629                 :            : //! \param[in] mat_blk EOS material block
     630                 :            : //! \param[in] rdof Maximum number of reconstructed degrees of freedom
     631                 :            : //! \param[in] nelem Total number of elements
     632                 :            : //! \param[in] geoElem Element geometry array
     633                 :            : //! \param[in] U Solution vector at recent time step
     634                 :            : //! \param[in] P Vector of primitive quantities at recent time step
     635                 :            : //! \param[in] ct Pressure relaxation time-scale for this system
     636                 :            : //! \param[in,out] R Right-hand side vector added to
     637                 :            : // *****************************************************************************
     638                 :            : {
     639                 :            :   using inciter::volfracIdx;
     640                 :            :   using inciter::volfracDofIdx;
     641                 :            :   using inciter::energyDofIdx;
     642                 :            :   using inciter::pressureIdx;
     643                 :            :   using inciter::densityIdx;
     644                 :            : 
     645                 :       1218 :   auto ncomp = U.nprop()/rdof;
     646                 :       1218 :   auto nprim = P.nprop()/rdof;
     647                 :            : 
     648 [ +  - ][ +  - ]:       2436 :   std::vector< real > apmat(nmat, 0.0), kmat(nmat, 0.0);
     649         [ +  - ]:       2436 :   std::vector< int > do_relax(nmat, 1);
     650                 :            : 
     651                 :            :   // Compute the basis function
     652         [ +  - ]:       2436 :   std::vector< tk::real > B(rdof, 0.0);
     653                 :       1218 :   B[0] = 1.0;
     654                 :            : 
     655                 :            :   // compute volume integrals
     656         [ +  + ]:     129578 :   for (std::size_t e=0; e<nelem; ++e)
     657                 :            :   {
     658         [ +  - ]:     128360 :     auto dx = geoElem(e,4)/2.0;
     659                 :            : 
     660                 :            :     auto state = evalPolynomialSol(mat_blk, 0, ncomp, nprim,
     661                 :            :       rdof, nmat, e, rdof, inpoel, coord, geoElem,
     662         [ +  - ]:     256720 :       {{0.25, 0.25, 0.25}}, B, U, P);
     663                 :            : 
     664                 :            :     // get bulk properties
     665                 :     128360 :     real rhob(0.0);
     666         [ +  + ]:     437640 :     for (std::size_t k=0; k<nmat; ++k)
     667                 :     309280 :       rhob += state[densityIdx(nmat, k)];
     668                 :            : 
     669                 :            :     // get pressures and bulk modulii
     670                 :     128360 :     real pb(0.0), nume(0.0), deno(0.0), trelax(0.0);
     671                 :     128360 :     bool is_relax(false);
     672         [ +  + ]:     437640 :     for (std::size_t k=0; k<nmat; ++k)
     673                 :            :     {
     674                 :     309280 :       do_relax[k] = 1;
     675                 :     309280 :       real arhomat = state[densityIdx(nmat, k)];
     676                 :     309280 :       real alphamat = state[volfracIdx(nmat, k)];
     677         [ +  + ]:     309280 :       if (alphamat >= inciter::volfracPRelaxLim()) {
     678                 :     128874 :         apmat[k] = state[ncomp+pressureIdx(nmat, k)];
     679         [ +  - ]:     257748 :         real amat = mat_blk[k].compute< inciter::EOS::soundspeed >( arhomat,
     680                 :     128874 :           apmat[k], alphamat, k );
     681                 :     128874 :         kmat[k] = arhomat * amat * amat;
     682                 :     128874 :         pb += apmat[k];
     683                 :            : 
     684                 :            :         // relaxation parameters
     685                 :     128874 :         trelax = std::max(trelax, ct*dx/amat);
     686                 :     128874 :         nume += alphamat * apmat[k] / kmat[k];
     687                 :     128874 :         deno += alphamat * alphamat / kmat[k];
     688                 :            : 
     689                 :     128874 :         is_relax = true;
     690                 :            :       }
     691                 :     180406 :       else do_relax[k] = 0;
     692                 :            :     }
     693                 :     128360 :     real p_relax(0.0);
     694         [ +  - ]:     128360 :     if (is_relax) p_relax = nume/deno;
     695                 :            : 
     696                 :            :     // compute pressure relaxation terms
     697         [ +  + ]:     437640 :     for (std::size_t k=0; k<nmat; ++k)
     698                 :            :     {
     699                 :            :       // only perform prelax on existing quantities
     700         [ +  + ]:     309280 :       if (do_relax[k] == 1) {
     701                 :     128874 :         auto s_alpha = (apmat[k]-p_relax*state[volfracIdx(nmat, k)])
     702                 :     128874 :           * (state[volfracIdx(nmat, k)]/kmat[k]) / trelax;
     703                 :            : 
     704 [ +  - ][ +  - ]:     128874 :         R(e, volfracDofIdx(nmat,k,1,0)) += geoElem(e,0) * s_alpha;
     705 [ +  - ][ +  - ]:     128874 :         R(e, energyDofIdx(nmat,k,1,0)) += geoElem(e,0) * (-pb*s_alpha);
     706                 :            :       }
     707                 :            :     }
     708                 :            :   }
     709                 :       1218 : }
     710                 :            : 
     711                 :            : std::vector< std::vector< tk::real > >
     712                 :          0 : solvevriem( std::size_t nelem,
     713                 :            :             const std::vector< std::vector< tk::real > >& vriem,
     714                 :            :             const std::vector< std::vector< tk::real > >& riemannLoc )
     715                 :            : // *****************************************************************************
     716                 :            : //  Solve the reconstruct velocity used for volume fraction equation by
     717                 :            : //  Least square method
     718                 :            : //! \param[in] nelem Numer of elements
     719                 :            : //! \param[in,out] vriem Vector of the riemann velocity
     720                 :            : //! \param[in,out] riemannLoc Vector of coordinates where Riemann velocity data
     721                 :            : //!   is available
     722                 :            : //! \return Vector of Riemann velocity polynomial solution
     723                 :            : // *****************************************************************************
     724                 :            : {
     725                 :            :   std::vector< std::vector< tk::real > >
     726 [ -  - ][ -  - ]:          0 :     vriempoly( nelem, std::vector<tk::real>(12,0.0) );
     727                 :            : 
     728         [ -  - ]:          0 :   for (std::size_t e=0; e<nelem; ++e)
     729                 :            :   {
     730                 :            :     // Use the normal method to construct the linear system A^T * A * x = u
     731                 :          0 :     auto numgp = riemannLoc[e].size()/3;
     732                 :            :     std::vector< std::vector< tk::real > > A(numgp,
     733 [ -  - ][ -  - ]:          0 :                                              std::vector<tk::real>(4, 1.0));
     734                 :            : 
     735         [ -  - ]:          0 :     for(std::size_t k = 0; k < numgp; k++)
     736                 :            :     {
     737                 :          0 :       auto mark = k * 3;
     738                 :          0 :       A[k][1] = riemannLoc[e][mark];
     739                 :          0 :       A[k][2] = riemannLoc[e][mark+1];
     740                 :          0 :       A[k][3] = riemannLoc[e][mark+2];
     741                 :            :     }
     742                 :            : 
     743         [ -  - ]:          0 :     for(std::size_t idir = 0; idir < 3; idir++)
     744                 :            :     {
     745                 :            :       double AA_T[4*4], u[4];
     746                 :            : 
     747         [ -  - ]:          0 :       for(std::size_t i = 0; i < 4; i++)
     748         [ -  - ]:          0 :         for(std::size_t j = 0; j < 4; j++)
     749                 :            :         {
     750                 :          0 :           auto id = 4 * i + j;
     751                 :          0 :           AA_T[id] = 0;
     752         [ -  - ]:          0 :           for(std::size_t k = 0; k < numgp; k++)
     753                 :          0 :             AA_T[id] += A[k][i] * A[k][j];
     754                 :            :         }
     755                 :            : 
     756         [ -  - ]:          0 :       std::vector<tk::real> vel(numgp, 1.0);
     757         [ -  - ]:          0 :       for(std::size_t k = 0; k < numgp; k++)
     758                 :            :       {
     759                 :          0 :         auto mark = k * 3 + idir;
     760                 :          0 :         vel[k] = vriem[e][mark];
     761                 :            :       }
     762         [ -  - ]:          0 :       for(std::size_t k = 0; k < 4; k++)
     763                 :            :       {
     764                 :          0 :         u[k] = 0;
     765         [ -  - ]:          0 :         for(std::size_t i = 0; i < numgp; i++)
     766                 :          0 :           u[k] += A[i][k] * vel[i];
     767                 :            :       }
     768                 :            :  
     769                 :            :       lapack_int IPIV[4];
     770                 :            :       #ifndef NDEBUG
     771                 :            :       lapack_int info =
     772                 :            :       #endif
     773         [ -  - ]:          0 :         LAPACKE_dsysv( LAPACK_ROW_MAJOR, 'U', 4, 1, AA_T, 4, IPIV, u, 1 );
     774 [ -  - ][ -  - ]:          0 :       Assert( info == 0, "Error in linear system solver" );
         [ -  - ][ -  - ]
     775                 :            : 
     776                 :          0 :       auto idirmark = idir * 4;
     777         [ -  - ]:          0 :       for(std::size_t k = 0; k < 4; k++)
     778                 :          0 :         vriempoly[e][idirmark+k] = u[k];
     779                 :            :     }
     780                 :            :   }
     781                 :          0 :   return vriempoly;
     782                 :            : }
     783                 :            : 
     784                 :          0 : void evaluRiemann( ncomp_t ncomp,
     785                 :            :                    const int e_left,
     786                 :            :                    const int e_right,
     787                 :            :                    const std::size_t nmat,
     788                 :            :                    const std::vector< tk::real >& fl,
     789                 :            :                    const std::array< tk::real, 3 >& fn,
     790                 :            :                    const std::array< tk::real, 3 >& gp,
     791                 :            :                    const std::array< std::vector< tk::real >, 2 >& state,
     792                 :            :                    std::vector< std::vector< tk::real > >& vriem,
     793                 :            :                    std::vector< std::vector< tk::real > >& riemannLoc )
     794                 :            : // *****************************************************************************
     795                 :            : //  Compute the riemann velocity at the interface
     796                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     797                 :            : //! \param[in] e_left Index for the left element
     798                 :            : //! \param[in] e_right Index for the right element
     799                 :            : //! \param[in] nmat Number of materials in this PDE system
     800                 :            : //! \param[in] fn Face/Surface normal
     801                 :            : //! \param[in] gp Gauss points coordinates
     802                 :            : //! \param[in] fl Surface flux
     803                 :            : //! \param[in] state Vector of state variables for left and right side
     804                 :            : //! \param[in,out] vriem Vector of the riemann velocity
     805                 :            : //! \param[in,out] riemannLoc Vector of coordinates where Riemann velocity data
     806                 :            : //!   is available
     807                 :            : // *****************************************************************************
     808                 :            : {
     809                 :            :   using inciter::densityIdx;
     810                 :            :   using inciter::momentumIdx;
     811                 :            : 
     812                 :          0 :   std::size_t el(0), er(0);
     813                 :          0 :   el = static_cast< std::size_t >(e_left);
     814         [ -  - ]:          0 :   if(e_right != -1)
     815                 :          0 :     er = static_cast< std::size_t >(e_right);
     816                 :            : 
     817         [ -  - ]:          0 :   riemannLoc[el].push_back( gp[0] );
     818         [ -  - ]:          0 :   riemannLoc[el].push_back( gp[1] );
     819         [ -  - ]:          0 :   riemannLoc[el].push_back( gp[2] );
     820                 :            : 
     821         [ -  - ]:          0 :   if(e_right != -1)
     822                 :            :   {
     823         [ -  - ]:          0 :     riemannLoc[er].push_back( gp[0] );
     824         [ -  - ]:          0 :     riemannLoc[er].push_back( gp[1] );
     825         [ -  - ]:          0 :     riemannLoc[er].push_back( gp[2] );
     826                 :            :   }
     827                 :            : 
     828                 :          0 :   tk::real rhobl(0.0), rhobr(0.0);
     829         [ -  - ]:          0 :   for (std::size_t k=0; k<nmat; ++k)
     830                 :            :   {
     831                 :          0 :     rhobl += state[0][densityIdx(nmat, k)];
     832                 :          0 :     rhobr += state[1][densityIdx(nmat, k)];
     833                 :            :   }
     834                 :            : 
     835                 :          0 :   auto ul = state[0][momentumIdx(nmat, 0)] / rhobl;
     836                 :          0 :   auto vl = state[0][momentumIdx(nmat, 1)] / rhobl;
     837                 :          0 :   auto wl = state[0][momentumIdx(nmat, 2)] / rhobl;
     838                 :            : 
     839                 :          0 :   auto ur = state[1][momentumIdx(nmat, 0)] / rhobr;
     840                 :          0 :   auto vr = state[1][momentumIdx(nmat, 1)] / rhobr;
     841                 :          0 :   auto wr = state[1][momentumIdx(nmat, 2)] / rhobr;
     842                 :            : 
     843                 :            :   // Compute the normal velocities from left and right cells
     844                 :          0 :   auto vnl = ul * fn[0] + vl * fn[1] + wl * fn[2];
     845                 :          0 :   auto vnr = ur * fn[0] + vr * fn[1] + wr * fn[2];
     846                 :            : 
     847                 :            :   // The interface velocity is evaluated by adding the normal velocity which
     848                 :            :   // is taken from the Riemann solver and the tangential velocity which is
     849                 :            :   // evaluated as an average of the left and right cells
     850                 :          0 :   auto urie = 0.5 * ((ul + ur) - fn[0] * (vnl + vnr)) + fl[ncomp+nmat] * fn[0];
     851                 :          0 :   auto vrie = 0.5 * ((vl + vr) - fn[1] * (vnl + vnr)) + fl[ncomp+nmat] * fn[1];
     852                 :          0 :   auto wrie = 0.5 * ((wl + wr) - fn[2] * (vnl + vnr)) + fl[ncomp+nmat] * fn[2];
     853                 :            : 
     854         [ -  - ]:          0 :   vriem[el].push_back(urie);
     855         [ -  - ]:          0 :   vriem[el].push_back(vrie);
     856         [ -  - ]:          0 :   vriem[el].push_back(wrie);
     857                 :            : 
     858         [ -  - ]:          0 :   if(e_right != -1)
     859                 :            :   {
     860         [ -  - ]:          0 :     vriem[er].push_back(urie);
     861         [ -  - ]:          0 :     vriem[er].push_back(vrie);
     862         [ -  - ]:          0 :     vriem[er].push_back(wrie);
     863                 :            :   }
     864                 :          0 : }
     865                 :            : 
     866                 :            : std::vector< std::array< tk::real, 3 > >
     867                 :    4028100 : fluxTerms(
     868                 :            :   std::size_t ncomp,
     869                 :            :   std::size_t nmat,
     870                 :            :   const std::vector< inciter::EOS >& /*mat_blk*/,
     871                 :            :   const std::vector< tk::real >& ugp )
     872                 :            : // *****************************************************************************
     873                 :            : //  Compute the flux-function for the multimaterial PDEs
     874                 :            : //! \param[in] ncomp Number of components in this PDE system
     875                 :            : //! \param[in] nmat Number of materials in this PDE system
     876                 :            : // //! \param[in] mat_blk EOS material block
     877                 :            : //! \param[in] ugp State vector at the Gauss point at which flux is required
     878                 :            : //! \return Flux vectors for all components in multi-material PDE system
     879                 :            : // *****************************************************************************
     880                 :            : {
     881                 :            :   using inciter::volfracIdx;
     882                 :            :   using inciter::densityIdx;
     883                 :            :   using inciter::momentumIdx;
     884                 :            :   using inciter::energyIdx;
     885                 :            :   using inciter::velocityIdx;
     886                 :            :   using inciter::pressureIdx;
     887                 :            :   using inciter::deformIdx;
     888                 :            : 
     889                 :            :   const auto& solidx =
     890                 :    4028100 :     inciter::g_inputdeck.get< tag::matidxmap, tag::solidx >();
     891                 :            : 
     892         [ +  - ]:    4028100 :   std::vector< std::array< tk::real, 3 > > fl( ncomp, {{0, 0, 0}} );
     893                 :            : 
     894                 :    4028100 :   tk::real rho(0.0);
     895         [ +  + ]:   12084300 :   for (std::size_t k=0; k<nmat; ++k)
     896                 :    8056200 :     rho += ugp[densityIdx(nmat, k)];
     897                 :            : 
     898                 :    4028100 :   auto u = ugp[ncomp+velocityIdx(nmat,0)];
     899                 :    4028100 :   auto v = ugp[ncomp+velocityIdx(nmat,1)];
     900                 :    4028100 :   auto w = ugp[ncomp+velocityIdx(nmat,2)];
     901                 :            : 
     902 [ +  - ][ -  + ]:    4028100 :   if (inciter::haveSolid(nmat, solidx))
     903                 :            :   {
     904         [ -  - ]:          0 :     std::vector< tk::real > al(nmat, 0.0);
     905                 :          0 :     std::vector< std::array< std::array< tk::real, 3 >, 3 > > g, asig;
     906                 :            :     std::array< std::array< tk::real, 3 >, 3 >
     907                 :          0 :       sig {{ {{0, 0, 0}}, {{0, 0, 0}}, {{0, 0, 0}} }};
     908         [ -  - ]:          0 :     for (std::size_t k=0; k<nmat; ++k)
     909                 :            :     {
     910                 :          0 :       al[k] = ugp[volfracIdx(nmat, k)];
     911                 :            :       // inv deformation gradient and Cauchy stress tensors
     912 [ -  - ][ -  - ]:          0 :       g.push_back(inciter::getDeformGrad(nmat, k, ugp));
     913 [ -  - ][ -  - ]:          0 :       asig.push_back(inciter::getCauchyStress(nmat, k, ncomp, ugp));
     914         [ -  - ]:          0 :       for (std::size_t i=0; i<3; ++i) asig[k][i][i] -= ugp[ncomp+pressureIdx(nmat,k)];
     915                 :            : 
     916         [ -  - ]:          0 :       for (size_t i=0; i<3; ++i)
     917         [ -  - ]:          0 :         for (size_t j=0; j<3; ++j)
     918                 :          0 :           sig[i][j] += asig[k][i][j];
     919                 :            :     }
     920                 :            : 
     921                 :            :     // conservative part of momentum flux
     922                 :          0 :     fl[momentumIdx(nmat, 0)][0] = ugp[momentumIdx(nmat, 0)] * u - sig[0][0];
     923                 :          0 :     fl[momentumIdx(nmat, 1)][0] = ugp[momentumIdx(nmat, 1)] * u - sig[0][1];
     924                 :          0 :     fl[momentumIdx(nmat, 2)][0] = ugp[momentumIdx(nmat, 2)] * u - sig[0][2];
     925                 :            : 
     926                 :          0 :     fl[momentumIdx(nmat, 0)][1] = ugp[momentumIdx(nmat, 0)] * v - sig[1][0];
     927                 :          0 :     fl[momentumIdx(nmat, 1)][1] = ugp[momentumIdx(nmat, 1)] * v - sig[1][1];
     928                 :          0 :     fl[momentumIdx(nmat, 2)][1] = ugp[momentumIdx(nmat, 2)] * v - sig[1][2];
     929                 :            : 
     930                 :          0 :     fl[momentumIdx(nmat, 0)][2] = ugp[momentumIdx(nmat, 0)] * w - sig[2][0];
     931                 :          0 :     fl[momentumIdx(nmat, 1)][2] = ugp[momentumIdx(nmat, 1)] * w - sig[2][1];
     932                 :          0 :     fl[momentumIdx(nmat, 2)][2] = ugp[momentumIdx(nmat, 2)] * w - sig[2][2];
     933                 :            : 
     934         [ -  - ]:          0 :     for (std::size_t k=0; k<nmat; ++k)
     935                 :            :     {
     936                 :            :       // conservative part of volume-fraction flux
     937                 :          0 :       fl[volfracIdx(nmat, k)][0] = 0.0;
     938                 :          0 :       fl[volfracIdx(nmat, k)][1] = 0.0;
     939                 :          0 :       fl[volfracIdx(nmat, k)][2] = 0.0;
     940                 :            : 
     941                 :            :       // conservative part of material continuity flux
     942                 :          0 :       fl[densityIdx(nmat, k)][0] = u * ugp[densityIdx(nmat, k)];
     943                 :          0 :       fl[densityIdx(nmat, k)][1] = v * ugp[densityIdx(nmat, k)];
     944                 :          0 :       fl[densityIdx(nmat, k)][2] = w * ugp[densityIdx(nmat, k)];
     945                 :            : 
     946                 :            :       // conservative part of material total-energy flux
     947                 :          0 :       fl[energyIdx(nmat, k)][0] = u * ugp[energyIdx(nmat, k)]
     948                 :          0 :         - u * asig[k][0][0] - v * asig[k][1][0] - w * asig[k][2][0];
     949                 :          0 :       fl[energyIdx(nmat, k)][1] = v * ugp[energyIdx(nmat, k)]
     950                 :          0 :         - u * asig[k][0][1] - v * asig[k][1][1] - w * asig[k][2][1];
     951                 :          0 :       fl[energyIdx(nmat, k)][2] = w * ugp[energyIdx(nmat, k)]
     952                 :          0 :         - u * asig[k][0][2] - v * asig[k][1][2] - w * asig[k][2][2];
     953                 :            : 
     954                 :            :       // conservative part of material inverse deformation gradient
     955                 :            :       // g_ij: \partial (g_il u_l) / \partial (x_j)
     956         [ -  - ]:          0 :       if (solidx[k] > 0)
     957                 :            :       {
     958         [ -  - ]:          0 :         for (std::size_t i=0; i<3; ++i)
     959                 :            :         {
     960         [ -  - ]:          0 :           for (std::size_t j=0; j<3; ++j)
     961                 :            :           {
     962                 :          0 :             fl[deformIdx(nmat,solidx[k],i,j)][j] =
     963                 :          0 :               u*g[k][i][0] + v*g[k][i][1] + w*g[k][i][2];
     964                 :            :           }
     965                 :            :           // other components are zero
     966                 :            :         }
     967                 :            :       }
     968                 :            :     }
     969                 :            :   }
     970                 :            :   else
     971                 :            :   {
     972                 :    4028100 :     tk::real p(0.0);
     973         [ +  - ]:    8056200 :     std::vector< tk::real > apk( nmat, 0.0 );
     974         [ +  + ]:   12084300 :     for (std::size_t k=0; k<nmat; ++k)
     975                 :            :     {
     976                 :    8056200 :       apk[k] = ugp[ncomp+pressureIdx(nmat,k)];
     977                 :    8056200 :       p += apk[k];
     978                 :            :     }
     979                 :            : 
     980                 :            :     // conservative part of momentum flux
     981                 :    4028100 :     fl[momentumIdx(nmat, 0)][0] = ugp[momentumIdx(nmat, 0)] * u + p;
     982                 :    4028100 :     fl[momentumIdx(nmat, 1)][0] = ugp[momentumIdx(nmat, 1)] * u;
     983                 :    4028100 :     fl[momentumIdx(nmat, 2)][0] = ugp[momentumIdx(nmat, 2)] * u;
     984                 :            : 
     985                 :    4028100 :     fl[momentumIdx(nmat, 0)][1] = ugp[momentumIdx(nmat, 0)] * v;
     986                 :    4028100 :     fl[momentumIdx(nmat, 1)][1] = ugp[momentumIdx(nmat, 1)] * v + p;
     987                 :    4028100 :     fl[momentumIdx(nmat, 2)][1] = ugp[momentumIdx(nmat, 2)] * v;
     988                 :            : 
     989                 :    4028100 :     fl[momentumIdx(nmat, 0)][2] = ugp[momentumIdx(nmat, 0)] * w;
     990                 :    4028100 :     fl[momentumIdx(nmat, 1)][2] = ugp[momentumIdx(nmat, 1)] * w;
     991                 :    4028100 :     fl[momentumIdx(nmat, 2)][2] = ugp[momentumIdx(nmat, 2)] * w + p;
     992                 :            : 
     993         [ +  + ]:   12084300 :     for (std::size_t k=0; k<nmat; ++k)
     994                 :            :     {
     995                 :            :       // conservative part of volume-fraction flux
     996                 :    8056200 :       fl[volfracIdx(nmat, k)][0] = 0.0;
     997                 :    8056200 :       fl[volfracIdx(nmat, k)][1] = 0.0;
     998                 :    8056200 :       fl[volfracIdx(nmat, k)][2] = 0.0;
     999                 :            : 
    1000                 :            :       // conservative part of material continuity flux
    1001                 :    8056200 :       fl[densityIdx(nmat, k)][0] = u * ugp[densityIdx(nmat, k)];
    1002                 :    8056200 :       fl[densityIdx(nmat, k)][1] = v * ugp[densityIdx(nmat, k)];
    1003                 :    8056200 :       fl[densityIdx(nmat, k)][2] = w * ugp[densityIdx(nmat, k)];
    1004                 :            : 
    1005                 :            :       // conservative part of material total-energy flux
    1006                 :    8056200 :       auto hmat = ugp[energyIdx(nmat, k)] + apk[k];
    1007                 :    8056200 :       fl[energyIdx(nmat, k)][0] = u * hmat;
    1008                 :    8056200 :       fl[energyIdx(nmat, k)][1] = v * hmat;
    1009                 :    8056200 :       fl[energyIdx(nmat, k)][2] = w * hmat;
    1010                 :            :     }
    1011                 :            :   }
    1012                 :            : 
    1013                 :    4028100 :   return fl;
    1014                 :            : }
    1015                 :            : 
    1016                 :            : }// tk::

Generated by: LCOV version 1.14