LCOV - code coverage report
Current view: top level - src/Model/Gas/Transport - Mixture_Averaged.H (source / functions) Coverage Total Hit
Test: coverage_merged.info Lines: 28.4 % 109 31
Test Date: 2026-03-09 13:26:47 Functions: 54.5 % 11 6

            Line data    Source code
       1              : #ifndef MODEL_GAS_TRANSPORT_MIXTURE_AVERAGED_H_
       2              : #define MODEL_GAS_TRANSPORT_MIXTURE_AVERAGED_H_
       3              : 
       4              : #include <vector>
       5              : #include <memory>
       6              : #include "IO/ParmParse.H"
       7              : #include "Model/Gas/Transport/Transport.H"
       8              : 
       9              : // Type: 0,1 determines if per species viscosity and thermal conductivity are 
      10              : //           constant (type=0) or computed using kinetic theory (type=1)
      11              : // Either way, mixture averaging is used to compute the mixture values
      12              : //
      13              : // For kinetic theory: Chapman-Enskog is used to compute viscosity
      14              : //                     and Eucken relation used to compute conductivity
      15              : 
      16              : 
      17              : // dynamic viscosity, mu, computed using Chapman-Enskog theory
      18              : //
      19              : //        5E20 sqrt(pi * m * kb * T)  
      20              : //  mu = ---------------------------- 
      21              : //              16 pi σ^2 Ω           
      22              : //
      23              : //            MW
      24              : //  where m = -- (mass per particle), MW: molecular weight, NA: Avogadro's number, kb: Boltzman constant
      25              : //            NA                                                                  
      26              : //
      27              : //  σ: Lennard-Jones collision diameter in Angstroms, Ω: collision integral
      28              : 
      29              : 
      30              : // thermal conductivity coefficient, k, computed using Eucken relation
      31              : //
      32              : //  k = mu * (cp + 1.25R), where cp and R are both per kg
      33              : //
      34              : 
      35              : namespace Model {
      36              : namespace Gas {
      37              : namespace Transport {
      38              : 
      39              : class Mixture_Averaged : public Transport {
      40              : public:
      41              :     static constexpr const char* name = "mixture_averaged";
      42            8 :     virtual const char* model_name() const override { return name; }
      43              : 
      44              : private:
      45              :     int nspecies;
      46              :     std::vector<double> &MW;
      47              :     Thermo::Thermo const * const thermo;
      48              :     std::string type;
      49              :     std::vector<double> val1; // constant viscosity mu or Lennard-Jones collision diameter depending on type
      50              :     std::vector<double> val2; // constant thermal conductivity or Lennard-Jones potential well depth depending on type
      51              : 
      52              : public:
      53              :     Mixture_Averaged() = delete;
      54            8 :     Mixture_Averaged(int a_nspecies, std::vector<double> &a_MW, Thermo::Thermo *a_thermo, IO::ParmParse& pp, std::string name)
      55            8 :         : nspecies(a_nspecies), MW(a_MW), thermo(a_thermo) // thermo is owned by Gas, should only be referenced here
      56              :     {
      57            8 :         pp.queryclass(name, *this);
      58            8 :     }
      59              : 
      60           16 :     ~Mixture_Averaged() override = default;
      61              : 
      62            8 :     static void Parse(Mixture_Averaged & value, IO::ParmParse & pp)
      63              :     {
      64              :         // Compute individual species transport properties as "constant" or from "LJ" (Lennard-Jones) theory
      65           32 :         pp.query_validate("type", value.type, {"constant", "LJ"});
      66            8 :         if (value.type == "constant")
      67              :         {
      68              :             // Dynamic viscosity if type=constant
      69           16 :             pp.queryarr_required("mu", value.val1, Unit::Pressure() * Unit::Time());
      70              :             // Thermal conductivity if type=constant
      71           24 :             pp.queryarr_required("k", value.val2, Unit::Power() / Unit::Length() / Unit::Temperature());
      72              :         }
      73            0 :         else if (value.type == "LJ")
      74              :         {
      75              :             // Lennard-Jones diameter if type=LJ
      76            0 :             pp.queryarr_required("LJdiameter", value.val1, Unit::Length());
      77              :             // Lennard-Jones well depth if type=LJ
      78            0 :             pp.queryarr_required("LJwelldepth", value.val2, Unit::Temperature());
      79              :         }
      80              :         else
      81              :         {
      82            0 :             Util::Abort(INFO, "Unrecognized type for transport model ", value.type);
      83              :         }
      84              :         //pp.query_default("P_1atm", value.P_1atm, "1_atm", Unit::Pressure());
      85              : 
      86           56 :         Util::Assert(INFO, TEST(value.val1.size() == (size_t)value.nspecies));
      87           56 :         Util::Assert(INFO, TEST(value.val2.size() == (size_t)value.nspecies));
      88            8 :     }
      89              : 
      90              : private:
      91            0 :     double collision_integral(double Tstar) const {
      92            0 :         double S =  1.16145 * pow(Tstar, -0.14874) 
      93            0 :                     + 0.52487 / exp(0.77320 * Tstar)
      94            0 :                     + 2.16178 / exp(2.43787 * Tstar);
      95            0 :         return S;
      96              :     }
      97            0 :     double mu_enskog(double T, int i) const {
      98            0 :         return 2.669570e-6 * sqrt(MW[i] * T) / (val1[i] * val1[i] * collision_integral(T / val2[i]));
      99              :     }
     100            0 :     double k_eucken(double T, Set::Patch<const Set::Scalar>& X, int i, int j, int k, int n) const 
     101              :     {
     102            0 :         if (!thermo) Util::Abort(INFO, "[Transport::Mixture_Averaged::k_eucken] Thermo model not set.");
     103            0 :         double cp = thermo->cp_mol(T, X, i, j, k);
     104            0 :         return mu_enskog(T, n) * (X(i, j, k, n) * cp + 1.25 * Set::Constant::Rg) / MW[n];
     105              :     }
     106              : 
     107              : public:
     108     13235200 :     double dynamic_viscosity(double T, Set::Patch<const Set::Scalar>& X, int i, int j, int k) const override 
     109              :     {
     110              :         // Wilke's Average: Dynamic viscosity, Pa-s
     111     13235200 :         double mu_mix = 0.0;
     112     13235200 :         if ( type == "constant" )
     113              :         {
     114              :             // dynamic viscosity, mu, is constant per species
     115     26470400 :             for (int a = 0; a < nspecies; ++a) {
     116     13235200 :                 double mua = val1[a];
     117     13235200 :                 double MWa = MW[a];
     118     13235200 :                 double phi = 0.0;
     119     26470400 :                 for (int b = 0; b < nspecies; ++b) {
     120     13235200 :                     double mub = val1[b];
     121     13235200 :                     double MWb = MW[b];
     122     13235200 :                     double ratio = pow(MWb / MWa, 0.25);
     123     13235200 :                     double mu_ratio = sqrt(mua / mub);
     124     13235200 :                     double term = sqrt(1.0 + MWa / MWb);
     125     13235200 :                     phi += X(i,j,k,b) * pow(1.0 + mu_ratio * ratio, 2.0) / (sqrt(8.0) * term);
     126              :                 }
     127     13235200 :                 mu_mix += X(i, j, k, a) * mua / phi;
     128              :             }
     129              :         }
     130            0 :         else if ( type == "LJ" )
     131              :         {
     132              :             // dynamic viscosity, mu, computed by Chapman-Enskog per species
     133            0 :             for (int a = 0; a < nspecies; ++a) {
     134            0 :                 double mua = mu_enskog(T, a);
     135            0 :                 double MWa = MW[a];
     136            0 :                 double phi = 0.0;
     137            0 :                 for (int b = 0; b < nspecies; ++b) {
     138            0 :                     double mub = mu_enskog(T, b);
     139            0 :                     double MWb = MW[b];
     140            0 :                     double ratio = pow(MWb / MWa, 0.25);
     141            0 :                     double mu_ratio = sqrt(mua / mub);
     142            0 :                     double term = sqrt(1.0 + MWa / MWb);
     143            0 :                     phi += X(i, j, k, b) * pow(1.0 + mu_ratio * ratio, 2.0) / (sqrt(8.0) * term);
     144              :                 }
     145            0 :                 mu_mix += X(i, j, k, a) * mua / phi;
     146              :             }
     147              :         }
     148              :         else
     149              :         {
     150            0 :             Util::Abort(INFO, "[Transport::Mixture_Averaged] Unknown type.");
     151              :         }
     152              : 
     153     13235200 :         if (!(mu_mix == mu_mix) ) mu_mix = 0.0;
     154     13235200 :         return mu_mix;
     155              :     }
     156              : 
     157            0 :     double thermal_conductivity(double T, Set::Patch<const Set::Scalar>& X, int i, int j, int k) const override 
     158              :     {
     159              :         // Wilke's Average: Thermal conductivity coefficient, W/(m-K)
     160            0 :         double k_mix = 0.0;
     161            0 :         if ( type == "constant" )
     162              :         {
     163              :             // thermal conductivity coefficient, k, is constant per species
     164            0 :             for (int a = 0; a < nspecies; ++a) {
     165            0 :                 double mua = val1[a];
     166            0 :                 double MWa = MW[a];
     167            0 :                 double phi = 0.0;
     168            0 :                 for (int b = 0; b < nspecies; ++b) {
     169            0 :                     double mub = val1[b];
     170            0 :                     double MWb = MW[b];
     171            0 :                     double ratio = pow(MWb / MWa, 0.25);
     172            0 :                     double mu_ratio = sqrt(mua / mub);
     173            0 :                     double term = sqrt(1.0 + MWa / MWb);
     174            0 :                     phi += X(i, j, k, b) * pow(1.0 + mu_ratio * ratio, 2.0) / (sqrt(8.0) * term);
     175              :                 }
     176            0 :                 k_mix += X(i, j, k, a) * val2[a] / phi;
     177              :             }
     178              :         }
     179            0 :         else if ( type == "LJ" )
     180              :         {
     181              :             // thermal conductivity coefficient, k, computed by Eucken relation per species
     182            0 :             for (int a = 0; a < nspecies; ++a) {
     183            0 :                 double mua = mu_enskog(T, a);
     184            0 :                 double MWa = MW[a];
     185            0 :                 double phi = 0.0;
     186            0 :                 for (int b = 0; b < nspecies; ++b) {
     187            0 :                     double mub = mu_enskog(T, b);
     188            0 :                     double MWb = MW[b];
     189            0 :                     double ratio = pow(MWb / MWa, 0.25);
     190            0 :                     double mu_ratio = sqrt(mua / mub);
     191            0 :                     double term = sqrt(1.0 + MWa / MWb);
     192            0 :                     phi += X(i, j, k, b) * pow(1.0 + mu_ratio * ratio, 2.0) / (sqrt(8.0) * term);
     193              :                 }
     194            0 :                 k_mix += X(i, j, k, a) * k_eucken(T, X, i, j, k, a) / phi;
     195              :             }
     196              :         }
     197              :         else
     198              :         {
     199            0 :             Util::Abort(INFO, "[Transport::Mixture_Averaged] Unknown type.");
     200              :         }
     201              : 
     202            0 :         return k_mix;
     203              :     }
     204              : 
     205            0 :     void diffusion_coeffs(
     206              :             Set::Patch<Set::Scalar>& DKM, double T, double P,
     207              :             Set::Patch<const Set::Scalar>& X, int i, int j, int k) override
     208              :     {
     209              :         // Mixture diffusion coefficients (Chapman–Enskog), m^2/s
     210            0 :         for (int a = 0; a < nspecies; ++a) {
     211            0 :             double sumD = 0.0;
     212            0 :             for (int b = 0; b < nspecies; ++b) {
     213            0 :                 if (a == b) continue;
     214              : 
     215            0 :                 double sigmaAB = 0.5 * (val1[a] + val1[b]);
     216            0 :                 double epsAB   = sqrt(val2[a] * val2[b]);
     217            0 :                 double Tstar   = T / epsAB;
     218              : 
     219              :                 double omegaAB =
     220            0 :                     1.06036 / pow(Tstar, 0.15610) +
     221            0 :                     0.19300 / exp(0.47635 * Tstar) +
     222            0 :                     1.03587 / exp(1.52996 * Tstar) +
     223            0 :                     1.76474 / exp(3.89411 * Tstar);
     224              : 
     225              :                 double DAB = 
     226            0 :                     0.0018583 * sqrt(T*T*T * (1.0 / MW[a] + 1.0 / MW[b])) /
     227            0 :                     ( (P / 101325.0) * sigmaAB*sigmaAB * omegaAB );
     228            0 :                 DAB /= 1.0e4;
     229              : 
     230            0 :                 sumD += X(i, j, k, b) / DAB;
     231              :             }
     232              : 
     233            0 :             DKM(i, j, k, a) = (1.0 - X(i, j, k ,a)) / sumD;
     234            0 :             if (!(DKM(i, j, k, a) == DKM(i, j, k, a))) DKM(i, j, k, a) = 0.0; // NaN guard
     235              :         }
     236            0 :     }
     237              : 
     238              : }; // class Mixture_Averaged
     239              : 
     240              : } // namespace Transport
     241              : } // namespace Gas
     242              : } // namespace Model
     243              : 
     244              : #endif
        

Generated by: LCOV version 2.0-1