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  using std::sqrt;
337  const auto T = T_from_v_e(v, e);
338 
339  const auto c2 = gamma_from_v_e(v, e) * _R_specific * T;
340  if (MetaPhysicL::raw_value(c2) < 0)
341  return getNaN("Sound speed squared (gamma * R * T) is negative: c2 = " +
343 
344  return sqrt(c2);
345 }
346 
347 void
348 CaloricallyImperfectGas::c_from_v_e(Real v, Real e, Real & c, Real & dc_dv, Real & dc_de) const
349 {
350  Real T, dT_dv, dT_de;
351  T_from_v_e(v, e, T, dT_dv, dT_de);
352 
353  Real gamma, dgamma_dv, dgamma_dT;
354  gamma_from_v_e(v, e, gamma, dgamma_dv, dgamma_dT);
355  c = std::sqrt(gamma * _R_specific * T);
356 
357  const Real dc_dT = 0.5 / c * _R_specific * (gamma + T * dgamma_dT);
358  dc_dv = dc_dT * dT_dv;
359  dc_de = dc_dT * dT_de;
360 }
361 
362 Real
364 {
365  return std::sqrt(gamma_from_p_T(p, T) * _R_specific * T);
366 }
367 
368 ADReal
370 {
371  using std::sqrt;
372  return sqrt(gamma_from_p_T(p, T) * _R_specific * T);
373 }
374 
375 void
377  const Real p, const Real T, Real & c, Real & dc_dp, Real & dc_dT) const
378 {
379  Real gamma, dgamma_dp, dgamma_dT;
380  gamma_from_p_T(p, T, gamma, dgamma_dp, dgamma_dT);
381  c = std::sqrt(gamma * _R_specific * T);
382  dc_dp = 0;
383  dc_dT = 0.5 / c * _R_specific * (gamma + T * dgamma_dT);
384 }
385 
386 Real
388 {
389  Real T = T_from_v_e(v, e);
390  return cp_from_T(T);
391 }
392 
393 void
394 CaloricallyImperfectGas::cp_from_v_e(Real v, Real e, Real & cp, Real & dcp_dv, Real & dcp_de) const
395 {
396  Real T = T_from_v_e(v, e);
397  Real dcp_dT;
398  cp_from_T(T, cp, dcp_dT);
399  dcp_dv = 0.0;
400  dcp_de = dcp_dT / cv_from_T(T);
401 }
402 
403 Real
405 {
406  Real T = T_from_v_e(v, e);
407  return cv_from_T(T);
408 }
409 
410 ADReal
412 {
413  Real x = 0;
414  Real raw1 = v.value();
415  Real raw2 = e.value();
416  Real dxd1 = 0;
417  Real dxd2 = 0;
418  cv_from_v_e(raw1, raw2, x, dxd1, dxd2);
419 
420  ADReal result = x;
421  result.derivatives() = v.derivatives() * dxd1 + e.derivatives() * dxd2;
422  return result;
423 }
424 
425 void
426 CaloricallyImperfectGas::cv_from_v_e(Real v, Real e, Real & cv, Real & dcv_dv, Real & dcv_de) const
427 {
428  Real T = T_from_v_e(v, e);
429  Real dcv_dT;
430  cv_from_T(T, cv, dcv_dT);
431  dcv_dv = 0.0;
432  dcv_de = dcv_dT / cv;
433 }
434 
435 Real
437 {
438  return cp_from_v_e(v, e) / cv_from_v_e(v, e);
439 }
440 
441 ADReal
443 {
444  Real x = 0;
445  Real raw1 = v.value();
446  Real raw2 = e.value();
447  Real dxd1 = 0;
448  Real dxd2 = 0;
449  gamma_from_v_e(raw1, raw2, x, dxd1, dxd2);
450 
451  ADReal result = x;
452  result.derivatives() = v.derivatives() * dxd1 + e.derivatives() * dxd2;
453  return result;
454 }
455 
456 void
458  Real v, Real e, Real & gamma, Real & dgamma_dv, Real & dgamma_de) const
459 {
460  Real cp, dcp_dv, dcp_de;
461  cp_from_v_e(v, e, cp, dcp_dv, dcp_de);
462  Real cv, dcv_dv, dcv_de;
463  cv_from_v_e(v, e, cv, dcv_dv, dcv_de);
464  gamma = cp / cv;
465  dgamma_dv = 0.0;
466  dgamma_de = 1.0 / cv * dcp_de - gamma / cv * dcv_de;
467 }
468 
469 void
471  Real p, Real T, Real & gamma, Real & dgamma_dp, Real & dgamma_dT) const
472 {
473  Real cp, dcp_dp, dcp_dT;
474  cp_from_p_T(p, T, cp, dcp_dp, dcp_dT);
475  Real cv, dcv_dp, dcv_dT;
476  cv_from_p_T(p, T, cv, dcv_dp, dcv_dT);
477  gamma = cp / cv;
478  dgamma_dp = 0.0;
479  dgamma_dT = 1.0 / cv * dcp_dT - gamma / cv * dcv_dT;
480 }
481 
482 Real
484 {
485  return cp_from_p_T(p, T) / cv_from_p_T(p, T);
486 }
487 
488 ADReal
490 {
491  Real x = 0;
492  Real raw1 = p.value();
493  Real raw2 = T.value();
494  Real dxd1 = 0;
495  Real dxd2 = 0;
496  gamma_from_p_T(raw1, raw2, x, dxd1, dxd2);
497  ADReal result = x;
498  result.derivatives() = p.derivatives() * dxd1 + T.derivatives() * dxd2;
499  return result;
500 }
501 
502 Real
504 {
505  const Real T = T_from_v_e(v, e);
506  const Real p = p_from_v_e(v, e);
507  return mu_from_p_T(p, T);
508 }
509 
510 void
511 CaloricallyImperfectGas::mu_from_v_e(Real v, Real e, Real & mu, Real & dmu_dv, Real & dmu_de) const
512 {
513  const Real T = T_from_v_e(v, e);
514  const Real p = p_from_v_e(v, e);
515  Real dmu_dp, dmu_dT;
516  mu_from_p_T(p, T, mu, dmu_dp, dmu_dT);
517  // only dmu_de = dmu/dT * dT/de = 1/cv * dmu/dT is nonzero
518  // (dmu/dv)_e = 0 because e only depends on T and e is constant
519  dmu_dv = 0.0;
520  dmu_de = dmu_dT / cv_from_p_T(p, T);
521 }
522 
523 Real
525 {
526  const Real T = T_from_v_e(v, e);
527  const Real p = p_from_v_e(v, e);
528  return k_from_p_T(p, T);
529 }
530 
531 void
532 CaloricallyImperfectGas::k_from_v_e(Real v, Real e, Real & k, Real & dk_dv, Real & dk_de) const
533 {
534  const Real T = T_from_v_e(v, e);
535  const Real p = p_from_v_e(v, e);
536  Real dk_dp, dk_dT;
537  k_from_p_T(p, T, k, dk_dp, dk_dT);
538  // only dk_de = dk/dT * dT/de = 1/cv * dk/dT is nonzero
539  // (dk/dv)_e = 0 because e only depends on T and e is constant
540  dk_dv = 0.0;
541  dk_de = dk_dT / cv_from_p_T(p, T);
542 }
543 
544 Real
546 {
547  Real T = T_from_v_e(v, e);
548  Real Z = Z_from_T(T);
549  return Z + _R_specific * std::log(v);
550 }
551 
552 void
553 CaloricallyImperfectGas::s_from_v_e(Real v, Real e, Real & s, Real & ds_dv, Real & ds_de) const
554 {
555  s = s_from_v_e(v, e);
556  // see documentation for derivation
557  ds_dv = _R_specific / v;
558  ds_de = 1.0 / T_from_v_e(v, e);
559 }
560 
561 Real
563 {
564  Real Z = Z_from_T(T);
565  Real v = 1.0 / rho_from_p_T(p, T);
566  return Z + _R_specific * std::log(v);
567 }
568 
569 void
570 CaloricallyImperfectGas::s_from_p_T(Real p, Real T, Real & s, Real & ds_dp, Real & ds_dT) const
571 {
572  s = s_from_p_T(p, T);
573  ds_dp = -_R_specific / p;
574  ds_dT = cp_from_p_T(p, T) / T;
575 }
576 
577 Real
579 {
580  Real T = T_from_p_h(p, h);
581  Real v = 1.0 / rho_from_p_T(p, T);
582  Real Z = Z_from_T(T);
583  return Z + _R_specific * std::log(v);
584 }
585 
586 void
587 CaloricallyImperfectGas::s_from_h_p(Real h, Real p, Real & s, Real & ds_dh, Real & ds_dp) const
588 {
589  s = s_from_h_p(h, p);
590  ds_dh = 1.0 / T_from_p_h(p, h);
591  ds_dp = -_R_specific / p;
592 }
593 
594 Real
596 {
597  auto s_diff = [&p, &s, this](Real x) { return this->s_from_p_T(p, x) - s; };
600  BrentsMethod::bracket(s_diff, min, max);
601  Real T = BrentsMethod::root(s_diff, min, max);
602  return rho_from_p_T(p, T);
603 }
604 
605 Real
606 CaloricallyImperfectGas::e_from_v_h(Real /*v*/, Real h) const
607 {
608  Real T = T_from_h(h);
609  return e_from_T(T);
610 }
611 
612 void
613 CaloricallyImperfectGas::e_from_v_h(Real v, Real h, Real & e, Real & de_dv, Real & de_dh) const
614 {
615  e = e_from_v_h(v, h);
616  Real cv = cv_from_v_e(v, e);
617  Real cp = cp_from_v_e(v, e);
618  de_dv = 0.0;
619  de_dh = cv / cp;
620 }
621 
622 Real
624 {
625  return p * _molar_mass / (_R * T);
626 }
627 
628 ADReal
630 {
631  return p * _molar_mass / (_R * T);
632 }
633 
634 void
636  const ADReal & p, const ADReal & T, ADReal & rho, ADReal & drho_dp, ADReal & drho_dT) const
637 {
638  rho = rho_from_p_T(p, T);
639  drho_dp = _molar_mass / (_R * T);
640  drho_dT = -p * _molar_mass / (_R * T * T);
641 }
642 
643 void
645  Real p, Real T, Real & rho, Real & drho_dp, Real & drho_dT) const
646 {
647  rho = rho_from_p_T(p, T);
648  drho_dp = _molar_mass / (_R * T);
649  drho_dT = -p * _molar_mass / (_R * T * T);
650 }
651 
652 Real
653 CaloricallyImperfectGas::e_from_p_rho(Real p, Real rho) const
654 {
655  return e_from_p_rho_template(p, rho);
656 }
657 
658 ADReal
659 CaloricallyImperfectGas::e_from_p_rho(const ADReal & p, const ADReal & rho) const
660 {
661  return e_from_p_rho_template(p, rho);
662 }
663 
664 void
665 CaloricallyImperfectGas::e_from_p_rho(
666  Real p, Real rho, Real & e, Real & de_dp, Real & de_drho) const
667 {
668  e_from_p_rho_template(p, rho, e, de_dp, de_drho);
669 }
670 
671 void
672 CaloricallyImperfectGas::e_from_p_rho(
673  const ADReal & p, const ADReal & rho, ADReal & e, ADReal & de_dp, ADReal & de_drho) const
674 {
675  e_from_p_rho_template(p, rho, e, de_dp, de_drho);
676 }
677 
678 Real
679 CaloricallyImperfectGas::e_from_T_v(Real T, Real /*v*/) const
680 {
681  return e_from_T(T);
682 }
683 
684 void
685 CaloricallyImperfectGas::e_from_T_v(Real T, Real v, Real & e, Real & de_dT, Real & de_dv) const
686 {
687  e = e_from_T_v(T, v);
688  de_dT = cv_from_T_v(T, v);
689  de_dv = 0.0;
690 }
691 
692 ADReal
694 {
695  Real x = 0;
696  Real raw1 = T.value();
697  Real raw2 = v.value();
698  Real dxd1 = 0;
699  Real dxd2 = 0;
700  e_from_T_v(raw1, raw2, x, dxd1, dxd2);
701 
702  ADReal result = x;
703  result.derivatives() = T.derivatives() * dxd1 + v.derivatives() * dxd2;
704  return result;
705 }
706 
707 Real
709 {
710  return _R_specific * T / v;
711 }
712 
713 void
714 CaloricallyImperfectGas::p_from_T_v(Real T, Real v, Real & p, Real & dp_dT, Real & dp_dv) const
715 {
716  p = _R_specific * T / v;
717  dp_dT = _R_specific / v;
718  dp_dv = -_R_specific * T / (v * v);
719 }
720 
721 Real
722 CaloricallyImperfectGas::h_from_T_v(Real T, Real /*v*/) const
723 {
724  return h_from_T(T);
725 }
726 
727 void
728 CaloricallyImperfectGas::h_from_T_v(Real T, Real /*v*/, Real & h, Real & dh_dT, Real & dh_dv) const
729 {
730  h = h_from_T(T);
731  dh_dT = cp_from_T(T);
732  dh_dv = 0.0;
733 }
734 
735 Real
737 {
738  Real p = p_from_T_v(T, v);
739  return s_from_p_T(p, T);
740 }
741 
742 void
743 CaloricallyImperfectGas::s_from_T_v(Real T, Real v, Real & s, Real & ds_dT, Real & ds_dv) const
744 {
745  Real p, dp_dT_v, dp_dv_T;
746  Real ds_dp_T, ds_dT_p;
747  p_from_T_v(T, v, p, dp_dT_v, dp_dv_T);
748  s_from_p_T(p, T, s, ds_dp_T, ds_dT_p);
749  ds_dT = ds_dT_p + ds_dp_T * dp_dT_v;
750  ds_dv = ds_dp_T * dp_dv_T;
751 }
752 
753 Real
754 CaloricallyImperfectGas::cv_from_T_v(Real T, Real /*v*/) const
755 {
756  return cv_from_T(T);
757 }
758 
759 Real
761 {
762  return _e_c;
763 }
764 
765 void
766 CaloricallyImperfectGas::v_e_spndl_from_T(Real /*T*/, Real & v, Real & e) const
767 {
768  v = 1. / _rho_c;
769  e = _e_c;
770 }
771 
772 Real
773 CaloricallyImperfectGas::h_from_p_T(Real /*p*/, Real T) const
774 {
775  return h_from_T(T);
776 }
777 
778 void
779 CaloricallyImperfectGas::h_from_p_T(Real p, Real T, Real & h, Real & dh_dp, Real & dh_dT) const
780 {
781  h = h_from_p_T(p, T);
782  dh_dp = 0.0;
783  dh_dT = cp_from_p_T(p, T);
784 }
785 
786 Real
787 CaloricallyImperfectGas::e_from_p_T(Real /*p*/, Real T) const
788 {
789  return e_from_T(T);
790 }
791 
792 ADReal
794 {
795  Real x = 0;
796  Real raw1 = p.value();
797  Real raw2 = T.value();
798  Real dxd1 = 0;
799  Real dxd2 = 0;
800  e_from_p_T(raw1, raw2, x, dxd1, dxd2);
801 
802  ADReal result = x;
803  result.derivatives() = p.derivatives() * dxd1 + T.derivatives() * dxd2;
804  return result;
805 }
806 
807 void
808 CaloricallyImperfectGas::e_from_p_T(Real p, Real T, Real & e, Real & de_dp, Real & de_dT) const
809 {
810  e = e_from_p_T(p, T);
811  de_dp = 0.0;
812  de_dT = cv_from_p_T(p, T);
813 }
814 
815 Real
817 {
818  return _molar_mass;
819 }
820 
821 Real
823 {
824  return _T_c;
825 }
826 
827 Real
829 {
830  return _rho_c;
831 }
832 
833 Real
835 {
836  return _e_c;
837 }
838 
839 Real
840 CaloricallyImperfectGas::T_from_p_h(Real /*p*/, Real h) const
841 {
842  return T_from_h(h);
843 }
844 
845 void
846 CaloricallyImperfectGas::T_from_p_h(Real p, Real h, Real & T, Real & dT_dp, Real & dT_dh) const
847 {
848  T = T_from_p_h(p, h);
849  dT_dp = 0;
850  dT_dh = 1.0 / cp_from_p_T(p, T);
851 }
852 
853 Real
854 CaloricallyImperfectGas::cv_from_p_T(Real /* pressure */, Real temperature) const
855 {
856  return cv_from_T(temperature);
857 }
858 
859 void
861  Real /*p*/, Real T, Real & cv, Real & dcv_dp, Real & dcv_dT) const
862 {
863  cv_from_T(T, cv, dcv_dT);
864  dcv_dp = 0.0;
865 }
866 
867 Real
868 CaloricallyImperfectGas::cp_from_p_T(Real /* pressure */, Real temperature) const
869 {
870  return cp_from_T(temperature);
871 }
872 
873 void
875  Real /*p*/, Real T, Real & cp, Real & dcp_dp, Real & dcp_dT) const
876 {
877  cp_from_T(T, cp, dcp_dT);
878  dcp_dp = 0.0;
879 }
880 
881 Real
882 CaloricallyImperfectGas::mu_from_p_T(Real /* pressure */, Real temperature) const
883 {
884  return _mu_T->value(temperature, Point());
885 }
886 
887 void
888 CaloricallyImperfectGas::mu_from_p_T(Real p, Real T, Real & mu, Real & dmu_dp, Real & dmu_dT) const
889 {
890  mu = this->mu_from_p_T(p, T);
891  dmu_dp = 0.0;
892  Real pert = 1.0e-7;
893  Real mu2 = this->mu_from_p_T(p, T * (1 + pert));
894  dmu_dT = (mu2 - mu) / (T * pert);
895 }
896 
897 Real
898 CaloricallyImperfectGas::k_from_p_T(Real /* pressure */, Real temperature) const
899 {
900  return _k_T->value(temperature, Point());
901 }
902 
903 void
904 CaloricallyImperfectGas::k_from_p_T(Real p, Real T, Real & k, Real & dk_dp, Real & dk_dT) const
905 {
906  k = k_from_p_T(p, T);
907  dk_dp = 0.0;
908  Real pert = 1.0e-7;
909  Real k2 = this->k_from_p_T(p, T * (1 + pert));
910  dk_dT = (k2 - k) / (T * pert);
911 }
912 
913 Real
915 {
916  // use the definition of the Gibbs free energy
917  Real T = T_from_v_e(v, e);
918  Real p = p_from_v_e(v, e);
919  return h_from_p_T(p, T) - T * s_from_p_T(p, T);
920 }
921 
922 Real
924 {
925  Real T = T_from_h(h);
926  Real e = e_from_T(T);
927  Real Z = Z_from_T(T);
928  Real v = std::exp((s - Z) / _R_specific);
929  return p_from_v_e(v, e);
930 }
931 
932 void
933 CaloricallyImperfectGas::p_from_h_s(Real h, Real s, Real & p, Real & dp_dh, Real & dp_ds) const
934 {
935  p = p_from_h_s(h, s);
936  Real pert = 1e-7;
937  Real p_pert = p_from_h_s(h * (1 + pert), s);
938  dp_dh = (p_pert - p) / (h * pert);
939  p_pert = p_from_h_s(h, s * (1 + pert));
940  dp_ds = (p_pert - p) / (s * pert);
941 }
942 
943 void
944 CaloricallyImperfectGas::outOfBounds(const std::string & function,
945  Real value,
946  Real min,
947  Real max) const
948 {
949  std::stringstream ss;
950  ss << "Function " << function << " encountered argument value of " << value
951  << " which is outside of the bounds of " << min << " .. " << max;
953  mooseError(ss.str());
954  else
955  mooseWarning(ss.str());
956 }
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 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
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
virtual Real p_from_v_e(Real v, Real e) const override
void mooseWarning(Args &&... args) const
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