Quinoa all test code coverage report
Current view: top level - PDE/MultiMat - MiscMultiMatFns.cpp (source / functions) Hit Total Coverage
Commit: -128-NOTFOUND Lines: 215 298 72.1 %
Date: 2025-10-02 14:31:17 Functions: 8 11 72.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 152 320 47.5 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/PDE/MultiMat/MiscMultiMatFns.hpp
       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     Misc multi-material system functions
       9                 :            :   \details   This file defines functions that required for multi-material
      10                 :            :     compressible hydrodynamics.
      11                 :            : */
      12                 :            : // *****************************************************************************
      13                 :            : 
      14                 :            : #include <iostream>
      15                 :            : 
      16                 :            : #include "MiscMultiMatFns.hpp"
      17                 :            : #include "Inciter/InputDeck/InputDeck.hpp"
      18                 :            : #include "Integrate/Basis.hpp"
      19                 :            : #include "MultiMat/MultiMatIndexing.hpp"
      20                 :            : #include "EoS/GetMatProp.hpp"
      21                 :            : 
      22                 :            : namespace inciter {
      23                 :            : 
      24                 :            : extern ctr::InputDeck g_inputdeck;
      25                 :            : 
      26                 :        237 : void initializeMaterialEoS( std::vector< EOS >& mat_blk )
      27                 :            : // *****************************************************************************
      28                 :            : //  Initialize the material block with configured EOS
      29                 :            : //! \param[in,out] mat_blk Material block that gets initialized
      30                 :            : // *****************************************************************************
      31                 :            : {
      32                 :            :   // EoS initialization
      33                 :            :   // ---------------------------------------------------------------------------
      34                 :        237 :   auto nmat = g_inputdeck.get< tag::multimat, tag::nmat >();
      35                 :        237 :   const auto& matprop = g_inputdeck.get< tag::material >();
      36                 :        237 :   const auto& matidxmap = g_inputdeck.get< tag::matidxmap >();
      37         [ +  + ]:        862 :   for (std::size_t k=0; k<nmat; ++k) {
      38                 :        625 :     auto mateos = matprop[matidxmap.get< tag::eosidx >()[k]].get<tag::eos>();
      39         [ +  - ]:        625 :     mat_blk.emplace_back(mateos, EqType::multimat, k);
      40                 :            :   }
      41                 :            : 
      42                 :            :   // set rho0 for all materials
      43                 :            :   // ---------------------------------------------------------------------------
      44         [ +  - ]:        474 :   std::vector< tk::real > rho0mat( nmat, 0.0 );
      45                 :        237 :   const auto& ic = g_inputdeck.get< tag::ic >();
      46                 :        237 :   const auto& icbox = ic.get< tag::box >();
      47                 :        237 :   const auto& icmbk = ic.get< tag::meshblock >();
      48                 :            :   // Get background properties
      49                 :        237 :   std::size_t k = ic.get< tag::materialid >() - 1;
      50                 :        237 :   tk::real pr = ic.get< tag::pressure >();
      51                 :        237 :   tk::real tmp = ic.get< tag::temperature >();
      52         [ +  - ]:        237 :   rho0mat[k] = mat_blk[k].compute< EOS::density >(pr, tmp);
      53                 :            : 
      54                 :            :   // Check inside used defined box
      55         [ +  + ]:        237 :   if (!icbox.empty())
      56                 :            :   {
      57         [ +  + ]:         86 :     for (const auto& b : icbox) {   // for all boxes
      58                 :         43 :       k = b.get< tag::materialid >() - 1;
      59                 :         43 :       auto boxmas = b.get< tag::mass >();
      60                 :            :       // if mass and volume are given, compute density as mass/volume
      61         [ -  + ]:         43 :       if (boxmas > 0.0) {
      62                 :            :         std::vector< tk::real > box
      63                 :          0 :           { b.get< tag::xmin >(), b.get< tag::xmax >(),
      64                 :          0 :             b.get< tag::ymin >(), b.get< tag::ymax >(),
      65         [ -  - ]:          0 :             b.get< tag::zmin >(), b.get< tag::zmax >() };
      66                 :          0 :         auto V_ex = (box[1]-box[0]) * (box[3]-box[2]) * (box[5]-box[4]);
      67                 :          0 :         rho0mat[k] = boxmas / V_ex;
      68                 :            :       }
      69                 :            :       // else compute density from eos
      70                 :            :       else {
      71                 :         43 :         pr = b.get< tag::pressure >();
      72                 :         43 :         tmp = b.get< tag::temperature >();
      73         [ +  - ]:         43 :         rho0mat[k] = mat_blk[k].compute< EOS::density >(pr, tmp);
      74                 :            :       }
      75                 :            :     }
      76                 :            :   }
      77                 :            : 
      78                 :            :   // Check inside user-specified mesh blocks
      79         [ -  + ]:        237 :   if (!icmbk.empty())
      80                 :            :   {
      81         [ -  - ]:          0 :     for (const auto& b : icmbk) { // for all blocks
      82                 :          0 :       k = b.get< tag::materialid >() - 1;
      83                 :          0 :       auto boxmas = b.get< tag::mass >();
      84                 :            :       // if mass and volume are given, compute density as mass/volume
      85         [ -  - ]:          0 :       if (boxmas > 0.0) {
      86                 :          0 :         auto V_ex = b.get< tag::volume >();
      87                 :          0 :         rho0mat[k] = boxmas / V_ex;
      88                 :            :       }
      89                 :            :       // else compute density from eos
      90                 :            :       else {
      91                 :          0 :         pr = b.get< tag::pressure >();
      92                 :          0 :         tmp = b.get< tag::temperature >();
      93         [ -  - ]:          0 :         rho0mat[k] = mat_blk[k].compute< EOS::density >(pr, tmp);
      94                 :            :       }
      95                 :            :     }
      96                 :            :   }
      97                 :            : 
      98                 :            :   // Store computed rho0's in the EOS-block
      99         [ +  + ]:        862 :   for (std::size_t i=0; i<nmat; ++i) {
     100         [ +  - ]:        625 :     mat_blk[i].set< EOS::setRho0 >(rho0mat[i]);
     101                 :            :   }
     102                 :        237 : }
     103                 :            : 
     104                 :            : bool
     105                 :       8073 : cleanTraceMultiMat(
     106                 :            :   tk::real t,
     107                 :            :   std::size_t nelem,
     108                 :            :   const std::vector< EOS >& mat_blk,
     109                 :            :   const tk::Fields& geoElem,
     110                 :            :   std::size_t nmat,
     111                 :            :   tk::Fields& U,
     112                 :            :   tk::Fields& P )
     113                 :            : // *****************************************************************************
     114                 :            : //  Clean up the state of trace materials for multi-material PDE system
     115                 :            : //! \param[in] t Physical time
     116                 :            : //! \param[in] nelem Number of elements
     117                 :            : //! \param[in] mat_blk EOS material block
     118                 :            : //! \param[in] geoElem Element geometry array
     119                 :            : //! \param[in] nmat Number of materials in this PDE system
     120                 :            : //! \param[in/out] U High-order solution vector which gets modified
     121                 :            : //! \param[in/out] P High-order vector of primitives which gets modified
     122                 :            : //! \return Boolean indicating if an unphysical material state was found
     123                 :            : // *****************************************************************************
     124                 :            : {
     125                 :       8073 :   const auto ndof = g_inputdeck.get< tag::ndof >();
     126                 :       8073 :   const auto rdof = g_inputdeck.get< tag::rdof >();
     127                 :       8073 :   const auto& solidx = g_inputdeck.get< tag::matidxmap, tag::solidx >();
     128                 :       8073 :   std::size_t ncomp = U.nprop()/rdof;
     129                 :       8073 :   auto neg_density = false;
     130                 :            : 
     131         [ +  - ]:       8073 :   std::vector< tk::real > ugp(ncomp, 0.0);
     132                 :            : 
     133         [ +  + ]:    2770553 :   for (std::size_t e=0; e<nelem; ++e)
     134                 :            :   {
     135                 :            :     // find material in largest quantity.
     136                 :    2762480 :     auto almax(0.0);
     137                 :    2762480 :     std::size_t kmax = 0;
     138         [ +  + ]:    9432900 :     for (std::size_t k=0; k<nmat; ++k)
     139                 :            :     {
     140         [ +  - ]:    6670420 :       auto al = U(e, volfracDofIdx(nmat, k, rdof, 0));
     141         [ +  + ]:    6670420 :       if (al > almax)
     142                 :            :       {
     143                 :    4261454 :         almax = al;
     144                 :    4261454 :         kmax = k;
     145                 :            :       }
     146                 :            :     }
     147                 :            : 
     148                 :            :     // get conserved quantities
     149         [ +  - ]:    5524960 :     std::vector< tk::real > B(rdof, 0.0);
     150                 :    2762480 :     B[0] = 1.0;
     151         [ +  - ]:    2762480 :     ugp = eval_state(ncomp, rdof, ndof, e, U, B);
     152                 :            : 
     153         [ +  - ]:    2762480 :     auto u = P(e, velocityDofIdx(nmat, 0, rdof, 0));
     154         [ +  - ]:    2762480 :     auto v = P(e, velocityDofIdx(nmat, 1, rdof, 0));
     155         [ +  - ]:    2762480 :     auto w = P(e, velocityDofIdx(nmat, 2, rdof, 0));
     156         [ +  - ]:    2762480 :     auto pmax = P(e, pressureDofIdx(nmat, kmax, rdof, 0))/almax;
     157         [ +  - ]:    2762480 :     auto gmax = getDeformGrad(nmat, kmax, ugp);
     158                 :    2762480 :     auto tmax = mat_blk[kmax].compute< EOS::temperature >(
     159 [ +  - ][ +  - ]:    2762480 :       U(e, densityDofIdx(nmat, kmax, rdof, 0)), u, v, w,
     160         [ +  - ]:    2762480 :       U(e, energyDofIdx(nmat, kmax, rdof, 0)), almax, gmax );
     161                 :            : 
     162                 :    2762480 :     tk::real p_target(0.0), d_al(0.0), d_arE(0.0);
     163                 :            :     //// get equilibrium pressure
     164                 :            :     //std::vector< tk::real > kmat(nmat, 0.0);
     165                 :            :     //tk::real ratio(0.0);
     166                 :            :     //for (std::size_t k=0; k<nmat; ++k)
     167                 :            :     //{
     168                 :            :     //  auto arhok = U(e, densityDofIdx(nmat,k,rdof,0));
     169                 :            :     //  auto alk = U(e, volfracDofIdx(nmat,k,rdof,0));
     170                 :            :     //  auto apk = P(e, pressureDofIdx(nmat,k,rdof,0)3);
     171                 :            :     //  auto ak = mat_blk[k].compute< EOS::soundspeed >(arhok, apk, alk, k);
     172                 :            :     //  kmat[k] = arhok * ak * ak;
     173                 :            : 
     174                 :            :     //  p_target += alk * apk / kmat[k];
     175                 :            :     //  ratio += alk * alk / kmat[k];
     176                 :            :     //}
     177                 :            :     //p_target /= ratio;
     178                 :            :     //p_target = std::max(p_target, 1e-14);
     179                 :    2762480 :     p_target = std::max(pmax, 1e-14);
     180                 :            : 
     181                 :            :     // 1. Correct minority materials and store volume/energy changes
     182         [ +  + ]:    9432900 :     for (std::size_t k=0; k<nmat; ++k)
     183                 :            :     {
     184                 :    6670420 :       bool ctm_element(false);
     185         [ +  - ]:    6670420 :       auto alk = U(e, volfracDofIdx(nmat, k, rdof, 0));
     186         [ +  - ]:    6670420 :       auto pk = P(e, pressureDofIdx(nmat, k, rdof, 0)) / alk;
     187                 :            : 
     188                 :            :       // Determine if element-e needs trace-material cleanup. This decision is
     189                 :            :       // based on specific scenarios.
     190                 :            :       // WARNING: Changing this decision-making logic can adversely affect
     191                 :            :       // code stability.
     192                 :    6670420 :       if (
     193                 :            :         // 1. if volume fraction is lesser than threshold
     194         [ +  + ]:    9484966 :         (alk < volfracPRelaxLim()) ||
     195                 :            :         // 2. if current and majority material is fluid, AND the material
     196                 :            :         //    (effective) pressure is negative
     197 [ +  - ][ +  - ]:    2814546 :         (solidx[k] == 0 && solidx[kmax] == 0 && matExists(alk) &&
                 [ +  - ]
     198 [ -  + ][ +  + ]:   12299512 :         pk < mat_blk[k].compute< EOS::min_eff_pressure >(1e-12,
     199 [ +  - ][ +  - ]:    2814546 :         U(e, densityDofIdx(nmat, k, rdof, 0)), alk))
     200                 :            :       )
     201                 :    3855874 :         ctm_element = true;
     202                 :            : 
     203         [ +  + ]:    6670420 :       if (ctm_element) {
     204                 :    3855874 :         tk::real prelax(0.0);
     205         [ -  + ]:    3855874 :         if (solidx[k] > 0) {
     206                 :            :           // for solids, reset deformation gradient and stress
     207         [ -  - ]:          0 :           resetSolidTensors(nmat, k, e, U, P);
     208                 :            :         }
     209                 :            :         // determine target relaxation pressure
     210                 :    3855874 :         prelax = mat_blk[k].compute< EOS::min_eff_pressure >(1e-10,
     211 [ +  - ][ +  - ]:    3855874 :           U(e, densityDofIdx(nmat, k, rdof, 0)), alk);
     212                 :    3855874 :         prelax = std::max(prelax, p_target);
     213                 :            : 
     214                 :            :         // energy change
     215         [ +  - ]:    3855874 :         auto arhomat = U(e, densityDofIdx(nmat, k, rdof, 0));
     216         [ +  - ]:    3855874 :         auto gmat = getDeformGrad(nmat, k, ugp);
     217                 :    3855874 :         auto arhoEmat = mat_blk[k].compute< EOS::totalenergy >(arhomat, u, v, w,
     218         [ +  - ]:    3855874 :           alk*prelax, alk, gmat);
     219                 :            : 
     220                 :            :         // total energy flux into majority material
     221         [ +  - ]:    3855874 :         d_arE += (U(e, energyDofIdx(nmat, k, rdof, 0))
     222                 :    3855874 :           - arhoEmat);
     223                 :            : 
     224                 :            :         // update state of trace material
     225         [ +  - ]:    3855874 :         U(e, volfracDofIdx(nmat, k, rdof, 0)) = alk;
     226         [ +  - ]:    3855874 :         U(e, energyDofIdx(nmat, k, rdof, 0)) = arhoEmat;
     227         [ +  - ]:    3855874 :         P(e, pressureDofIdx(nmat, k, rdof, 0)) = alk*prelax;
     228                 :            : 
     229         [ +  + ]:    7255330 :         for (std::size_t i=1; i<rdof; ++i) {
     230         [ +  - ]:    3399456 :           U(e, energyDofIdx(nmat, k, rdof, i)) = 0.0;
     231                 :            :         }
     232                 :            :       }
     233                 :            :     }
     234                 :            : 
     235         [ +  - ]:    2762480 :     U(e, volfracDofIdx(nmat, kmax, rdof, 0)) += d_al;
     236                 :            : 
     237                 :            :     // 2. Flux energy change into majority material
     238         [ +  - ]:    2762480 :     U(e, energyDofIdx(nmat, kmax, rdof, 0)) += d_arE;
     239         [ +  - ]:    2762480 :     P(e, pressureDofIdx(nmat, kmax, rdof, 0)) =
     240                 :    5524960 :       mat_blk[kmax].compute< EOS::pressure >(
     241 [ +  - ][ +  - ]:    2762480 :       U(e, densityDofIdx(nmat, kmax, rdof, 0)), u, v, w,
     242         [ +  - ]:    2762480 :       U(e, energyDofIdx(nmat, kmax, rdof, 0)),
     243         [ +  - ]:    2762480 :       U(e, volfracDofIdx(nmat, kmax, rdof, 0)), kmax, gmax );
     244                 :            : 
     245                 :            :     // 3. enforce unit sum of volume fractions
     246                 :    2762480 :     auto alsum = 0.0;
     247         [ +  + ]:    9432900 :     for (std::size_t k=0; k<nmat; ++k)
     248         [ +  - ]:    6670420 :       alsum += U(e, volfracDofIdx(nmat, k, rdof, 0));
     249                 :            : 
     250         [ +  + ]:    9432900 :     for (std::size_t k=0; k<nmat; ++k) {
     251         [ +  - ]:    6670420 :       U(e, volfracDofIdx(nmat, k, rdof, 0)) /= alsum;
     252         [ +  - ]:    6670420 :       U(e, densityDofIdx(nmat, k, rdof, 0)) /= alsum;
     253         [ +  - ]:    6670420 :       U(e, energyDofIdx(nmat, k, rdof, 0)) /= alsum;
     254         [ +  - ]:    6670420 :       P(e, pressureDofIdx(nmat, k, rdof, 0)) /= alsum;
     255         [ -  + ]:    6670420 :       if (solidx[k] > 0) {
     256         [ -  - ]:          0 :         for (std::size_t i=0; i<6; ++i)
     257         [ -  - ]:          0 :           P(e, stressDofIdx(nmat, solidx[k], i, rdof, 0)) /= alsum;
     258                 :            :       }
     259                 :            :     }
     260                 :            : 
     261         [ +  - ]:    2762480 :     pmax = P(e, pressureDofIdx(nmat, kmax, rdof, 0)) /
     262         [ +  - ]:    2762480 :       U(e, volfracDofIdx(nmat, kmax, rdof, 0));
     263                 :            : 
     264                 :            :     // check for unphysical state
     265         [ +  + ]:    9432900 :     for (std::size_t k=0; k<nmat; ++k)
     266                 :            :     {
     267         [ +  - ]:    6670420 :       auto alpha = U(e, volfracDofIdx(nmat, k, rdof, 0));
     268         [ +  - ]:    6670420 :       auto arho = U(e, densityDofIdx(nmat, k, rdof, 0));
     269         [ +  - ]:    6670420 :       auto apr = P(e, pressureDofIdx(nmat, k, rdof, 0));
     270                 :            : 
     271                 :            :       // lambda for screen outputs
     272                 :          0 :       auto screenout = [&]()
     273                 :            :       {
     274                 :          0 :         std::cout << "Physical time:     " << t << std::endl;
     275                 :          0 :         std::cout << "Element centroid:  " << geoElem(e,1) << ", "
     276                 :          0 :           << geoElem(e,2) << ", " << geoElem(e,3) << std::endl;
     277                 :          0 :         std::cout << "Material-id:       " << k << std::endl;
     278                 :          0 :         std::cout << "Volume-fraction:   " << alpha << std::endl;
     279                 :          0 :         std::cout << "Partial density:   " << arho << std::endl;
     280                 :          0 :         std::cout << "Partial pressure:  " << apr << std::endl;
     281                 :          0 :         std::cout << "Major pressure:    " << pmax << " (mat " << kmax << ")"
     282                 :          0 :           << std::endl;
     283                 :          0 :         std::cout << "Major temperature: " << tmax << " (mat " << kmax << ")"
     284                 :          0 :           << std::endl;
     285                 :          0 :         std::cout << "Velocity:          " << u << ", " << v << ", " << w
     286                 :          0 :           << std::endl;
     287                 :    6670420 :       };
     288                 :            : 
     289         [ -  + ]:    6670420 :       if (arho < 0.0)
     290                 :            :       {
     291                 :          0 :         neg_density = true;
     292         [ -  - ]:          0 :         screenout();
     293                 :            :       }
     294                 :            :     }
     295                 :            :   }
     296                 :      16146 :   return neg_density;
     297                 :            : }
     298                 :            : 
     299                 :            : tk::real
     300                 :        760 : timeStepSizeMultiMat(
     301                 :            :   const std::vector< EOS >& mat_blk,
     302                 :            :   const std::vector< int >& esuf,
     303                 :            :   const tk::Fields& geoFace,
     304                 :            :   const tk::Fields& geoElem,
     305                 :            :   const std::size_t nelem,
     306                 :            :   std::size_t nmat,
     307                 :            :   const tk::Fields& U,
     308                 :            :   const tk::Fields& P )
     309                 :            : // *****************************************************************************
     310                 :            : //  Time step restriction for multi material cell-centered schemes
     311                 :            : //! \param[in] mat_blk EOS material block
     312                 :            : //! \param[in] esuf Elements surrounding elements array
     313                 :            : //! \param[in] geoFace Face geometry array
     314                 :            : //! \param[in] geoElem Element geometry array
     315                 :            : //! \param[in] nelem Number of elements
     316                 :            : //! \param[in] nmat Number of materials in this PDE system
     317                 :            : //! \param[in] U High-order solution vector
     318                 :            : //! \param[in] P High-order vector of primitives
     319                 :            : //! \return Maximum allowable time step based on cfl criterion
     320                 :            : // *****************************************************************************
     321                 :            : {
     322                 :        760 :   const auto ndof = g_inputdeck.get< tag::ndof >();
     323                 :        760 :   const auto rdof = g_inputdeck.get< tag::rdof >();
     324                 :        760 :   std::size_t ncomp = U.nprop()/rdof;
     325                 :        760 :   std::size_t nprim = P.nprop()/rdof;
     326                 :            : 
     327                 :            :   tk::real u, v, w, a, vn, dSV_l, dSV_r;
     328         [ +  - ]:       1520 :   std::vector< tk::real > delt(U.nunk(), 0.0);
     329 [ +  - ][ +  - ]:       1520 :   std::vector< tk::real > ugp(ncomp, 0.0), pgp(nprim, 0.0);
     330                 :            : 
     331                 :            :   // compute maximum characteristic speed at all internal element faces
     332         [ +  + ]:     674860 :   for (std::size_t f=0; f<esuf.size()/2; ++f)
     333                 :            :   {
     334                 :     674100 :     std::size_t el = static_cast< std::size_t >(esuf[2*f]);
     335                 :     674100 :     auto er = esuf[2*f+1];
     336                 :            : 
     337                 :            :     std::array< tk::real, 3 > fn;
     338         [ +  - ]:     674100 :     fn[0] = geoFace(f,1);
     339         [ +  - ]:     674100 :     fn[1] = geoFace(f,2);
     340         [ +  - ]:     674100 :     fn[2] = geoFace(f,3);
     341                 :            : 
     342                 :            :     // left element
     343                 :            : 
     344                 :            :     // Compute the basis function for the left element
     345         [ +  - ]:     674100 :     std::vector< tk::real > B_l(rdof, 0.0);
     346                 :     674100 :     B_l[0] = 1.0;
     347                 :            : 
     348                 :            :     // get conserved quantities
     349         [ +  - ]:     674100 :     ugp = eval_state(ncomp, rdof, ndof, el, U, B_l);
     350                 :            :     // get primitive quantities
     351         [ +  - ]:     674100 :     pgp = eval_state(nprim, rdof, ndof, el, P, B_l);
     352                 :            : 
     353                 :            :     // advection velocity
     354                 :     674100 :     u = pgp[velocityIdx(nmat, 0)];
     355                 :     674100 :     v = pgp[velocityIdx(nmat, 1)];
     356                 :     674100 :     w = pgp[velocityIdx(nmat, 2)];
     357                 :            : 
     358 [ +  - ][ +  - ]:     674100 :     vn = u*geoFace(f,1) + v*geoFace(f,2) + w*geoFace(f,3);
                 [ +  - ]
     359                 :            : 
     360                 :            :     // acoustic speed
     361                 :     674100 :     a = 0.0;
     362         [ +  + ]:    2022300 :     for (std::size_t k=0; k<nmat; ++k)
     363                 :            :     {
     364         [ +  + ]:    1348200 :       if (ugp[volfracIdx(nmat, k)] > 1.0e-04) {
     365         [ +  - ]:     708665 :         auto gk = getDeformGrad(nmat, k, ugp);
     366         [ +  - ]:     708665 :         gk = tk::rotateTensor(gk, fn);
     367         [ +  - ]:    2125995 :         a = std::max( a, mat_blk[k].compute< EOS::soundspeed >(
     368                 :     708665 :           ugp[densityIdx(nmat, k)],
     369                 :    1417330 :           pgp[pressureIdx(nmat, k)], ugp[volfracIdx(nmat, k)], k, gk ) );
     370                 :            :       }
     371                 :            :     }
     372                 :            : 
     373         [ +  - ]:     674100 :     dSV_l = geoFace(f,0) * (std::fabs(vn) + a);
     374                 :            : 
     375                 :            :     // right element
     376         [ +  + ]:     674100 :     if (er > -1) {
     377                 :     521540 :       std::size_t eR = static_cast< std::size_t >( er );
     378                 :            : 
     379                 :            :       // Compute the basis function for the right element
     380         [ +  - ]:     521540 :       std::vector< tk::real > B_r(rdof, 0.0);
     381                 :     521540 :       B_r[0] = 1.0;
     382                 :            : 
     383                 :            :       // get conserved quantities
     384         [ +  - ]:     521540 :       ugp = eval_state( ncomp, rdof, ndof, eR, U, B_r);
     385                 :            :       // get primitive quantities
     386         [ +  - ]:     521540 :       pgp = eval_state( nprim, rdof, ndof, eR, P, B_r);
     387                 :            : 
     388                 :            :       // advection velocity
     389                 :     521540 :       u = pgp[velocityIdx(nmat, 0)];
     390                 :     521540 :       v = pgp[velocityIdx(nmat, 1)];
     391                 :     521540 :       w = pgp[velocityIdx(nmat, 2)];
     392                 :            : 
     393 [ +  - ][ +  - ]:     521540 :       vn = u*geoFace(f,1) + v*geoFace(f,2) + w*geoFace(f,3);
                 [ +  - ]
     394                 :            : 
     395                 :            :       // acoustic speed
     396                 :     521540 :       a = 0.0;
     397         [ +  + ]:    1564620 :       for (std::size_t k=0; k<nmat; ++k)
     398                 :            :       {
     399         [ +  + ]:    1043080 :         if (ugp[volfracIdx(nmat, k)] > 1.0e-04) {
     400         [ +  - ]:     549014 :           auto gk = getDeformGrad(nmat, k, ugp);
     401         [ +  - ]:     549014 :           gk = tk::rotateTensor(gk, fn);
     402         [ +  - ]:    1647042 :           a = std::max( a, mat_blk[k].compute< EOS::soundspeed >(
     403                 :     549014 :             ugp[densityIdx(nmat, k)],
     404                 :    1098028 :             pgp[pressureIdx(nmat, k)], ugp[volfracIdx(nmat, k)], k, gk ) );
     405                 :            :         }
     406                 :            :       }
     407                 :            : 
     408         [ +  - ]:     521540 :       dSV_r = geoFace(f,0) * (std::fabs(vn) + a);
     409                 :            : 
     410                 :     521540 :       delt[eR] += std::max( dSV_l, dSV_r );
     411                 :            :     } else {
     412                 :     152560 :       dSV_r = dSV_l;
     413                 :            :     }
     414                 :            : 
     415                 :     674100 :     delt[el] += std::max( dSV_l, dSV_r );
     416                 :            :   }
     417                 :            : 
     418                 :        760 :   tk::real mindt = std::numeric_limits< tk::real >::max();
     419                 :            : 
     420                 :            :   // compute allowable dt
     421         [ +  + ]:     279520 :   for (std::size_t e=0; e<nelem; ++e)
     422                 :            :   {
     423         [ +  - ]:     278760 :     mindt = std::min( mindt, geoElem(e,0)/delt[e] );
     424                 :            :   }
     425                 :            : 
     426                 :       1520 :   return mindt;
     427                 :            : }
     428                 :            : 
     429                 :            : tk::real
     430                 :        100 : timeStepSizeMultiMatFV(
     431                 :            :   const std::vector< EOS >& mat_blk,
     432                 :            :   const tk::Fields& geoElem,
     433                 :            :   std::size_t nelem,
     434                 :            :   std::size_t nmat,
     435                 :            :   const tk::Fields& U,
     436                 :            :   const tk::Fields& P,
     437                 :            :   std::vector< tk::real >& local_dte )
     438                 :            : // *****************************************************************************
     439                 :            : //  Time step restriction for multi material cell-centered FV scheme
     440                 :            : //! \param[in] mat_blk Material EOS block
     441                 :            : //! \param[in] geoElem Element geometry array
     442                 :            : //! \param[in] nelem Number of elements
     443                 :            : //! \param[in] nmat Number of materials in this PDE system
     444                 :            : //! \param[in] U High-order solution vector
     445                 :            : //! \param[in] P High-order vector of primitives
     446                 :            : //! \param[in,out] local_dte Time step size for each element (for local
     447                 :            : //!   time stepping)
     448                 :            : //! \return Maximum allowable time step based on cfl criterion
     449                 :            : // *****************************************************************************
     450                 :            : {
     451                 :        100 :   const auto ndof = g_inputdeck.get< tag::ndof >();
     452                 :        100 :   const auto rdof = g_inputdeck.get< tag::rdof >();
     453                 :            :   const auto use_mass_avg =
     454                 :        100 :     g_inputdeck.get< tag::multimat, tag::dt_sos_massavg >();
     455                 :        100 :   std::size_t ncomp = U.nprop()/rdof;
     456                 :        100 :   std::size_t nprim = P.nprop()/rdof;
     457                 :            : 
     458 [ +  - ][ +  - ]:        200 :   std::vector< tk::real > ugp(ncomp, 0.0), pgp(nprim, 0.0);
     459                 :        100 :   tk::real mindt = std::numeric_limits< tk::real >::max();
     460                 :            : 
     461                 :            :   // loop over all elements
     462         [ +  + ]:     106220 :   for (std::size_t e=0; e<nelem; ++e)
     463                 :            :   {
     464                 :            :     // basis function at centroid
     465         [ +  - ]:     106120 :     std::vector< tk::real > B(rdof, 0.0);
     466                 :     106120 :     B[0] = 1.0;
     467                 :            : 
     468                 :            :     // get conserved quantities
     469         [ +  - ]:     106120 :     ugp = eval_state(ncomp, rdof, ndof, e, U, B);
     470                 :            :     // get primitive quantities
     471         [ +  - ]:     106120 :     pgp = eval_state(nprim, rdof, ndof, e, P, B);
     472                 :            : 
     473                 :            :     // magnitude of advection velocity
     474                 :     106120 :     auto u = pgp[velocityIdx(nmat, 0)];
     475                 :     106120 :     auto v = pgp[velocityIdx(nmat, 1)];
     476                 :     106120 :     auto w = pgp[velocityIdx(nmat, 2)];
     477                 :     106120 :     auto vmag = std::sqrt(tk::dot({u, v, w}, {u, v, w}));
     478                 :            : 
     479                 :            :     // acoustic speed
     480                 :     106120 :     tk::real a = 0.0;
     481                 :     106120 :     tk::real mixtureDensity = 0.0;
     482         [ +  + ]:     318360 :     for (std::size_t k=0; k<nmat; ++k)
     483                 :            :     {
     484         [ -  + ]:     212240 :       if (use_mass_avg > 0)
     485                 :            :       {
     486                 :            :         // mass averaging SoS
     487         [ -  - ]:          0 :         a += ugp[densityIdx(nmat,k)]*mat_blk[k].compute< EOS::soundspeed >(
     488                 :          0 :           ugp[densityIdx(nmat, k)], pgp[pressureIdx(nmat, k)],
     489                 :          0 :           ugp[volfracIdx(nmat, k)], k );
     490                 :            : 
     491                 :          0 :         mixtureDensity += ugp[densityIdx(nmat,k)];
     492                 :            :       }
     493                 :            :       else
     494                 :            :       {
     495         [ +  + ]:     212240 :         if (ugp[volfracIdx(nmat, k)] > 1.0e-04)
     496                 :            :         {
     497         [ +  - ]:     324165 :           a = std::max( a, mat_blk[k].compute< EOS::soundspeed >(
     498                 :     108055 :             ugp[densityIdx(nmat, k)], pgp[pressureIdx(nmat, k)],
     499                 :     216110 :             ugp[volfracIdx(nmat, k)], k ) );
     500                 :            :         }
     501                 :            :       }
     502                 :            :     }
     503         [ -  + ]:     106120 :     if (use_mass_avg > 0) a /= mixtureDensity;
     504                 :            : 
     505                 :            :     // characteristic wave speed
     506                 :     106120 :     auto v_char = vmag + a;
     507                 :            : 
     508                 :            :     // characteristic length (radius of insphere)
     509 [ +  - ][ +  - ]:     106120 :     auto dx = std::min(std::cbrt(geoElem(e,0)), geoElem(e,4))
     510                 :     106120 :       /std::sqrt(24.0);
     511                 :            : 
     512                 :            :     // element dt
     513                 :     106120 :     local_dte[e] = dx/v_char;
     514                 :     106120 :     mindt = std::min(mindt, local_dte[e]);
     515                 :            :   }
     516                 :            : 
     517                 :        200 :   return mindt;
     518                 :            : }
     519                 :            : 
     520                 :            : tk::real
     521                 :          0 : timeStepSizeViscousFV(
     522                 :            :   const tk::Fields& geoElem,
     523                 :            :   std::size_t nelem,
     524                 :            :   std::size_t nmat,
     525                 :            :   const tk::Fields& U )
     526                 :            : // *****************************************************************************
     527                 :            : //  Compute the time step size restriction based on this physics
     528                 :            : //! \param[in] geoElem Element geometry array
     529                 :            : //! \param[in] nelem Number of elements
     530                 :            : //! \param[in] nmat Number of materials
     531                 :            : //! \param[in] U Solution vector
     532                 :            : //! \return Maximum allowable time step based on viscosity
     533                 :            : // *****************************************************************************
     534                 :            : {
     535                 :          0 :   const auto& ndof = g_inputdeck.get< tag::ndof >();
     536                 :          0 :   const auto& rdof = g_inputdeck.get< tag::rdof >();
     537                 :          0 :   std::size_t ncomp = U.nprop()/rdof;
     538                 :            : 
     539                 :          0 :   auto mindt = std::numeric_limits< tk::real >::max();
     540                 :            : 
     541         [ -  - ]:          0 :   for (std::size_t e=0; e<nelem; ++e)
     542                 :            :   {
     543                 :            :     // get conserved quantities at centroid
     544         [ -  - ]:          0 :     std::vector< tk::real > B(rdof, 0.0);
     545                 :          0 :     B[0] = 1.0;
     546         [ -  - ]:          0 :     auto ugp = eval_state(ncomp, rdof, ndof, e, U, B);
     547                 :            : 
     548                 :            :     // Kinematic viscosity
     549                 :          0 :     tk::real nu(0.0);
     550         [ -  - ]:          0 :     for (std::size_t k=0; k<nmat; ++k)
     551                 :            :     {
     552                 :          0 :       auto alk = ugp[volfracIdx(nmat, k)];
     553         [ -  - ]:          0 :       auto mu = getmatprop< tag::mu >(k);
     554         [ -  - ]:          0 :       if (alk > 1.0e-04) nu = std::max(nu, alk*mu/ugp[densityIdx(nmat,k)]);
     555                 :            :     }
     556                 :            : 
     557                 :            :     // characteristic length (radius of insphere)
     558 [ -  - ][ -  - ]:          0 :     auto dx = std::min(std::cbrt(geoElem(e,0)), geoElem(e,4))
     559                 :          0 :       /std::sqrt(24.0);
     560                 :            : 
     561                 :            :     // element dt
     562                 :          0 :     mindt = std::min(mindt, dx*dx/nu);
     563                 :            :   }
     564                 :            : 
     565                 :          0 :   return mindt;
     566                 :            : }
     567                 :            : 
     568                 :            : void
     569                 :          0 : resetSolidTensors(
     570                 :            :   std::size_t nmat,
     571                 :            :   std::size_t k,
     572                 :            :   std::size_t e,
     573                 :            :   tk::Fields& U,
     574                 :            :   tk::Fields& P )
     575                 :            : // *****************************************************************************
     576                 :            : //  Reset the solid tensors
     577                 :            : //! \param[in] nmat Number of materials in this PDE system
     578                 :            : //! \param[in] k Material id whose deformation gradient is required
     579                 :            : //! \param[in] e Id of element whose solution is to be limited
     580                 :            : //! \param[in/out] U High-order solution vector which gets modified
     581                 :            : //! \param[in/out] P High-order vector of primitives which gets modified
     582                 :            : // *****************************************************************************
     583                 :            : {
     584                 :          0 :   const auto& solidx = g_inputdeck.get< tag::matidxmap, tag::solidx >();
     585                 :          0 :   const auto rdof = g_inputdeck.get< tag::rdof >();
     586                 :            : 
     587         [ -  - ]:          0 :   if (solidx[k] == 0) return; // fluid: nothing to reset here
     588                 :            : 
     589                 :            :   // Load g and symmetrize once to reduce roundoff
     590                 :          0 :   std::array<std::array<tk::real,3>,3> g{};
     591         [ -  - ]:          0 :   for (size_t i=0;i<3;++i)
     592         [ -  - ]:          0 :     for (size_t j=0;j<3;++j)
     593         [ -  - ]:          0 :       g[i][j] = U(e, deformDofIdx(nmat, solidx[k], i, j, rdof, 0));
     594                 :            :   // symmetric part
     595         [ -  - ]:          0 :   for (size_t i=0;i<3;++i)
     596         [ -  - ]:          0 :     for (size_t j=i+1;j<3;++j) {
     597                 :          0 :       tk::real sij = 0.5*(g[i][j] + g[j][i]);
     598                 :          0 :       g[i][j] = g[j][i] = sij;
     599                 :            :     }
     600                 :            : 
     601                 :            :   // Robust determinant and spherical replacement
     602                 :            :   // Clamp to avoid NaNs; eps should be small but > 0
     603                 :          0 :   auto detg = std::max(1e-18, tk::determinant(g));
     604                 :          0 :   const tk::real new_gii = std::pow(detg, 1.0/3.0); // = J^{-1/3} > 0
     605                 :            : 
     606                 :            :   // Set g and zero elastic (deviatoric) Cauchy stress DOFs ONLY (not pressure)
     607         [ -  - ]:          0 :   for (size_t i=0;i<3;++i)
     608         [ -  - ]:          0 :     for (size_t j=0;j<3;++j) {
     609 [ -  - ][ -  - ]:          0 :       U(e, deformDofIdx(nmat, solidx[k], i, j, rdof, 0)) = (i==j) ? new_gii : 0.0;
     610         [ -  - ]:          0 :       P(e, stressDofIdx(nmat, solidx[k], stressCmp[i][j], rdof, 0)) = 0.0;
     611                 :            :       // Clear higher DOFs for g and elastic stress
     612         [ -  - ]:          0 :       for (size_t l=1; l<rdof; ++l) {
     613         [ -  - ]:          0 :         U(e, deformDofIdx(nmat, solidx[k], i, j, rdof, l)) = 0.0;
     614         [ -  - ]:          0 :         P(e, stressDofIdx(nmat, solidx[k], stressCmp[i][j], rdof, l)) = 0.0;
     615                 :            :       }
     616                 :            :     }
     617                 :            : }
     618                 :            : 
     619                 :            : std::array< std::array< tk::real, 3 >, 3 >
     620                 :   23473651 : getDeformGrad(
     621                 :            :   std::size_t nmat,
     622                 :            :   std::size_t k,
     623                 :            :   const std::vector< tk::real >& state )
     624                 :            : // *****************************************************************************
     625                 :            : //  Get the inverse deformation gradient tensor for a material at given location
     626                 :            : //! \param[in] nmat Number of materials in this PDE system
     627                 :            : //! \param[in] k Material id whose deformation gradient is required
     628                 :            : //! \param[in] state State vector at location
     629                 :            : //! \return Inverse deformation gradient tensor (g_k) of material k
     630                 :            : // *****************************************************************************
     631                 :            : {
     632                 :   23473651 :   const auto& solidx = g_inputdeck.get< tag::matidxmap, tag::solidx >();
     633                 :            :   std::array< std::array< tk::real, 3 >, 3 > gk;
     634                 :            : 
     635         [ -  + ]:   23473651 :   if (solidx[k] > 0) {
     636                 :            :     // deformation gradient for solids
     637         [ -  - ]:          0 :     for (std::size_t i=0; i<3; ++i) {
     638         [ -  - ]:          0 :       for (std::size_t j=0; j<3; ++j)
     639                 :          0 :         gk[i][j] = state[deformIdx(nmat,solidx[k],i,j)];
     640                 :            :     }
     641                 :            :   }
     642                 :            :   else {
     643                 :            :     // empty vector for fluids
     644                 :   23473651 :     gk = {{}};
     645                 :            :   }
     646                 :            : 
     647                 :   23473651 :   return gk;
     648                 :            : }
     649                 :            : 
     650                 :            : std::array< std::array< tk::real, 3 >, 3 >
     651                 :    4160000 : getCauchyStress(
     652                 :            :   std::size_t nmat,
     653                 :            :   std::size_t k,
     654                 :            :   std::size_t ncomp,
     655                 :            :   const std::vector< tk::real >& state )
     656                 :            : // *****************************************************************************
     657                 :            : //  Get the elastic Cauchy stress tensor for a material at given location
     658                 :            : //! \param[in] nmat Number of materials in this PDE system
     659                 :            : //! \param[in] k Material id whose deformation gradient is required
     660                 :            : //! \param[in] ncomp Number of components in the PDE system
     661                 :            : //! \param[in] state State vector at location
     662                 :            : //! \return Elastic Cauchy stress tensor (alpha * \sigma_ij) of material k
     663                 :            : // *****************************************************************************
     664                 :            : {
     665                 :    4160000 :   const auto& solidx = g_inputdeck.get< tag::matidxmap, tag::solidx >();
     666                 :            :   std::array< std::array< tk::real, 3 >, 3 >
     667                 :    4160000 :     asigk{{ {{0,0,0}}, {{0,0,0}}, {{0,0,0}} }};
     668                 :            : 
     669                 :            :   // elastic Cauchy stress for solids
     670         [ -  + ]:    4160000 :   if (solidx[k] > 0) {
     671         [ -  - ]:          0 :     for (std::size_t i=0; i<3; ++i) {
     672         [ -  - ]:          0 :       for (std::size_t j=0; j<3; ++j)
     673                 :          0 :         asigk[i][j] = state[ncomp +
     674                 :          0 :           stressIdx(nmat, solidx[k], stressCmp[i][j])];
     675                 :            :     }
     676                 :            :   }
     677                 :            : 
     678                 :    4160000 :   return asigk;
     679                 :            : }
     680                 :            : 
     681                 :            : bool
     682                 :    7380705 : haveSolid(
     683                 :            :   std::size_t nmat,
     684                 :            :   const std::vector< std::size_t >& solidx )
     685                 :            : // *****************************************************************************
     686                 :            : //  Check whether we have solid materials in our problem
     687                 :            : //! \param[in] nmat Number of materials in this PDE system
     688                 :            : //! \param[in] solidx Material index indicator
     689                 :            : //! \return true if we have at least one solid, false otherwise.
     690                 :            : // *****************************************************************************
     691                 :            : {
     692                 :    7380705 :   bool haveSolid = false;
     693         [ +  + ]:   22142865 :   for (std::size_t k=0; k<nmat; ++k)
     694         [ -  + ]:   14762160 :     if (solidx[k] > 0) haveSolid = true;
     695                 :            : 
     696                 :    7380705 :   return haveSolid;
     697                 :            : }
     698                 :            : 
     699                 :   11366424 : std::size_t numSolids(
     700                 :            :   std::size_t nmat,
     701                 :            :   const std::vector< std::size_t >& solidx )
     702                 :            : // *****************************************************************************
     703                 :            : //  Count total number of solid materials in the problem
     704                 :            : //! \param[in] nmat Number of materials in this PDE system
     705                 :            : //! \param[in] solidx Material index indicator
     706                 :            : //! \return Total number of solid materials in the problem
     707                 :            : // *****************************************************************************
     708                 :            : {
     709                 :            :   // count number of solid materials
     710                 :   11366424 :   std::size_t nsld(0);
     711         [ +  + ]:   37333302 :   for (std::size_t k=0; k<nmat; ++k)
     712         [ -  + ]:   25966878 :     if (solidx[k] > 0) ++nsld;
     713                 :            : 
     714                 :   11366424 :   return nsld;
     715                 :            : }
     716                 :            : 
     717                 :            : } //inciter::

Generated by: LCOV version 1.14