https://mooseframework.inl.gov
Loading...
Searching...
No Matches
CO2FluidProperties.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 "CO2FluidProperties.h"
11#include "BrentsMethod.h"
12#include "Conversion.h"
13#include "MathUtils.h"
14#include "libmesh/utility.h"
15
17
20{
23 "Fluid properties for carbon dioxide (CO2) using the Span & Wagner EOS");
24 return params;
25}
26
31
33
34std::string
36{
37 return "co2";
38}
39
40Real
42{
43 return _Mco2;
44}
45
46Real
51
52Real
57
58Real
63
64Real
69
70Real
75
76Real
78{
79 if (temperature < _triple_point_temperature)
80 throw MooseException("Temperature is below the triple point temperature in " + name() +
81 ": meltingPressure()");
82
83 Real Tstar = temperature / _triple_point_temperature;
84
86 (1.0 + 1955.539 * (Tstar - 1.0) + 2055.4593 * Utility::pow<2>(Tstar - 1.0));
87}
88
89Real
91{
92 if (temperature > _triple_point_temperature)
93 throw MooseException("Temperature is above the triple point temperature in " + name() +
94 ": sublimationPressure()");
95
96 Real Tstar = temperature / _triple_point_temperature;
97
98 Real pressure = _triple_point_pressure *
99 std::exp((-14.740846 * (1.0 - Tstar) + 2.4327015 * std::pow(1.0 - Tstar, 1.9) -
100 5.3061778 * std::pow(1.0 - Tstar, 2.9)) /
101 Tstar);
102
103 return pressure;
104}
105
106Real
108{
109 if (temperature < _triple_point_temperature || temperature > _critical_temperature)
110 throw MooseException("Temperature is out of range in " + name() + ": vaporPressure()");
111
112 Real Tstar = temperature / _critical_temperature;
113
114 Real logpressure =
115 (-7.0602087 * (1.0 - Tstar) + 1.9391218 * std::pow(1.0 - Tstar, 1.5) -
116 1.6463597 * Utility::pow<2>(1.0 - Tstar) - 3.2995634 * Utility::pow<4>(1.0 - Tstar)) /
117 Tstar;
118
119 return _critical_pressure * std::exp(logpressure);
120}
121
122void
123CO2FluidProperties::vaporPressure(Real, Real &, Real &) const
124{
125 mooseError("vaporPressure() is not implemented");
126}
127
128Real
130{
131 if (temperature < _triple_point_temperature || temperature > _critical_temperature)
132 throw MooseException("Temperature is out of range in " + name() + ": saturatedLiquiDensity()");
133
134 Real Tstar = temperature / _critical_temperature;
135
136 Real logdensity = 1.9245108 * std::pow(1.0 - Tstar, 0.34) -
137 0.62385555 * std::pow(1.0 - Tstar, 0.5) -
138 0.32731127 * std::pow(1.0 - Tstar, 10.0 / 6.0) +
139 0.39245142 * std::pow(1.0 - Tstar, 11.0 / 6.0);
140
141 return _critical_density * std::exp(logdensity);
142}
143
144Real
146{
147 if (temperature < _triple_point_temperature || temperature > _critical_temperature)
148 throw MooseException("Temperature is out of range in " + name() + ": saturatedVaporDensity()");
149
150 Real Tstar = temperature / _critical_temperature;
151
152 Real logdensity =
153 (-1.7074879 * std::pow(1.0 - Tstar, 0.34) - 0.82274670 * std::pow(1.0 - Tstar, 0.5) -
154 4.6008549 * (1.0 - Tstar) - 10.111178 * std::pow(1.0 - Tstar, 7.0 / 3.0) -
155 29.742252 * std::pow(1.0 - Tstar, 14.0 / 3.0));
156
157 return _critical_density * std::exp(logdensity);
158}
159
160Real
161CO2FluidProperties::alpha(Real delta, Real tau) const
162{
163 // Ideal gas component of the Helmholtz free energy
164 Real sum0 = 0.0;
165 for (std::size_t i = 0; i < _a0.size(); ++i)
166 sum0 += _a0[i] * std::log(1.0 - std::exp(-_theta0[i] * tau));
167
168 Real phi0 = std::log(delta) + 8.37304456 - 3.70454304 * tau + 2.5 * std::log(tau) + sum0;
169
170 // Residual component of the Helmholtz free energy
171 Real theta, Delta, Psi;
172 Real phir = 0.0;
173 for (std::size_t i = 0; i < _n1.size(); ++i)
174 phir += _n1[i] * MathUtils::pow(delta, _d1[i]) * std::pow(tau, _t1[i]);
175
176 for (std::size_t i = 0; i < _n2.size(); ++i)
177 phir += _n2[i] * MathUtils::pow(delta, _d2[i]) * std::pow(tau, _t2[i]) *
178 std::exp(-MathUtils::pow(delta, _c2[i]));
179
180 for (std::size_t i = 0; i < _n3.size(); ++i)
181 phir += _n3[i] * MathUtils::pow(delta, _d3[i]) * MathUtils::pow(tau, _t3[i]) *
182 std::exp(-_alpha3[i] * Utility::pow<2>(delta - _eps3[i]) -
183 _beta3[i] * Utility::pow<2>(tau - _gamma3[i]));
184
185 for (std::size_t i = 0; i < _n4.size(); ++i)
186 {
187 theta = 1.0 - tau + _A4[i] * std::pow(Utility::pow<2>(delta - 1.0), 1.0 / (2.0 * _beta4[i]));
188 Delta = Utility::pow<2>(theta) + _B4[i] * std::pow(Utility::pow<2>(delta - 1.0), _a4[i]);
189 Psi = std::exp(-_C4[i] * Utility::pow<2>(delta - 1.0) - _D4[i] * Utility::pow<2>(tau - 1.0));
190 phir += _n4[i] * std::pow(Delta, _b4[i]) * delta * Psi;
191 }
192
193 // The Helmholtz free energy is the sum of these components
194 return phi0 + phir;
195}
196
197Real
198CO2FluidProperties::dalpha_ddelta(Real delta, Real tau) const
199{
200 // Derivative of the ideal gas component wrt gamma
201 Real dphi0dd = 1.0 / delta;
202
203 // Derivative of the residual component wrt gamma
204 Real theta, Delta, Psi, dDelta_dd, dPsi_dd;
205 Real dphirdd = 0.0;
206
207 for (std::size_t i = 0; i < _n1.size(); ++i)
208 dphirdd += _n1[i] * _d1[i] * MathUtils::pow(delta, _d1[i] - 1.0) * std::pow(tau, _t1[i]);
209
210 for (std::size_t i = 0; i < _n2.size(); ++i)
211 dphirdd += _n2[i] * std::exp(-MathUtils::pow(delta, _c2[i])) *
212 (MathUtils::pow(delta, _d2[i] - 1.0) * std::pow(tau, _t2[i]) *
213 (_d2[i] - _c2[i] * MathUtils::pow(delta, _c2[i])));
214
215 for (std::size_t i = 0; i < _n3.size(); ++i)
216 dphirdd += _n3[i] * MathUtils::pow(delta, _d3[i]) * MathUtils::pow(tau, _t3[i]) *
217 std::exp(-_alpha3[i] * Utility::pow<2>(delta - _eps3[i]) -
218 _beta3[i] * Utility::pow<2>(tau - _gamma3[i])) *
219 (_d3[i] / delta - 2.0 * _alpha3[i] * (delta - _eps3[i]));
220
221 for (std::size_t i = 0; i < _n4.size(); ++i)
222 {
223 theta = 1.0 - tau + _A4[i] * std::pow(Utility::pow<2>(delta - 1.0), 1.0 / (2.0 * _beta4[i]));
224 Delta = Utility::pow<2>(theta) + _B4[i] * std::pow(Utility::pow<2>(delta - 1.0), _a4[i]);
225 Psi = std::exp(-_C4[i] * Utility::pow<2>(delta - 1.0) - _D4[i] * Utility::pow<2>(tau - 1.0));
226 dPsi_dd = -2.0 * _C4[i] * (delta - 1.0) * Psi;
227 dDelta_dd = (delta - 1.0) *
228 (_A4[i] * theta * 2.0 / _beta4[i] *
229 std::pow(Utility::pow<2>(delta - 1.0), 1.0 / (2.0 * _beta4[i]) - 1.0) +
230 2.0 * _B4[i] * _a4[i] * std::pow(Utility::pow<2>(delta - 1.0), _a4[i] - 1.0));
231
232 dphirdd += _n4[i] * (std::pow(Delta, _b4[i]) * (Psi + delta * dPsi_dd) +
233 _b4[i] * std::pow(Delta, _b4[i] - 1.0) * dDelta_dd * delta * Psi);
234 }
235
236 // The derivative of the free energy wrt delta is the sum of these components
237 return dphi0dd + dphirdd;
238}
239
240Real
241CO2FluidProperties::dalpha_dtau(Real delta, Real tau) const
242{
243 // Derivative of the ideal gas component wrt tau
244 Real sum0 = 0.0;
245 for (std::size_t i = 0; i < _a0.size(); ++i)
246 sum0 += _a0[i] * _theta0[i] * (1.0 / (1.0 - std::exp(-_theta0[i] * tau)) - 1.0);
247
248 Real dphi0dt = -3.70454304 + 2.5 / tau + sum0;
249
250 // Derivative of the residual component wrt tau
251 Real theta, Delta, Psi, dDelta_dt, dPsi_dt;
252 Real dphirdt = 0.0;
253 for (std::size_t i = 0; i < _n1.size(); ++i)
254 dphirdt += _n1[i] * _t1[i] * MathUtils::pow(delta, _d1[i]) * std::pow(tau, _t1[i] - 1.0);
255
256 for (std::size_t i = 0; i < _n2.size(); ++i)
257 dphirdt += _n2[i] * _t2[i] * MathUtils::pow(delta, _d2[i]) * std::pow(tau, _t2[i] - 1.0) *
258 std::exp(-MathUtils::pow(delta, _c2[i]));
259
260 for (std::size_t i = 0; i < _n3.size(); ++i)
261 dphirdt += _n3[i] * MathUtils::pow(delta, _d3[i]) * MathUtils::pow(tau, _t3[i]) *
262 std::exp(-_alpha3[i] * Utility::pow<2>(delta - _eps3[i]) -
263 _beta3[i] * Utility::pow<2>(tau - _gamma3[i])) *
264 (_t3[i] / tau - 2.0 * _beta3[i] * (tau - _gamma3[i]));
265
266 for (std::size_t i = 0; i < _n4.size(); ++i)
267 {
268 theta = 1.0 - tau + _A4[i] * std::pow(Utility::pow<2>(delta - 1.0), 1.0 / (2.0 * _beta4[i]));
269 Delta = Utility::pow<2>(theta) + _B4[i] * std::pow(Utility::pow<2>(delta - 1.0), _a4[i]);
270 Psi = std::exp(-_C4[i] * Utility::pow<2>(delta - 1.0) - _D4[i] * Utility::pow<2>(tau - 1.0));
271 dDelta_dt = -2.0 * theta * _b4[i] * std::pow(Delta, _b4[i] - 1.0);
272 dPsi_dt = -2.0 * _D4[i] * (tau - 1.0) * Psi;
273
274 dphirdt += _n4[i] * delta * (Psi * dDelta_dt + std::pow(Delta, _b4[i]) * dPsi_dt);
275 }
276
277 // The derivative of the free energy wrt tau is the sum of these components
278 return dphi0dt + dphirdt;
279}
280
281Real
282CO2FluidProperties::d2alpha_ddelta2(Real delta, Real tau) const
283{
284 // Second derivative of the ideal gas component wrt gamma
285 Real d2phi0dd2 = -1.0 / delta / delta;
286
287 // Second derivative of the residual component wrt gamma
288 Real d2phirdd2 = 0.0;
289 Real theta, Delta, Psi, dDelta_dd, dPsi_dd, d2Delta_dd2, d2Psi_dd2;
290
291 for (std::size_t i = 0; i < _n1.size(); ++i)
292 d2phirdd2 += _n1[i] * _d1[i] * (_d1[i] - 1.0) * MathUtils::pow(delta, _d1[i] - 2) *
293 std::pow(tau, _t1[i]);
294
295 for (std::size_t i = 0; i < _n2.size(); ++i)
296 d2phirdd2 += _n2[i] * std::exp(-MathUtils::pow(delta, _c2[i])) *
297 MathUtils::pow(delta, _d2[i] - 2) * std::pow(tau, _t2[i]) *
298 ((_d2[i] - _c2[i] * MathUtils::pow(delta, _c2[i])) *
299 (_d2[i] - 1.0 - _c2[i] * MathUtils::pow(delta, _c2[i])) -
300 _c2[i] * _c2[i] * MathUtils::pow(delta, _c2[i]));
301
302 for (std::size_t i = 0; i < _n3.size(); ++i)
303 d2phirdd2 +=
304 _n3[i] * MathUtils::pow(tau, _t3[i]) *
305 std::exp(-_alpha3[i] * Utility::pow<2>(delta - _eps3[i]) -
306 _beta3[i] * Utility::pow<2>(tau - _gamma3[i])) *
307 (-2.0 * _alpha3[i] * MathUtils::pow(delta, _d3[i]) +
308 4.0 * _alpha3[i] * _alpha3[i] * MathUtils::pow(delta, _d3[i]) *
309 Utility::pow<2>(delta - _eps3[i]) -
310 4.0 * _d3[i] * _alpha3[i] * MathUtils::pow(delta, _d3[i] - 1.0) * (delta - _eps3[i]) +
311 _d3[i] * (_d3[i] - 1.0) * MathUtils::pow(delta, _d3[i] - 2.0));
312
313 for (std::size_t i = 0; i < _n4.size(); ++i)
314 {
315 theta = 1.0 - tau + _A4[i] * std::pow(Utility::pow<2>(delta - 1.0), 1.0 / (2.0 * _beta4[i]));
316 Delta = Utility::pow<2>(theta) + _B4[i] * std::pow(Utility::pow<2>(delta - 1.0), _a4[i]);
317 Psi = std::exp(-_C4[i] * Utility::pow<2>(delta - 1.0) - _D4[i] * Utility::pow<2>(tau - 1.0));
318 dPsi_dd = -2.0 * _C4[i] * (delta - 1.0) * Psi;
319 dDelta_dd = (delta - 1.0) *
320 (_A4[i] * theta * 2.0 / _beta4[i] *
321 std::pow(Utility::pow<2>(delta - 1.0), 1.0 / (2.0 * _beta4[i]) - 1.0) +
322 2.0 * _B4[i] * _a4[i] * std::pow(Utility::pow<2>(delta - 1.0), _a4[i] - 1.0));
323 d2Psi_dd2 = 3.0 * _D4[i] * Psi * (2.0 * _C4[i] * Utility::pow<2>(delta - 1.0) - 1.0);
324 d2Delta_dd2 = 1.0 / (delta - 1.0) * dDelta_dd +
325 (delta - 1.0) * (delta - 1.0) *
326 (4.0 * _B4[i] * _a4[i] * (_a4[i] - 1.0) *
327 std::pow(Utility::pow<2>(delta - 1.0), _a4[i] - 2.0) +
328 2.0 * _A4[i] * _A4[i] *
329 Utility::pow<2>(std::pow(Utility::pow<2>(delta - 1.0),
330 1.0 / (2.0 * _beta4[i]) - 1.0)) /
331 _beta4[i] / _beta4[i] +
332 (4.0 / _beta4[i]) * _A4[i] * theta * (1.0 / (2.0 * _beta4[i]) - 1.0) *
333 std::pow(Utility::pow<2>(delta - 1.0), 1.0 / (2.0 * _beta4[i]) - 2.0));
334 d2phirdd2 +=
335 _n4[i] *
336 (std::pow(Delta, _b4[i]) * (2.0 * dPsi_dd + delta * d2Psi_dd2) +
337 2.0 * _b4[i] * std::pow(Delta, _b4[i] - 1.0) * dDelta_dd * (Psi + delta * dPsi_dd) +
338 _b4[i] *
339 (std::pow(Delta, _b4[i] - 1.0) * d2Delta_dd2 +
340 (_b4[i] - 1.0) * std::pow(Delta, _b4[i] - 2.0) * Utility::pow<2>(dDelta_dd)) *
341 delta * Psi);
342 }
343 // The second derivative of the free energy wrt delta is the sum of these components
344 return d2phi0dd2 + d2phirdd2;
345}
346
347Real
348CO2FluidProperties::d2alpha_dtau2(Real delta, Real tau) const
349{
350 // Second derivative of the ideal gas component wrt tau
351 Real sum0 = 0.0;
352 for (std::size_t i = 0; i < _a0.size(); ++i)
353 sum0 += _a0[i] * _theta0[i] * _theta0[i] * std::exp(-_theta0[i] * tau) /
354 Utility::pow<2>(1.0 - std::exp(-_theta0[i] * tau));
355
356 Real d2phi0dt2 = -2.5 / tau / tau - sum0;
357
358 // Second derivative of the residual component wrt tau
359 Real d2phirdt2 = 0.0;
360 Real theta, Delta, Psi, dPsi_dt, dDelta_dt, d2Delta_dt2, d2Psi_dt2;
361
362 for (std::size_t i = 0; i < _n1.size(); ++i)
363 d2phirdt2 += _n1[i] * _t1[i] * (_t1[i] - 1.0) * MathUtils::pow(delta, _d1[i]) *
364 std::pow(tau, _t1[i] - 2.0);
365
366 for (std::size_t i = 0; i < _n2.size(); ++i)
367 d2phirdt2 += _n2[i] * _t2[i] * (_t2[i] - 1.0) * MathUtils::pow(delta, _d2[i]) *
368 std::exp(-MathUtils::pow(delta, _c2[i])) * std::pow(tau, _t2[i] - 2.0);
369
370 for (std::size_t i = 0; i < _n3.size(); ++i)
371 d2phirdt2 += _n3[i] * MathUtils::pow(delta, _d3[i]) * MathUtils::pow(tau, _t3[i]) *
372 std::exp(-_alpha3[i] * Utility::pow<2>(delta - _eps3[i]) -
373 _beta3[i] * Utility::pow<2>(tau - _gamma3[i])) *
374 (Utility::pow<2>(_t3[i] / tau - 2.0 * _beta3[i] * (tau - _gamma3[i])) -
375 _t3[i] / tau / tau - 2.0 * _beta3[i]);
376
377 for (std::size_t i = 0; i < _n4.size(); ++i)
378 {
379 theta = 1.0 - tau + _A4[i] * std::pow(Utility::pow<2>(delta - 1.0), 1.0 / (2.0 * _beta4[i]));
380 Delta = Utility::pow<2>(theta) + _B4[i] * std::pow(Utility::pow<2>(delta - 1.0), _a4[i]);
381 Psi = std::exp(-_C4[i] * Utility::pow<2>(delta - 1.0) - _D4[i] * Utility::pow<2>(tau - 1.0));
382 dDelta_dt = -2.0 * theta * _b4[i] * std::pow(Delta, _b4[i] - 1.0);
383 d2Delta_dt2 = 2.0 * _b4[i] * std::pow(Delta, _b4[i] - 1.0) +
384 4.0 * theta * theta * _b4[i] * (_b4[i] - 1.0) * std::pow(Delta, _b4[i] - 2.0);
385 dPsi_dt = -2.0 * _D4[i] * (tau - 1.0) * Psi;
386 d2Psi_dt2 = 2.0 * _D4[i] * (2.0 * _D4[i] * (tau - 1.0) * (tau - 1.0) - 1.0) * Psi;
387 d2phirdt2 +=
388 _n4[i] * delta *
389 (Psi * d2Delta_dt2 + 2.0 * dDelta_dt * dPsi_dt + std::pow(Delta, _b4[i]) * d2Psi_dt2);
390 }
391
392 // The second derivative of the free energy wrt tau is the sum of these components
393 return d2phi0dt2 + d2phirdt2;
394}
395
396Real
397CO2FluidProperties::d2alpha_ddeltatau(Real delta, Real tau) const
398{
399 // Note: second derivative of the ideal gas component wrt delta and tau is 0
400 // Derivative of the residual component wrt gamma
401 Real theta, Delta, Psi, dDelta_dd, dPsi_dd, dDelta_dt, dPsi_dt, d2Delta_ddt, d2Psi_ddt;
402 Real d2phirddt = 0.0;
403 for (std::size_t i = 0; i < _n1.size(); ++i)
404 d2phirddt += _n1[i] * _d1[i] * _t1[i] * MathUtils::pow(delta, _d1[i] - 1.0) *
405 std::pow(tau, _t1[i] - 1.0);
406
407 for (std::size_t i = 0; i < _n2.size(); ++i)
408 d2phirddt += _n2[i] * std::exp(-MathUtils::pow(delta, _c2[i])) *
409 (MathUtils::pow(delta, _d2[i] - 1.0) * _t2[i] * std::pow(tau, _t2[i] - 1.0) *
410 (_d2[i] - _c2[i] * MathUtils::pow(delta, _c2[i])));
411
412 for (std::size_t i = 0; i < _n3.size(); ++i)
413 d2phirddt += _n3[i] * MathUtils::pow(delta, _d3[i]) * MathUtils::pow(tau, _t3[i]) *
414 std::exp(-_alpha3[i] * Utility::pow<2>(delta - _eps3[i]) -
415 _beta3[i] * Utility::pow<2>(tau - _gamma3[i])) *
416 (_d3[i] / delta - 2.0 * _alpha3[i] * (delta - _eps3[i])) *
417 (_t3[i] / tau - 2.0 * _beta3[i] * (tau - _gamma3[i]));
418
419 for (std::size_t i = 0; i < _n4.size(); ++i)
420 {
421 theta = 1.0 - tau + _A4[i] * std::pow(Utility::pow<2>(delta - 1.0), 1.0 / (2.0 * _beta4[i]));
422 Delta = Utility::pow<2>(theta) + _B4[i] * std::pow(Utility::pow<2>(delta - 1.0), _a4[i]);
423 Psi = std::exp(-_C4[i] * Utility::pow<2>(delta - 1.0) - _D4[i] * Utility::pow<2>(tau - 1.0));
424 dPsi_dd = -2.0 * _C4[i] * (delta - 1.0) * Psi;
425 dPsi_dt = -2.0 * _D4[i] * (tau - 1.0) * Psi;
426 d2Psi_ddt = 4.0 * _C4[i] * _D4[i] * (delta - 1.0) * (tau - 1.0) * Psi;
427 dDelta_dd = (delta - 1.0) *
428 (_A4[i] * theta * 2.0 / _beta4[i] *
429 std::pow(Utility::pow<2>(delta - 1.0), 1.0 / (2.0 * _beta4[i]) - 1.0) +
430 2.0 * _B4[i] * _a4[i] * std::pow(Utility::pow<2>(delta - 1.0), _a4[i] - 1.0));
431 dDelta_dt = -2.0 * theta * _b4[i] * std::pow(Delta, _b4[i] - 1.0);
432 d2Delta_ddt = -2.0 * _A4[i] * _b4[i] / _beta4[i] * std::pow(Delta, _b4[i] - 1.0) *
433 (delta - 1.0) *
434 std::pow(Utility::pow<2>(delta - 1.0), 1.0 / (2.0 * _beta4[i]) - 1.0) -
435 2.0 * theta * _b4[i] * (_b4[i] - 1.0) * std::pow(Delta, _b4[i] - 2.0) * dDelta_dd;
436
437 d2phirddt += _n4[i] * (std::pow(Delta, _b4[i]) * (dPsi_dt + delta * d2Psi_ddt) +
438 delta * _b4[i] * std::pow(Delta, _b4[i] - 1.0) * dDelta_dd * dPsi_dt +
439 dDelta_dt * (Psi + delta * dPsi_dd) + d2Delta_ddt * delta * Psi);
440 }
441
442 return d2phirddt;
443}
444
445Real
446CO2FluidProperties::p_from_rho_T(Real density, Real temperature) const
447{
448 // Check that the input parameters are within the region of validity
449 if (temperature < 216.0 || temperature > 1100.0 || density <= 0.0)
450 throw MooseException("Parameters out of range in " + name() + ": pressure()");
451
452 Real pressure = 0.0;
453
454 if (temperature > _triple_point_temperature && temperature < _critical_temperature)
455 {
456 Real gas_density = saturatedVaporDensity(temperature);
457 Real liquid_density = saturatedLiquidDensity(temperature);
458
459 if (density < gas_density || density > liquid_density)
460 pressure = HelmholtzFluidProperties::p_from_rho_T(density, temperature);
461 else
462 pressure = vaporPressure(temperature);
463 }
464 else
465 pressure = HelmholtzFluidProperties::p_from_rho_T(density, temperature);
466
467 return pressure;
468}
469
470Real
471CO2FluidProperties::rho_from_p_T(Real pressure, Real temperature) const
472{
473 // Check that the input parameters are within the region of validity
474 if (temperature < 216.0 || temperature > 1100.0 || pressure <= 0.0)
475 throw MooseException("Parameters out of range in " + name() + ": rho_from_p_T()");
476
477 // Also check that the pressure and temperature are not in the solid phase region
478 if (((temperature > _triple_point_temperature) && (pressure > meltingPressure(temperature))) ||
479 ((temperature < _triple_point_temperature) && (pressure > sublimationPressure(temperature))))
480 throw MooseException("Input pressure and temperature in " + name() +
481 ": rho_from_p_T() correspond to solid CO2 phase");
482
483 Real density;
484 // Initial estimate of a bracketing interval for the density
485 Real lower_density = 100.0;
486 Real upper_density = 1000.0;
487
488 // The density is found by finding the zero of the pressure calculated using the
489 // Span and Wagner EOS minus the input pressure
490 auto pressure_diff = [&pressure, &temperature, this](Real x)
491 { return p_from_rho_T(x, temperature) - pressure; };
492
493 BrentsMethod::bracket(pressure_diff, lower_density, upper_density);
494 density = BrentsMethod::root(pressure_diff, lower_density, upper_density);
495
496 return density;
497}
498
499void
501 Real pressure, Real temperature, Real & rho, Real & drho_dp, Real & drho_dT) const
502{
503 HelmholtzFluidProperties::rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
504}
505
506Real
507CO2FluidProperties::mu_from_p_T(Real pressure, Real temperature) const
508{
509 Real rho = rho_from_p_T(pressure, temperature);
510 return mu_from_rho_T(rho, temperature);
511}
512
513void
515 Real pressure, Real temperature, Real & mu, Real & dmu_dp, Real & dmu_dT) const
516{
517 Real rho, drho_dp, drho_dT;
518 HelmholtzFluidProperties::rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
519
520 Real dmu_drho;
521 mu_from_rho_T(rho, temperature, drho_dT, mu, dmu_drho, dmu_dT);
522 dmu_dp = dmu_drho * drho_dp;
523}
524
525Real
526CO2FluidProperties::mu_from_rho_T(Real density, Real temperature) const
527{
528 // Check that the input parameters are within the region of validity
529 if (temperature < 216.0 || temperature > 1000.0 || density > 1400.0)
530 throw MooseException("Parameters out of range in " + name() + ": mu_from_rho_T()");
531
532 Real Tstar = temperature / 251.196;
533
534 // Viscosity in the zero-density limit
535 Real sum = 0.0;
536
537 for (std::size_t i = 0; i < _mu_a.size(); ++i)
538 sum += _mu_a[i] * MathUtils::pow(std::log(Tstar), i);
539
540 Real mu0 = 1.00697 * std::sqrt(temperature) / std::exp(sum);
541
542 // Excess viscosity due to finite density
543 Real mue = _mu_d[0] * density + _mu_d[1] * Utility::pow<2>(density) +
544 _mu_d[2] * Utility::pow<6>(density) / Utility::pow<3>(Tstar) +
545 _mu_d[3] * Utility::pow<8>(density) + _mu_d[4] * Utility::pow<8>(density) / Tstar;
546
547 return (mu0 + mue) * 1.0e-6; // convert to Pa.s
548}
549
550void
552 Real temperature,
553 Real ddensity_dT,
554 Real & mu,
555 Real & dmu_drho,
556 Real & dmu_dT) const
557{
558 // Check that the input parameters are within the region of validity
559 if (temperature < 216.0 || temperature > 1000.0 || density > 1400.0)
560 throw MooseException("Parameters out of range in " + name() + ": mu_drhoT()");
561
562 Real Tstar = temperature / 251.196;
563 Real dTstar_dT = 1.0 / 251.196;
564
565 // Viscosity in the zero-density limit. Note this is only a function of T.
566 // Start the sum at i = 1 so the derivative is defined
567 Real sum0 = _mu_a[0], dsum0_dTstar = 0.0;
568
569 for (std::size_t i = 1; i < _mu_a.size(); ++i)
570 {
571 sum0 += _mu_a[i] * MathUtils::pow(std::log(Tstar), i);
572 dsum0_dTstar += i * _mu_a[i] * MathUtils::pow(std::log(Tstar), i - 1) / Tstar;
573 }
574
575 Real mu0 = 1.00697 * std::sqrt(temperature) / std::exp(sum0);
576 Real dmu0_dT = (0.5 * 1.00697 / std::sqrt(temperature) -
577 1.00697 * std::sqrt(temperature) * dsum0_dTstar * dTstar_dT) /
578 std::exp(sum0);
579
580 // Excess viscosity due to finite density
581 Real mue = _mu_d[0] * density + _mu_d[1] * Utility::pow<2>(density) +
582 _mu_d[2] * Utility::pow<6>(density) / Utility::pow<3>(Tstar) +
583 _mu_d[3] * Utility::pow<8>(density) + _mu_d[4] * Utility::pow<8>(density) / Tstar;
584
585 Real dmue_drho = _mu_d[0] + 2.0 * _mu_d[1] * density +
586 6.0 * _mu_d[2] * Utility::pow<5>(density) / Utility::pow<3>(Tstar) +
587 8.0 * _mu_d[3] * Utility::pow<7>(density) +
588 8.0 * _mu_d[4] * Utility::pow<7>(density) / Tstar;
589
590 Real dmue_dT = (-3.0 * _mu_d[2] * Utility::pow<6>(density) / Utility::pow<4>(Tstar) -
591 _mu_d[4] * Utility::pow<8>(density) / Tstar / Tstar) *
592 dTstar_dT;
593
594 // Viscosity in Pa.s is
595 mu = (mu0 + mue) * 1.0e-6;
596 dmu_drho = dmue_drho * 1.0e-6;
597 dmu_dT = (dmu0_dT + dmue_dT) * 1.0e-6 + dmu_drho * ddensity_dT;
598}
599
600void
601CO2FluidProperties::rho_mu_from_p_T(Real pressure, Real temperature, Real & rho, Real & mu) const
602{
603 rho = rho_from_p_T(pressure, temperature);
604 mu = mu_from_rho_T(rho, temperature);
605}
606
607void
609 Real temperature,
610 Real & rho,
611 Real & drho_dp,
612 Real & drho_dT,
613 Real & mu,
614 Real & dmu_dp,
615 Real & dmu_dT) const
616{
617 rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
618 Real dmu_drho;
619 mu_from_rho_T(rho, temperature, drho_dT, mu, dmu_drho, dmu_dT);
620 dmu_dp = dmu_drho * drho_dp;
621}
622
623Real
625{
626 // This correlation uses temperature in C
627 Real Tc = temperature - _T_c2k;
628 // The partial volume
629 Real V = 37.51 - 9.585e-2 * Tc + 8.74e-4 * Tc * Tc - 5.044e-7 * Tc * Tc * Tc;
630
631 return 1.0e6 * _Mco2 / V;
632}
633
634std::vector<Real>
636{
637 return {-8.55445, 4.01195, 9.52345};
638}
639
640Real
641CO2FluidProperties::k_from_p_T(Real pressure, Real temperature) const
642{
643 // Require density first
644 Real density = rho_from_p_T(pressure, temperature);
645 return k_from_rho_T(density, temperature);
646}
647
648void
650 Real pressure, Real temperature, Real & k, Real & dk_dp, Real & dk_dT) const
651{
652 k = this->k_from_p_T(pressure, temperature);
653 // Calculate derivatives using finite differences. Note: this will be slow as
654 // multiple calculations of density are required
655 const Real eps = 1.0e-6;
656 const Real peps = pressure * eps;
657 const Real Teps = temperature * eps;
658
659 dk_dp = (this->k_from_p_T(pressure + peps, temperature) - k) / peps;
660 dk_dT = (this->k_from_p_T(pressure, temperature + Teps) - k) / Teps;
661}
662
663Real
664CO2FluidProperties::k_from_rho_T(Real density, Real temperature) const
665{
666 // Check the temperature is in the range of validity (216.592 K <= T <= 1000 K)
667 if (temperature <= _triple_point_temperature || temperature >= 1000.0)
668 throw MooseException("Temperature " + Moose::stringify(temperature) +
669 "K out of range (200K, 1000K) in " + name() + ": k()");
670
671 // Scaled variables
672 Real Tr = temperature / _critical_temperature;
673 Real rhor = density / _critical_density;
674
675 Real sum1 = 0.0;
676 for (std::size_t i = 0; i < _k_n1.size(); ++i)
677 sum1 += _k_n1[i] * std::pow(Tr, _k_g1[i]) * MathUtils::pow(rhor, _k_h1[i]);
678
679 Real sum2 = 0.0;
680 for (std::size_t i = 0; i < _k_n2.size(); ++i)
681 sum2 += _k_n2[i] * std::pow(Tr, _k_g2[i]) * MathUtils::pow(rhor, _k_h2[i]);
682
683 // Near-critical enhancement
684 Real alpha =
685 1.0 - _k_a[9] * std::acosh(1.0 + _k_a[10] * std::pow(Utility::pow<2>(1.0 - Tr), _k_a[11]));
686 Real lambdac =
687 rhor *
688 std::exp(-std::pow(rhor, _k_a[0]) / _k_a[0] - Utility::pow<2>(_k_a[1] * (Tr - 1.0)) -
689 Utility::pow<2>(_k_a[2] * (rhor - 1.0))) /
690 std::pow(std::pow(Utility::pow<2>(
691 1.0 - 1.0 / Tr +
692 _k_a[3] * std::pow(Utility::pow<2>(rhor - 1.0), 1.0 / (2.0 * _k_a[4]))),
693 _k_a[5]) +
694 std::pow(Utility::pow<2>(_k_a[6] * (rhor - alpha)), _k_a[7]),
695 _k_a[8]);
696
697 return 4.81384 * (sum1 + std::exp(-5.0 * rhor * rhor) * sum2 + 0.775547504 * lambdac) / 1000.0;
698}
registerMooseObject("FluidPropertiesApp", CO2FluidProperties)
const std::vector< double > x
const double mu
const double rho
const std::string name
Definition Setup.h:21
CO2 fluid properties Most thermophysical properties taken from: Span and Wagner, "A New Equation of S...
virtual Real p_from_rho_T(Real density, Real temperature) const override
Pressure as a function of density and temperature.
virtual Real rho_from_p_T(Real pressure, Real temperature) const override
virtual Real criticalDensity() const override
Critical density.
virtual Real molarMass() const override
Molar mass [kg/mol].
Real meltingPressure(Real temperature) const
Melting pressure.
const std::array< unsigned int, 5 > _d3
virtual Real k_from_p_T(Real pressure, Real temperature) const override
const std::array< Real, 3 > _b4
const std::array< Real, 7 > _k_g2
const std::array< Real, 3 > _n4
virtual Real alpha(Real delta, Real tau) const override
Helmholtz free energy.
const std::array< Real, 3 > _D4
const Real _critical_pressure
Critical pressure (Pa)
virtual Real triplePointPressure() const override
Triple point pressure.
Real saturatedLiquidDensity(Real temperature) const
Saturated liquid density of CO2 Valid for temperatures between the triple point temperature and criti...
virtual Real d2alpha_ddeltatau(Real delta, Real tau) const override
Second derivative of Helmholtz free energy wrt delta and tau.
const std::array< unsigned int, 7 > _k_h2
virtual void rho_mu_from_p_T(Real pressure, Real temperature, Real &rho, Real &mu) const override
Combined methods.
const std::array< Real, 7 > _k_n2
const std::array< Real, 27 > _n2
const std::array< unsigned int, 27 > _c2
virtual Real d2alpha_ddelta2(Real delta, Real tau) const override
Second derivative of Helmholtz free energy wrt delta.
const std::array< Real, 3 > _k_n1
virtual Real mu_from_rho_T(Real density, Real temperature) const override
const std::array< Real, 3 > _a4
const std::array< Real, 12 > _k_a
const std::array< unsigned int, 27 > _d2
const std::array< Real, 5 > _beta3
virtual Real mu_from_p_T(Real pressure, Real temperature) const override
virtual Real criticalTemperature() const override
Critical temperature.
CO2FluidProperties(const InputParameters &parameters)
const std::array< Real, 3 > _A4
const std::array< Real, 5 > _theta0
virtual std::vector< Real > henryCoefficients() const override
Henry's law coefficients for dissolution in water.
const std::array< Real, 7 > _t1
virtual Real dalpha_ddelta(Real delta, Real tau) const override
Derivative of Helmholtz free energy wrt delta.
const std::array< unsigned int, 3 > _k_h1
virtual Real vaporPressure(Real temperature) const override
Vapor pressure.
const std::array< Real, 5 > _eps3
Real sublimationPressure(Real temperature) const
Sublimation pressure.
virtual Real k_from_rho_T(Real density, Real temperature) const override
const std::array< Real, 7 > _n1
Coefficients for the residual component of the Helmholtz free energy.
const std::array< Real, 5 > _n3
const std::array< Real, 3 > _beta4
const std::array< Real, 5 > _mu_d
virtual Real triplePointTemperature() const override
Triple point temperature.
virtual Real criticalPressure() const override
Critical pressure.
const Real _critical_density
Critical density (kg/m^3)
const Real _triple_point_temperature
Triple point temperature (K)
virtual Real dalpha_dtau(Real delta, Real tau) const override
Derivative of Helmholtz free energy wrt tau.
Real partialDensity(Real temperature) const
Partial density of dissolved CO2 From Garcia, Density of aqueous solutions of CO2,...
const std::array< Real, 3 > _C4
virtual std::string fluidName() const override
Fluid name.
const Real _Mco2
Molar mass of CO2 (kg/mol)
const Real _critical_temperature
Critical temperature (K)
const std::array< Real, 5 > _mu_a
Coefficients for viscosity.
virtual Real d2alpha_dtau2(Real delta, Real tau) const override
Second derivative of Helmholtz free energy wrt tau.
const std::array< unsigned int, 7 > _d1
static InputParameters validParams()
const std::array< Real, 5 > _alpha3
const std::array< unsigned int, 5 > _t3
const std::array< Real, 5 > _a0
Coefficients for the ideal gas component of the Helmholtz free energy.
const std::array< Real, 3 > _k_g1
Coefficients for the thermal conductivity.
Real saturatedVaporDensity(Real temperature) const
Saturated vapor density of CO2 Valid for temperatures between the triple point temperature and critic...
const std::array< Real, 3 > _B4
const std::array< Real, 27 > _t2
const std::array< Real, 5 > _gamma3
const Real _triple_point_pressure
Triple point pressure (Pa)
const Real _T_c2k
Conversion of temperature from Celsius to Kelvin.
Base class equation of state for fluids that use a Helmholtz free energy alpha(delta,...
static InputParameters validParams()
virtual Real rho_from_p_T(Real pressure, Real temperature) const override
virtual Real p_from_rho_T(Real rho, Real T) const
Pressure as a function of density and temperature.
void addClassDescription(const std::string &doc_string)
void mooseError(Args &&... args) const
Real root(std::function< Real(Real)> const &f, Real x1, Real x2, Real tol=1.0e-12)
Finds the root of a function using Brent's method.
void bracket(std::function< Real(Real)> const &f, Real &x1, Real &x2)
Function to bracket a root of a given function.
T pow(T x, int e)
std::string stringify(const T &t)