https://mooseframework.inl.gov
Water97FluidProperties.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 
10 #include "Water97FluidProperties.h"
11 #include "MathUtils.h"
12 #include "libmesh/utility.h"
13 
14 registerMooseObject("FluidPropertiesApp", Water97FluidProperties);
15 
18 {
20  params.addClassDescription("Fluid properties for water and steam (H2O) using IAPWS-IF97");
21  return params;
22 }
23 
25  : SinglePhaseFluidProperties(parameters),
26  _Mh2o(18.015e-3),
27  _Rw(461.526),
28  _p_critical(22.064e6),
29  _T_critical(647.096),
30  _rho_critical(322.0),
31  _p_triple(611.657),
32  _T_triple(273.16)
33 {
34 }
35 
37 
38 std::string
40 {
41  return "water";
42 }
43 
44 Real
46 {
47  return _Mh2o;
48 }
49 
50 Real
52 {
53  return _p_critical;
54 }
55 
56 Real
58 {
59  return _T_critical;
60 }
61 
62 Real
64 {
65  return _rho_critical;
66 }
67 
68 Real
70 {
71  return _p_triple;
72 }
73 
74 Real
76 {
77  return _T_triple;
78 }
79 
80 Real
82 {
84 }
85 
86 ADReal
88 {
90 }
91 
92 void
94  Real pressure, Real temperature, Real & rho, Real & drho_dp, Real & drho_dT) const
95 {
96  rho_from_p_T_template(pressure, temperature, rho, drho_dp, drho_dT);
97 }
98 
99 void
101  const ADReal & temperature,
102  ADReal & rho,
103  ADReal & drho_dp,
104  ADReal & drho_dT) const
105 {
106  rho_from_p_T_template(pressure, temperature, rho, drho_dp, drho_dT);
107 }
108 
109 Real
111 {
113 }
114 
115 ADReal
117 {
119 }
120 
121 void
123  Real pressure, Real temperature, Real & v, Real & dv_dp, Real & dv_dT) const
124 {
125  v_from_p_T_template(pressure, temperature, v, dv_dp, dv_dT);
126 }
127 
128 void
130  const ADReal & temperature,
131  ADReal & v,
132  ADReal & dv_dp,
133  ADReal & dv_dT) const
134 {
135  v_from_p_T_template(pressure, temperature, v, dv_dp, dv_dT);
136 }
137 
138 Real
139 Water97FluidProperties::p_from_v_e(const Real v, const Real e) const
140 {
141  return p_from_v_e_template(v, e);
142 }
143 
144 ADReal
146 {
147  return p_from_v_e_template(v, e);
148 }
149 
150 Real
152 {
153  return e_from_p_rho_template(p, rho);
154 }
155 
156 ADReal
158 {
159  return e_from_p_rho_template(p, rho);
160 }
161 
162 void
164  const Real p, const Real rho, Real & e, Real & de_dp, Real & de_drho) const
165 {
166  e_from_p_rho_template(p, rho, e, de_dp, de_drho);
167 }
168 
169 void
171  const ADReal & p, const ADReal & rho, ADReal & e, ADReal & de_dp, ADReal & de_drho) const
172 {
173  e_from_p_rho_template(p, rho, e, de_dp, de_drho);
174 }
175 
176 Real
178 {
180 }
181 
182 ADReal
184 {
186 }
187 
188 void
190  Real pressure, Real temperature, Real & e, Real & de_dp, Real & de_dT) const
191 {
192  e_from_p_T_template(pressure, temperature, e, de_dp, de_dT);
193 }
194 
195 void
197  const ADReal & temperature,
198  ADReal & e,
199  ADReal & de_dp,
200  ADReal & de_dT) const
201 {
202  e_from_p_T_template(pressure, temperature, e, de_dp, de_dT);
203 }
204 
205 ADReal
207 {
208  const auto [p, T] = p_T_from_v_h(v, h);
209  return e_from_p_T(p, T);
210 }
211 
212 Real
213 Water97FluidProperties::T_from_v_e(const Real v, const Real e) const
214 {
215  return p_T_from_v_e(v, e).second;
216 }
217 
218 ADReal
220 {
221  return p_T_from_v_e(v, e).second;
222 }
223 
224 ADReal
226 {
227  const auto [p, T] = p_T_from_v_e(v, e);
228  return c_from_p_T(p, T);
229 }
230 
231 Real
232 Water97FluidProperties::c_from_p_T(const Real p, const Real T) const
233 {
234  return c_from_p_T_template(p, T);
235 }
236 
237 ADReal
239 {
240  return c_from_p_T_template(p, T);
241 }
242 
243 Real
245 {
247 }
248 
249 ADReal
251 {
253 }
254 
255 ADReal
257 {
258  const auto [p, T] = p_T_from_v_e(v, e);
259  return cp_from_p_T(p, T);
260 }
261 
262 Real
264 {
266 }
267 
268 ADReal
270 {
272 }
273 
274 ADReal
276 {
277  const auto [p, T] = p_T_from_v_e(v, e);
278  return cv_from_p_T(p, T);
279 }
280 
281 Real
283 {
285 }
286 
287 ADReal
289 {
291 }
292 
293 void
295  Real pressure, Real temperature, Real & mu, Real & dmu_dp, Real & dmu_dT) const
296 {
297  Real rho, drho_dp, drho_dT;
298  this->rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
299  Real dmu_drho;
300  this->mu_from_rho_T(rho, temperature, drho_dT, mu, dmu_drho, dmu_dT);
301  dmu_dp = dmu_drho * drho_dp;
302 }
303 
304 Real
306 {
308 }
309 
310 void
312  Real temperature,
313  Real ddensity_dT,
314  Real & mu,
315  Real & dmu_drho,
316  Real & dmu_dT) const
317 {
318  const Real mu_star = 1.0e-6;
319  const Real rhobar = density / _rho_critical;
320  const Real Tbar = temperature / _T_critical;
321  const Real drhobar_drho = 1.0 / _rho_critical;
322  const Real dTbar_dT = 1.0 / _T_critical;
323 
324  // Limit of zero density. Derivative wrt rho is 0
325  Real sum0 = 0.0, dsum0_dTbar = 0.0;
326  for (std::size_t i = 0; i < _mu_H0.size(); ++i)
327  {
328  sum0 += _mu_H0[i] / MathUtils::pow(Tbar, i);
329  dsum0_dTbar -= i * _mu_H0[i] / MathUtils::pow(Tbar, i + 1);
330  }
331 
332  const Real mu0 = 100.0 * std::sqrt(Tbar) / sum0;
333  const Real dmu0_dTbar =
334  50.0 / std::sqrt(Tbar) / sum0 - 100.0 * std::sqrt(Tbar) * dsum0_dTbar / sum0 / sum0;
335 
336  // Residual component due to finite density
337  Real sum1 = 0.0, dsum1_drhobar = 0.0, dsum1_dTbar = 0.0;
338  for (unsigned int i = 0; i < 6; ++i)
339  {
340  const Real fact = MathUtils::pow(1.0 / Tbar - 1.0, i);
341  const Real dfact_dTbar = i * MathUtils::pow(1.0 / Tbar - 1.0, i - 1) / Tbar / Tbar;
342 
343  for (unsigned int j = 0; j < 7; ++j)
344  {
345  sum1 += fact * _mu_Hij[i][j] * MathUtils::pow(rhobar - 1.0, j);
346  dsum1_dTbar -= dfact_dTbar * _mu_Hij[i][j] * MathUtils::pow(rhobar - 1.0, j);
347  dsum1_drhobar += j * fact * _mu_Hij[i][j] * MathUtils::pow(rhobar - 1.0, j - 1);
348  }
349  }
350 
351  const Real mu1 = std::exp(rhobar * sum1);
352  const Real dmu1_drhobar = (sum1 + rhobar * dsum1_drhobar) * mu1;
353  const Real dmu1_dTbar = (rhobar * dsum1_dTbar) * mu1;
354 
355  // Viscosity and its derivatives are then
356  mu = mu_star * mu0 * mu1;
357  dmu_drho = mu_star * mu0 * dmu1_drhobar * drhobar_drho;
358  dmu_dT = mu_star * (dmu0_dTbar * mu1 + mu0 * dmu1_dTbar) * dTbar_dT + dmu_drho * ddensity_dT;
359 }
360 
361 ADReal
363 {
364  const auto [rho, T] = rho_T_from_v_e(v, e);
365  return mu_from_rho_T_template(rho, T);
366 }
367 
368 void
370  Real temperature,
371  Real & rho,
372  Real & mu) const
373 {
374  rho = this->rho_from_p_T(pressure, temperature);
375  mu = this->mu_from_rho_T(rho, temperature);
376 }
377 
378 void
380  Real temperature,
381  Real & rho,
382  Real & drho_dp,
383  Real & drho_dT,
384  Real & mu,
385  Real & dmu_dp,
386  Real & dmu_dT) const
387 {
388  this->rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
389  Real dmu_drho;
390  this->mu_from_rho_T(rho, temperature, drho_dT, mu, dmu_drho, dmu_dT);
391  dmu_dp = dmu_drho * drho_dp;
392 }
393 
394 Real
396 {
398 }
399 
400 ADReal
402 {
404 }
405 
406 void
407 Water97FluidProperties::k_from_p_T(Real, Real, Real &, Real &, Real &) const
408 {
409  mooseError("k_from_p_T() is not implemented.");
410 }
411 
412 Real
414 {
416 }
417 
418 Real
420 {
421  return k_from_v_e_template(v, e);
422 }
423 
424 ADReal
426 {
427  return k_from_v_e_template(v, e);
428 }
429 
430 Real
431 Water97FluidProperties::s_from_p_T(Real pressure, Real temperature) const
432 {
433  return s_from_p_T_template(pressure, temperature);
434 }
435 
436 ADReal
437 Water97FluidProperties::s_from_p_T(const ADReal & pressure, const ADReal & temperature) const
438 {
439  return s_from_p_T_template(pressure, temperature);
440 }
441 
442 void
443 Water97FluidProperties::s_from_p_T(
444  const Real pressure, const Real temperature, Real & s, Real & ds_dp, Real & ds_dT) const
445 {
446  s_from_p_T_template(pressure, temperature, s, ds_dp, ds_dT);
447 }
448 
449 Real
451 {
452  Real T = T_from_p_h(pressure, enthalpy);
453  return s_from_p_T(pressure, T);
454 }
455 
456 ADReal
458 {
460  return s_from_p_T_template(pressure, temperature);
461 }
462 
463 void
465  const Real enthalpy, const Real pressure, Real & s, Real & ds_dh, Real & ds_dp) const
466 {
467  ADReal p = pressure;
468  Moose::derivInsert(p.derivatives(), 0, 1.0);
469 
470  ADReal h = enthalpy;
471  Moose::derivInsert(h.derivatives(), 1, 1.0);
472 
473  ADReal T = T_from_p_h_ad(p, h);
474  ADReal entropy = s_from_p_T_template(p, T);
475 
476  ds_dh = entropy.derivatives()[1];
477  ds_dp = entropy.derivatives()[0];
478  s = entropy.value();
479 }
480 
481 void
482 Water97FluidProperties::s_from_p_T(const ADReal & pressure,
483  const ADReal & temperature,
484  ADReal & s,
485  ADReal & ds_dp,
486  ADReal & ds_dT) const
487 {
488  s_from_p_T_template(pressure, temperature, s, ds_dp, ds_dT);
489 }
490 
491 Real
493 {
495 }
496 
497 ADReal
499 {
501 }
502 
503 void
505  Real pressure, Real temperature, Real & h, Real & dh_dp, Real & dh_dT) const
506 {
507  h_from_p_T_template(pressure, temperature, h, dh_dp, dh_dT);
508 }
509 
510 void
512  const ADReal & temperature,
513  ADReal & h,
514  ADReal & dh_dp,
515  ADReal & dh_dT) const
516 {
517  h_from_p_T_template(pressure, temperature, h, dh_dp, dh_dT);
518 }
519 
520 Real
522 {
523  // Check whether the input temperature is within the region of validity of this equation.
524  // Valid for 273.15 K <= t <= 647.096 K
525  if (temperature < 273.15 || temperature > _T_critical)
526  mooseException(name(),
527  ": vaporPressure(): Temperature ",
528  temperature,
529  " is outside range 273.15 K <= T "
530  "<= 647.096 K");
531 
532  Real theta, theta2, a, b, c, p;
533  theta = temperature + _n4[8] / (temperature - _n4[9]);
534  theta2 = theta * theta;
535  a = theta2 + _n4[0] * theta + _n4[1];
536  b = _n4[2] * theta2 + _n4[3] * theta + _n4[4];
537  c = _n4[5] * theta2 + _n4[6] * theta + _n4[7];
538  p = Utility::pow<4>(2.0 * c / (-b + std::sqrt(b * b - 4.0 * a * c)));
539 
540  return p * 1.e6;
541 }
542 
543 ADReal
545 {
546  using std::pow, std::sqrt;
547  // Check whether the input pressure is within the region of validity of this equation.
548  // Valid for 611.213 Pa <= p <= 22.064 MPa
549  if (pressure.value() < 611.23 || pressure.value() > _p_critical)
550  mooseException(name() + ": vaporTemperature(): Pressure ",
551  pressure.value(),
552  " is outside range 611.213 Pa <= p <= 22.064 MPa");
553 
554  const ADReal beta = pow(pressure / 1.e6, 0.25);
555  const ADReal beta2 = beta * beta;
556  const ADReal e = beta2 + _n4[2] * beta + _n4[5];
557  const ADReal f = _n4[0] * beta2 + _n4[3] * beta + _n4[6];
558  const ADReal g = _n4[1] * beta2 + _n4[4] * beta + _n4[7];
559  const ADReal d = 2.0 * g / (-f - sqrt(f * f - 4.0 * e * g));
560 
561  return (_n4[9] + d - sqrt((_n4[9] + d) * (_n4[9] + d) - 4.0 * (_n4[8] + _n4[9] * d))) / 2.0;
562 }
563 
564 Real
566 {
567  const ADReal p = pressure;
568 
569  return vaporTemperature_ad(p).value();
570 }
571 
572 void
573 Water97FluidProperties::vaporTemperature(Real pressure, Real & Tsat, Real & dTsat_dp) const
574 {
575  ADReal p = pressure;
576  Moose::derivInsert(p.derivatives(), 0, 1.0);
577 
578  const ADReal T = vaporTemperature_ad(p);
579 
580  Tsat = T.value();
581  dTsat_dp = T.derivatives()[0];
582 }
583 
584 Real
586 {
587  // Check whether the input temperature is within the region of validity of this equation.
588  // Valid for 623.15 K <= t <= 863.15 K
589  if (temperature < 623.15 || temperature > 863.15)
590  mooseException(name(),
591  ": b23p(): Temperature ",
592  temperature,
593  " is outside range of 623.15 K <= T <= 863.15 K");
594 
595  return (_n23[0] + _n23[1] * temperature + _n23[2] * temperature * temperature) * 1.e6;
596 }
597 
598 Real
600 {
601  // Check whether the input pressure is within the region of validity of this equation.
602  // Valid for 16.529 MPa <= p <= 100 MPa
603  if (pressure < 16.529e6 || pressure > 100.0e6)
604  mooseException(
605  name(), ": b23T(): Pressure ", pressure, "is outside range 16.529 MPa <= p <= 100 MPa");
606 
607  return _n23[3] + std::sqrt((pressure / 1.e6 - _n23[4]) / _n23[2]);
608 }
609 
610 unsigned int
612 {
613  unsigned int region;
614 
615  // Need to calculate enthalpies at the boundaries to delineate regions
616  Real p273 = vaporPressure(273.15);
617  Real p623 = vaporPressure(623.15);
618 
619  if (pressure >= p273 && pressure <= p623)
620  {
621  if (enthalpy >= h_from_p_T(pressure, 273.15) &&
623  region = 1;
624  else if (enthalpy > h_from_p_T(pressure, vaporTemperature(pressure)) &&
625  enthalpy <= h_from_p_T(pressure, 1073.15))
626  region = 2;
627  else if (enthalpy > h_from_p_T(pressure, 1073.15) && enthalpy <= h_from_p_T(pressure, 2273.15))
628  region = 5;
629  else
630  mooseException("Enthalpy ", enthalpy, " is out of range in ", name(), ": inRegionPH()");
631  }
632  else if (pressure > p623 && pressure <= 50.0e6)
633  {
634  if (enthalpy >= h_from_p_T(pressure, 273.15) && enthalpy <= h_from_p_T(pressure, 623.15))
635  region = 1;
636  else if (enthalpy > h_from_p_T(pressure, 623.15) &&
637  enthalpy <= h_from_p_T(pressure, b23T(pressure)))
638  region = 3;
639  else if (enthalpy > h_from_p_T(pressure, b23T(pressure)) &&
640  enthalpy <= h_from_p_T(pressure, 1073.15))
641  region = 2;
642  else if (enthalpy > h_from_p_T(pressure, 1073.15) && enthalpy <= h_from_p_T(pressure, 2273.15))
643  region = 5;
644  else
645  mooseException("Enthalpy ", enthalpy, " is out of range in ", name(), ": inRegionPH()");
646  }
647  else if (pressure > 50.0e6 && pressure <= 100.0e6)
648  {
649  if (enthalpy >= h_from_p_T(pressure, 273.15) && enthalpy <= h_from_p_T(pressure, 623.15))
650  region = 1;
651  else if (enthalpy > h_from_p_T(pressure, 623.15) &&
652  enthalpy <= h_from_p_T(pressure, b23T(pressure)))
653  region = 3;
654  else if (enthalpy > h_from_p_T(pressure, b23T(pressure)) &&
655  enthalpy <= h_from_p_T(pressure, 1073.15))
656  region = 2;
657  else
658  mooseException("Enthalpy ", enthalpy, " is out of range in ", name(), ": inRegionPH()");
659  }
660  else
661  mooseException("Pressure ", pressure, " is out of range in ", name(), ": inRegionPH()");
662 
663  return region;
664 }
665 
666 unsigned int
668 {
669  unsigned int subregion;
670 
671  if (pressure <= 4.0e6)
672  subregion = 1;
673  else if (pressure > 4.0e6 && pressure < 6.5467e6)
674  subregion = 2;
675  else
676  {
677  if (enthalpy >= b2bc(pressure))
678  subregion = 2;
679  else
680  subregion = 3;
681  }
682 
683  return subregion;
684 }
685 
686 unsigned int
688 {
689  unsigned int subregion;
690 
691  if (enthalpy <= b3ab(pressure))
692  subregion = 1;
693  else
694  subregion = 2;
695 
696  return subregion;
697 }
698 
699 Real
701 {
702  // Check whether the input pressure is within the region of validity of this equation.
703  if (pressure < 6.5467e6 || pressure > 100.0e6)
704  mooseException(
705  name(), ": b2bc(): Pressure ", pressure, " is outside range of 6.5467 MPa <= p <= 100 MPa");
706 
707  Real pi = pressure / 1.0e6;
708 
709  return (0.26526571908428e4 + std::sqrt((pi - 0.45257578905948e1) / 0.12809002730136e-3)) * 1.0e3;
710 }
711 
712 Real
714 {
715  const ADReal p = pressure;
716  const ADReal h = enthalpy;
717 
718  return T_from_p_h_ad(p, h).value();
719 }
720 
721 void
723  Real pressure, Real enthalpy, Real & temperature, Real & dT_dp, Real & dT_dh) const
724 {
725  ADReal p = pressure;
726  Moose::derivInsert(p.derivatives(), 0, 1.0);
727  ADReal h = enthalpy;
728  Moose::derivInsert(h.derivatives(), 1, 1.0);
729 
730  const ADReal T = T_from_p_h_ad(p, h);
731 
732  temperature = T.value();
733  dT_dp = T.derivatives()[0];
734  dT_dh = T.derivatives()[1];
735 }
736 
737 ADReal
739 {
740  return T_from_p_h_ad(pressure, enthalpy);
741 }
742 
743 ADReal
745 {
746  ADReal temperature = 0.0;
747 
748  // Determine which region the point is in
749  const unsigned int region = inRegionPH(pressure.value(), enthalpy.value());
750 
751  switch (region)
752  {
753  case 1:
755  break;
756 
757  case 2:
758  {
759  // First, determine which subregion the point is in:
760  const unsigned int subregion = subregion2ph(pressure.value(), enthalpy.value());
761 
762  if (subregion == 1)
764  else if (subregion == 2)
766  else
768  break;
769  }
770 
771  case 3:
772  {
773  // First, determine which subregion the point is in:
774  const unsigned int subregion = subregion3ph(pressure.value(), enthalpy.value());
775 
776  if (subregion == 1)
778  else
780  break;
781  }
782 
783  case 5:
784  mooseError("temperature_from_ph() not implemented for region 5");
785  break;
786 
787  default:
788  mooseError("inRegionPH() has given an incorrect region");
789  }
790 
791  return temperature;
792 }
793 
794 ADReal
796 {
797  using std::pow;
798 
799  const ADReal pi = pressure / 1.0e6;
800  const ADReal eta = enthalpy / 2500.0e3;
801  ADReal sum = 0.0;
802 
803  for (std::size_t i = 0; i < _nph1.size(); ++i)
804  sum += _nph1[i] * pow(pi, _Iph1[i]) * pow(eta + 1.0, _Jph1[i]);
805 
806  return sum;
807 }
808 
809 ADReal
811  const ADReal & enthalpy) const
812 {
813  using std::pow, std::abs;
814 
815  const ADReal pi = pressure / 1.0e6;
816  const ADReal eta = enthalpy / 2000.0e3;
817  ADReal sum = 0.0;
818 
819  // Factor out the negative in pow(eta - 2.1, _Jph2a[i]) to avoid fpe in dbg (see #13163)
820  const Real sgn = MathUtils::sign(eta.value() - 2.1);
821 
822  for (std::size_t i = 0; i < _nph2a.size(); ++i)
823  sum += _nph2a[i] * pow(pi, _Iph2a[i]) * pow(abs(eta - 2.1), _Jph2a[i]) * pow(sgn, _Jph2a[i]);
824 
825  return sum;
826 }
827 
828 ADReal
830  const ADReal & enthalpy) const
831 {
832  using std::pow, std::abs;
833 
834  const ADReal pi = pressure / 1.0e6;
835  const ADReal eta = enthalpy / 2000.0e3;
836  ADReal sum = 0.0;
837 
838  // Factor out the negatives in pow(pi - 2.0, _Iph2b[i])* pow(eta - 2.6, _Jph2b[i])
839  // to avoid fpe in dbg (see #13163)
840  const Real sgn0 = MathUtils::sign(pi.value() - 2.0);
841  const Real sgn1 = MathUtils::sign(eta.value() - 2.6);
842 
843  for (std::size_t i = 0; i < _nph2b.size(); ++i)
844  sum += _nph2b[i] * pow(abs(pi - 2.0), _Iph2b[i]) * pow(sgn0, _Iph2b[i]) *
845  pow(abs(eta - 2.6), _Jph2b[i]) * pow(sgn1, _Jph2b[i]);
846 
847  return sum;
848 }
849 
850 ADReal
852  const ADReal & enthalpy) const
853 {
854  using std::pow, std::abs;
855 
856  const ADReal pi = pressure / 1.0e6;
857  const ADReal eta = enthalpy / 2000.0e3;
858  ADReal sum = 0.0;
859 
860  // Factor out the negative in pow(eta - 1.8, _Jph2c[i]) to avoid fpe in dbg (see #13163)
861  const Real sgn = MathUtils::sign(eta.value() - 1.8);
862 
863  for (std::size_t i = 0; i < _nph2c.size(); ++i)
864  sum += _nph2c[i] * pow(pi + 25.0, _Iph2c[i]) * pow(abs(eta - 1.8), _Jph2c[i]) *
865  pow(sgn, _Jph2c[i]);
866 
867  return sum;
868 }
869 
870 Real
872 {
873  // Check whether the input pressure is within the region of validity of this equation.
874  if (pressure < b23p(623.15) || pressure > 100.0e6)
875  mooseException(
876  name(), ": b3ab(): Pressure ", pressure, "is outside range of 16.529 MPa <= p <= 100 MPa");
877 
878  Real pi = pressure / 1.0e6;
879  Real eta = 0.201464004206875e4 + 0.374696550136983e1 * pi - 0.219921901054187e-1 * pi * pi +
880  0.87513168600995e-4 * pi * pi * pi;
881 
882  return eta * 1.0e3;
883 }
884 
885 ADReal
887  const ADReal & enthalpy) const
888 {
889  using std::pow;
890 
891  const ADReal pi = pressure / 100.0e6;
892  const ADReal eta = enthalpy / 2300.0e3;
893  ADReal sum = 0.0;
894 
895  for (std::size_t i = 0; i < _nph3a.size(); ++i)
896  sum += _nph3a[i] * pow(pi + 0.24, _Iph3a[i]) * pow(eta - 0.615, _Jph3a[i]);
897 
898  return sum * 760.0;
899 }
900 
901 ADReal
903  const ADReal & enthalpy) const
904 {
905  using std::pow;
906 
907  const ADReal pi = pressure / 100.0e6;
908  const ADReal eta = enthalpy / 2800.0e3;
909  ADReal sum = 0.0;
910 
911  for (size_t i = 0; i < _nph3b.size(); ++i)
912  sum += _nph3b[i] * pow(pi + 0.298, _Iph3b[i]) * pow(eta - 0.72, _Jph3b[i]);
913 
914  return sum * 860.0;
915 }
916 
917 Real
918 Water97FluidProperties::henryConstant(Real temperature, const std::vector<Real> & coeffs) const
919 {
920  const Real A = coeffs[0];
921  const Real B = coeffs[1];
922  const Real C = coeffs[2];
923 
924  const Real Tr = temperature / 647.096;
925  const Real tau = 1.0 - Tr;
926 
927  const Real lnkh =
928  A / Tr + B * std::pow(tau, 0.355) / Tr + C * std::pow(Tr, -0.41) * std::exp(tau);
929 
930  // The vapor pressure used in this formulation
931  const std::vector<Real> a{
932  -7.85951783, 1.84408259, -11.7866497, 22.6807411, -15.9618719, 1.80122502};
933  const std::vector<Real> b{1.0, 1.5, 3.0, 3.5, 4.0, 7.5};
934  Real sum = 0.0;
935 
936  for (std::size_t i = 0; i < a.size(); ++i)
937  sum += a[i] * std::pow(tau, b[i]);
938 
939  return 22.064e6 * std::exp(sum / Tr) * std::exp(lnkh);
940 }
941 
942 void
944  const std::vector<Real> & coeffs,
945  Real & Kh,
946  Real & dKh_dT) const
947 {
948  const Real A = coeffs[0];
949  const Real B = coeffs[1];
950  const Real C = coeffs[2];
951 
952  const Real pc = 22.064e6;
953  const Real Tc = 647.096;
954 
955  const Real Tr = temperature / Tc;
956  const Real tau = 1.0 - Tr;
957 
958  const Real lnkh =
959  A / Tr + B * std::pow(tau, 0.355) / Tr + C * std::pow(Tr, -0.41) * std::exp(tau);
960  const Real dlnkh_dT =
961  (-A / Tr / Tr - B * std::pow(tau, 0.355) / Tr / Tr - 0.355 * B * std::pow(tau, -0.645) / Tr -
962  0.41 * C * std::pow(Tr, -1.41) * std::exp(tau) - C * std::pow(Tr, -0.41) * std::exp(tau)) /
963  Tc;
964 
965  // The vapor pressure used in this formulation
966  const std::vector<Real> a{
967  -7.85951783, 1.84408259, -11.7866497, 22.6807411, -15.9618719, 1.80122502};
968  const std::vector<Real> b{1.0, 1.5, 3.0, 3.5, 4.0, 7.5};
969  Real sum = 0.0;
970  Real dsum = 0.0;
971 
972  for (std::size_t i = 0; i < a.size(); ++i)
973  {
974  sum += a[i] * std::pow(tau, b[i]);
975  dsum += a[i] * b[i] * std::pow(tau, b[i] - 1.0);
976  }
977 
978  const Real p = pc * std::exp(sum / Tr);
979  const Real dp_dT = -p / Tc / Tr * (sum / Tr + dsum);
980 
981  // Henry's constant and its derivative wrt temperature
982  Kh = p * std::exp(lnkh);
983  dKh_dT = (p * dlnkh_dT + dp_dT) * std::exp(lnkh);
984 }
985 
986 ADReal
988  const std::vector<Real> & coeffs) const
989 {
990  const Real T = temperature.value();
991  Real Kh_real = 0.0;
992  Real dKh_dT_real = 0.0;
993  henryConstant(T, coeffs, Kh_real, dKh_dT_real);
994 
995  ADReal Kh = Kh_real;
996  Kh.derivatives() = temperature.derivatives() * dKh_dT_real;
997 
998  return Kh;
999 }
1000 
1001 unsigned int
1003 {
1004  Real pMPa = pressure / 1.0e6;
1005  const Real P3cd = 19.00881189173929;
1006  unsigned int subregion = 0;
1007 
1008  if (pMPa > 40.0 && pMPa <= 100.0)
1009  {
1010  if (temperature <= tempXY(pressure, AB))
1011  subregion = 0;
1012  else // (temperature > tempXY(pressure, AB))
1013  subregion = 1;
1014  }
1015  else if (pMPa > 25.0 && pMPa <= 40.0)
1016  {
1017  if (temperature <= tempXY(pressure, CD))
1018  subregion = 2;
1019  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, AB))
1020  subregion = 3;
1021  else if (temperature > tempXY(pressure, AB) && temperature <= tempXY(pressure, EF))
1022  subregion = 4;
1023  else // (temperature > tempXY(pressure, EF))
1024  subregion = 5;
1025  }
1026  else if (pMPa > 23.5 && pMPa <= 25.0)
1027  {
1028  if (temperature <= tempXY(pressure, CD))
1029  subregion = 2;
1030  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, GH))
1031  subregion = 6;
1032  else if (temperature > tempXY(pressure, GH) && temperature <= tempXY(pressure, EF))
1033  subregion = 7;
1034  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, IJ))
1035  subregion = 8;
1036  else if (temperature > tempXY(pressure, IJ) && temperature <= tempXY(pressure, JK))
1037  subregion = 9;
1038  else // (temperature > tempXY(pressure, JK))
1039  subregion = 10;
1040  }
1041  else if (pMPa > 23.0 && pMPa <= 23.5)
1042  {
1043  if (temperature <= tempXY(pressure, CD))
1044  subregion = 2;
1045  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, GH))
1046  subregion = 11;
1047  else if (temperature > tempXY(pressure, GH) && temperature <= tempXY(pressure, EF))
1048  subregion = 7;
1049  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, IJ))
1050  subregion = 8;
1051  else if (temperature > tempXY(pressure, IJ) && temperature <= tempXY(pressure, JK))
1052  subregion = 9;
1053  else // (temperature > tempXY(pressure, JK))
1054  subregion = 10;
1055  }
1056  else if (pMPa > 22.5 && pMPa <= 23.0)
1057  {
1058  if (temperature <= tempXY(pressure, CD))
1059  subregion = 2;
1060  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, GH))
1061  subregion = 11;
1062  else if (temperature > tempXY(pressure, GH) && temperature <= tempXY(pressure, MN))
1063  subregion = 12;
1064  else if (temperature > tempXY(pressure, MN) && temperature <= tempXY(pressure, EF))
1065  subregion = 13;
1066  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, OP))
1067  subregion = 14;
1068  else if (temperature > tempXY(pressure, OP) && temperature <= tempXY(pressure, IJ))
1069  subregion = 15;
1070  else if (temperature > tempXY(pressure, IJ) && temperature <= tempXY(pressure, JK))
1071  subregion = 9;
1072  else // (temperature > tempXY(pressure, JK))
1073  subregion = 10;
1074  }
1075  else if (pMPa > vaporPressure(643.15) * 1.0e-6 &&
1076  pMPa <= 22.5) // vaporPressure(643.15) = 21.04 MPa
1077  {
1078  if (temperature <= tempXY(pressure, CD))
1079  subregion = 2;
1080  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, QU))
1081  subregion = 16;
1082  else if (temperature > tempXY(pressure, QU) && temperature <= tempXY(pressure, RX))
1083  {
1084  if (pMPa > 22.11 && pMPa <= 22.5)
1085  {
1086  if (temperature <= tempXY(pressure, UV))
1087  subregion = 20;
1088  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1089  subregion = 21;
1090  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1091  subregion = 22;
1092  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1093  subregion = 23;
1094  }
1095  else if (pMPa > 22.064 && pMPa <= 22.11)
1096  {
1097  if (temperature <= tempXY(pressure, UV))
1098  subregion = 20;
1099  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1100  subregion = 24;
1101  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1102  subregion = 25;
1103  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1104  subregion = 23;
1105  }
1106  else if (temperature <= vaporTemperature(pressure))
1107  {
1108  if (pMPa > 21.93161551 && pMPa <= 22.064)
1110  subregion = 20;
1111  else
1112  subregion = 24;
1113  else // (pMPa > vaporPressure(643.15) * 1.0e-6 && pMPa <= 21.93161551)
1114  subregion = 20;
1115  }
1117  {
1118  if (pMPa > 21.90096265 && pMPa <= 22.064)
1119  {
1120  if (temperature <= tempXY(pressure, WX))
1121  subregion = 25;
1122  else
1123  subregion = 23;
1124  }
1125  else
1126  subregion = 23;
1127  }
1128  }
1129  else if (temperature > tempXY(pressure, RX) && temperature <= tempXY(pressure, JK))
1130  subregion = 17;
1131  else
1132  subregion = 10;
1133  }
1134  else if (pMPa > 20.5 &&
1135  pMPa <= vaporPressure(643.15) * 1.0e-6) // vaporPressure(643.15) = 21.04 MPa
1136  {
1137  if (temperature <= tempXY(pressure, CD))
1138  subregion = 2;
1140  subregion = 16;
1142  subregion = 17;
1143  else // (temperature > tempXY(pressure, JK))
1144  subregion = 10;
1145  }
1146  else if (pMPa > P3cd && pMPa <= 20.5) // P3cd = 19.00881189173929
1147  {
1148  if (temperature <= tempXY(pressure, CD))
1149  subregion = 2;
1151  subregion = 18;
1152  else
1153  subregion = 19;
1154  }
1155  else if (pMPa > vaporPressure(623.15) * 1.0e-6 && pMPa <= P3cd)
1156  {
1158  subregion = 2;
1159  else
1160  subregion = 19;
1161  }
1162  else if (pMPa > 22.11 && pMPa <= 22.5)
1163  {
1165  subregion = 20;
1166  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1167  subregion = 21;
1168  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1169  subregion = 22;
1170  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1171  subregion = 23;
1172  }
1173  else if (pMPa > 22.064 && pMPa <= 22.11)
1174  {
1176  subregion = 20;
1177  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1178  subregion = 24;
1179  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1180  subregion = 25;
1181  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1182  subregion = 23;
1183  }
1184  else
1185  mooseError("subregion3(): Shouldn't have got here!");
1186 
1187  return subregion;
1188 }
1189 
1190 unsigned int
1192 {
1193  // Valid for 273.15 K <= T <= 1073.15 K, p <= 100 MPa
1194  // 1073.15 K <= T <= 2273.15 K, p <= 50 Mpa
1195  if (temperature >= 273.15 && temperature <= 1073.15)
1196  {
1197  if (pressure < vaporPressure(273.15) || pressure > 100.0e6)
1198  mooseException("Pressure ", pressure, " is out of range in ", name(), ": inRegion()");
1199  }
1200  else if (temperature > 1073.15 && temperature <= 2273.15)
1201  {
1202  if (pressure < 0.0 || pressure > 50.0e6)
1203  mooseException("Pressure ", pressure, " is out of range in ", name(), ": inRegion()");
1204  }
1205  else
1206  mooseException("Temperature ", temperature, " is out of range in ", name(), ": inRegion()");
1207 
1208  // Determine the phase region that the (P, T) point lies in
1209  unsigned int region;
1210 
1211  if (temperature >= 273.15 && temperature <= 623.15)
1212  {
1213  if (pressure > vaporPressure(temperature) && pressure <= 100.0e6)
1214  region = 1;
1215  else
1216  region = 2;
1217  }
1218  else if (temperature > 623.15 && temperature <= 863.15)
1219  {
1220  if (pressure <= b23p(temperature))
1221  region = 2;
1222  else
1223  region = 3;
1224  }
1225  else if (temperature > 863.15 && temperature <= 1073.15)
1226  region = 2;
1227  else
1228  region = 5;
1229 
1230  return region;
1231 }
T v_from_p_T_template(const T &pressure, const T &temperature) const
const Real _T_critical
Critical temperature (K)
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
virtual Real mu_from_p_T(Real pressure, Real temperature) const override
static InputParameters validParams()
virtual void rho_mu_from_p_T(Real pressure, Real temperature, Real &rho, Real &mu) const override
Combined methods.
virtual Real triplePointTemperature() const override
Triple point temperature.
ADReal temperature_from_ph3b(const ADReal &pressure, const ADReal &enthalpy) const
Backwards equation T(p, h) in Region 3b Eq.
ADReal temperature_from_ph3a(const ADReal &pressure, const ADReal &enthalpy) const
Backwards equation T(p, h) in Region 3a Eq.
unsigned int inRegion(Real pressure, Real temperature) const
Determines the phase region that the given pressure and temperature values lie in.
const std::array< Real, 5 > _n23
Constants for the boundary between regions 2 and 3.
T tempXY(const T &pressure, subregionEnum xy) const
Boundaries between subregions in region 3.
std::pair< T, T > rho_T_from_v_e(const T &v, const T &e) const
Computes the density (first member of the pair) and temperature (second member of the pair) as functi...
Real vaporTemperature(Real pressure) const override
Saturation temperature as a function of pressure.
Real p_from_v_e(Real v, Real e) const override
ADReal temperature_from_ph2b(const ADReal &pressure, const ADReal &enthalpy) const
Backwards equation T(p, h) in Region 2b Eq.
const Real _p_critical
Critical pressure (Pa)
const std::array< int, 33 > _Jph3b
Real T_from_v_e(Real v, Real e) const override
const std::array< int, 20 > _Iph1
virtual Real e_from_p_T(Real pressure, Real temperature) const override
Real b2bc(Real pressure) const
Boundary between subregions b and c in region 2.
static InputParameters validParams()
virtual std::string fluidName() const override
Fluid name.
const std::array< int, 23 > _Jph2c
const std::array< Real, 36 > _nph2a
T k_from_v_e_template(const T &v, const T &e) const
T e_from_p_T_template(const T &pressure, const T &temperature) const
registerMooseObject("FluidPropertiesApp", Water97FluidProperties)
virtual Real criticalDensity() const override
Critical density.
T k_from_p_T_template(const T &pressure, const T &temperature) const
Real b23T(Real pressure) const
Auxillary equation for the boundary between regions 2 and 3.
Water97FluidProperties(const InputParameters &parameters)
virtual ADReal cv_from_v_e(const ADReal &v, const ADReal &e) const override
T c_from_p_T_template(const T &pressure, const T &temperature) const
T rho_from_p_T_template(const T &pressure, const T &temperature) const
unsigned int subregion3(Real pressure, Real temperature) const
Provides the correct subregion index for a (P,T) point in region 3.
const std::array< int, 36 > _Jph2a
static const std::string density
Definition: NS.h:33
const std::array< std::array< Real, 7 >, 6 > _mu_Hij
ADReal vaporTemperature_ad(const ADReal &pressure) const
AD version of saturation temperature as a function of pressure (used internally)
int sgn(T val)
The sign function.
Definition: Numerics.h:41
T h_from_p_T_template(const T &pressure, const T &temperature) const
const std::array< Real, 33 > _nph3b
static const std::string temperature
Definition: NS.h:59
const std::array< Real, 38 > _nph2b
std::pair< T, T > p_T_from_v_h(const T &v, const T &h) const
Computes the pressure (first member of the pair) and temperature (second member of the pair) as funct...
virtual Real h_from_p_T(Real pressure, Real temperature) const override
virtual Real criticalTemperature() const override
Critical temperature.
const std::array< int, 33 > _Iph3b
virtual Real k_from_p_T(Real pressure, Real temperature) const override
ADReal mu_from_v_e(const ADReal &v, const ADReal &e) const override
DualNumber< Real, DNDerivativeType, true > ADReal
unsigned int subregion2ph(Real pressure, Real enthalpy) const
Provides the correct subregion index for a (P,h) point in region 2.
const Real _T_triple
Triple point temperature (K)
std::pair< T, T > p_T_from_v_e(const T &v, const T &e) const
Computes the pressure (first member of the pair) and temperature (second member of the pair) as funct...
const std::array< int, 23 > _Iph2c
ADReal temperature_from_ph2a(const ADReal &pressure, const ADReal &enthalpy) const
Backwards equation T(p, h) in Region 2a Eq.
T cv_from_p_T_template(const T &pressure, const T &temperature) const
const std::array< int, 20 > _Jph1
e e e e s T T T T T rho v v T e h
const std::string & name() const
const std::array< int, 36 > _Iph2a
Real k_from_v_e(Real v, Real e) const override
const std::array< int, 38 > _Jph2b
Real f(Real x)
Test function for Brents method.
const std::array< int, 31 > _Jph3a
virtual Real s_from_h_p(Real enthalpy, Real pressure) const override
static const std::string mu
Definition: NS.h:123
ADReal T_from_p_h_ad(const ADReal &pressure, const ADReal &enthalpy) const
AD version of backwards equation T(p, h) (used internally) From Revised Release on the IAPWS Industri...
const std::array< int, 31 > _Iph3a
virtual Real v_from_p_T(Real pressure, Real temperature) const override
T sign(T x)
virtual Real triplePointPressure() const override
Triple point pressure.
Common class for single phase fluid properties.
const std::array< Real, 20 > _nph1
ADReal temperature_from_ph1(const ADReal &pressure, const ADReal &enthalpy) const
Backwards equation T(p, h) in Region 1 Eq.
ADReal e_from_v_h(const ADReal &v, const ADReal &h) const override
unsigned int subregion3ph(Real pressure, Real enthalpy) const
Provides the correct subregion index for a (P,h) point in region 3.
virtual Real T_from_p_h(Real pressure, Real enthalpy) const override
Backwards equation T(p, h) From Revised Release on the IAPWS Industrial Formulation 1997 for the Ther...
T mu_from_rho_T_template(const T &density, const T &temperature) const
virtual Real c_from_p_T(Real pressure, Real temperature) const override
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
T p_from_v_e_template(const T &v, const T &e) const
const std::array< Real, 31 > _nph3a
T k_from_rho_T_template(const T &density, const T &temperature) const
Real b23p(Real temperature) const
Auxillary equation for the boundary between regions 2 and 3.
const Real _rho_critical
Critical density (kg/m^3)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
Definition: NS.h:84
const std::array< int, 38 > _Iph2b
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
virtual Real e_from_p_rho(Real p, Real rho) const override
virtual Real criticalPressure() const override
Critical pressure.
Real b3ab(Real pressure) const
Boundary between subregions a and b in region 3.
Water (H2O) fluid properties as a function of pressure (Pa) and temperature (K) from IAPWS-IF97: Revi...
static const std::string pressure
Definition: NS.h:56
virtual Real vaporPressure(Real temperature) const override
Vapor pressure.
void mooseError(Args &&... args) const
Real henryConstant(Real temperature, const std::vector< Real > &coeffs) const
IAPWS formulation of Henry&#39;s law constant for dissolution in water From Guidelines on the Henry&#39;s con...
unsigned int inRegionPH(Real pressure, Real enthalpy) const
Determines the phase region that the given pressure and enthaply values lie in.
void addClassDescription(const std::string &doc_string)
void derivInsert(SemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< N >> &derivs, libMesh::dof_id_type index, Real value)
virtual Real k_from_rho_T(Real density, Real temperature) const override
T cp_from_p_T_template(const T &pressure, const T &temperature) const
virtual Real rho_from_p_T(Real pressure, Real temperature) const override
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
const Real _p_triple
Triple point pressure (Pa)
T mu_from_p_T_template(const T &pressure, const T &temperature) const
T e_from_p_rho_template(const T &p, const T &rho) const
T pow(T x, int e)
virtual ADReal c_from_v_e(const ADReal &v, const ADReal &e) const override
virtual Real cv_from_p_T(Real pressure, Real temperature) const override
ADReal temperature_from_ph2c(const ADReal &pressure, const ADReal &enthalpy) const
Backwards equation T(p, h) in Region 2c Eq.
virtual Real mu_from_rho_T(Real density, Real temperature) const override
const std::array< Real, 23 > _nph2c
virtual Real cp_from_p_T(Real pressure, Real temperature) const override
const Real _Mh2o
Water molar mass (kg/mol)
MooseUnits pow(const MooseUnits &, int)
static const std::string C
Definition: NS.h:168
virtual ADReal cp_from_v_e(const ADReal &v, const ADReal &e) const override
virtual Real molarMass() const override
Molar mass [kg/mol].
const Real pi
const std::array< Real, 10 > _n4
Constants for region 4 (the saturation curve up to the critical point)
const std::array< Real, 4 > _mu_H0
Constants from Release on the IAPWS Formulation 2008 for the Viscosity of Ordinary Water Substance...