Alamo
Mixture_Averaged.H
Go to the documentation of this file.
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"
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
35namespace Model {
36namespace Gas {
37namespace Transport {
38
40public:
41 static constexpr const char* name = "mixture_averaged";
42 virtual const char* model_name() const override { return name; }
43
44private:
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
52public:
53 Mixture_Averaged() = delete;
54 Mixture_Averaged(int a_nspecies, std::vector<double> &a_MW, Thermo::Thermo *a_thermo, IO::ParmParse& pp, std::string name)
55 : nspecies(a_nspecies), MW(a_MW), thermo(a_thermo) // thermo is owned by Gas, should only be referenced here
56 {
57 pp.queryclass(name, *this);
58 }
59
60 ~Mixture_Averaged() override = default;
61
62 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 pp.query_validate("type", value.type, {"constant", "LJ"});
66 if (value.type == "constant")
67 {
68 // Dynamic viscosity if type=constant
69 pp.queryarr_required("mu", value.val1, Unit::Pressure() * Unit::Time());
70 // Thermal conductivity if type=constant
72 }
73 else if (value.type == "LJ")
74 {
75 // Lennard-Jones diameter if type=LJ
76 pp.queryarr_required("LJdiameter", value.val1, Unit::Length());
77 // Lennard-Jones well depth if type=LJ
78 pp.queryarr_required("LJwelldepth", value.val2, Unit::Temperature());
79 }
80 else
81 {
82 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 Util::Assert(INFO, TEST(value.val1.size() == (size_t)value.nspecies));
87 Util::Assert(INFO, TEST(value.val2.size() == (size_t)value.nspecies));
88 }
89
90private:
91 double collision_integral(double Tstar) const {
92 double S = 1.16145 * pow(Tstar, -0.14874)
93 + 0.52487 / exp(0.77320 * Tstar)
94 + 2.16178 / exp(2.43787 * Tstar);
95 return S;
96 }
97 double mu_enskog(double T, int i) const {
98 return 2.669570e-6 * sqrt(MW[i] * T) / (val1[i] * val1[i] * collision_integral(T / val2[i]));
99 }
100 double k_eucken(double T, Set::Patch<const Set::Scalar>& X, int i, int j, int k, int n) const
101 {
102 if (!thermo) Util::Abort(INFO, "[Transport::Mixture_Averaged::k_eucken] Thermo model not set.");
103 double cp = thermo->cp_mol(T, X, i, j, k);
104 return mu_enskog(T, n) * (X(i, j, k, n) * cp + 1.25 * Set::Constant::Rg) / MW[n];
105 }
106
107public:
108 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 double mu_mix = 0.0;
112 if ( type == "constant" )
113 {
114 // dynamic viscosity, mu, is constant per species
115 for (int a = 0; a < nspecies; ++a) {
116 double mua = val1[a];
117 double MWa = MW[a];
118 double phi = 0.0;
119 for (int b = 0; b < nspecies; ++b) {
120 double mub = val1[b];
121 double MWb = MW[b];
122 double ratio = pow(MWb / MWa, 0.25);
123 double mu_ratio = sqrt(mua / mub);
124 double term = sqrt(1.0 + MWa / MWb);
125 phi += X(i,j,k,b) * pow(1.0 + mu_ratio * ratio, 2.0) / (sqrt(8.0) * term);
126 }
127 mu_mix += X(i, j, k, a) * mua / phi;
128 }
129 }
130 else if ( type == "LJ" )
131 {
132 // dynamic viscosity, mu, computed by Chapman-Enskog per species
133 for (int a = 0; a < nspecies; ++a) {
134 double mua = mu_enskog(T, a);
135 double MWa = MW[a];
136 double phi = 0.0;
137 for (int b = 0; b < nspecies; ++b) {
138 double mub = mu_enskog(T, b);
139 double MWb = MW[b];
140 double ratio = pow(MWb / MWa, 0.25);
141 double mu_ratio = sqrt(mua / mub);
142 double term = sqrt(1.0 + MWa / MWb);
143 phi += X(i, j, k, b) * pow(1.0 + mu_ratio * ratio, 2.0) / (sqrt(8.0) * term);
144 }
145 mu_mix += X(i, j, k, a) * mua / phi;
146 }
147 }
148 else
149 {
150 Util::Abort(INFO, "[Transport::Mixture_Averaged] Unknown type.");
151 }
152
153 if (!(mu_mix == mu_mix) ) mu_mix = 0.0;
154 return mu_mix;
155 }
156
157 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 double k_mix = 0.0;
161 if ( type == "constant" )
162 {
163 // thermal conductivity coefficient, k, is constant per species
164 for (int a = 0; a < nspecies; ++a) {
165 double mua = val1[a];
166 double MWa = MW[a];
167 double phi = 0.0;
168 for (int b = 0; b < nspecies; ++b) {
169 double mub = val1[b];
170 double MWb = MW[b];
171 double ratio = pow(MWb / MWa, 0.25);
172 double mu_ratio = sqrt(mua / mub);
173 double term = sqrt(1.0 + MWa / MWb);
174 phi += X(i, j, k, b) * pow(1.0 + mu_ratio * ratio, 2.0) / (sqrt(8.0) * term);
175 }
176 k_mix += X(i, j, k, a) * val2[a] / phi;
177 }
178 }
179 else if ( type == "LJ" )
180 {
181 // thermal conductivity coefficient, k, computed by Eucken relation per species
182 for (int a = 0; a < nspecies; ++a) {
183 double mua = mu_enskog(T, a);
184 double MWa = MW[a];
185 double phi = 0.0;
186 for (int b = 0; b < nspecies; ++b) {
187 double mub = mu_enskog(T, b);
188 double MWb = MW[b];
189 double ratio = pow(MWb / MWa, 0.25);
190 double mu_ratio = sqrt(mua / mub);
191 double term = sqrt(1.0 + MWa / MWb);
192 phi += X(i, j, k, b) * pow(1.0 + mu_ratio * ratio, 2.0) / (sqrt(8.0) * term);
193 }
194 k_mix += X(i, j, k, a) * k_eucken(T, X, i, j, k, a) / phi;
195 }
196 }
197 else
198 {
199 Util::Abort(INFO, "[Transport::Mixture_Averaged] Unknown type.");
200 }
201
202 return k_mix;
203 }
204
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 for (int a = 0; a < nspecies; ++a) {
211 double sumD = 0.0;
212 for (int b = 0; b < nspecies; ++b) {
213 if (a == b) continue;
214
215 double sigmaAB = 0.5 * (val1[a] + val1[b]);
216 double epsAB = sqrt(val2[a] * val2[b]);
217 double Tstar = T / epsAB;
218
219 double omegaAB =
220 1.06036 / pow(Tstar, 0.15610) +
221 0.19300 / exp(0.47635 * Tstar) +
222 1.03587 / exp(1.52996 * Tstar) +
223 1.76474 / exp(3.89411 * Tstar);
224
225 double DAB =
226 0.0018583 * sqrt(T*T*T * (1.0 / MW[a] + 1.0 / MW[b])) /
227 ( (P / 101325.0) * sigmaAB*sigmaAB * omegaAB );
228 DAB /= 1.0e4;
229
230 sumD += X(i, j, k, b) / DAB;
231 }
232
233 DKM(i, j, k, a) = (1.0 - X(i, j, k ,a)) / sumD;
234 if (!(DKM(i, j, k, a) == DKM(i, j, k, a))) DKM(i, j, k, a) = 0.0; // NaN guard
235 }
236 }
237
238}; // class Mixture_Averaged
239
240} // namespace Transport
241} // namespace Gas
242} // namespace Model
243
244#endif
#define X(name)
#define TEST(x)
Definition Util.H:25
#define INFO
Definition Util.H:24
void queryclass(std::string name, T *value)
Definition ParmParse.H:960
int queryarr_required(std::string name, std::vector< T > &value)
Definition ParmParse.H:643
int query_validate(std::string name, int &value, std::vector< int > possibleintvals)
Definition ParmParse.H:336
virtual double cp_mol(double T, Set::Patch< const Set::Scalar > &X, int i, int j, int k) const =0
Mixture_Averaged(int a_nspecies, std::vector< double > &a_MW, Thermo::Thermo *a_thermo, IO::ParmParse &pp, std::string name)
static constexpr const char * name
void diffusion_coeffs(Set::Patch< Set::Scalar > &DKM, double T, double P, Set::Patch< const Set::Scalar > &X, int i, int j, int k) override
virtual const char * model_name() const override
double dynamic_viscosity(double T, Set::Patch< const Set::Scalar > &X, int i, int j, int k) const override
double collision_integral(double Tstar) const
static void Parse(Mixture_Averaged &value, IO::ParmParse &pp)
double mu_enskog(double T, int i) const
double thermal_conductivity(double T, Set::Patch< const Set::Scalar > &X, int i, int j, int k) const override
double k_eucken(double T, Set::Patch< const Set::Scalar > &X, int i, int j, int k, int n) const
Set::Scalar Rg
Definition Set.cpp:14
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:19
void Abort(const char *msg)
Definition Util.cpp:268
AMREX_FORCE_INLINE void Assert(std::string file, std::string func, int line, std::string smt, bool pass, Args const &... args)
Definition Util.H:58
static Unit Time()
Definition Unit.H:199
static Unit Temperature()
Definition Unit.H:201
static Unit Pressure()
Definition Unit.H:217
static Unit Power()
Definition Unit.H:219
static Unit Length()
Definition Unit.H:198