https://mooseframework.inl.gov
CaloricallyImperfectGas.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 #include "Conversion.h"
12 #include "metaphysicl/raw_type.h"
13 #include "Function.h"
14 #include "BrentsMethod.h"
15 
16 registerMooseObject("FluidPropertiesApp", CaloricallyImperfectGas);
17 
20 {
22  params += NaNInterface::validParams();
23 
24  params.addRequiredParam<Real>("molar_mass", "Constant molar mass of the fluid [kg/mol]");
25  params.addRequiredParam<FunctionName>("mu", "Dynamic viscosity, [Pa-s]");
26  params.addRequiredParam<FunctionName>("k", "Thermal conductivity, [W/(m-K)]");
27  params.addParam<Real>("T_c", 0, "Critical temperature, [K]");
28  params.addParam<Real>("rho_c", 0, "Critical density, [kg/m3]");
29  params.addParam<Real>("e_c", 0, "Specific internal energy at the critical point, [J/kg]");
30  params.addRequiredParam<FunctionName>(
31  "e", "Specific internal energy as a function of temperature [J/kg]");
32  params.addRequiredParam<Real>("min_temperature", "Smallest temperature for lookup tables [K]");
33  params.addRequiredParam<Real>("max_temperature", "Largest temperature for lookup tables [K]");
34  params.addParam<Real>(
35  "temperature_resolution", 1, "Step size in temperature for creating the inverse lookup T(e)");
36  params.addParam<bool>("out_of_bound_error", true, "Error if out of bounds");
37  params.addClassDescription("Fluid properties for an ideal gas with imperfect caloric behavior.");
38 
39  return params;
40 }
41 
43  : SinglePhaseFluidProperties(parameters),
44  NaNInterface(this),
45  _molar_mass(getParam<Real>("molar_mass")),
46  _R_specific(_R / _molar_mass),
47  _T_c(getParam<Real>("T_c")),
48  _rho_c(getParam<Real>("rho_c")),
49  _e_c(getParam<Real>("e_c")),
50  _min_temperature(getParam<Real>("min_temperature")),
51  _max_temperature(getParam<Real>("max_temperature")),
52  _delta_T(getParam<Real>("temperature_resolution")),
53  _out_of_bound_error(getParam<bool>("out_of_bound_error")),
54  _tol(1e-4)
55 {
56 }
57 
58 void
60 {
62  _e_T = &getFunction("e");
63  _mu_T = &getFunction("mu");
64  _k_T = &getFunction("k");
65 
67 }
68 
69 void
71 {
72  // estimate number of points in inverse lookup & then adjust
73  // the _delta_T so (n - 1) * _delta_T = _max_temperature - _min_temperature
74  unsigned int n = std::floor((_max_temperature - _min_temperature) / _delta_T) + 1;
76 
77  // ensure e(T) is monotonic
78  for (unsigned int j = 0; j < n; ++j)
79  {
81 
82  // Note that the function behavior at the end points
83  // can lead to de/dT = 0 & we want to allow that
84  Real cv = _e_T->timeDerivative(temperature, Point());
85  if (cv < 0 || (cv == 0 && j > 0 && j < n - 1))
86  mooseError("e(T) is not monotonically increasing with T");
87  }
88 
89  // backward lookup tables
90  _min_e = _e_T->value(_min_temperature, Point());
91  _max_e = _e_T->value(_max_temperature, Point());
92  _delta_e = (_max_e - _min_e) / ((Real)n - 1.0);
95  _delta_h = (_max_h - _min_h) / ((Real)n - 1.0);
96 
97  _T_e_lookup.resize(n);
98  _T_h_lookup.resize(n);
99  _Z_T_lookup.resize(n);
100  for (unsigned int j = 0; j < n; ++j)
101  {
102  // internal energy
103  {
105 
106  // guarding against roundoff when summing
107  // at least once I saw roundoff cause an error here
109 
110  // The temperature is found by e - e(T) = 0
113  auto e_diff = [&internal_energy, this](Real x)
114  { return this->e_from_p_T(0.0, x) - internal_energy; };
115  BrentsMethod::bracket(e_diff, min, max);
118  }
119 
120  // enthalpy
121  {
122  Real enthalpy = _min_h + j * _delta_h;
123 
124  // guarding against roundoff when summing
125  // at least once I saw roundoff cause an error here
126  enthalpy = std::min(enthalpy, _max_h);
127 
128  // The temperature is found by h - h(T) = 0
131  auto h_diff = [&enthalpy, this](Real x) { return this->h_from_p_T(0.0, x) - enthalpy; };
132  BrentsMethod::bracket(h_diff, min, max);
135  }
136 
137  // Z(T)
138  {
139  if (j == 0)
140  _Z_T_lookup[j] = 0;
141  else
142  {
144  Real temperature_prev = _min_temperature + (j - 1) * _delta_T;
146  Real f2 = cv_from_T(temperature_prev) / temperature_prev;
147  _Z_T_lookup[j] = _Z_T_lookup[j - 1] + 0.5 * _delta_T * (f1 + f2);
148  }
149  }
150  }
151 }
152 
153 std::string
155 {
156  return "caloric_imperfect_gas";
157 }
158 
159 Real
161 {
162  if (T < _min_temperature || T > _max_temperature)
164 
165  return _e_T->value(T, Point());
166 }
167 
168 Real
170 {
171  if (T < _min_temperature || T > _max_temperature)
173  return _e_T->value(T, Point()) + _R_specific * T;
174 }
175 
176 Real
178 {
179  if (T < _min_temperature || T > _max_temperature)
181 
182  return _e_T->timeDerivative(T, Point()) + _R_specific;
183 }
184 
185 void
186 CaloricallyImperfectGas::cv_from_T(Real T, Real & cv, Real & dcv_dT) const
187 {
188  if (T < _min_temperature || T > _max_temperature)
189  outOfBounds("cv_from_T (3 args)", T, _min_temperature, _max_temperature);
190  Real pert = 1.0e-7;
191  cv = cv_from_T(T);
192  Real cv_pert = cv_from_T(T * (1 + pert));
193  dcv_dT = (cv_pert - cv) / (T * pert);
194 }
195 
196 void
197 CaloricallyImperfectGas::cp_from_T(Real T, Real & cp, Real & dcp_dT) const
198 {
199  if (T < _min_temperature || T > _max_temperature)
200  outOfBounds("cp_from_T (3 args)", T, _min_temperature, _max_temperature);
201  Real pert = 1.0e-7;
202  cp = cp_from_T(T);
203  Real cp_pert = cp_from_T(T * (1 + pert));
204  dcp_dT = (cp_pert - cp) / (T * pert);
205 }
206 
207 Real
209 {
210  if (e < _min_e || e > _max_e)
211  outOfBounds("T_from_e", e, _min_e, _max_e);
212 
213  if (e < _min_e)
214  return _T_e_lookup[0];
215  else if (e > _max_e)
216  return _T_e_lookup.back();
217 
218  unsigned int index = std::floor((e - _min_e) / _delta_e);
219  Real x = (e - _min_e - index * _delta_e) / _delta_e;
220  return x * _T_e_lookup[index + 1] + (1 - x) * _T_e_lookup[index];
221 }
222 
223 Real
225 {
226  if (h < _min_h || h > _max_h)
227  outOfBounds("h_from_e", h, _min_h, _max_h);
228 
229  if (h < _min_h)
230  return _T_h_lookup[0];
231  else if (h > _max_h)
232  return _T_h_lookup.back();
233 
234  unsigned int index = std::floor((h - _min_h) / _delta_h);
235  Real x = (h - _min_h - index * _delta_h) / _delta_h;
236  return x * _T_h_lookup[index + 1] + (1 - x) * _T_h_lookup[index];
237 }
238 
239 Real
241 {
242  if (T < _min_temperature || T > _max_temperature)
244 
245  unsigned int index = std::floor((T - _min_temperature) / _delta_T);
246  Real x = (T - _min_temperature - index * _delta_T) / _delta_T;
247  return x * _Z_T_lookup[index + 1] + (1 - x) * _Z_T_lookup[index];
248 }
249 
250 Real
252 {
253  if (v == 0.0)
254  return getNaN("Invalid value of specific volume detected (v = " + Moose::stringify(v) + ").");
255 
256  return _R_specific * T_from_e(e) / v;
257 }
258 
259 ADReal
261 {
262  if (v.value() == 0.0)
263  return getNaN("Invalid value of specific volume detected (v = " + Moose::stringify(v.value()) +
264  ").");
265 
266  Real x = 0;
267  Real raw1 = v.value();
268  Real raw2 = e.value();
269  Real dxd1 = 0;
270  Real dxd2 = 0;
271  p_from_v_e(raw1, raw2, x, dxd1, dxd2);
272 
273  ADReal result = x;
274  result.derivatives() = v.derivatives() * dxd1 + e.derivatives() * dxd2;
275  return result;
276 }
277 
278 void
279 CaloricallyImperfectGas::p_from_v_e(Real v, Real e, Real & p, Real & dp_dv, Real & dp_de) const
280 {
281  p = p_from_v_e(v, e);
282  Real T = T_from_e(e);
283  dp_dv = -_R_specific * T / v / v;
284  dp_de = _R_specific / v / cv_from_T(T);
285 }
286 
287 Real
288 CaloricallyImperfectGas::T_from_v_e(Real /*v*/, Real e) const
289 {
290  return T_from_e(e);
291 }
292 
293 ADReal
295 {
296  if (v.value() == 0.0)
297  return getNaN("Invalid value of specific volume detected (v = " + Moose::stringify(v.value()) +
298  ").");
299 
300  Real x = 0;
301  Real raw1 = v.value();
302  Real raw2 = e.value();
303  Real dxd1 = 0;
304  Real dxd2 = 0;
305  T_from_v_e(raw1, raw2, x, dxd1, dxd2);
306 
307  ADReal result = x;
308  result.derivatives() = v.derivatives() * dxd1 + e.derivatives() * dxd2;
309  return result;
310 }
311 
312 void
313 CaloricallyImperfectGas::T_from_v_e(Real v, Real e, Real & T, Real & dT_dv, Real & dT_de) const
314 {
315  T = T_from_e(e);
316  dT_dv = 0.0;
317  dT_de = 1.0 / cv_from_v_e(v, e);
318 }
319 
320 Real
322 {
323  Real T = T_from_v_e(v, e);
324 
325  const Real c2 = gamma_from_v_e(v, e) * _R_specific * T;
326  if (c2 < 0)
327  return getNaN("Sound speed squared (gamma * R * T) is negative: c2 = " + Moose::stringify(c2) +
328  ".");
329 
330  return std::sqrt(c2);
331 }
332 
333 ADReal
335 {
336  const auto T = T_from_v_e(v, e);
337 
338  const auto c2 = gamma_from_v_e(v, e) * _R_specific * T;
339  if (MetaPhysicL::raw_value(c2) < 0)
340  return getNaN("Sound speed squared (gamma * R * T) is negative: c2 = " +
342 
343  return std::sqrt(c2);
344 }
345 
346 void
347 CaloricallyImperfectGas::c_from_v_e(Real v, Real e, Real & c, Real & dc_dv, Real & dc_de) const
348 {
349  Real T, dT_dv, dT_de;
350  T_from_v_e(v, e, T, dT_dv, dT_de);
351 
352  Real gamma, dgamma_dv, dgamma_dT;
353  gamma_from_v_e(v, e, gamma, dgamma_dv, dgamma_dT);
354  c = std::sqrt(gamma * _R_specific * T);
355 
356  const Real dc_dT = 0.5 / c * _R_specific * (gamma + T * dgamma_dT);
357  dc_dv = dc_dT * dT_dv;
358  dc_de = dc_dT * dT_de;
359 }
360 
361 Real
363 {
364  return std::sqrt(gamma_from_p_T(p, T) * _R_specific * T);
365 }
366 
367 ADReal
369 {
370  return std::sqrt(gamma_from_p_T(p, T) * _R_specific * T);
371 }
372 
373 void
375  const Real p, const Real T, Real & c, Real & dc_dp, Real & dc_dT) const
376 {
377  Real gamma, dgamma_dp, dgamma_dT;
378  gamma_from_p_T(p, T, gamma, dgamma_dp, dgamma_dT);
379  c = std::sqrt(gamma * _R_specific * T);
380  dc_dp = 0;
381  dc_dT = 0.5 / c * _R_specific * (gamma + T * dgamma_dT);
382 }
383 
384 Real
386 {
387  Real T = T_from_v_e(v, e);
388  return cp_from_T(T);
389 }
390 
391 void
392 CaloricallyImperfectGas::cp_from_v_e(Real v, Real e, Real & cp, Real & dcp_dv, Real & dcp_de) const
393 {
394  Real T = T_from_v_e(v, e);
395  Real dcp_dT;
396  cp_from_T(T, cp, dcp_dT);
397  dcp_dv = 0.0;
398  dcp_de = dcp_dT / cv_from_T(T);
399 }
400 
401 Real
403 {
404  Real T = T_from_v_e(v, e);
405  return cv_from_T(T);
406 }
407 
408 ADReal
410 {
411  Real x = 0;
412  Real raw1 = v.value();
413  Real raw2 = e.value();
414  Real dxd1 = 0;
415  Real dxd2 = 0;
416  cv_from_v_e(raw1, raw2, x, dxd1, dxd2);
417 
418  ADReal result = x;
419  result.derivatives() = v.derivatives() * dxd1 + e.derivatives() * dxd2;
420  return result;
421 }
422 
423 void
424 CaloricallyImperfectGas::cv_from_v_e(Real v, Real e, Real & cv, Real & dcv_dv, Real & dcv_de) const
425 {
426  Real T = T_from_v_e(v, e);
427  Real dcv_dT;
428  cv_from_T(T, cv, dcv_dT);
429  dcv_dv = 0.0;
430  dcv_de = dcv_dT / cv;
431 }
432 
433 Real
435 {
436  return cp_from_v_e(v, e) / cv_from_v_e(v, e);
437 }
438 
439 ADReal
441 {
442  Real x = 0;
443  Real raw1 = v.value();
444  Real raw2 = e.value();
445  Real dxd1 = 0;
446  Real dxd2 = 0;
447  gamma_from_v_e(raw1, raw2, x, dxd1, dxd2);
448 
449  ADReal result = x;
450  result.derivatives() = v.derivatives() * dxd1 + e.derivatives() * dxd2;
451  return result;
452 }
453 
454 void
456  Real v, Real e, Real & gamma, Real & dgamma_dv, Real & dgamma_de) const
457 {
458  Real cp, dcp_dv, dcp_de;
459  cp_from_v_e(v, e, cp, dcp_dv, dcp_de);
460  Real cv, dcv_dv, dcv_de;
461  cv_from_v_e(v, e, cv, dcv_dv, dcv_de);
462  gamma = cp / cv;
463  dgamma_dv = 0.0;
464  dgamma_de = 1.0 / cv * dcp_de - gamma / cv * dcv_de;
465 }
466 
467 void
469  Real p, Real T, Real & gamma, Real & dgamma_dp, Real & dgamma_dT) const
470 {
471  Real cp, dcp_dp, dcp_dT;
472  cp_from_p_T(p, T, cp, dcp_dp, dcp_dT);
473  Real cv, dcv_dp, dcv_dT;
474  cv_from_p_T(p, T, cv, dcv_dp, dcv_dT);
475  gamma = cp / cv;
476  dgamma_dp = 0.0;
477  dgamma_dT = 1.0 / cv * dcp_dT - gamma / cv * dcv_dT;
478 }
479 
480 Real
482 {
483  return cp_from_p_T(p, T) / cv_from_p_T(p, T);
484 }
485 
486 ADReal
488 {
489  Real x = 0;
490  Real raw1 = p.value();
491  Real raw2 = T.value();
492  Real dxd1 = 0;
493  Real dxd2 = 0;
494  gamma_from_p_T(raw1, raw2, x, dxd1, dxd2);
495  ADReal result = x;
496  result.derivatives() = p.derivatives() * dxd1 + T.derivatives() * dxd2;
497  return result;
498 }
499 
500 Real
502 {
503  const Real T = T_from_v_e(v, e);
504  const Real p = p_from_v_e(v, e);
505  return mu_from_p_T(p, T);
506 }
507 
508 void
509 CaloricallyImperfectGas::mu_from_v_e(Real v, Real e, Real & mu, Real & dmu_dv, Real & dmu_de) const
510 {
511  const Real T = T_from_v_e(v, e);
512  const Real p = p_from_v_e(v, e);
513  Real dmu_dp, dmu_dT;
514  mu_from_p_T(p, T, mu, dmu_dp, dmu_dT);
515  // only dmu_de = dmu/dT * dT/de = 1/cv * dmu/dT is nonzero
516  // (dmu/dv)_e = 0 because e only depends on T and e is constant
517  dmu_dv = 0.0;
518  dmu_de = dmu_dT / cv_from_p_T(p, T);
519 }
520 
521 Real
523 {
524  const Real T = T_from_v_e(v, e);
525  const Real p = p_from_v_e(v, e);
526  return k_from_p_T(p, T);
527 }
528 
529 void
530 CaloricallyImperfectGas::k_from_v_e(Real v, Real e, Real & k, Real & dk_dv, Real & dk_de) const
531 {
532  const Real T = T_from_v_e(v, e);
533  const Real p = p_from_v_e(v, e);
534  Real dk_dp, dk_dT;
535  k_from_p_T(p, T, k, dk_dp, dk_dT);
536  // only dk_de = dk/dT * dT/de = 1/cv * dk/dT is nonzero
537  // (dk/dv)_e = 0 because e only depends on T and e is constant
538  dk_dv = 0.0;
539  dk_de = dk_dT / cv_from_p_T(p, T);
540 }
541 
542 Real
544 {
545  Real T = T_from_v_e(v, e);
546  Real Z = Z_from_T(T);
547  return Z + _R_specific * std::log(v);
548 }
549 
550 void
551 CaloricallyImperfectGas::s_from_v_e(Real v, Real e, Real & s, Real & ds_dv, Real & ds_de) const
552 {
553  s = s_from_v_e(v, e);
554  // see documentation for derivation
555  ds_dv = _R_specific / v;
556  ds_de = 1.0 / T_from_v_e(v, e);
557 }
558 
559 Real
561 {
562  Real Z = Z_from_T(T);
563  Real v = 1.0 / rho_from_p_T(p, T);
564  return Z + _R_specific * std::log(v);
565 }
566 
567 void
568 CaloricallyImperfectGas::s_from_p_T(Real p, Real T, Real & s, Real & ds_dp, Real & ds_dT) const
569 {
570  s = s_from_p_T(p, T);
571  ds_dp = -_R_specific / p;
572  ds_dT = cp_from_p_T(p, T) / T;
573 }
574 
575 Real
577 {
578  Real T = T_from_p_h(p, h);
579  Real v = 1.0 / rho_from_p_T(p, T);
580  Real Z = Z_from_T(T);
581  return Z + _R_specific * std::log(v);
582 }
583 
584 void
585 CaloricallyImperfectGas::s_from_h_p(Real h, Real p, Real & s, Real & ds_dh, Real & ds_dp) const
586 {
587  s = s_from_h_p(h, p);
588  ds_dh = 1.0 / T_from_p_h(p, h);
589  ds_dp = -_R_specific / p;
590 }
591 
592 Real
594 {
595  auto s_diff = [&p, &s, this](Real x) { return this->s_from_p_T(p, x) - s; };
598  BrentsMethod::bracket(s_diff, min, max);
599  Real T = BrentsMethod::root(s_diff, min, max);
600  return rho_from_p_T(p, T);
601 }
602 
603 Real
604 CaloricallyImperfectGas::e_from_v_h(Real /*v*/, Real h) const
605 {
606  Real T = T_from_h(h);
607  return e_from_T(T);
608 }
609 
610 void
611 CaloricallyImperfectGas::e_from_v_h(Real v, Real h, Real & e, Real & de_dv, Real & de_dh) const
612 {
613  e = e_from_v_h(v, h);
614  Real cv = cv_from_v_e(v, e);
615  Real cp = cp_from_v_e(v, e);
616  de_dv = 0.0;
617  de_dh = cv / cp;
618 }
619 
620 Real
622 {
623  return p * _molar_mass / (_R * T);
624 }
625 
626 ADReal
628 {
629  return p * _molar_mass / (_R * T);
630 }
631 
632 void
634  const ADReal & p, const ADReal & T, ADReal & rho, ADReal & drho_dp, ADReal & drho_dT) const
635 {
636  rho = rho_from_p_T(p, T);
637  drho_dp = _molar_mass / (_R * T);
638  drho_dT = -p * _molar_mass / (_R * T * T);
639 }
640 
641 void
643  Real p, Real T, Real & rho, Real & drho_dp, Real & drho_dT) const
644 {
645  rho = rho_from_p_T(p, T);
646  drho_dp = _molar_mass / (_R * T);
647  drho_dT = -p * _molar_mass / (_R * T * T);
648 }
649 
650 Real
651 CaloricallyImperfectGas::e_from_p_rho(Real p, Real rho) const
652 {
653  return e_from_p_rho_template(p, rho);
654 }
655 
656 ADReal
657 CaloricallyImperfectGas::e_from_p_rho(const ADReal & p, const ADReal & rho) const
658 {
659  return e_from_p_rho_template(p, rho);
660 }
661 
662 void
663 CaloricallyImperfectGas::e_from_p_rho(
664  Real p, Real rho, Real & e, Real & de_dp, Real & de_drho) const
665 {
666  e_from_p_rho_template(p, rho, e, de_dp, de_drho);
667 }
668 
669 void
670 CaloricallyImperfectGas::e_from_p_rho(
671  const ADReal & p, const ADReal & rho, ADReal & e, ADReal & de_dp, ADReal & de_drho) const
672 {
673  e_from_p_rho_template(p, rho, e, de_dp, de_drho);
674 }
675 
676 Real
677 CaloricallyImperfectGas::e_from_T_v(Real T, Real /*v*/) const
678 {
679  return e_from_T(T);
680 }
681 
682 void
683 CaloricallyImperfectGas::e_from_T_v(Real T, Real v, Real & e, Real & de_dT, Real & de_dv) const
684 {
685  e = e_from_T_v(T, v);
686  de_dT = cv_from_T_v(T, v);
687  de_dv = 0.0;
688 }
689 
690 ADReal
692 {
693  Real x = 0;
694  Real raw1 = T.value();
695  Real raw2 = v.value();
696  Real dxd1 = 0;
697  Real dxd2 = 0;
698  e_from_T_v(raw1, raw2, x, dxd1, dxd2);
699 
700  ADReal result = x;
701  result.derivatives() = T.derivatives() * dxd1 + v.derivatives() * dxd2;
702  return result;
703 }
704 
705 Real
707 {
708  return _R_specific * T / v;
709 }
710 
711 void
712 CaloricallyImperfectGas::p_from_T_v(Real T, Real v, Real & p, Real & dp_dT, Real & dp_dv) const
713 {
714  p = _R_specific * T / v;
715  dp_dT = _R_specific / v;
716  dp_dv = -_R_specific * T / (v * v);
717 }
718 
719 Real
720 CaloricallyImperfectGas::h_from_T_v(Real T, Real /*v*/) const
721 {
722  return h_from_T(T);
723 }
724 
725 void
726 CaloricallyImperfectGas::h_from_T_v(Real T, Real /*v*/, Real & h, Real & dh_dT, Real & dh_dv) const
727 {
728  h = h_from_T(T);
729  dh_dT = cp_from_T(T);
730  dh_dv = 0.0;
731 }
732 
733 Real
735 {
736  Real p = p_from_T_v(T, v);
737  return s_from_p_T(p, T);
738 }
739 
740 void
741 CaloricallyImperfectGas::s_from_T_v(Real T, Real v, Real & s, Real & ds_dT, Real & ds_dv) const
742 {
743  Real p, dp_dT_v, dp_dv_T;
744  Real ds_dp_T, ds_dT_p;
745  p_from_T_v(T, v, p, dp_dT_v, dp_dv_T);
746  s_from_p_T(p, T, s, ds_dp_T, ds_dT_p);
747  ds_dT = ds_dT_p + ds_dp_T * dp_dT_v;
748  ds_dv = ds_dp_T * dp_dv_T;
749 }
750 
751 Real
752 CaloricallyImperfectGas::cv_from_T_v(Real T, Real /*v*/) const
753 {
754  return cv_from_T(T);
755 }
756 
757 Real CaloricallyImperfectGas::e_spndl_from_v(Real /*v*/) const { return _e_c; }
758 
759 void
760 CaloricallyImperfectGas::v_e_spndl_from_T(Real /*T*/, Real & v, Real & e) const
761 {
762  v = 1. / _rho_c;
763  e = _e_c;
764 }
765 
766 Real
767 CaloricallyImperfectGas::h_from_p_T(Real /*p*/, Real T) const
768 {
769  return h_from_T(T);
770 }
771 
772 void
773 CaloricallyImperfectGas::h_from_p_T(Real p, Real T, Real & h, Real & dh_dp, Real & dh_dT) const
774 {
775  h = h_from_p_T(p, T);
776  dh_dp = 0.0;
777  dh_dT = cp_from_p_T(p, T);
778 }
779 
780 Real
781 CaloricallyImperfectGas::e_from_p_T(Real /*p*/, Real T) const
782 {
783  return e_from_T(T);
784 }
785 
786 ADReal
788 {
789  Real x = 0;
790  Real raw1 = p.value();
791  Real raw2 = T.value();
792  Real dxd1 = 0;
793  Real dxd2 = 0;
794  e_from_p_T(raw1, raw2, x, dxd1, dxd2);
795 
796  ADReal result = x;
797  result.derivatives() = p.derivatives() * dxd1 + T.derivatives() * dxd2;
798  return result;
799 }
800 
801 void
802 CaloricallyImperfectGas::e_from_p_T(Real p, Real T, Real & e, Real & de_dp, Real & de_dT) const
803 {
804  e = e_from_p_T(p, T);
805  de_dp = 0.0;
806  de_dT = cv_from_p_T(p, T);
807 }
808 
809 Real
811 {
812  return _molar_mass;
813 }
814 
815 Real
817 {
818  return _T_c;
819 }
820 
821 Real
823 {
824  return _rho_c;
825 }
826 
827 Real
829 {
830  return _e_c;
831 }
832 
833 Real
834 CaloricallyImperfectGas::T_from_p_h(Real /*p*/, Real h) const
835 {
836  return T_from_h(h);
837 }
838 
839 void
840 CaloricallyImperfectGas::T_from_p_h(Real p, Real h, Real & T, Real & dT_dp, Real & dT_dh) const
841 {
842  T = T_from_p_h(p, h);
843  dT_dp = 0;
844  dT_dh = 1.0 / cp_from_p_T(p, T);
845 }
846 
847 Real
848 CaloricallyImperfectGas::cv_from_p_T(Real /* pressure */, Real temperature) const
849 {
850  return cv_from_T(temperature);
851 }
852 
853 void
855  Real /*p*/, Real T, Real & cv, Real & dcv_dp, Real & dcv_dT) const
856 {
857  cv_from_T(T, cv, dcv_dT);
858  dcv_dp = 0.0;
859 }
860 
861 Real
862 CaloricallyImperfectGas::cp_from_p_T(Real /* pressure */, Real temperature) const
863 {
864  return cp_from_T(temperature);
865 }
866 
867 void
869  Real /*p*/, Real T, Real & cp, Real & dcp_dp, Real & dcp_dT) const
870 {
871  cp_from_T(T, cp, dcp_dT);
872  dcp_dp = 0.0;
873 }
874 
875 Real
876 CaloricallyImperfectGas::mu_from_p_T(Real /* pressure */, Real temperature) const
877 {
878  return _mu_T->value(temperature, Point());
879 }
880 
881 void
882 CaloricallyImperfectGas::mu_from_p_T(Real p, Real T, Real & mu, Real & dmu_dp, Real & dmu_dT) const
883 {
884  mu = this->mu_from_p_T(p, T);
885  dmu_dp = 0.0;
886  Real pert = 1.0e-7;
887  Real mu2 = this->mu_from_p_T(p, T * (1 + pert));
888  dmu_dT = (mu2 - mu) / (T * pert);
889 }
890 
891 Real
892 CaloricallyImperfectGas::k_from_p_T(Real /* pressure */, Real temperature) const
893 {
894  return _k_T->value(temperature, Point());
895 }
896 
897 void
898 CaloricallyImperfectGas::k_from_p_T(Real p, Real T, Real & k, Real & dk_dp, Real & dk_dT) const
899 {
900  k = k_from_p_T(p, T);
901  dk_dp = 0.0;
902  Real pert = 1.0e-7;
903  Real k2 = this->k_from_p_T(p, T * (1 + pert));
904  dk_dT = (k2 - k) / (T * pert);
905 }
906 
907 Real
909 {
910  // use the definition of the Gibbs free energy
911  Real T = T_from_v_e(v, e);
912  Real p = p_from_v_e(v, e);
913  return h_from_p_T(p, T) - T * s_from_p_T(p, T);
914 }
915 
916 Real
918 {
919  Real T = T_from_h(h);
920  Real e = e_from_T(T);
921  Real Z = Z_from_T(T);
922  Real v = std::exp((s - Z) / _R_specific);
923  return p_from_v_e(v, e);
924 }
925 
926 void
927 CaloricallyImperfectGas::p_from_h_s(Real h, Real s, Real & p, Real & dp_dh, Real & dp_ds) const
928 {
929  p = p_from_h_s(h, s);
930  Real pert = 1e-7;
931  Real p_pert = p_from_h_s(h * (1 + pert), s);
932  dp_dh = (p_pert - p) / (h * pert);
933  p_pert = p_from_h_s(h, s * (1 + pert));
934  dp_ds = (p_pert - p) / (s * pert);
935 }
936 
937 void
938 CaloricallyImperfectGas::outOfBounds(const std::string & function,
939  Real value,
940  Real min,
941  Real max) const
942 {
943  std::stringstream ss;
944  ss << "Function " << function << " encountered argument value of " << value
945  << " which is outside of the bounds of " << min << " .. " << max;
947  mooseError(ss.str());
948  else
949  mooseWarning(ss.str());
950 }
virtual void initialSetup() override
static const std::string cv
Definition: NS.h:122
virtual Real mu_from_p_T(Real p, Real T) const override
A calorically imperfect gas fluid property class This fluid property assumes that internal energy is ...
CaloricallyImperfectGas(const InputParameters &parameters)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
static InputParameters validParams()
virtual Real cv_from_T_v(Real T, Real v) const override
virtual Real criticalInternalEnergy() const override
Critical specific internal energy.
virtual Real p_from_h_s(Real h, Real s) const override
const Function & getFunction(const std::string &name) const
virtual Real e_from_v_h(Real v, Real h) const override
virtual Real timeDerivative(Real t, const Point &p) const
virtual Real cp_from_p_T(Real p, Real T) const override
Real _min_e
internal energy and enthalpy limits when creating lookup tables
const bool _out_of_bound_error
Flag to error if out of bounds.
Real _delta_e
step size in internal energy and enthalpy
virtual Real h_from_T_v(Real T, Real v) const override
virtual Real gamma_from_v_e(Real v, Real e) const override
void outOfBounds(const std::string &function, Real value, Real min, Real max) const
function that handles exceeding parameter limits
virtual void v_e_spndl_from_T(Real T, Real &v, Real &e) const override
Specific internal energy from temperature and specific volume.
auto raw_value(const Eigen::Map< T > &in)
Real getNaN() const
Throws an error or returns a NaN with or without a warning, with a default message.
Definition: NaNInterface.h:46
virtual Real molarMass() const override
Molar mass [kg/mol].
static const Real _R
Universal gas constant (J/mol/K)
virtual Real T_from_p_h(Real p, Real h) const override
virtual Real criticalDensity() const override
Critical density.
virtual Real rho_from_p_s(Real p, Real s) const override
static const std::string temperature
Definition: NS.h:59
virtual Real mu_from_v_e(Real v, Real e) const override
virtual Real g_from_v_e(Real v, Real e) const override
DualNumber< Real, DNDerivativeType, true > ADReal
virtual Real k_from_v_e(Real v, Real e) const override
void mooseWarning(Args &&... args) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
auto max(const L &left, const R &right)
virtual Real cv_from_v_e(Real v, Real e) const override
static InputParameters validParams()
Real e_from_T(Real T) const
helper functions for e(T) and h(T), T(e), T(h), cv(T), cp(T)
virtual Real k_from_p_T(Real pressure, Real temperature) const override
virtual Real criticalTemperature() const override
Critical temperature.
static const std::string cp
Definition: NS.h:121
e e e e s T T T T T rho v v T e h
virtual Real T_from_v_e(Real v, Real e) const override
virtual std::string fluidName() const override
Fluid name.
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
const Function * _k_T
Thermal conductivity.
const std::vector< double > x
virtual Real s_from_p_T(Real p, Real T) const override
static const std::string mu
Definition: NS.h:123
Real cv_from_T(const CppType &T) const
virtual Real e_spndl_from_v(Real v) const override
Specific internal energy from temperature and specific volume.
Real root(std::function< Real(Real)> const &f, Real x1, Real x2, Real tol=1.0e-12)
Finds the root of a function using Brent&#39;s method.
Definition: BrentsMethod.C:66
void setupLookupTables()
sets up the T(e) reverse lookup table
std::vector< Real > _T_h_lookup
inverse lookup table data
virtual Real e_from_p_T(Real p, Real T) const override
virtual Real e_from_T_v(Real T, Real v) const override
Common class for single phase fluid properties.
const Function * _mu_T
Dynamic viscosity.
virtual Real cp_from_v_e(Real v, Real e) const override
virtual Real rho_from_p_T(Real p, Real T) const override
virtual Real c_from_v_e(Real v, Real e) const override
virtual Real s_from_v_e(Real v, Real e) const override
std::string stringify(const T &t)
const Function * _e_T
Internal energy as a function of temperature.
virtual Real h_from_p_T(Real p, Real T) const override
virtual Real p_from_T_v(Real T, Real v) const override
static const std::string Z
Definition: NS.h:169
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
Definition: NS.h:84
Real _delta_T
temperature interval in lookup tables
virtual Real p_from_v_e(Real v, Real e) const override
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
static const std::string internal_energy
Definition: NS.h:61
virtual Real gamma_from_p_T(Real p, Real T) const override
static InputParameters validParams()
Definition: NaNInterface.C:15
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
virtual Real s_from_h_p(Real h, Real p) const override
virtual Real value(Real t, const Point &p) const
virtual void initialSetup()
registerMooseObject("FluidPropertiesApp", CaloricallyImperfectGas)
const Real & _molar_mass
molar mass
Interface class for producing errors, warnings, or just quiet NaNs.
Definition: NaNInterface.h:22
Real _min_temperature
temperature limits when creating lookup tables
auto min(const L &left, const R &right)
const Real _R_specific
Specific gas constant (R / molar mass)
static const std::string k
Definition: NS.h:130
virtual Real s_from_T_v(Real T, Real v) const override
virtual Real cv_from_p_T(Real p, Real T) const override
std::vector< Real > _Z_T_lookup
Z(T) lookup table on uniform grid between _min_temperature and _max_temperature.
virtual Real c_from_p_T(Real p, Real T) const override
void bracket(std::function< Real(Real)> const &f, Real &x1, Real &x2)
Function to bracket a root of a given function.
Definition: BrentsMethod.C:17