https://mooseframework.inl.gov
HydrogenFluidProperties.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 #include "Conversion.h"
12 #include "MathUtils.h"
13 #include "libmesh/utility.h"
14 
15 registerMooseObject("FluidPropertiesApp", HydrogenFluidProperties);
16 
19 {
21  params.addClassDescription("Fluid properties for Hydrogen (H2)");
22  return params;
23 }
24 
26  : HelmholtzFluidProperties(parameters),
27  _Mh2(2.01588e-3),
28  _p_critical(1.315e6),
29  _T_critical(33.19),
30  _rho_molar_critical(15.508),
31  _rho_critical(1000.0 * _rho_molar_critical * _Mh2),
32  _p_triple(7.7e3),
33  _T_triple(13.952)
34 {
35 }
36 
37 std::string
39 {
40  return "hydrogen";
41 }
42 
43 Real
45 {
46  return _Mh2;
47 }
48 
49 Real
51 {
52  return _p_critical;
53 }
54 
55 Real
57 {
58  return _T_critical;
59 }
60 
61 Real
63 {
64  return _rho_critical;
65 }
66 
67 Real
69 {
70  return _p_triple;
71 }
72 
73 Real
75 {
76  return _T_triple;
77 }
78 
79 Real
81 {
82  // Scaled variables
83  const Real Tstar = temperature / 30.41;
84  const Real logTstar = std::log(Tstar);
85  const Real Tr = temperature / _T_critical;
86  const Real rhor = density / 90.5;
87 
88  // Ideal gas component
89  Real sum = 0.0;
90  for (std::size_t i = 0; i < _amu.size(); ++i)
91  sum += _amu[i] * MathUtils::pow(logTstar, i);
92 
93  const Real mu0 =
94  0.021357 * std::sqrt(1000.0 * _Mh2 * temperature) / (0.297 * 0.297 * std::exp(sum));
95 
96  // The excess contribution due to density
97  Real sumr = 0.0;
98  for (std::size_t i = 0; i < _bmu.size(); ++i)
99  sumr += _bmu[i];
100 
101  const Real mu1 = MathUtils::pow(0.297, 3) * sumr * mu0 / Tstar;
102 
103  // The viscosity is then
104  const Real mu =
105  mu0 + mu1 * density +
106  _cmu[0] * rhor * rhor *
107  std::exp(_cmu[1] * Tr + _cmu[2] / Tr + _cmu[3] * rhor * rhor / (_cmu[4] + Tr) +
108  _cmu[5] * MathUtils::pow(rhor, 6));
109 
110  return mu * 1.0e-6;
111 }
112 
113 void
115  Real temperature,
116  Real ddensity_dT,
117  Real & mu,
118  Real & dmu_drho,
119  Real & dmu_dT) const
120 {
121  // Scaled variables
122  const Real Tstar = temperature / 30.41;
123  const Real logTstar = std::log(Tstar);
124  const Real Tr = temperature / _T_critical;
125  const Real rhor = density / 90.5;
126  const Real drhor_drho = 1.0 / 90.5;
127  const Real dTr_dT = 1.0 / _T_critical;
128 
129  // The dilute gas component
130  Real sum = 0.0, dsum_dT = 0.0;
131  for (std::size_t i = 0; i < _amu.size(); ++i)
132  {
133  sum += _amu[i] * MathUtils::pow(logTstar, i);
134  dsum_dT += i * _amu[i] * MathUtils::pow(logTstar, i) / (temperature * logTstar);
135  }
136 
137  const Real mu0 =
138  0.021357 * std::sqrt(1000.0 * _Mh2 * temperature) / (0.297 * 0.297 * std::exp(sum));
139  const Real dmu0_dT = 21.357 * _Mh2 * (1.0 - 2.0 * temperature * dsum_dT) * std::exp(-sum) /
140  (2.0 * std::sqrt(1000.0 * _Mh2 * temperature) * 0.297 * 0.297);
141 
142  // The excess contribution due to density
143  Real sumr = 0.0;
144  for (std::size_t i = 0; i < _bmu.size(); ++i)
145  sumr += _bmu[i];
146 
147  const Real mu1 = MathUtils::pow(0.297, 3) * sumr * mu0 / Tstar;
148  const Real dmu1_dT =
149  MathUtils::pow(0.297, 3) * sumr * (dmu0_dT / Tstar - mu0 / (30.41 * Tstar * Tstar));
150 
151  // The viscosity and derivatives are then
152  const Real exponent = _cmu[1] * Tr + _cmu[2] / Tr + _cmu[3] * rhor * rhor / (_cmu[4] + Tr) +
153  _cmu[5] * MathUtils::pow(rhor, 6);
154  const Real dexponent_drho =
155  (2.0 * _cmu[3] * rhor / (_cmu[4] + Tr) + 6.0 * _cmu[5] * MathUtils::pow(rhor, 5)) *
156  drhor_drho;
157  const Real dexponent_dT =
158  (_cmu[1] - _cmu[2] / Tr / Tr - _cmu[3] * rhor * rhor / (_cmu[4] + Tr) / (_cmu[4] + Tr)) *
159  dTr_dT;
160 
161  mu = (mu0 + mu1 * density + _cmu[0] * rhor * rhor * std::exp(exponent)) * 1.0e-6;
162  dmu_drho =
163  (mu1 + _cmu[0] * rhor * std::exp(exponent) * (2.0 * drhor_drho + rhor * dexponent_drho)) *
164  1.0e-6;
165  dmu_dT =
166  (dmu0_dT + density * dmu1_dT + _cmu[0] * rhor * rhor * dexponent_dT * std::exp(exponent)) *
167  1.0e-6 +
168  dmu_drho * ddensity_dT;
169 }
170 
171 Real
173 {
174  // Require density first
177 }
178 
179 void
181  Real pressure, Real temperature, Real & mu, Real & dmu_dp, Real & dmu_dT) const
182 {
183  Real rho, drho_dp, drho_dT;
184  rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
185 
186  Real dmu_drho;
187  mu_from_rho_T(rho, temperature, drho_dT, mu, dmu_drho, dmu_dT);
188  dmu_dp = dmu_drho * drho_dp;
189 }
190 
191 void
193  Real temperature,
194  Real & rho,
195  Real & mu) const
196 {
199 }
200 
201 void
203  Real temperature,
204  Real & rho,
205  Real & drho_dp,
206  Real & drho_dT,
207  Real & mu,
208  Real & dmu_dp,
209  Real & dmu_dT) const
210 {
211  rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
212  Real dmu_drho;
213  mu_from_rho_T(rho, temperature, drho_dT, mu, dmu_drho, dmu_dT);
214  dmu_dp = dmu_drho * drho_dp;
215 }
216 
217 Real
219 {
220  // // Scaled variables
221  const Real Tr = temperature / 33.145;
222  const Real rhor = density / 31.262;
223 
224  // The ideal gas component
225  Real sum1 = 0.0;
226  for (std::size_t i = 0; i < _a1k.size(); ++i)
227  sum1 += _a1k[i] * MathUtils::pow(Tr, i);
228 
229  Real sum2 = 0.0;
230  for (std::size_t i = 0; i < _a2k.size(); ++i)
231  sum2 += _a2k[i] * MathUtils::pow(Tr, i);
232 
233  const Real lambda0 = sum1 / sum2;
234 
235  // The excess contribution due to density
236  Real lambdah = 0.0;
237  for (std::size_t i = 0; i < _b1k.size(); ++i)
238  lambdah += (_b1k[i] + _b2k[i] * Tr) * MathUtils::pow(rhor, i + 1);
239 
240  // The critical enhancement
241  const Real lambdac = 6.24e-4 / (-2.58e-7 + std::abs(Tr - 1.0)) *
242  std::exp(-MathUtils::pow(0.837 * (rhor - 1.0), 2));
243 
244  // The thermal conductivity
245  return lambda0 + lambdah + lambdac;
246 }
247 
248 Real
250 {
251  // Require density first
254 }
255 
256 void
258  Real pressure, Real temperature, Real & k, Real & dk_dp, Real & dk_dT) const
259 {
260  k = this->k_from_p_T(pressure, temperature);
261  // Calculate derivatives using finite differences
262  const Real eps = 1.0e-6;
263  const Real peps = pressure * eps;
264  const Real Teps = temperature * eps;
265 
266  dk_dp = (this->k_from_p_T(pressure + peps, temperature) - k) / peps;
267  dk_dT = (this->k_from_p_T(pressure, temperature + Teps) - k) / Teps;
268 }
269 
270 std::vector<Real>
272 {
273  return {-4.73284, 6.08954, 6.06066};
274 }
275 
276 Real
278 {
279  if (temperature < _T_triple || temperature > _T_critical)
280  throw MooseException("Temperature is out of range in " + name() + ": vaporPressure()");
281 
282  const Real Tr = temperature / _T_critical;
283  const Real theta = 1.0 - Tr;
284 
285  const Real logpressure = (-4.89789 * theta + 0.988588 * std::pow(theta, 1.5) +
286  0.349689 * Utility::pow<2>(theta) + 0.499356 * std::pow(theta, 2.85)) /
287  Tr;
288 
289  return _p_critical * std::exp(logpressure);
290 }
291 
292 void
293 HydrogenFluidProperties::vaporPressure(Real, Real &, Real &) const
294 {
295  mooseError("vaporPressure() is not implemented");
296 }
297 
298 Real
300 {
301  // Ideal gas component of the Helmholtz free energy
302  Real alpha0 = std::log(delta) + 1.5 * std::log(tau) - 1.4579856475 + 1.888076782 * tau;
303 
304  for (std::size_t i = 0; i < _a.size(); ++i)
305  alpha0 += _a[i] * std::log(1.0 - std::exp(_b[i] * tau));
306 
307  // Residual component of the Helmholtz free energy
308  Real alphar = 0.0;
309 
310  for (std::size_t i = 0; i < _t1.size(); ++i)
311  alphar += _N1[i] * MathUtils::pow(delta, _d1[i]) * std::pow(tau, _t1[i]);
312 
313  for (std::size_t i = 0; i < _t2.size(); ++i)
314  alphar += _N2[i] * MathUtils::pow(delta, _d2[i]) * std::pow(tau, _t2[i]) * std::exp(-delta);
315 
316  for (std::size_t i = 0; i < _t3.size(); ++i)
317  alphar += _N3[i] * MathUtils::pow(delta, _d3[i]) * std::pow(tau, _t3[i]) *
318  std::exp(_phi3[i] * Utility::pow<2>(delta - _D3[i]) +
319  _beta3[i] * Utility::pow<2>(tau - _gamma3[i]));
320 
321  // The Helmholtz free energy is the sum of these two
322  return alpha0 + alphar;
323 }
324 
325 Real
327 {
328  // Ideal gas component of the Helmholtz free energy
329  Real dalpha0 = 1.0 / delta;
330 
331  // Residual component of the Helmholtz free energy
332  Real dalphar = 0.0;
333 
334  for (std::size_t i = 0; i < _t1.size(); ++i)
335  dalphar += _N1[i] * _d1[i] * MathUtils::pow(delta, _d1[i]) * std::pow(tau, _t1[i]);
336 
337  for (std::size_t i = 0; i < _t2.size(); ++i)
338  dalphar += _N2[i] * MathUtils::pow(delta, _d2[i]) * std::pow(tau, _t2[i]) * std::exp(-delta) *
339  (_d2[i] - delta);
340 
341  for (std::size_t i = 0; i < _t3.size(); ++i)
342  dalphar += _N3[i] * MathUtils::pow(delta, _d3[i]) * std::pow(tau, _t3[i]) *
343  std::exp(_phi3[i] * Utility::pow<2>(delta - _D3[i]) +
344  _beta3[i] * Utility::pow<2>(tau - _gamma3[i])) *
345  (_d3[i] + delta * (2.0 * _phi3[i] * (delta - _D3[i])));
346 
347  // The Helmholtz free energy is the sum of these two
348  return dalpha0 + dalphar / delta;
349 }
350 
351 Real
353 {
354  // Ideal gas component of the Helmholtz free energy
355  Real dalpha0 = 1.5 / tau + 1.888076782;
356 
357  for (std::size_t i = 0; i < _a.size(); ++i)
358  dalpha0 += _a[i] * _b[i] * (1.0 - 1.0 / (1.0 - std::exp(_b[i] * tau)));
359 
360  // Residual component of the Helmholtz free energy
361  Real dalphar = 0.0;
362 
363  for (std::size_t i = 0; i < _t1.size(); ++i)
364  dalphar += _N1[i] * _t1[i] * MathUtils::pow(delta, _d1[i]) * std::pow(tau, _t1[i]);
365 
366  for (std::size_t i = 0; i < _t2.size(); ++i)
367  dalphar +=
368  _N2[i] * _t2[i] * MathUtils::pow(delta, _d2[i]) * std::pow(tau, _t2[i]) * std::exp(-delta);
369 
370  for (std::size_t i = 0; i < _t3.size(); ++i)
371  dalphar += _N3[i] * MathUtils::pow(delta, _d3[i]) * std::pow(tau, _t3[i]) *
372  std::exp(_phi3[i] * Utility::pow<2>(delta - _D3[i]) +
373  _beta3[i] * Utility::pow<2>(tau - _gamma3[i])) *
374  (_t3[i] + tau * (2.0 * _beta3[i] * (tau - _gamma3[i])));
375 
376  // The Helmholtz free energy is the sum of these two
377  return dalpha0 + dalphar / tau;
378 }
379 
380 Real
382 {
383  // Ideal gas component of the Helmholtz free energy
384  Real dalpha0 = -1.0 / delta / delta;
385 
386  // Residual component of the Helmholtz free energy
387  Real dalphar = 0.0;
388 
389  for (std::size_t i = 0; i < _t1.size(); ++i)
390  dalphar +=
391  _N1[i] * _d1[i] * (_d1[i] - 1.0) * MathUtils::pow(delta, _d1[i]) * std::pow(tau, _t1[i]);
392 
393  for (std::size_t i = 0; i < _t2.size(); ++i)
394  dalphar += _N2[i] * MathUtils::pow(delta, _d2[i]) * std::pow(tau, _t2[i]) * std::exp(-delta) *
395  (delta * delta - 2.0 * _d2[i] * delta + _d2[i] * (_d2[i] - 1.0));
396 
397  for (std::size_t i = 0; i < _t3.size(); ++i)
398  dalphar += _N3[i] * MathUtils::pow(delta, _d3[i]) * std::pow(tau, _t3[i]) *
399  std::exp(_phi3[i] * Utility::pow<2>(delta - _D3[i]) +
400  _beta3[i] * Utility::pow<2>(tau - _gamma3[i])) *
401  (_d3[i] * _d3[i] +
402  2.0 * delta * delta * _phi3[i] *
403  (1.0 + 2.0 * _phi3[i] * (_D3[i] - delta) * (_D3[i] - delta)) +
404  _d3[i] * (4.0 * delta * _phi3[i] * (delta - _D3[i]) - 1.0));
405 
406  // The Helmholtz free energy is the sum of these two
407  return dalpha0 + dalphar / delta / delta;
408 }
409 
410 Real
412 {
413  // Ideal gas component of the Helmholtz free energy
414  Real dalpha0 = -1.5 / tau / tau;
415 
416  for (std::size_t i = 0; i < _a.size(); ++i)
417  {
418  Real exptau = std::exp(_b[i] * tau);
419  dalpha0 -= _a[i] * (_b[i] * _b[i] * exptau / (1.0 - exptau) * (exptau / (1.0 - exptau) + 1.0));
420  }
421 
422  // Residual component of the Helmholtz free energy
423  Real dalphar = 0.0;
424 
425  for (std::size_t i = 0; i < _t1.size(); ++i)
426  dalphar +=
427  _N1[i] * _t1[i] * (_t1[i] - 1.0) * MathUtils::pow(delta, _d1[i]) * std::pow(tau, _t1[i]);
428 
429  for (std::size_t i = 0; i < _t2.size(); ++i)
430  dalphar += _N2[i] * _t2[i] * (_t2[i] - 1.0) * MathUtils::pow(delta, _d2[i]) *
431  std::pow(tau, _t2[i]) * std::exp(-delta);
432 
433  for (std::size_t i = 0; i < _t3.size(); ++i)
434  dalphar += _N3[i] * MathUtils::pow(delta, _d3[i]) * std::pow(tau, _t3[i]) *
435  std::exp(_phi3[i] * Utility::pow<2>(delta - _D3[i]) +
436  _beta3[i] * Utility::pow<2>(tau - _gamma3[i])) *
437  (_t3[i] * _t3[i] +
438  2.0 * _beta3[i] * tau * tau *
439  (1.0 + 2.0 * _beta3[i] * MathUtils::pow(tau - _gamma3[i], 2)) -
440  _t3[i] * (1.0 + 4.0 * _beta3[i] * tau * (tau - _gamma3[i])));
441 
442  // The Helmholtz free energy is the sum of these two
443  return dalpha0 + dalphar / tau / tau;
444 }
445 
446 Real
448 {
449  // Residual component of the Helmholtz free energy
450  Real dalphar = 0.0;
451 
452  for (std::size_t i = 0; i < _t1.size(); ++i)
453  dalphar += _N1[i] * _d1[i] * _t1[i] * std::pow(delta, _d1[i]) * std::pow(tau, _t1[i]);
454 
455  for (std::size_t i = 0; i < _t2.size(); ++i)
456  dalphar += _N2[i] * _t2[i] * std::pow(delta, _d2[i]) * std::pow(tau, _t2[i]) *
457  std::exp(-delta) * (_d2[i] - delta);
458 
459  for (std::size_t i = 0; i < _t3.size(); ++i)
460  dalphar += _N3[i] * std::pow(delta, _d3[i]) * std::pow(tau, _t3[i]) *
461  std::exp(_phi3[i] * Utility::pow<2>(delta - _D3[i]) +
462  _beta3[i] * Utility::pow<2>(tau - _gamma3[i])) *
463  (_d3[i] + delta * (2.0 * _phi3[i] * (delta - _D3[i]))) *
464  (_t3[i] + 2.0 * _beta3[i] * tau * (tau - _gamma3[i]));
465 
466  // The Helmholtz free energy is the sum of these two
467  return dalphar / delta / tau;
468 }
const std::array< Real, 2 > _N2
virtual Real dalpha_dtau(Real delta, Real tau) const override
Derivative of Helmholtz free energy wrt tau.
const std::array< Real, 6 > _cmu
const std::array< Real, 5 > _beta3
const std::array< Real, 5 > _t3
virtual Real d2alpha_ddelta2(Real delta, Real tau) const override
Second derivative of Helmholtz free energy wrt delta.
const std::array< Real, 5 > _b2k
virtual Real criticalTemperature() const override
Critical temperature.
const std::array< Real, 7 > _N1
Coefficients for residual component of the Helmholtz free energy.
const std::array< Real, 5 > _N3
const std::array< unsigned int, 7 > _d1
const Real eps
virtual Real mu_from_p_T(Real pressure, Real temperature) const override
const Real _T_triple
Triple point temperature (K)
virtual Real mu_from_rho_T(Real density, Real temperature) const override
HydrogenFluidProperties(const InputParameters &parameters)
const std::array< Real, 7 > _t1
virtual Real dalpha_ddelta(Real delta, Real tau) const override
Derivative of Helmholtz free energy wrt delta.
virtual Real triplePointPressure() const override
Triple point pressure.
virtual Real k_from_p_T(Real pressure, Real temperature) const override
const std::array< Real, 4 > _a2k
static const std::string density
Definition: NS.h:33
int delta(unsigned int i, unsigned int j)
Delta function, which returns zero if $i j$ and unity if $i=j$.
const std::array< Real, 5 > _phi3
const std::array< Real, 5 > _b
const std::array< unsigned int, 2 > _d2
static const std::string temperature
Definition: NS.h:59
const std::array< Real, 5 > _b1k
virtual const std::string & name() const
virtual std::vector< Real > henryCoefficients() const override
Henry&#39;s law coefficients for dissolution in water.
const std::array< Real, 5 > _D3
virtual std::string fluidName() const override
Fluid name.
const std::array< Real, 5 > _amu
Coefficients for viscosity.
const std::array< Real, 5 > _a
Coefficients for ideal gas component of the Helmholtz free energy.
virtual Real triplePointTemperature() const override
Triple point temperature.
virtual Real d2alpha_ddeltatau(Real delta, Real tau) const override
Second derivative of Helmholtz free energy wrt delta and tau.
static InputParameters validParams()
const std::array< Real, 5 > _gamma3
const Real _rho_critical
Critical density (kg/m^3)
static const std::string mu
Definition: NS.h:123
const Real _Mh2
Hydrogen molar mass (kg/mol)
Hydrogen (H2) fluid properties as a function of pressure (Pa) and temperature (K).
const std::array< Real, 7 > _a1k
Coefficients for thermal conductivity.
virtual Real k_from_rho_T(Real density, Real temperature) const override
virtual Real rho_from_p_T(Real pressure, Real temperature) const override
static InputParameters validParams()
virtual Real criticalDensity() const override
Critical density.
const Real _T_critical
Critical temperature (K)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual Real molarMass() const override
Molar mass [kg/mol].
virtual Real alpha(Real delta, Real tau) const override
Helmholtz free energy for H2 From Leachman et al (reference above)
static const std::string pressure
Definition: NS.h:56
const Real _p_triple
Triple point pressure (Pa)
const std::array< Real, 2 > _t2
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
const Real _p_critical
Critical pressure (Pa)
virtual void rho_mu_from_p_T(Real pressure, Real temperature, Real &rho, Real &mu) const override
Combined methods.
const std::array< unsigned int, 5 > _d3
T pow(T x, int e)
registerMooseObject("FluidPropertiesApp", HydrogenFluidProperties)
virtual Real d2alpha_dtau2(Real delta, Real tau) const override
Second derivative of Helmholtz free energy wrt tau.
virtual Real criticalPressure() const override
Critical pressure.
Base class equation of state for fluids that use a Helmholtz free energy alpha(delta, tau), where delta is a scaled density and tau is a scaled temperature.
MooseUnits pow(const MooseUnits &, int)
static const std::string k
Definition: NS.h:130
virtual Real vaporPressure(Real temperature) const override
Vapor pressure.
const std::array< Real, 7 > _bmu