LCOV - code coverage report
Current view: top level - src/fluidproperties - IdealGasMixtureFluidProperties.C (source / functions) Hit Total Coverage
Test: idaholab/moose fluid_properties: #31405 (292dce) with base fef103 Lines: 91 124 73.4 %
Date: 2025-09-04 07:53:14 Functions: 26 52 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "IdealGasMixtureFluidProperties.h"
      11             : #include "IdealGasFluidProperties.h"
      12             : 
      13             : registerMooseObject("FluidPropertiesApp", IdealGasMixtureFluidProperties);
      14             : 
      15             : /**
      16             :  * Defines a mass-specific property z from (p,T)
      17             :  */
      18             : #define define_mass_specific_prop_from_p_T(prop)                                                   \
      19             :   Real IdealGasMixtureFluidProperties::prop##_from_p_T(                                            \
      20             :       Real p, Real T, const std::vector<Real> & x_secondary) const                                 \
      21             :   {                                                                                                \
      22             :     const auto x = secondaryToAllMassFractions(x_secondary);                                       \
      23             :     mooseAssert(x.size() == _n_components, "Size mismatch");                                       \
      24             :                                                                                                    \
      25             :     Real z = 0;                                                                                    \
      26             :     for (const auto i : make_range(_n_components))                                                 \
      27             :       z += x[i] * _component_fps[i]->prop##_from_p_T(p, T);                                        \
      28             :                                                                                                    \
      29             :     return z;                                                                                      \
      30             :   }                                                                                                \
      31             :   ADReal IdealGasMixtureFluidProperties::prop##_from_p_T(                                          \
      32             :       const ADReal & p, const ADReal & T, const std::vector<ADReal> & x_secondary) const           \
      33             :   {                                                                                                \
      34             :     const auto x = secondaryToAllMassFractions(x_secondary);                                       \
      35             :     mooseAssert(x.size() == _n_components, "Size mismatch");                                       \
      36             :                                                                                                    \
      37             :     ADReal z = 0;                                                                                  \
      38             :     for (const auto i : make_range(_n_components))                                                 \
      39             :       z += x[i] * _component_fps[i]->prop##_from_p_T(p, T);                                        \
      40             :                                                                                                    \
      41             :     return z;                                                                                      \
      42             :   }
      43             : 
      44             : /**
      45             :  * Defines a transport property y from (p,T)
      46             :  */
      47             : #define define_transport_prop_from_p_T(prop)                                                       \
      48             :   Real IdealGasMixtureFluidProperties::prop##_from_p_T(                                            \
      49             :       Real p, Real T, const std::vector<Real> & x_secondary) const                                 \
      50             :   {                                                                                                \
      51             :     const auto x = secondaryToAllMassFractions(x_secondary);                                       \
      52             :     const auto psi = molarFractionsFromMassFractions(x);                                           \
      53             :     mooseAssert(psi.size() == _n_components, "Size mismatch");                                     \
      54             :                                                                                                    \
      55             :     Real y = 0;                                                                                    \
      56             :     for (const auto i : make_range(_n_components))                                                 \
      57             :       y += psi[i] * _component_fps[i]->prop##_from_p_T(p, T);                                      \
      58             :                                                                                                    \
      59             :     return y;                                                                                      \
      60             :   }                                                                                                \
      61             :   ADReal IdealGasMixtureFluidProperties::prop##_from_p_T(                                          \
      62             :       const ADReal & p, const ADReal & T, const std::vector<ADReal> & x_secondary) const           \
      63             :   {                                                                                                \
      64             :     const auto x = secondaryToAllMassFractions(x_secondary);                                       \
      65             :     const auto psi = molarFractionsFromMassFractions(x);                                           \
      66             :     mooseAssert(psi.size() == _n_components, "Size mismatch");                                     \
      67             :                                                                                                    \
      68             :     ADReal y = 0;                                                                                  \
      69             :     for (const auto i : make_range(_n_components))                                                 \
      70             :       y += psi[i] * _component_fps[i]->prop##_from_p_T(p, T);                                      \
      71             :                                                                                                    \
      72             :     return y;                                                                                      \
      73             :   }
      74             : 
      75             : // clang-format off
      76          42 : define_mass_specific_prop_from_p_T(v)
      77          27 : define_mass_specific_prop_from_p_T(e)
      78          39 : define_mass_specific_prop_from_p_T(s)
      79          27 : define_mass_specific_prop_from_p_T(cp)
      80          27 : define_mass_specific_prop_from_p_T(cv)
      81             : 
      82          27 : define_transport_prop_from_p_T(mu)
      83          27 : define_transport_prop_from_p_T(k)
      84             : 
      85             : #undef define_mass_specific_prop_from_p_T
      86             : #undef define_transport_prop_from_p_T
      87             : 
      88          64 : InputParameters IdealGasMixtureFluidProperties::validParams()
      89             : // clang-format on
      90             : {
      91          64 :   InputParameters params = VaporMixtureFluidProperties::validParams();
      92          64 :   params += NaNInterface::validParams();
      93             : 
      94          64 :   params.addClassDescription("Class for fluid properties of an ideal gas mixture");
      95             : 
      96         128 :   params.addRequiredParam<std::vector<UserObjectName>>(
      97             :       "component_fluid_properties",
      98             :       "Name of component fluid properties user objects. The first entry should be the primary "
      99             :       "component.");
     100             : 
     101          64 :   return params;
     102           0 : }
     103             : 
     104          36 : IdealGasMixtureFluidProperties::IdealGasMixtureFluidProperties(const InputParameters & parameters)
     105             :   : VaporMixtureFluidProperties(parameters),
     106             :     NaNInterface(this),
     107          72 :     _component_fp_names(getParam<std::vector<UserObjectName>>("component_fluid_properties")),
     108          36 :     _n_components(_component_fp_names.size()),
     109          72 :     _n_secondary_components(_n_components - 1)
     110             : {
     111          36 :   if (_n_components == 0)
     112           0 :     mooseError("There must be at least one entry in 'component_fluid_properties'.");
     113             : 
     114          36 :   _component_fps.resize(_n_components);
     115         106 :   for (const auto i : make_range(_n_components))
     116             :   {
     117             :     const auto & single_phase_fp =
     118          72 :         getUserObjectByName<SinglePhaseFluidProperties>(_component_fp_names[i]);
     119          72 :     _component_fps[i] = dynamic_cast<const IdealGasFluidProperties *>(&single_phase_fp);
     120          72 :     if (!_component_fps[i])
     121           2 :       mooseError(
     122             :           "Each entry in 'component_fluid_properties' must have type 'IdealGasFluidProperties'.");
     123             :   }
     124          34 : }
     125             : 
     126             : const SinglePhaseFluidProperties &
     127           0 : IdealGasMixtureFluidProperties::getPrimaryFluidProperties() const
     128             : {
     129           0 :   return *_component_fps[0];
     130             : }
     131             : 
     132             : const SinglePhaseFluidProperties &
     133           0 : IdealGasMixtureFluidProperties::getSecondaryFluidProperties(unsigned int i) const
     134             : {
     135             :   mooseAssert(i < getNumberOfSecondaryVapors(), "Requested secondary index too high.");
     136           0 :   return *_component_fps[i + 1];
     137             : }
     138             : 
     139             : template <typename CppType>
     140             : std::vector<CppType>
     141          86 : IdealGasMixtureFluidProperties::secondaryToAllMassFractions_templ(
     142             :     const std::vector<CppType> & x_secondary) const
     143             : {
     144             :   mooseAssert(x_secondary.size() == _n_secondary_components, "Size mismatch");
     145             : 
     146           0 :   CppType sum = 0;
     147         172 :   for (const auto i : make_range(_n_secondary_components))
     148          86 :     sum += x_secondary[i];
     149             : 
     150          86 :   const CppType x_primary = 1.0 - sum;
     151             : 
     152             :   std::vector<CppType> x;
     153          86 :   x.push_back(x_primary);
     154          86 :   x.insert(x.end(), x_secondary.begin(), x_secondary.end());
     155             : 
     156          86 :   return x;
     157           0 : }
     158             : 
     159             : std::vector<ADReal>
     160           0 : IdealGasMixtureFluidProperties::secondaryToAllMassFractions(
     161             :     const std::vector<ADReal> & x_secondary) const
     162             : {
     163           0 :   return secondaryToAllMassFractions_templ(x_secondary);
     164             : }
     165             : 
     166             : std::vector<Real>
     167          86 : IdealGasMixtureFluidProperties::secondaryToAllMassFractions(
     168             :     const std::vector<Real> & x_secondary) const
     169             : {
     170          86 :   return secondaryToAllMassFractions_templ(x_secondary);
     171             : }
     172             : 
     173             : template <typename CppType>
     174             : CppType
     175          30 : IdealGasMixtureFluidProperties::mixtureMolarMass_templ(const std::vector<CppType> & x) const
     176             : {
     177             :   mooseAssert(x.size() == _n_components, "Size mismatch");
     178             : 
     179           0 :   CppType sum = 0;
     180          90 :   for (const auto i : make_range(_n_components))
     181          60 :     sum += x[i] / _component_fps[i]->molarMass();
     182             : 
     183          30 :   return 1.0 / sum;
     184             : }
     185             : 
     186             : ADReal
     187           0 : IdealGasMixtureFluidProperties::mixtureMolarMass(const std::vector<ADReal> & x) const
     188             : {
     189           0 :   return mixtureMolarMass_templ(x);
     190             : }
     191             : 
     192             : Real
     193          30 : IdealGasMixtureFluidProperties::mixtureMolarMass(const std::vector<Real> & x) const
     194             : {
     195          30 :   return mixtureMolarMass_templ(x);
     196             : }
     197             : 
     198             : template <typename CppType>
     199             : CppType
     200          10 : IdealGasMixtureFluidProperties::mixtureSpecificHeatRatio_templ(const std::vector<CppType> & x) const
     201             : {
     202             :   mooseAssert(x.size() == _n_components, "Size mismatch");
     203             : 
     204           0 :   CppType cp_mix = 0, cv_mix = 0;
     205          30 :   for (const auto i : make_range(_n_components))
     206             :   {
     207             :     // cp and cv are constant due to ideal gas assumption; any (p, T) is fine:
     208          20 :     cp_mix += x[i] * _component_fps[i]->cp_from_p_T(0, 0);
     209          20 :     cv_mix += x[i] * _component_fps[i]->cv_from_p_T(0, 0);
     210             :   }
     211             : 
     212          10 :   return cp_mix / cv_mix;
     213             : }
     214             : 
     215             : ADReal
     216           0 : IdealGasMixtureFluidProperties::mixtureSpecificHeatRatio(const std::vector<ADReal> & x) const
     217             : {
     218           0 :   return mixtureSpecificHeatRatio_templ(x);
     219             : }
     220             : 
     221             : Real
     222          10 : IdealGasMixtureFluidProperties::mixtureSpecificHeatRatio(const std::vector<Real> & x) const
     223             : {
     224          10 :   return mixtureSpecificHeatRatio_templ(x);
     225             : }
     226             : 
     227             : template <typename CppType>
     228             : std::vector<CppType>
     229          18 : IdealGasMixtureFluidProperties::molarFractionsFromMassFractions_templ(
     230             :     const std::vector<CppType> & x) const
     231             : {
     232             :   mooseAssert(x.size() == _n_components, "Size mismatch");
     233             : 
     234          18 :   const auto M = mixtureMolarMass(x);
     235          18 :   std::vector<CppType> psi(_n_components);
     236          54 :   for (const auto i : make_range(_n_components))
     237          36 :     psi[i] = x[i] * M / _component_fps[i]->molarMass();
     238             : 
     239          18 :   return psi;
     240           0 : }
     241             : 
     242             : std::vector<ADReal>
     243           0 : IdealGasMixtureFluidProperties::molarFractionsFromMassFractions(const std::vector<ADReal> & x) const
     244             : {
     245           0 :   return molarFractionsFromMassFractions_templ(x);
     246             : }
     247             : 
     248             : std::vector<Real>
     249          18 : IdealGasMixtureFluidProperties::molarFractionsFromMassFractions(const std::vector<Real> & x) const
     250             : {
     251          18 :   return molarFractionsFromMassFractions_templ(x);
     252             : }
     253             : 
     254             : ADReal
     255           0 : IdealGasMixtureFluidProperties::rho_from_p_T(const ADReal & p,
     256             :                                              const ADReal & T,
     257             :                                              const std::vector<ADReal> & x_secondary) const
     258             : {
     259           0 :   return 1.0 / v_from_p_T(p, T, x_secondary);
     260             : }
     261             : 
     262             : Real
     263           1 : IdealGasMixtureFluidProperties::rho_from_p_T(Real p,
     264             :                                              Real T,
     265             :                                              const std::vector<Real> & x_secondary) const
     266             : {
     267           1 :   return 1.0 / v_from_p_T(p, T, x_secondary);
     268             : }
     269             : 
     270             : template <typename CppType>
     271             : CppType
     272           1 : IdealGasMixtureFluidProperties::e_from_p_rho_templ(const CppType & p,
     273             :                                                    const CppType & rho,
     274             :                                                    const std::vector<CppType> & x_secondary) const
     275             : {
     276           1 :   const auto x = secondaryToAllMassFractions(x_secondary);
     277             :   mooseAssert(x.size() == _n_components, "Size mismatch");
     278             : 
     279           1 :   const auto M = mixtureMolarMass(x);
     280             : 
     281           0 :   CppType e_ref_sum = 0;
     282           0 :   CppType cv_sum = 0;
     283           3 :   for (const auto i : make_range(_n_components))
     284             :   {
     285           2 :     e_ref_sum += x[i] * _component_fps[i]->referenceSpecificInternalEnergy();
     286             :     // cv is constant due to ideal gas assumption; any (p, T) is fine:
     287           2 :     cv_sum += x[i] * _component_fps[i]->cv_from_p_T(0, 0);
     288             :   }
     289             : 
     290           1 :   return cv_sum * M * p / (_R * rho) + e_ref_sum;
     291           1 : }
     292             : 
     293             : ADReal
     294           0 : IdealGasMixtureFluidProperties::e_from_p_rho(const ADReal & p,
     295             :                                              const ADReal & rho,
     296             :                                              const std::vector<ADReal> & x_secondary) const
     297             : {
     298           0 :   return e_from_p_rho_templ(p, rho, x_secondary);
     299             : }
     300             : 
     301             : Real
     302           1 : IdealGasMixtureFluidProperties::e_from_p_rho(Real p,
     303             :                                              Real rho,
     304             :                                              const std::vector<Real> & x_secondary) const
     305             : {
     306           1 :   return e_from_p_rho_templ(p, rho, x_secondary);
     307             : }
     308             : 
     309             : template <typename CppType>
     310             : CppType
     311           1 : IdealGasMixtureFluidProperties::p_from_v_e_templ(const CppType & v,
     312             :                                                  const CppType & e,
     313             :                                                  const std::vector<CppType> & x_secondary) const
     314             : {
     315           1 :   const auto x = secondaryToAllMassFractions(x_secondary);
     316           1 :   const auto M = mixtureMolarMass(x);
     317             : 
     318           2 :   return _R * T_from_v_e(v, e, x_secondary) / (M * v);
     319           1 : }
     320             : 
     321             : ADReal
     322           0 : IdealGasMixtureFluidProperties::p_from_v_e(const ADReal & v,
     323             :                                            const ADReal & e,
     324             :                                            const std::vector<ADReal> & x_secondary) const
     325             : {
     326           0 :   return p_from_v_e_templ(v, e, x_secondary);
     327             : }
     328             : 
     329             : Real
     330           1 : IdealGasMixtureFluidProperties::p_from_v_e(Real v,
     331             :                                            Real e,
     332             :                                            const std::vector<Real> & x_secondary) const
     333             : {
     334           1 :   return p_from_v_e_templ(v, e, x_secondary);
     335             : }
     336             : 
     337             : template <typename CppType>
     338             : CppType
     339           2 : IdealGasMixtureFluidProperties::T_from_v_e_templ(const CppType & /*v*/,
     340             :                                                  const CppType & e,
     341             :                                                  const std::vector<CppType> & x_secondary) const
     342             : {
     343           2 :   const auto x = secondaryToAllMassFractions(x_secondary);
     344             :   mooseAssert(x.size() == _n_components, "Size mismatch");
     345             : 
     346           0 :   CppType e_ref_sum = 0;
     347           0 :   CppType cv_sum = 0;
     348           6 :   for (const auto i : make_range(_n_components))
     349             :   {
     350           4 :     e_ref_sum += x[i] * _component_fps[i]->referenceSpecificInternalEnergy();
     351             :     // cv is constant due to ideal gas assumption; any (p, T) is fine:
     352           4 :     cv_sum += x[i] * _component_fps[i]->cv_from_p_T(0, 0);
     353             :   }
     354             : 
     355           2 :   return (e - e_ref_sum) / cv_sum;
     356           2 : }
     357             : 
     358             : ADReal
     359           0 : IdealGasMixtureFluidProperties::T_from_v_e(const ADReal & v,
     360             :                                            const ADReal & e,
     361             :                                            const std::vector<ADReal> & x_secondary) const
     362             : {
     363           0 :   return T_from_v_e_templ(v, e, x_secondary);
     364             : }
     365             : 
     366             : Real
     367           2 : IdealGasMixtureFluidProperties::T_from_v_e(Real v,
     368             :                                            Real e,
     369             :                                            const std::vector<Real> & x_secondary) const
     370             : {
     371           2 :   return T_from_v_e_templ(v, e, x_secondary);
     372             : }
     373             : 
     374             : template <typename CppType>
     375             : CppType
     376          10 : IdealGasMixtureFluidProperties::c_from_p_T_templ(const CppType & /*p*/,
     377             :                                                  const CppType & T,
     378             :                                                  const std::vector<CppType> & x_secondary) const
     379             : {
     380          10 :   const auto x = secondaryToAllMassFractions(x_secondary);
     381          10 :   const auto M = mixtureMolarMass(x);
     382          10 :   const auto gamma = mixtureSpecificHeatRatio(x);
     383             : 
     384          10 :   return std::sqrt(gamma * _R * T / M);
     385          10 : }
     386             : 
     387             : ADReal
     388           0 : IdealGasMixtureFluidProperties::c_from_p_T(const ADReal & p,
     389             :                                            const ADReal & T,
     390             :                                            const std::vector<ADReal> & x_secondary) const
     391             : {
     392           0 :   return c_from_p_T_templ(p, T, x_secondary);
     393             : }
     394             : 
     395             : Real
     396          10 : IdealGasMixtureFluidProperties::c_from_p_T(Real p,
     397             :                                            Real T,
     398             :                                            const std::vector<Real> & x_secondary) const
     399             : {
     400          10 :   return c_from_p_T_templ(p, T, x_secondary);
     401             : }

Generated by: LCOV version 1.14