https://mooseframework.inl.gov
Loading...
Searching...
No Matches
NASA7IdealGasFluidProperties.C
Go to the documentation of this file.
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
11
13
16{
18
20 params.addRequiredParam<MooseEnum>("species", species, "Gas species");
21
22 // The temperature inversions start at the upper end of the temperature range of the data, and
23 // none of them needs a pressure guess
24 params.suppressParameter<Real>("T_initial_guess");
25 params.suppressParameter<Real>("p_initial_guess");
26
27 params.addClassDescription("Ideal gas with temperature-dependent heat capacity, enthalpy, and "
28 "entropy from NASA 7-coefficient polynomials");
29
30 return params;
31}
32
34 : SinglePhaseFluidProperties(parameters),
35 _data(NASA7::speciesData(getParam<MooseEnum>("species"))),
36 _R_specific(_R / _data.molar_mass),
37 _lennard_jones(GasTransportUtils::lennardJonesParameters(_data.name)),
38 _is_steam(_data.name == "H2O")
39{
40}
41
42std::string
47
48Real
53
54Real
56{
57 // The internal energy is convex in temperature over nearly all of the range of the data, so
58 // Newton's method started above the solution approaches it from above (see T_from_energy)
59 return _data.T_max;
60}
61
67
68template <typename CppType>
69void
71{
72 const auto T_raw = MetaPhysicL::raw_value(T);
73 if (std::isnan(T_raw) || T_raw <= 0)
74 flagInvalidSolution("Non-positive or not-a-number temperature");
75 else if (T_raw < _data.T_min || T_raw > _data.T_max)
76 flagSolutionWarning(
77 "Temperature outside the range of the NASA-7 data; the polynomials are extrapolated");
78}
79
80template <typename CppType>
81void
83{
85 // Range of validity of the IAPWS 2008 viscosity and IAPWS 2011 thermal conductivity
86 // formulations: from the triple point to 1173.15 K
87 const auto T_raw = MetaPhysicL::raw_value(T);
88 if (_is_steam && (T_raw < 273.16 || T_raw > 1173.15))
89 flagSolutionWarning("Temperature outside the range of validity of the IAPWS transport "
90 "formulations for steam");
91}
92
93template <typename CppType>
94CppType
96{
98 return _R_specific * T * (NASA7::hOverRT(_data, T) - 1);
99}
100
101template <typename CppType>
102CppType
104{
106 return _R_specific * T * NASA7::hOverRT(_data, T);
107}
108
109template <typename CppType>
110CppType
112{
115}
116
117template <typename CppType>
118CppType
120{
122 return _R_specific * (NASA7::cpOverR(_data, T) - 1);
123}
124
125template <typename CppType>
126CppType
128{
130 const auto cp_R = NASA7::cpOverR(_data, T);
131 return cp_R / (cp_R - 1);
132}
133
134template <typename CppType>
135CppType
143
144template <typename CppType>
145CppType
147{
149 // The modified Eucken correlation overestimates the conductivity of polar gases, that of steam
150 // by 20% to 40%
151 if (_is_steam)
157}
158
159template <typename CppType>
160CppType
161NASA7IdealGasFluidProperties::rho_from_p_T_template(const CppType & p, const CppType & T) const
162{
163 return p / (_R_specific * T);
164}
165
166template <typename CppType>
167CppType
168NASA7IdealGasFluidProperties::v_from_p_T_template(const CppType & p, const CppType & T) const
169{
170 return _R_specific * T / p;
171}
172
173template <typename CppType>
174CppType
175NASA7IdealGasFluidProperties::e_from_p_T_template(const CppType & /*p*/, const CppType & T) const
176{
177 return e_from_T(T);
178}
179
180template <typename CppType>
181CppType
182NASA7IdealGasFluidProperties::h_from_p_T_template(const CppType & /*p*/, const CppType & T) const
183{
184 return h_from_T(T);
185}
186
187template <typename CppType>
188CppType
189NASA7IdealGasFluidProperties::s_from_p_T_template(const CppType & p, const CppType & T) const
190{
191 using std::log;
194}
195
196template <typename CppType>
197CppType
198NASA7IdealGasFluidProperties::cp_from_p_T_template(const CppType & /*p*/, const CppType & T) const
199{
200 return cp_from_T(T);
201}
202
203template <typename CppType>
204CppType
205NASA7IdealGasFluidProperties::cv_from_p_T_template(const CppType & /*p*/, const CppType & T) const
206{
207 return cv_from_T(T);
208}
209
210template <typename CppType>
211CppType
212NASA7IdealGasFluidProperties::c_from_p_T_template(const CppType & /*p*/, const CppType & T) const
213{
214 using std::sqrt;
215 return sqrt(gamma_from_T(T) * _R_specific * T);
216}
217
218template <typename CppType>
219CppType
220NASA7IdealGasFluidProperties::gamma_from_p_T_template(const CppType & /*p*/,
221 const CppType & T) const
222{
223 return gamma_from_T(T);
224}
225
226template <typename CppType>
227CppType
228NASA7IdealGasFluidProperties::mu_from_p_T_template(const CppType & /*p*/, const CppType & T) const
229{
230 return mu_from_T(T);
231}
232
233template <typename CppType>
234CppType
235NASA7IdealGasFluidProperties::k_from_p_T_template(const CppType & /*p*/, const CppType & T) const
236{
237 return k_from_T(T);
238}
239
240template <typename CppType>
241CppType
242NASA7IdealGasFluidProperties::p_from_T_v_template(const CppType & T, const CppType & v) const
243{
244 return _R_specific * T / v;
245}
246
247template <typename CppType>
248CppType
249NASA7IdealGasFluidProperties::e_from_T_v_template(const CppType & T, const CppType & /*v*/) const
250{
251 return e_from_T(T);
252}
253
254template <typename CppType>
255CppType
256NASA7IdealGasFluidProperties::h_from_T_v_template(const CppType & T, const CppType & /*v*/) const
257{
258 return h_from_T(T);
259}
260
261template <typename CppType>
262CppType
263NASA7IdealGasFluidProperties::s_from_T_v_template(const CppType & T, const CppType & v) const
264{
265 return s_from_p_T_template(p_from_T_v_template(T, v), T);
266}
267
268template <typename CppType>
269CppType
270NASA7IdealGasFluidProperties::cv_from_T_v_template(const CppType & T, const CppType & /*v*/) const
271{
272 return cv_from_T(T);
273}
274
275template <typename CppType>
276CppType
277NASA7IdealGasFluidProperties::e_from_p_rho_template(const CppType & p, const CppType & rho) const
278{
279 return e_from_T(p / (rho * _R_specific));
280}
281
282template <typename CppType>
283CppType
284NASA7IdealGasFluidProperties::T_from_energy(const CppType & y, const Real k) const
285{
286 // Start at the upper end of the temperature range of the data. y(T) is convex over nearly all of
287 // that range, because the heat capacity increases with temperature, so Newton's method started
288 // above the solution approaches it from above. Started below it, the first step can overshoot
289 // far beyond the range, where the extrapolated polynomials eventually give dy/dT <= 0 and a
290 // second, spurious solution. For the built-in species, this start finds the solution up to at
291 // least 1.7 T_max.
292 const Real T0 = _data.T_max;
293
294 // The energies include the enthalpy of formation, so they can be close to zero, where the
295 // convergence test of NewtonSolve, which is relative to the target value, would demand accuracy
296 // below roundoff. Solve y(T) + shift = y + shift instead, with the shift (dy/dT) T - y(T) at T0.
297 // Both sides are then close to (dy/dT) T, and the convergence test bounds the relative error in
298 // temperature.
299 const Real shift = _R_specific * T0 * (NASA7::cpOverR(_data, T0) - NASA7::hOverRT(_data, T0));
300
301 const auto shifted_y = [this, k, shift](const CppType & /*y*/,
302 const CppType & T,
303 CppType & y_T,
304 CppType & dy_T_dy,
305 CppType & dy_T_dT)
306 {
307 y_T = _R_specific * T * (NASA7::hOverRT(_data, T) - k) + shift;
308 dy_T_dy = 0;
309 dy_T_dT = _R_specific * (NASA7::cpOverR(_data, T) - k);
310 };
311
312 const CppType target = y + shift;
314 target,
315 T0,
317 shifted_y,
318 name() + "::T_from_energy",
321 .first;
322}
323
324template <typename CppType>
325CppType
326NASA7IdealGasFluidProperties::T_from_v_e_template(const CppType & /*v*/, const CppType & e) const
327{
328 const auto T = T_from_energy(e, 1);
330 return T;
331}
332
333template <typename CppType>
334CppType
335NASA7IdealGasFluidProperties::p_from_v_e_template(const CppType & v, const CppType & e) const
336{
337 const auto T = T_from_energy(e, 1);
339 return _R_specific * T / v;
340}
341
342template <typename CppType>
343CppType
344NASA7IdealGasFluidProperties::c_from_v_e_template(const CppType & /*v*/, const CppType & e) const
345{
346 using std::sqrt;
347 const auto T = T_from_energy(e, 1);
348 return sqrt(gamma_from_T(T) * _R_specific * T);
349}
350
351template <typename CppType>
352CppType
353NASA7IdealGasFluidProperties::cp_from_v_e_template(const CppType & /*v*/, const CppType & e) const
354{
355 return cp_from_T(T_from_energy(e, 1));
356}
357
358template <typename CppType>
359CppType
360NASA7IdealGasFluidProperties::cv_from_v_e_template(const CppType & /*v*/, const CppType & e) const
361{
362 return cv_from_T(T_from_energy(e, 1));
363}
364
365template <typename CppType>
366CppType
367NASA7IdealGasFluidProperties::gamma_from_v_e_template(const CppType & /*v*/,
368 const CppType & e) const
369{
370 return gamma_from_T(T_from_energy(e, 1));
371}
372
373template <typename CppType>
374CppType
375NASA7IdealGasFluidProperties::s_from_v_e_template(const CppType & v, const CppType & e) const
376{
377 return s_from_T_v_template(T_from_energy(e, 1), v);
378}
379
380template <typename CppType>
381CppType
382NASA7IdealGasFluidProperties::g_from_v_e_template(const CppType & v, const CppType & e) const
383{
384 using std::log;
385 const auto T = T_from_energy(e, 1);
387 const auto p = _R_specific * T / v;
388 // g = h - T s
389 return _R_specific * T *
391}
392
393template <typename CppType>
394CppType
395NASA7IdealGasFluidProperties::mu_from_v_e_template(const CppType & /*v*/, const CppType & e) const
396{
397 return mu_from_T(T_from_energy(e, 1));
398}
399
400template <typename CppType>
401CppType
402NASA7IdealGasFluidProperties::k_from_v_e_template(const CppType & /*v*/, const CppType & e) const
403{
404 return k_from_T(T_from_energy(e, 1));
405}
406
407template <typename CppType>
408CppType
409NASA7IdealGasFluidProperties::T_from_p_h_template(const CppType & /*p*/, const CppType & h) const
410{
411 const auto T = T_from_energy(h, 0);
413 return T;
414}
415
416template <typename CppType>
417CppType
418NASA7IdealGasFluidProperties::s_from_h_p_template(const CppType & h, const CppType & p) const
419{
420 return s_from_p_T_template(p, T_from_energy(h, 0));
421}
422
423template <typename CppType>
424CppType
425NASA7IdealGasFluidProperties::p_from_h_s_template(const CppType & h, const CppType & s) const
426{
427 using std::exp;
428 const auto T = T_from_energy(h, 0);
430 // Inverse of s = R_s (s0/R - ln(p / p_ref))
432}
433
434template <typename CppType>
435CppType
436NASA7IdealGasFluidProperties::e_from_v_h_template(const CppType & /*v*/, const CppType & h) const
437{
438 const auto T = T_from_energy(h, 0);
440 return h - _R_specific * T;
441}
442
443template <typename CppType>
444CppType
445NASA7IdealGasFluidProperties::T_from_p_s(const CppType & p, const CppType & s) const
446{
447 using std::exp, std::log;
448
449 // Solve s0(T)/R = s/R_s + ln(p/p_ref) for x = ln(T). The standard entropy s0/R increases with x,
450 // with slope cp/R, and is convex in x over nearly all of the range of the data, because the heat
451 // capacity increases with temperature, so Newton's method started at the upper end of the range
452 // approaches the solution from above. In T instead of ln(T), the first step from the upper end
453 // would overshoot to negative temperatures for solutions near the lower end.
454 const CppType target = s / _R_specific + log(p / NASA7::reference_pressure);
455 const auto s0_from_x = [this](const CppType & /*target*/,
456 const CppType & x,
457 CppType & s0_x,
458 CppType & ds0_x_dtarget,
459 CppType & ds0_x_dx)
460 {
461 const CppType T = exp(x);
462 s0_x = NASA7::sOverR(_data, T);
463 ds0_x_dtarget = 0;
464 ds0_x_dx = NASA7::cpOverR(_data, T);
465 };
466
467 return exp(FluidPropertiesUtils::NewtonSolve(target,
468 target,
469 std::log(_data.T_max),
471 s0_from_x,
472 name() + "::T_from_p_s",
475 .first);
476}
477
478template <typename CppType>
479CppType
480NASA7IdealGasFluidProperties::rho_from_p_s_template(const CppType & p, const CppType & s) const
481{
482 const auto T = T_from_p_s(p, s);
484 return p / (_R_specific * T);
485}
486
491#define definePropertyFromTemplate(want, prop1, prop2) \
492 template <typename CppType> \
493 void NASA7IdealGasFluidProperties::want##_from_##prop1##_##prop2##_template( \
494 const CppType & prop1, \
495 const CppType & prop2, \
496 CppType & val, \
497 CppType & d##want##d1, \
498 CppType & d##want##d2) const \
499 { \
500 const auto value = [this](const auto & x, const auto & y) \
501 { return this->want##_from_##prop1##_##prop2##_template(x, y); }; \
502 xyDerivatives(prop1, prop2, val, d##want##d1, d##want##d2, value); \
503 } \
504 \
505 Real NASA7IdealGasFluidProperties::want##_from_##prop1##_##prop2(Real prop1, Real prop2) const \
506 { \
507 return want##_from_##prop1##_##prop2##_template(prop1, prop2); \
508 } \
509 \
510 ADReal NASA7IdealGasFluidProperties::want##_from_##prop1##_##prop2(const ADReal & prop1, \
511 const ADReal & prop2) const \
512 { \
513 return want##_from_##prop1##_##prop2##_template(prop1, prop2); \
514 } \
515 \
516 void NASA7IdealGasFluidProperties::want##_from_##prop1##_##prop2( \
517 Real prop1, Real prop2, Real & val, Real & d##want##d1, Real & d##want##d2) const \
518 { \
519 want##_from_##prop1##_##prop2##_template(prop1, prop2, val, d##want##d1, d##want##d2); \
520 } \
521 \
522 void NASA7IdealGasFluidProperties::want##_from_##prop1##_##prop2(const ADReal & prop1, \
523 const ADReal & prop2, \
524 ADReal & val, \
525 ADReal & d##want##d1, \
526 ADReal & d##want##d2) const \
527 { \
528 want##_from_##prop1##_##prop2##_template(prop1, prop2, val, d##want##d1, d##want##d2); \
529 }
530
531// clang-format off
532definePropertyFromTemplate(rho, p, T)
533definePropertyFromTemplate(v, p, T)
534definePropertyFromTemplate(e, p, T)
535definePropertyFromTemplate(h, p, T)
536definePropertyFromTemplate(s, p, T)
537definePropertyFromTemplate(cp, p, T)
538definePropertyFromTemplate(cv, p, T)
539definePropertyFromTemplate(c, p, T)
540definePropertyFromTemplate(gamma, p, T)
541definePropertyFromTemplate(mu, p, T)
542definePropertyFromTemplate(k, p, T)
543definePropertyFromTemplate(p, T, v)
544definePropertyFromTemplate(e, T, v)
545definePropertyFromTemplate(h, T, v)
546definePropertyFromTemplate(s, T, v)
547definePropertyFromTemplate(cv, T, v)
548definePropertyFromTemplate(e, p, rho)
549definePropertyFromTemplate(T, v, e)
550definePropertyFromTemplate(p, v, e)
551definePropertyFromTemplate(c, v, e)
552definePropertyFromTemplate(cp, v, e)
553definePropertyFromTemplate(cv, v, e)
554definePropertyFromTemplate(gamma, v, e)
555definePropertyFromTemplate(s, v, e)
556definePropertyFromTemplate(g, v, e)
557definePropertyFromTemplate(mu, v, e)
558definePropertyFromTemplate(k, v, e)
559definePropertyFromTemplate(T, p, h)
560definePropertyFromTemplate(s, h, p)
561definePropertyFromTemplate(p, h, s)
562definePropertyFromTemplate(e, v, h)
563definePropertyFromTemplate(rho, p, s)
564// clang-format on
565
566#undef definePropertyFromTemplate
const std::vector< double > y
const std::vector< double > x
const double mu
const Real p
const double rho
const double T
const double v
registerMooseObject("FluidPropertiesApp", NASA7IdealGasFluidProperties)
const std::string name
Definition Setup.h:21
void suppressParameter(const std::string &name)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
const std::string & name() const
Ideal gas whose heat capacity, enthalpy, and entropy depend on temperature through NASA 7-coefficient...
const NASA7::SpeciesData _data
NASA 7-coefficient data of the species.
NASA7IdealGasFluidProperties(const InputParameters &parameters)
CppType T_from_energy(const CppType &y, const Real k) const
Temperature at which R_s T (h/(RT) - k) equals y, by Newton's method: k = 1 for the specific internal...
const bool _is_steam
Whether the species is steam, whose viscosity and thermal conductivity come from IAPWS.
std::string fluidName() const override
Fluid name.
CppType gamma_from_T(const CppType &T) const
CppType mu_from_T(const CppType &T) const
CppType T_from_p_s(const CppType &p, const CppType &s) const
Temperature at which the specific entropy at pressure p equals s, by Newton's method on the logarithm...
void checkTemperature(const CppType &T) const
Flags a temperature outside the range of the data as a solution warning, because the polynomials are ...
CppType cp_from_T(const CppType &T) const
CppType k_from_T(const CppType &T) const
Real molarMass() const override
Molar mass [kg/mol].
CppType e_from_T(const CppType &T) const
Properties that depend on temperature only.
CppType h_from_T(const CppType &T) const
CppType cv_from_T(const CppType &T) const
void checkTransportTemperature(const CppType &T) const
Checks the temperature as checkTemperature does and, for steam, also flags a temperature outside the ...
const GasTransportUtils::LennardJonesParameters _lennard_jones
Lennard-Jones parameters of the species.
virtual const GasTransportUtils::LennardJonesParameters * lennardJonesParameters() const override
Lennard-Jones parameters of the gas, from which a mixture computes binary diffusion coefficients,...
const Real _R_specific
Specific gas constant [J/(kg K)].
virtual Real newtonStartTemperature() const override
The upper end of the temperature range of the NASA 7-coefficient data [K].
Common class for single phase fluid properties.
const bool _verbose_newton
Whether to output information about newton solves to console.
static InputParameters validParams()
const Real _tolerance
Newton's method may be used to convert between variable sets.
const unsigned int _max_newton_its
Maximum number of iterations for the variable conversion newton solves.
e e e e s T T T T T rho v v T e h
auto exp(const T &)
auto log(const T &)
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
std::pair< T, T > NewtonSolve(const T &x, const T &y, const Real z_initial_guess, const Real tolerance, const Functor &y_from_x_z, const std::string &caller_name, const unsigned int max_its=100, const bool verbose=false)
NewtonSolve does a 1D Newton Solve to solve the equation y = f(x, z) for variable z.
Transport properties of dilute gases: Lennard-Jones parameters of the NASA 7-coefficient species,...
CppType modifiedEuckenConductivity(const CppType &mu, const CppType &cp_over_R, const Real R_specific)
Thermal conductivity of a dilute gas from the modified Eucken correlation [W/(m K)],...
CppType steamViscosityZeroDensity(const CppType &T)
Viscosity of steam in the limit of zero density [Pa s], from the IAPWS 2008 formulation,...
CppType steamConductivityZeroDensity(const CppType &T)
Thermal conductivity of steam in the limit of zero density [W/(m K)], from the IAPWS 2011 formulation...
CppType viscosity(const CppType &T, const Real molar_mass, const LennardJonesParameters &lj)
Chapman-Enskog viscosity of a dilute gas [Pa s].
auto raw_value(const Eigen::Map< T > &in)
Standard-state thermodynamic properties of ideal-gas species from NASA 7-coefficient polynomials.
CppType hOverRT(const SpeciesData &data, const CppType &T)
Standard-state molar enthalpy divided by the gas constant and temperature, h/(RT)
CppType cpOverR(const SpeciesData &data, const CppType &T)
Standard-state molar isobaric heat capacity divided by the gas constant, cp/R.
CppType sOverR(const SpeciesData &data, const CppType &T)
Standard-state molar entropy divided by the gas constant, s/R, at the reference pressure of the data ...
constexpr Real reference_pressure
Pressure at which the standard-state entropy of the built-in species applies [Pa].
std::string speciesNames()
Names of the built-in species, separated by spaces.
Parameters of the Lennard-Jones (12-6) potential of a species.
Real T_max
Upper end of the temperature range of the fit [K].
std::string name
Species name, e.g. "H2O".
Real molar_mass
Molar mass [kg/mol].