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  // Check whether the input pressure is within the region of validity of this equation.
547  // Valid for 611.213 Pa <= p <= 22.064 MPa
548  if (pressure.value() < 611.23 || pressure.value() > _p_critical)
549  mooseException(name() + ": vaporTemperature(): Pressure ",
550  pressure.value(),
551  " is outside range 611.213 Pa <= p <= 22.064 MPa");
552 
553  const ADReal beta = std::pow(pressure / 1.e6, 0.25);
554  const ADReal beta2 = beta * beta;
555  const ADReal e = beta2 + _n4[2] * beta + _n4[5];
556  const ADReal f = _n4[0] * beta2 + _n4[3] * beta + _n4[6];
557  const ADReal g = _n4[1] * beta2 + _n4[4] * beta + _n4[7];
558  const ADReal d = 2.0 * g / (-f - std::sqrt(f * f - 4.0 * e * g));
559 
560  return (_n4[9] + d - std::sqrt((_n4[9] + d) * (_n4[9] + d) - 4.0 * (_n4[8] + _n4[9] * d))) / 2.0;
561 }
562 
563 Real
565 {
566  const ADReal p = pressure;
567 
568  return vaporTemperature_ad(p).value();
569 }
570 
571 void
572 Water97FluidProperties::vaporTemperature(Real pressure, Real & Tsat, Real & dTsat_dp) const
573 {
574  ADReal p = pressure;
575  Moose::derivInsert(p.derivatives(), 0, 1.0);
576 
577  const ADReal T = vaporTemperature_ad(p);
578 
579  Tsat = T.value();
580  dTsat_dp = T.derivatives()[0];
581 }
582 
583 Real
585 {
586  // Check whether the input temperature is within the region of validity of this equation.
587  // Valid for 623.15 K <= t <= 863.15 K
588  if (temperature < 623.15 || temperature > 863.15)
589  mooseException(name(),
590  ": b23p(): Temperature ",
591  temperature,
592  " is outside range of 623.15 K <= T <= 863.15 K");
593 
594  return (_n23[0] + _n23[1] * temperature + _n23[2] * temperature * temperature) * 1.e6;
595 }
596 
597 Real
599 {
600  // Check whether the input pressure is within the region of validity of this equation.
601  // Valid for 16.529 MPa <= p <= 100 MPa
602  if (pressure < 16.529e6 || pressure > 100.0e6)
603  mooseException(
604  name(), ": b23T(): Pressure ", pressure, "is outside range 16.529 MPa <= p <= 100 MPa");
605 
606  return _n23[3] + std::sqrt((pressure / 1.e6 - _n23[4]) / _n23[2]);
607 }
608 
609 unsigned int
611 {
612  unsigned int region;
613 
614  // Need to calculate enthalpies at the boundaries to delineate regions
615  Real p273 = vaporPressure(273.15);
616  Real p623 = vaporPressure(623.15);
617 
618  if (pressure >= p273 && pressure <= p623)
619  {
620  if (enthalpy >= h_from_p_T(pressure, 273.15) &&
622  region = 1;
623  else if (enthalpy > h_from_p_T(pressure, vaporTemperature(pressure)) &&
624  enthalpy <= h_from_p_T(pressure, 1073.15))
625  region = 2;
626  else if (enthalpy > h_from_p_T(pressure, 1073.15) && enthalpy <= h_from_p_T(pressure, 2273.15))
627  region = 5;
628  else
629  mooseException("Enthalpy ", enthalpy, " is out of range in ", name(), ": inRegionPH()");
630  }
631  else if (pressure > p623 && pressure <= 50.0e6)
632  {
633  if (enthalpy >= h_from_p_T(pressure, 273.15) && enthalpy <= h_from_p_T(pressure, 623.15))
634  region = 1;
635  else if (enthalpy > h_from_p_T(pressure, 623.15) &&
636  enthalpy <= h_from_p_T(pressure, b23T(pressure)))
637  region = 3;
638  else if (enthalpy > h_from_p_T(pressure, b23T(pressure)) &&
639  enthalpy <= h_from_p_T(pressure, 1073.15))
640  region = 2;
641  else if (enthalpy > h_from_p_T(pressure, 1073.15) && enthalpy <= h_from_p_T(pressure, 2273.15))
642  region = 5;
643  else
644  mooseException("Enthalpy ", enthalpy, " is out of range in ", name(), ": inRegionPH()");
645  }
646  else if (pressure > 50.0e6 && pressure <= 100.0e6)
647  {
648  if (enthalpy >= h_from_p_T(pressure, 273.15) && enthalpy <= h_from_p_T(pressure, 623.15))
649  region = 1;
650  else if (enthalpy > h_from_p_T(pressure, 623.15) &&
651  enthalpy <= h_from_p_T(pressure, b23T(pressure)))
652  region = 3;
653  else if (enthalpy > h_from_p_T(pressure, b23T(pressure)) &&
654  enthalpy <= h_from_p_T(pressure, 1073.15))
655  region = 2;
656  else
657  mooseException("Enthalpy ", enthalpy, " is out of range in ", name(), ": inRegionPH()");
658  }
659  else
660  mooseException("Pressure ", pressure, " is out of range in ", name(), ": inRegionPH()");
661 
662  return region;
663 }
664 
665 unsigned int
667 {
668  unsigned int subregion;
669 
670  if (pressure <= 4.0e6)
671  subregion = 1;
672  else if (pressure > 4.0e6 && pressure < 6.5467e6)
673  subregion = 2;
674  else
675  {
676  if (enthalpy >= b2bc(pressure))
677  subregion = 2;
678  else
679  subregion = 3;
680  }
681 
682  return subregion;
683 }
684 
685 unsigned int
687 {
688  unsigned int subregion;
689 
690  if (enthalpy <= b3ab(pressure))
691  subregion = 1;
692  else
693  subregion = 2;
694 
695  return subregion;
696 }
697 
698 Real
700 {
701  // Check whether the input pressure is within the region of validity of this equation.
702  if (pressure < 6.5467e6 || pressure > 100.0e6)
703  mooseException(
704  name(), ": b2bc(): Pressure ", pressure, " is outside range of 6.5467 MPa <= p <= 100 MPa");
705 
706  Real pi = pressure / 1.0e6;
707 
708  return (0.26526571908428e4 + std::sqrt((pi - 0.45257578905948e1) / 0.12809002730136e-3)) * 1.0e3;
709 }
710 
711 Real
713 {
714  const ADReal p = pressure;
715  const ADReal h = enthalpy;
716 
717  return T_from_p_h_ad(p, h).value();
718 }
719 
720 void
722  Real pressure, Real enthalpy, Real & temperature, Real & dT_dp, Real & dT_dh) const
723 {
724  ADReal p = pressure;
725  Moose::derivInsert(p.derivatives(), 0, 1.0);
726  ADReal h = enthalpy;
727  Moose::derivInsert(h.derivatives(), 1, 1.0);
728 
729  const ADReal T = T_from_p_h_ad(p, h);
730 
731  temperature = T.value();
732  dT_dp = T.derivatives()[0];
733  dT_dh = T.derivatives()[1];
734 }
735 
736 ADReal
738 {
739  return T_from_p_h_ad(pressure, enthalpy);
740 }
741 
742 ADReal
744 {
745  ADReal temperature = 0.0;
746 
747  // Determine which region the point is in
748  const unsigned int region = inRegionPH(pressure.value(), enthalpy.value());
749 
750  switch (region)
751  {
752  case 1:
754  break;
755 
756  case 2:
757  {
758  // First, determine which subregion the point is in:
759  const unsigned int subregion = subregion2ph(pressure.value(), enthalpy.value());
760 
761  if (subregion == 1)
763  else if (subregion == 2)
765  else
767  break;
768  }
769 
770  case 3:
771  {
772  // First, determine which subregion the point is in:
773  const unsigned int subregion = subregion3ph(pressure.value(), enthalpy.value());
774 
775  if (subregion == 1)
777  else
779  break;
780  }
781 
782  case 5:
783  mooseError("temperature_from_ph() not implemented for region 5");
784  break;
785 
786  default:
787  mooseError("inRegionPH() has given an incorrect region");
788  }
789 
790  return temperature;
791 }
792 
793 ADReal
795 {
796  const ADReal pi = pressure / 1.0e6;
797  const ADReal eta = enthalpy / 2500.0e3;
798  ADReal sum = 0.0;
799 
800  for (std::size_t i = 0; i < _nph1.size(); ++i)
801  sum += _nph1[i] * std::pow(pi, _Iph1[i]) * std::pow(eta + 1.0, _Jph1[i]);
802 
803  return sum;
804 }
805 
806 ADReal
808  const ADReal & enthalpy) const
809 {
810  const ADReal pi = pressure / 1.0e6;
811  const ADReal eta = enthalpy / 2000.0e3;
812  ADReal sum = 0.0;
813 
814  // Factor out the negative in std::pow(eta - 2.1, _Jph2a[i]) to avoid fpe in dbg (see #13163)
815  const Real sgn = MathUtils::sign(eta.value() - 2.1);
816 
817  for (std::size_t i = 0; i < _nph2a.size(); ++i)
818  sum += _nph2a[i] * std::pow(pi, _Iph2a[i]) * std::pow(std::abs(eta - 2.1), _Jph2a[i]) *
819  std::pow(sgn, _Jph2a[i]);
820 
821  return sum;
822 }
823 
824 ADReal
826  const ADReal & enthalpy) const
827 {
828  const ADReal pi = pressure / 1.0e6;
829  const ADReal eta = enthalpy / 2000.0e3;
830  ADReal sum = 0.0;
831 
832  // Factor out the negatives in std::pow(pi - 2.0, _Iph2b[i])* std::pow(eta - 2.6, _Jph2b[i])
833  // to avoid fpe in dbg (see #13163)
834  const Real sgn0 = MathUtils::sign(pi.value() - 2.0);
835  const Real sgn1 = MathUtils::sign(eta.value() - 2.6);
836 
837  for (std::size_t i = 0; i < _nph2b.size(); ++i)
838  sum += _nph2b[i] * std::pow(std::abs(pi - 2.0), _Iph2b[i]) * std::pow(sgn0, _Iph2b[i]) *
839  std::pow(std::abs(eta - 2.6), _Jph2b[i]) * std::pow(sgn1, _Jph2b[i]);
840 
841  return sum;
842 }
843 
844 ADReal
846  const ADReal & enthalpy) const
847 {
848  const ADReal pi = pressure / 1.0e6;
849  const ADReal eta = enthalpy / 2000.0e3;
850  ADReal sum = 0.0;
851 
852  // Factor out the negative in std::pow(eta - 1.8, _Jph2c[i]) to avoid fpe in dbg (see #13163)
853  const Real sgn = MathUtils::sign(eta.value() - 1.8);
854 
855  for (std::size_t i = 0; i < _nph2c.size(); ++i)
856  sum += _nph2c[i] * std::pow(pi + 25.0, _Iph2c[i]) * std::pow(std::abs(eta - 1.8), _Jph2c[i]) *
857  std::pow(sgn, _Jph2c[i]);
858 
859  return sum;
860 }
861 
862 Real
864 {
865  // Check whether the input pressure is within the region of validity of this equation.
866  if (pressure < b23p(623.15) || pressure > 100.0e6)
867  mooseException(
868  name(), ": b3ab(): Pressure ", pressure, "is outside range of 16.529 MPa <= p <= 100 MPa");
869 
870  Real pi = pressure / 1.0e6;
871  Real eta = 0.201464004206875e4 + 0.374696550136983e1 * pi - 0.219921901054187e-1 * pi * pi +
872  0.87513168600995e-4 * pi * pi * pi;
873 
874  return eta * 1.0e3;
875 }
876 
877 ADReal
879  const ADReal & enthalpy) const
880 {
881  const ADReal pi = pressure / 100.0e6;
882  const ADReal eta = enthalpy / 2300.0e3;
883  ADReal sum = 0.0;
884 
885  for (std::size_t i = 0; i < _nph3a.size(); ++i)
886  sum += _nph3a[i] * std::pow(pi + 0.24, _Iph3a[i]) * std::pow(eta - 0.615, _Jph3a[i]);
887 
888  return sum * 760.0;
889 }
890 
891 ADReal
893  const ADReal & enthalpy) const
894 {
895  const ADReal pi = pressure / 100.0e6;
896  const ADReal eta = enthalpy / 2800.0e3;
897  ADReal sum = 0.0;
898 
899  for (std::size_t i = 0; i < _nph3b.size(); ++i)
900  sum += _nph3b[i] * std::pow(pi + 0.298, _Iph3b[i]) * std::pow(eta - 0.72, _Jph3b[i]);
901 
902  return sum * 860.0;
903 }
904 
905 Real
906 Water97FluidProperties::henryConstant(Real temperature, const std::vector<Real> & coeffs) const
907 {
908  const Real A = coeffs[0];
909  const Real B = coeffs[1];
910  const Real C = coeffs[2];
911 
912  const Real Tr = temperature / 647.096;
913  const Real tau = 1.0 - Tr;
914 
915  const Real lnkh =
916  A / Tr + B * std::pow(tau, 0.355) / Tr + C * std::pow(Tr, -0.41) * std::exp(tau);
917 
918  // The vapor pressure used in this formulation
919  const std::vector<Real> a{
920  -7.85951783, 1.84408259, -11.7866497, 22.6807411, -15.9618719, 1.80122502};
921  const std::vector<Real> b{1.0, 1.5, 3.0, 3.5, 4.0, 7.5};
922  Real sum = 0.0;
923 
924  for (std::size_t i = 0; i < a.size(); ++i)
925  sum += a[i] * std::pow(tau, b[i]);
926 
927  return 22.064e6 * std::exp(sum / Tr) * std::exp(lnkh);
928 }
929 
930 void
932  const std::vector<Real> & coeffs,
933  Real & Kh,
934  Real & dKh_dT) const
935 {
936  const Real A = coeffs[0];
937  const Real B = coeffs[1];
938  const Real C = coeffs[2];
939 
940  const Real pc = 22.064e6;
941  const Real Tc = 647.096;
942 
943  const Real Tr = temperature / Tc;
944  const Real tau = 1.0 - Tr;
945 
946  const Real lnkh =
947  A / Tr + B * std::pow(tau, 0.355) / Tr + C * std::pow(Tr, -0.41) * std::exp(tau);
948  const Real dlnkh_dT =
949  (-A / Tr / Tr - B * std::pow(tau, 0.355) / Tr / Tr - 0.355 * B * std::pow(tau, -0.645) / Tr -
950  0.41 * C * std::pow(Tr, -1.41) * std::exp(tau) - C * std::pow(Tr, -0.41) * std::exp(tau)) /
951  Tc;
952 
953  // The vapor pressure used in this formulation
954  const std::vector<Real> a{
955  -7.85951783, 1.84408259, -11.7866497, 22.6807411, -15.9618719, 1.80122502};
956  const std::vector<Real> b{1.0, 1.5, 3.0, 3.5, 4.0, 7.5};
957  Real sum = 0.0;
958  Real dsum = 0.0;
959 
960  for (std::size_t i = 0; i < a.size(); ++i)
961  {
962  sum += a[i] * std::pow(tau, b[i]);
963  dsum += a[i] * b[i] * std::pow(tau, b[i] - 1.0);
964  }
965 
966  const Real p = pc * std::exp(sum / Tr);
967  const Real dp_dT = -p / Tc / Tr * (sum / Tr + dsum);
968 
969  // Henry's constant and its derivative wrt temperature
970  Kh = p * std::exp(lnkh);
971  dKh_dT = (p * dlnkh_dT + dp_dT) * std::exp(lnkh);
972 }
973 
974 ADReal
976  const std::vector<Real> & coeffs) const
977 {
978  const Real T = temperature.value();
979  Real Kh_real = 0.0;
980  Real dKh_dT_real = 0.0;
981  henryConstant(T, coeffs, Kh_real, dKh_dT_real);
982 
983  ADReal Kh = Kh_real;
984  Kh.derivatives() = temperature.derivatives() * dKh_dT_real;
985 
986  return Kh;
987 }
988 
989 unsigned int
991 {
992  Real pMPa = pressure / 1.0e6;
993  const Real P3cd = 19.00881189173929;
994  unsigned int subregion = 0;
995 
996  if (pMPa > 40.0 && pMPa <= 100.0)
997  {
998  if (temperature <= tempXY(pressure, AB))
999  subregion = 0;
1000  else // (temperature > tempXY(pressure, AB))
1001  subregion = 1;
1002  }
1003  else if (pMPa > 25.0 && pMPa <= 40.0)
1004  {
1005  if (temperature <= tempXY(pressure, CD))
1006  subregion = 2;
1007  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, AB))
1008  subregion = 3;
1009  else if (temperature > tempXY(pressure, AB) && temperature <= tempXY(pressure, EF))
1010  subregion = 4;
1011  else // (temperature > tempXY(pressure, EF))
1012  subregion = 5;
1013  }
1014  else if (pMPa > 23.5 && pMPa <= 25.0)
1015  {
1016  if (temperature <= tempXY(pressure, CD))
1017  subregion = 2;
1018  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, GH))
1019  subregion = 6;
1020  else if (temperature > tempXY(pressure, GH) && temperature <= tempXY(pressure, EF))
1021  subregion = 7;
1022  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, IJ))
1023  subregion = 8;
1024  else if (temperature > tempXY(pressure, IJ) && temperature <= tempXY(pressure, JK))
1025  subregion = 9;
1026  else // (temperature > tempXY(pressure, JK))
1027  subregion = 10;
1028  }
1029  else if (pMPa > 23.0 && pMPa <= 23.5)
1030  {
1031  if (temperature <= tempXY(pressure, CD))
1032  subregion = 2;
1033  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, GH))
1034  subregion = 11;
1035  else if (temperature > tempXY(pressure, GH) && temperature <= tempXY(pressure, EF))
1036  subregion = 7;
1037  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, IJ))
1038  subregion = 8;
1039  else if (temperature > tempXY(pressure, IJ) && temperature <= tempXY(pressure, JK))
1040  subregion = 9;
1041  else // (temperature > tempXY(pressure, JK))
1042  subregion = 10;
1043  }
1044  else if (pMPa > 22.5 && pMPa <= 23.0)
1045  {
1046  if (temperature <= tempXY(pressure, CD))
1047  subregion = 2;
1048  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, GH))
1049  subregion = 11;
1050  else if (temperature > tempXY(pressure, GH) && temperature <= tempXY(pressure, MN))
1051  subregion = 12;
1052  else if (temperature > tempXY(pressure, MN) && temperature <= tempXY(pressure, EF))
1053  subregion = 13;
1054  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, OP))
1055  subregion = 14;
1056  else if (temperature > tempXY(pressure, OP) && temperature <= tempXY(pressure, IJ))
1057  subregion = 15;
1058  else if (temperature > tempXY(pressure, IJ) && temperature <= tempXY(pressure, JK))
1059  subregion = 9;
1060  else // (temperature > tempXY(pressure, JK))
1061  subregion = 10;
1062  }
1063  else if (pMPa > vaporPressure(643.15) * 1.0e-6 &&
1064  pMPa <= 22.5) // vaporPressure(643.15) = 21.04 MPa
1065  {
1066  if (temperature <= tempXY(pressure, CD))
1067  subregion = 2;
1068  else if (temperature > tempXY(pressure, CD) && temperature <= tempXY(pressure, QU))
1069  subregion = 16;
1070  else if (temperature > tempXY(pressure, QU) && temperature <= tempXY(pressure, RX))
1071  {
1072  if (pMPa > 22.11 && pMPa <= 22.5)
1073  {
1074  if (temperature <= tempXY(pressure, UV))
1075  subregion = 20;
1076  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1077  subregion = 21;
1078  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1079  subregion = 22;
1080  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1081  subregion = 23;
1082  }
1083  else if (pMPa > 22.064 && pMPa <= 22.11)
1084  {
1085  if (temperature <= tempXY(pressure, UV))
1086  subregion = 20;
1087  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1088  subregion = 24;
1089  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1090  subregion = 25;
1091  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1092  subregion = 23;
1093  }
1094  else if (temperature <= vaporTemperature(pressure))
1095  {
1096  if (pMPa > 21.93161551 && pMPa <= 22.064)
1098  subregion = 20;
1099  else
1100  subregion = 24;
1101  else // (pMPa > vaporPressure(643.15) * 1.0e-6 && pMPa <= 21.93161551)
1102  subregion = 20;
1103  }
1105  {
1106  if (pMPa > 21.90096265 && pMPa <= 22.064)
1107  {
1108  if (temperature <= tempXY(pressure, WX))
1109  subregion = 25;
1110  else
1111  subregion = 23;
1112  }
1113  else
1114  subregion = 23;
1115  }
1116  }
1117  else if (temperature > tempXY(pressure, RX) && temperature <= tempXY(pressure, JK))
1118  subregion = 17;
1119  else
1120  subregion = 10;
1121  }
1122  else if (pMPa > 20.5 &&
1123  pMPa <= vaporPressure(643.15) * 1.0e-6) // vaporPressure(643.15) = 21.04 MPa
1124  {
1125  if (temperature <= tempXY(pressure, CD))
1126  subregion = 2;
1128  subregion = 16;
1130  subregion = 17;
1131  else // (temperature > tempXY(pressure, JK))
1132  subregion = 10;
1133  }
1134  else if (pMPa > P3cd && pMPa <= 20.5) // P3cd = 19.00881189173929
1135  {
1136  if (temperature <= tempXY(pressure, CD))
1137  subregion = 2;
1139  subregion = 18;
1140  else
1141  subregion = 19;
1142  }
1143  else if (pMPa > vaporPressure(623.15) * 1.0e-6 && pMPa <= P3cd)
1144  {
1146  subregion = 2;
1147  else
1148  subregion = 19;
1149  }
1150  else if (pMPa > 22.11 && pMPa <= 22.5)
1151  {
1153  subregion = 20;
1154  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1155  subregion = 21;
1156  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1157  subregion = 22;
1158  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1159  subregion = 23;
1160  }
1161  else if (pMPa > 22.064 && pMPa <= 22.11)
1162  {
1164  subregion = 20;
1165  else if (temperature > tempXY(pressure, UV) && temperature <= tempXY(pressure, EF))
1166  subregion = 24;
1167  else if (temperature > tempXY(pressure, EF) && temperature <= tempXY(pressure, WX))
1168  subregion = 25;
1169  else // (temperature > tempXY(pressure, WX) && temperature <= tempXY(pressure, RX))
1170  subregion = 23;
1171  }
1172  else
1173  mooseError("subregion3(): Shouldn't have got here!");
1174 
1175  return subregion;
1176 }
1177 
1178 unsigned int
1180 {
1181  // Valid for 273.15 K <= T <= 1073.15 K, p <= 100 MPa
1182  // 1073.15 K <= T <= 2273.15 K, p <= 50 Mpa
1183  if (temperature >= 273.15 && temperature <= 1073.15)
1184  {
1185  if (pressure < vaporPressure(273.15) || pressure > 100.0e6)
1186  mooseException("Pressure ", pressure, " is out of range in ", name(), ": inRegion()");
1187  }
1188  else if (temperature > 1073.15 && temperature <= 2273.15)
1189  {
1190  if (pressure < 0.0 || pressure > 50.0e6)
1191  mooseException("Pressure ", pressure, " is out of range in ", name(), ": inRegion()");
1192  }
1193  else
1194  mooseException("Temperature ", temperature, " is out of range in ", name(), ": inRegion()");
1195 
1196  // Determine the phase region that the (P, T) point lies in
1197  unsigned int region;
1198 
1199  if (temperature >= 273.15 && temperature <= 623.15)
1200  {
1201  if (pressure > vaporPressure(temperature) && pressure <= 100.0e6)
1202  region = 1;
1203  else
1204  region = 2;
1205  }
1206  else if (temperature > 623.15 && temperature <= 863.15)
1207  {
1208  if (pressure <= b23p(temperature))
1209  region = 2;
1210  else
1211  region = 3;
1212  }
1213  else if (temperature > 863.15 && temperature <= 1073.15)
1214  region = 2;
1215  else
1216  region = 5;
1217 
1218  return region;
1219 }
T v_from_p_T_template(const T &pressure, const T &temperature) const
const Real _T_critical
Critical temperature (K)
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)
virtual const std::string & name() const
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::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
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
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.
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...
void mooseError(Args &&... args) const
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...