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 (enthalpy < h_from_p_T(pressure, 273.15))
620  mooseException("Enthalpy ", enthalpy, " is out of range in ", name(), ": inRegionPH()");
621 
622  if (pressure >= p273 && pressure <= p623)
623  {
624  // Use region 1 definition of h_from_p_T to get the lower bound
625  if (enthalpy <=
626  _Rw * _T_star[0] *
628  region = 1;
629  // Use region 2 definition of h_from_p_T to get the upper bound
630  else if (enthalpy <=
631  _Rw * _T_star[1] *
633  region = 4;
634  else if (enthalpy <= h_from_p_T(pressure, 1073.15))
635  region = 2;
636  else if (enthalpy <= h_from_p_T(pressure, 2273.15))
637  region = 5;
638  else
639  mooseException("Enthalpy ", enthalpy, " is out of range in ", name(), ": inRegionPH()");
640  }
641  else if (pressure > p623 && pressure <= 50.0e6)
642  {
643  if (enthalpy <= h_from_p_T(pressure, 623.15))
644  region = 1;
645  else if (enthalpy <= h_from_p_T(pressure, b23T(pressure)))
646  region = 3;
647  else if (enthalpy <= h_from_p_T(pressure, 1073.15))
648  region = 2;
649  else if (enthalpy <= h_from_p_T(pressure, 2273.15))
650  region = 5;
651  else
652  mooseException("Enthalpy ", enthalpy, " is out of range in ", name(), ": inRegionPH()");
653  }
654  else if (pressure > 50.0e6 && pressure <= 100.0e6)
655  {
656  if (enthalpy <= h_from_p_T(pressure, 623.15))
657  region = 1;
658  else if (enthalpy <= h_from_p_T(pressure, b23T(pressure)))
659  region = 3;
660  else if (enthalpy <= h_from_p_T(pressure, 1073.15))
661  region = 2;
662  else
663  mooseException("Enthalpy ", enthalpy, " is out of range in ", name(), ": inRegionPH()");
664  }
665  else
666  mooseException("Pressure ", pressure, " is out of range in ", name(), ": inRegionPH()");
667 
668  return region;
669 }
670 
671 unsigned int
673 {
674  unsigned int subregion;
675 
676  if (pressure <= 4.0e6)
677  subregion = 1;
678  else if (pressure > 4.0e6 && pressure < 6.5467e6)
679  subregion = 2;
680  else
681  {
682  if (enthalpy >= b2bc(pressure))
683  subregion = 2;
684  else
685  subregion = 3;
686  }
687 
688  return subregion;
689 }
690 
691 unsigned int
693 {
694  unsigned int subregion;
695 
696  if (enthalpy <= b3ab(pressure))
697  subregion = 1;
698  else
699  subregion = 2;
700 
701  return subregion;
702 }
703 
704 Real
706 {
707  // Check whether the input pressure is within the region of validity of this equation.
708  if (pressure < 6.5467e6 || pressure > 100.0e6)
709  mooseException(
710  name(), ": b2bc(): Pressure ", pressure, " is outside range of 6.5467 MPa <= p <= 100 MPa");
711 
712  Real pi = pressure / 1.0e6;
713 
714  return (0.26526571908428e4 + std::sqrt((pi - 0.45257578905948e1) / 0.12809002730136e-3)) * 1.0e3;
715 }
716 
717 Real
719 {
720  const ADReal p = pressure;
721  const ADReal h = enthalpy;
722 
723  return T_from_p_h_ad(p, h).value();
724 }
725 
726 void
728  Real pressure, Real enthalpy, Real & temperature, Real & dT_dp, Real & dT_dh) const
729 {
730  ADReal p = pressure;
731  Moose::derivInsert(p.derivatives(), 0, 1.0);
732  ADReal h = enthalpy;
733  Moose::derivInsert(h.derivatives(), 1, 1.0);
734 
735  const ADReal T = T_from_p_h_ad(p, h);
736 
737  temperature = T.value();
738  dT_dp = T.derivatives()[0];
739  dT_dh = T.derivatives()[1];
740 }
741 
742 ADReal
744 {
745  return T_from_p_h_ad(pressure, enthalpy);
746 }
747 
748 ADReal
750 {
751  ADReal temperature = 0.0;
752 
753  // Determine which region the point is in
754  const unsigned int region = inRegionPH(pressure.value(), enthalpy.value());
755 
756  switch (region)
757  {
758  case 1:
760  break;
761 
762  case 2:
763  {
764  // First, determine which subregion the point is in:
765  const unsigned int subregion = subregion2ph(pressure.value(), enthalpy.value());
766 
767  if (subregion == 1)
769  else if (subregion == 2)
771  else
773  break;
774  }
775 
776  case 3:
777  {
778  // First, determine which subregion the point is in:
779  const unsigned int subregion = subregion3ph(pressure.value(), enthalpy.value());
780 
781  if (subregion == 1)
783  else
785  break;
786  }
787 
788  case 4:
790  break;
791 
792  case 5:
793  {
794  Real T_min = 1073.15;
795  Real T_max = 2273.15;
796  Real T_find = 0.;
797  Real T_error = 1.0;
798 
799  // Bisection solve
800  while (T_error > libMesh::TOLERANCE)
801  {
802  T_find = 0.5 * (T_min + T_max);
803  Real h_find = h_from_p_T(pressure.value(), T_find);
804 
805  if (h_find > enthalpy.value())
806  T_max = T_find;
807  else
808  T_min = T_find;
809 
810  T_error = std::abs((T_max - T_min) / T_find);
811  }
813  mooseDoOnce(
814  mooseWarning("The derivatives for T_from_p_h_ad are currently neglected, set to 0."));
815  temperature = T_find;
816 
817  break;
818  }
819  default:
820  mooseError("inRegionPH() has given an incorrect region");
821  }
822 
823  return temperature;
824 }
825 
826 ADReal
828 {
829  using std::pow;
830 
831  const ADReal pi = pressure / 1.0e6;
832  const ADReal eta = enthalpy / 2500.0e3;
833  ADReal sum = 0.0;
834 
835  for (std::size_t i = 0; i < _nph1.size(); ++i)
836  sum += _nph1[i] * pow(pi, _Iph1[i]) * pow(eta + 1.0, _Jph1[i]);
837 
838  return sum;
839 }
840 
841 ADReal
843  const ADReal & enthalpy) const
844 {
845  using std::pow, std::abs;
846 
847  const ADReal pi = pressure / 1.0e6;
848  const ADReal eta = enthalpy / 2000.0e3;
849  ADReal sum = 0.0;
850 
851  // Factor out the negative in pow(eta - 2.1, _Jph2a[i]) to avoid fpe in dbg (see #13163)
852  const Real sgn = MathUtils::sign(eta.value() - 2.1);
853 
854  for (std::size_t i = 0; i < _nph2a.size(); ++i)
855  sum += _nph2a[i] * pow(pi, _Iph2a[i]) * pow(abs(eta - 2.1), _Jph2a[i]) * pow(sgn, _Jph2a[i]);
856 
857  return sum;
858 }
859 
860 ADReal
862  const ADReal & enthalpy) const
863 {
864  using std::pow, std::abs;
865 
866  const ADReal pi = pressure / 1.0e6;
867  const ADReal eta = enthalpy / 2000.0e3;
868  ADReal sum = 0.0;
869 
870  // Factor out the negatives in pow(pi - 2.0, _Iph2b[i])* pow(eta - 2.6, _Jph2b[i])
871  // to avoid fpe in dbg (see #13163)
872  const Real sgn0 = MathUtils::sign(pi.value() - 2.0);
873  const Real sgn1 = MathUtils::sign(eta.value() - 2.6);
874 
875  for (std::size_t i = 0; i < _nph2b.size(); ++i)
876  sum += _nph2b[i] * pow(abs(pi - 2.0), _Iph2b[i]) * pow(sgn0, _Iph2b[i]) *
877  pow(abs(eta - 2.6), _Jph2b[i]) * pow(sgn1, _Jph2b[i]);
878 
879  return sum;
880 }
881 
882 ADReal
884  const ADReal & enthalpy) const
885 {
886  using std::pow, std::abs;
887 
888  const ADReal pi = pressure / 1.0e6;
889  const ADReal eta = enthalpy / 2000.0e3;
890  ADReal sum = 0.0;
891 
892  // Factor out the negative in pow(eta - 1.8, _Jph2c[i]) to avoid fpe in dbg (see #13163)
893  const Real sgn = MathUtils::sign(eta.value() - 1.8);
894 
895  for (std::size_t i = 0; i < _nph2c.size(); ++i)
896  sum += _nph2c[i] * pow(pi + 25.0, _Iph2c[i]) * pow(abs(eta - 1.8), _Jph2c[i]) *
897  pow(sgn, _Jph2c[i]);
898 
899  return sum;
900 }
901 
902 Real
904 {
905  // Check whether the input pressure is within the region of validity of this equation.
906  if (pressure < b23p(623.15) || pressure > 100.0e6)
907  mooseException(
908  name(), ": b3ab(): Pressure ", pressure, "is outside range of 16.529 MPa <= p <= 100 MPa");
909 
910  Real pi = pressure / 1.0e6;
911  Real eta = 0.201464004206875e4 + 0.374696550136983e1 * pi - 0.219921901054187e-1 * pi * pi +
912  0.87513168600995e-4 * pi * pi * pi;
913 
914  return eta * 1.0e3;
915 }
916 
917 ADReal
919  const ADReal & enthalpy) const
920 {
921  using std::pow;
922 
923  const ADReal pi = pressure / 100.0e6;
924  const ADReal eta = enthalpy / 2300.0e3;
925  ADReal sum = 0.0;
926 
927  for (std::size_t i = 0; i < _nph3a.size(); ++i)
928  sum += _nph3a[i] * pow(pi + 0.24, _Iph3a[i]) * pow(eta - 0.615, _Jph3a[i]);
929 
930  return sum * 760.0;
931 }
932 
933 ADReal
935  const ADReal & enthalpy) const
936 {
937  using std::pow;
938 
939  const ADReal pi = pressure / 100.0e6;
940  const ADReal eta = enthalpy / 2800.0e3;
941  ADReal sum = 0.0;
942 
943  for (size_t i = 0; i < _nph3b.size(); ++i)
944  sum += _nph3b[i] * pow(pi + 0.298, _Iph3b[i]) * pow(eta - 0.72, _Jph3b[i]);
945 
946  return sum * 860.0;
947 }
948 
949 Real
950 Water97FluidProperties::henryConstant(Real temperature, const std::vector<Real> & coeffs) const
951 {
952  const Real A = coeffs[0];
953  const Real B = coeffs[1];
954  const Real C = coeffs[2];
955 
956  const Real Tr = temperature / 647.096;
957  const Real tau = 1.0 - Tr;
958 
959  const Real lnkh =
960  A / Tr + B * std::pow(tau, 0.355) / Tr + C * std::pow(Tr, -0.41) * std::exp(tau);
961 
962  // The vapor pressure used in this formulation
963  const std::vector<Real> a{
964  -7.85951783, 1.84408259, -11.7866497, 22.6807411, -15.9618719, 1.80122502};
965  const std::vector<Real> b{1.0, 1.5, 3.0, 3.5, 4.0, 7.5};
966  Real sum = 0.0;
967 
968  for (std::size_t i = 0; i < a.size(); ++i)
969  sum += a[i] * std::pow(tau, b[i]);
970 
971  return 22.064e6 * std::exp(sum / Tr) * std::exp(lnkh);
972 }
973 
974 void
976  const std::vector<Real> & coeffs,
977  Real & Kh,
978  Real & dKh_dT) const
979 {
980  const Real A = coeffs[0];
981  const Real B = coeffs[1];
982  const Real C = coeffs[2];
983 
984  const Real pc = 22.064e6;
985  const Real Tc = 647.096;
986 
987  const Real Tr = temperature / Tc;
988  const Real tau = 1.0 - Tr;
989 
990  const Real lnkh =
991  A / Tr + B * std::pow(tau, 0.355) / Tr + C * std::pow(Tr, -0.41) * std::exp(tau);
992  const Real dlnkh_dT =
993  (-A / Tr / Tr - B * std::pow(tau, 0.355) / Tr / Tr - 0.355 * B * std::pow(tau, -0.645) / Tr -
994  0.41 * C * std::pow(Tr, -1.41) * std::exp(tau) - C * std::pow(Tr, -0.41) * std::exp(tau)) /
995  Tc;
996 
997  // The vapor pressure used in this formulation
998  const std::vector<Real> a{
999  -7.85951783, 1.84408259, -11.7866497, 22.6807411, -15.9618719, 1.80122502};
1000  const std::vector<Real> b{1.0, 1.5, 3.0, 3.5, 4.0, 7.5};
1001  Real sum = 0.0;
1002  Real dsum = 0.0;
1003 
1004  for (std::size_t i = 0; i < a.size(); ++i)
1005  {
1006  sum += a[i] * std::pow(tau, b[i]);
1007  dsum += a[i] * b[i] * std::pow(tau, b[i] - 1.0);
1008  }
1009 
1010  const Real p = pc * std::exp(sum / Tr);
1011  const Real dp_dT = -p / Tc / Tr * (sum / Tr + dsum);
1012 
1013  // Henry's constant and its derivative wrt temperature
1014  Kh = p * std::exp(lnkh);
1015  dKh_dT = (p * dlnkh_dT + dp_dT) * std::exp(lnkh);
1016 }
1017 
1018 ADReal
1020  const std::vector<Real> & coeffs) const
1021 {
1022  const Real T = temperature.value();
1023  Real Kh_real = 0.0;
1024  Real dKh_dT_real = 0.0;
1025  henryConstant(T, coeffs, Kh_real, dKh_dT_real);
1026 
1027  ADReal Kh = Kh_real;
1028  Kh.derivatives() = temperature.derivatives() * dKh_dT_real;
1029 
1030  return Kh;
1031 }
1032 
1033 unsigned int
1035 {
1036  Real pMPa = pressure / 1.0e6;
1037  const Real P3cd = 19.00881189173929;
1038  unsigned int subregion = 0;
1039 
1040  if (pMPa > 40.0 && pMPa <= 100.0)
1041  {
1042  if (temperature <= tempXY(pressure, AB))
1043  subregion = 0;
1044  else // (temperature > tempXY(pressure, AB))
1045  subregion = 1;
1046  }
1047  else if (pMPa > 25.0 && pMPa <= 40.0)
1048  {
1049  if (temperature <= tempXY(pressure, CD))
1050  subregion = 2;
1051  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, AB))
1052  subregion = 3;
1053  else if (temperature > tempXY(pressure, AB) && temperature <= tempXY(pressure, EF))
1054  subregion = 4;
1055  else // (temperature > tempXY(pressure, EF))
1056  subregion = 5;
1057  }
1058  else if (pMPa > 23.5 && pMPa <= 25.0)
1059  {
1060  if (temperature <= tempXY(pressure, CD))
1061  subregion = 2;
1062  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, GH))
1063  subregion = 6;
1064  else if (temperature > tempXY(pressure, GH) && temperature <= tempXY(pressure, EF))
1065  subregion = 7;
1066  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, IJ))
1067  subregion = 8;
1068  else if (temperature > tempXY(pressure, IJ) && temperature <= tempXY(pressure, JK))
1069  subregion = 9;
1070  else // (temperature > tempXY(pressure, JK))
1071  subregion = 10;
1072  }
1073  else if (pMPa > 23.0 && pMPa <= 23.5)
1074  {
1075  if (temperature <= tempXY(pressure, CD))
1076  subregion = 2;
1077  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, GH))
1078  subregion = 11;
1079  else if (temperature > tempXY(pressure, GH) && temperature <= tempXY(pressure, EF))
1080  subregion = 7;
1081  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, IJ))
1082  subregion = 8;
1083  else if (temperature > tempXY(pressure, IJ) && temperature <= tempXY(pressure, JK))
1084  subregion = 9;
1085  else // (temperature > tempXY(pressure, JK))
1086  subregion = 10;
1087  }
1088  else if (pMPa > 22.5 && pMPa <= 23.0)
1089  {
1090  if (temperature <= tempXY(pressure, CD))
1091  subregion = 2;
1092  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, GH))
1093  subregion = 11;
1094  else if (temperature > tempXY(pressure, GH) && temperature <= tempXY(pressure, MN))
1095  subregion = 12;
1096  else if (temperature > tempXY(pressure, MN) && temperature <= tempXY(pressure, EF))
1097  subregion = 13;
1098  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, OP))
1099  subregion = 14;
1100  else if (temperature > tempXY(pressure, OP) && temperature <= tempXY(pressure, IJ))
1101  subregion = 15;
1102  else if (temperature > tempXY(pressure, IJ) && temperature <= tempXY(pressure, JK))
1103  subregion = 9;
1104  else // (temperature > tempXY(pressure, JK))
1105  subregion = 10;
1106  }
1107  else if (pMPa > vaporPressure(643.15) * 1.0e-6 &&
1108  pMPa <= 22.5) // vaporPressure(643.15) = 21.04 MPa
1109  {
1110  if (temperature <= tempXY(pressure, CD))
1111  subregion = 2;
1112  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, QU))
1113  subregion = 16;
1114  else if (temperature > tempXY(pressure, QU) && temperature <= tempXY(pressure, RX))
1115  {
1116  if (pMPa > 22.11 && pMPa <= 22.5)
1117  {
1118  if (temperature <= tempXY(pressure, UV))
1119  subregion = 20;
1120  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1121  subregion = 21;
1122  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1123  subregion = 22;
1124  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1125  subregion = 23;
1126  }
1127  else if (pMPa > 22.064 && pMPa <= 22.11)
1128  {
1129  if (temperature <= tempXY(pressure, UV))
1130  subregion = 20;
1131  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1132  subregion = 24;
1133  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1134  subregion = 25;
1135  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1136  subregion = 23;
1137  }
1138  else if (temperature <= vaporTemperature(pressure))
1139  {
1140  if (pMPa > 21.93161551 && pMPa <= 22.064)
1142  subregion = 20;
1143  else
1144  subregion = 24;
1145  else // (pMPa > vaporPressure(643.15) * 1.0e-6 && pMPa <= 21.93161551)
1146  subregion = 20;
1147  }
1149  {
1150  if (pMPa > 21.90096265 && pMPa <= 22.064)
1151  {
1152  if (temperature <= tempXY(pressure, WX))
1153  subregion = 25;
1154  else
1155  subregion = 23;
1156  }
1157  else
1158  subregion = 23;
1159  }
1160  }
1161  else if (temperature > tempXY(pressure, RX) && temperature <= tempXY(pressure, JK))
1162  subregion = 17;
1163  else
1164  subregion = 10;
1165  }
1166  else if (pMPa > 20.5 &&
1167  pMPa <= vaporPressure(643.15) * 1.0e-6) // vaporPressure(643.15) = 21.04 MPa
1168  {
1169  if (temperature <= tempXY(pressure, CD))
1170  subregion = 2;
1172  subregion = 16;
1174  subregion = 17;
1175  else // (temperature > tempXY(pressure, JK))
1176  subregion = 10;
1177  }
1178  else if (pMPa > P3cd && pMPa <= 20.5) // P3cd = 19.00881189173929
1179  {
1180  if (temperature <= tempXY(pressure, CD))
1181  subregion = 2;
1183  subregion = 18;
1184  else
1185  subregion = 19;
1186  }
1187  else if (pMPa > vaporPressure(623.15) * 1.0e-6 && pMPa <= P3cd)
1188  {
1190  subregion = 2;
1191  else
1192  subregion = 19;
1193  }
1194  else if (pMPa > 22.11 && pMPa <= 22.5)
1195  {
1197  subregion = 20;
1198  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1199  subregion = 21;
1200  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1201  subregion = 22;
1202  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1203  subregion = 23;
1204  }
1205  else if (pMPa > 22.064 && pMPa <= 22.11)
1206  {
1208  subregion = 20;
1209  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1210  subregion = 24;
1211  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1212  subregion = 25;
1213  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1214  subregion = 23;
1215  }
1216  else
1217  mooseError("subregion3(): Shouldn't have got here!");
1218 
1219  return subregion;
1220 }
1221 
1222 unsigned int
1224 {
1225  // Valid for 273.15 K <= T <= 1073.15 K, p <= 100 MPa
1226  // 1073.15 K <= T <= 2273.15 K, p <= 50 Mpa
1227  if (temperature >= 273.15 && temperature <= 1073.15)
1228  {
1229  if (pressure < vaporPressure(273.15) || pressure > 100.0e6)
1230  mooseException("Pressure ", pressure, " is out of range in ", name(), ": inRegion()");
1231  }
1232  else if (temperature > 1073.15 && temperature <= 2273.15)
1233  {
1234  if (pressure < 0.0 || pressure > 50.0e6)
1235  mooseException("Pressure ", pressure, " is out of range in ", name(), ": inRegion()");
1236  }
1237  else
1238  mooseException("Temperature ", temperature, " is out of range in ", name(), ": inRegion()");
1239 
1240  // Determine the phase region that the (P, T) point lies in
1241  unsigned int region;
1242 
1243  if (temperature >= 273.15 && temperature <= 623.15)
1244  {
1245  if (pressure > vaporPressure(temperature) && pressure <= 100.0e6)
1246  region = 1;
1247  else
1248  region = 2;
1249  }
1250  else if (temperature > 623.15 && temperature <= 863.15)
1251  {
1252  if (pressure <= b23p(temperature))
1253  region = 2;
1254  else
1255  region = 3;
1256  }
1257  else if (temperature > 863.15 && temperature <= 1073.15)
1258  region = 2;
1259  else
1260  region = 5;
1261 
1262  return region;
1263 }
T v_from_p_T_template(const T &pressure, const T &temperature) const
const Real _T_critical
Critical temperature (K)
T dgamma2_dtau(const T &pi, const T &tau) const
Derivative of Gibbs free energy in Region 2 wrt tau.
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.
const bool _allow_imperfect_jacobians
Flag to set unimplemented Jacobian entries to zero.
Real p_from_v_e(Real v, Real e) const override
const double T
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
static constexpr Real TOLERANCE
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:34
const double v
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:60
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
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...
DualNumber< Real, DNDerivativeType, false > ADReal
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.
const std::array< Real, 5 > _p_star
Pressure scale for each region.
T cv_from_p_T_template(const T &pressure, const T &temperature) const
const std::array< int, 20 > _Jph1
const std::array< Real, 5 > _T_star
Temperature scale for each region.
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
const double rho
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.
T dgamma1_dtau(const T &pi, const T &tau) const
Derivative of Gibbs free energy in Region 1 wrt tau.
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
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
const Real p
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:57
virtual Real vaporPressure(Real temperature) const override
Vapor pressure.
void mooseWarning(Args &&... args) const
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
const Real _Rw
Specific gas constant for H2O (universal gas constant / molar mass of water - J/kg/K) ...
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
const double mu
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:172
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...