https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PorousFlowBrineCO2.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 "PorousFlowBrineCO2.h"
13#include "MathUtils.h"
14#include "Conversion.h"
15
17
20{
22 params.addRequiredParam<UserObjectName>("brine_fp", "The name of the user object for brine");
23 params.addRequiredParam<UserObjectName>("co2_fp", "The name of the user object for CO2");
24 params.addParam<unsigned int>("salt_component", 2, "The component number of salt");
25 params.addClassDescription("Fluid state class for brine and CO2");
26 return params;
27}
28
31 _salt_component(getParam<unsigned int>("salt_component")),
32 _brine_fp(getUserObject<BrineFluidProperties>("brine_fp")),
33 _co2_fp(getUserObject<SinglePhaseFluidProperties>("co2_fp")),
34 _Mh2o(_brine_fp.molarMassH2O()),
35 _invMh2o(1.0 / _Mh2o),
36 _Mco2(_co2_fp.molarMass()),
37 _Mnacl(_brine_fp.molarMassNaCl()),
38 _Rbar(_R * 10.0),
39 _Tlower(372.15),
40 _Tupper(382.15),
41 _Zmin(1.0e-4),
42 _co2_henry(_co2_fp.henryCoefficients())
43{
44 // Check that the correct FluidProperties UserObjects have been provided
45 if (_co2_fp.fluidName() != "co2")
46 paramError("co2_fp", "A valid CO2 FluidProperties UserObject must be provided");
47
48 if (_brine_fp.fluidName() != "brine")
49 paramError("brine_fp", "A valid Brine FluidProperties UserObject must be provided");
50
51 // Set the number of phases and components, and their indexes
52 _num_phases = 2;
56
57 // Check that _aqueous_phase_number is <= total number of phases
59 paramError("liquid_phase_number",
60 "This value is larger than the possible number of phases ",
62
63 // Check that _aqueous_fluid_component is <= total number of fluid components
65 paramError("liquid_fluid_component",
66 "This value is larger than the possible number of fluid components",
68
69 // Check that the salt component index is not identical to the liquid fluid component
72 "salt_component",
73 "The value provided must be different from the value entered in liquid_fluid_component");
74
75 // Check that _salt_component is <= total number of fluid components
77 paramError("salt_component",
78 "The value provided is larger than the possible number of fluid components",
80
82}
83
84std::string
86{
87 return "brine-co2";
88}
89
90void
92 Real temperature,
93 Real Xnacl,
94 Real Z,
95 unsigned int qp,
96 std::vector<FluidStateProperties> & fsp) const
97{
98 // Make AD versions of primary variables then call AD thermophysicalProperties()
99 ADReal p = pressure;
100 Moose::derivInsert(p.derivatives(), _pidx, 1.0);
101 ADReal T = temperature;
102 Moose::derivInsert(T.derivatives(), _Tidx, 1.0);
103 ADReal Zco2 = Z;
104 Moose::derivInsert(Zco2.derivatives(), _Zidx, 1.0);
105 ADReal X = Xnacl;
106 Moose::derivInsert(X.derivatives(), _Xidx, 1.0);
107
108 thermophysicalProperties(p, T, X, Zco2, qp, fsp);
109}
110
111void
113 const ADReal & temperature,
114 const ADReal & Xnacl,
115 const ADReal & Z,
116 unsigned int qp,
117 std::vector<FluidStateProperties> & fsp) const
118{
121
122 // Check whether the input temperature is within the region of validity
123 checkVariables(pressure.value(), temperature.value());
124
125 // Clear all of the FluidStateProperties data
127
128 FluidStatePhaseEnum phase_state;
129 massFractions(pressure, temperature, Xnacl, Z, phase_state, fsp);
130
131 switch (phase_state)
132 {
134 {
135 // Set the gas saturations
136 gas.saturation = 1.0;
137
138 // Calculate gas properties
139 gasProperties(pressure, temperature, fsp);
140
141 break;
142 }
143
145 {
146 // Calculate the liquid properties
147 const ADReal liquid_pressure = pressure - _pc.capillaryPressure(1.0, qp);
148 liquidProperties(liquid_pressure, temperature, Xnacl, fsp);
149
150 break;
151 }
152
154 {
155 // Calculate the gas and liquid properties in the two phase region
156 twoPhaseProperties(pressure, temperature, Xnacl, Z, qp, fsp);
157
158 break;
159 }
160 }
161
162 // Liquid saturations can now be set
163 liquid.saturation = 1.0 - gas.saturation;
164
165 // Save pressures to FluidStateProperties object
166 gas.pressure = pressure;
167 liquid.pressure = pressure - _pc.capillaryPressure(liquid.saturation, qp);
168}
169
170void
172 const ADReal & temperature,
173 const ADReal & Xnacl,
174 const ADReal & Z,
175 FluidStatePhaseEnum & phase_state,
176 std::vector<FluidStateProperties> & fsp) const
177{
180
181 ADReal Xco2 = 0.0;
182 ADReal Yh2o = 0.0;
183 ADReal Yco2 = 0.0;
184
185 // If the amount of CO2 is less than the smallest solubility, then all CO2 will
186 // be dissolved, and the equilibrium mass fractions do not need to be computed
187 if (Z.value() < _Zmin)
188 phase_state = FluidStatePhaseEnum::LIQUID;
189
190 else
191 {
192 // Equilibrium mass fraction of CO2 in liquid and H2O in gas phases
193 equilibriumMassFractions(pressure, temperature, Xnacl, Xco2, Yh2o);
194
195 Yco2 = 1.0 - Yh2o;
196
197 // Determine which phases are present based on the value of z
198 phaseState(Z.value(), Xco2.value(), Yco2.value(), phase_state);
199 }
200
201 // The equilibrium mass fractions calculated above are only correct in the two phase
202 // state. If only liquid or gas phases are present, the mass fractions are given by
203 // the total mass fraction z
204 ADReal Xh2o = 0.0;
205
206 switch (phase_state)
207 {
209 {
210 Xco2 = Z;
211 Yco2 = 0.0;
212 Xh2o = 1.0 - Z;
213 Yh2o = 0.0;
214 break;
215 }
216
218 {
219 Xco2 = 0.0;
220 Yco2 = Z;
221 Yh2o = 1.0 - Z;
222 break;
223 }
224
226 {
227 // Keep equilibrium mass fractions
228 Xh2o = 1.0 - Xco2;
229 break;
230 }
231 }
232
233 // Save the mass fractions in the FluidStateProperties object
235 liquid.mass_fraction[_gas_fluid_component] = Xco2;
236 liquid.mass_fraction[_salt_component] = Xnacl;
239}
240
241void
243 const ADReal & temperature,
244 std::vector<FluidStateProperties> & fsp) const
245{
247
248 // Gas density, viscosity and enthalpy are approximated with pure CO2 - no correction due
249 // to the small amount of water vapor is made
250 ADReal co2_density, co2_viscosity;
251 _co2_fp.rho_mu_from_p_T(pressure, temperature, co2_density, co2_viscosity);
252
253 // Save the values to the FluidStateProperties object. Note that derivatives wrt z are 0
254 gas.density = co2_density;
255 gas.viscosity = co2_viscosity;
256
257 mooseAssert(gas.density.value() > 0.0, "Gas density must be greater than zero");
258
260 gas.enthalpy = _co2_fp.h_from_p_T(pressure, temperature);
261
263 gas.internal_energy = gas.enthalpy - pressure / gas.density;
264}
265
266void
268 const ADReal & temperature,
269 const ADReal & Xnacl,
270 std::vector<FluidStateProperties> & fsp) const
271{
273
274 // The liquid density includes the density increase due to dissolved CO2
275 const ADReal brine_density = _brine_fp.rho_from_p_T_X(pressure, temperature, Xnacl);
276
277 // Mass fraction of CO2 in liquid phase
278 const ADReal Xco2 = liquid.mass_fraction[_gas_fluid_component];
279
280 // The liquid density
281 const ADReal co2_partial_density = partialDensityCO2(temperature);
282
283 const ADReal liquid_density = 1.0 / (Xco2 / co2_partial_density + (1.0 - Xco2) / brine_density);
284
285 // Assume that liquid viscosity is just the brine viscosity
286 const ADReal liquid_viscosity = _brine_fp.mu_from_p_T_X(pressure, temperature, Xnacl);
287
288 // Save the values to the FluidStateProperties object
289 liquid.density = liquid_density;
290 liquid.viscosity = liquid_viscosity;
291
292 mooseAssert(liquid.density.value() > 0.0, "Liquid density must be greater than zero");
293
295 {
296 // Liquid enthalpy (including contribution due to the enthalpy of dissolution)
297 const ADReal brine_enthalpy = _brine_fp.h_from_p_T_X(pressure, temperature, Xnacl);
298
299 // Enthalpy of CO2
300 const ADReal co2_enthalpy = _co2_fp.h_from_p_T(pressure, temperature);
301
302 // Enthalpy of dissolution
303 const ADReal hdis = enthalpyOfDissolution(temperature);
304
305 liquid.enthalpy = (1.0 - Xco2) * brine_enthalpy + Xco2 * (co2_enthalpy + hdis);
306 }
307
309 liquid.internal_energy = liquid.enthalpy - pressure / liquid.density;
310}
311
312ADReal
314 const ADReal & temperature,
315 const ADReal & Xnacl,
316 const ADReal & Z,
317 std::vector<FluidStateProperties> & fsp) const
318{
319 auto & gas = fsp[_gas_phase_number];
320 auto & liquid = fsp[_aqueous_phase_number];
321
322 // Approximate liquid density as saturation isn't known yet, by using the gas
323 // pressure rather than the liquid pressure. This does result in a small error
324 // in the calculated saturation, but this is below the error associated with
325 // the correlations. A more accurate saturation could be found iteraviely,
326 // at the cost of increased computational expense
327
328 // Gas density
329 const ADReal gas_density = _co2_fp.rho_from_p_T(pressure, temperature);
330
331 // Approximate liquid density as saturation isn't known yet
332 const ADReal brine_density = _brine_fp.rho_from_p_T_X(pressure, temperature, Xnacl);
333
334 // Mass fraction of CO2 in liquid phase
335 const ADReal Xco2 = liquid.mass_fraction[_gas_fluid_component];
336
337 // The liquid density
338 const ADReal co2_partial_density = partialDensityCO2(temperature);
339
340 const ADReal liquid_density = 1.0 / (Xco2 / co2_partial_density + (1.0 - Xco2) / brine_density);
341
342 const ADReal Yco2 = gas.mass_fraction[_gas_fluid_component];
343
344 // Set mass equilibrium constants used in the calculation of vapor mass fraction
345 const ADReal K0 = Yco2 / Xco2;
346 const ADReal K1 = (1.0 - Yco2) / (1.0 - Xco2);
347 const ADReal vapor_mass_fraction = vaporMassFraction(Z, K0, K1);
348
349 // The gas saturation in the two phase case
350 const ADReal saturation = vapor_mass_fraction * liquid_density /
351 (gas_density + vapor_mass_fraction * (liquid_density - gas_density));
352
353 return saturation;
354}
355
356void
358 const ADReal & temperature,
359 const ADReal & Xnacl,
360 const ADReal & Z,
361 unsigned int qp,
362 std::vector<FluidStateProperties> & fsp) const
363{
364 auto & gas = fsp[_gas_phase_number];
365
366 // Calculate all of the gas phase properties, as these don't depend on saturation
367 gasProperties(pressure, temperature, fsp);
368
369 // The gas saturation in the two phase case
370 gas.saturation = saturation(pressure, temperature, Xnacl, Z, fsp);
371
372 // The liquid pressure and properties can now be calculated
373 const ADReal liquid_pressure = pressure - _pc.capillaryPressure(1.0 - gas.saturation, qp);
374 liquidProperties(liquid_pressure, temperature, Xnacl, fsp);
375}
376
377void
379 const ADReal & temperature,
380 const ADReal & Xnacl,
381 ADReal & Xco2,
382 ADReal & Yh2o) const
383{
384 // Mole fractions at equilibrium
385 ADReal xco2, yh2o;
386 equilibriumMoleFractions(pressure, temperature, Xnacl, xco2, yh2o);
387
388 // The mass fraction of H2O in gas (assume no salt in gas phase) and derivatives
389 // wrt p, T, and X
390 Yh2o = yh2o * _Mh2o / (yh2o * _Mh2o + (1.0 - yh2o) * _Mco2);
391
392 // NaCl molality (mol/kg)
393 const ADReal mnacl = Xnacl / (1.0 - Xnacl) / _Mnacl;
394
395 // The molality of CO2 in 1kg of H2O
396 const ADReal mco2 = xco2 * (2.0 * mnacl + _invMh2o) / (1.0 - xco2);
397 // The mass fraction of CO2 in brine is then
398 const ADReal denominator = (1.0 + mnacl * _Mnacl + mco2 * _Mco2);
399 Xco2 = mco2 * _Mco2 / denominator;
400}
401
402void
404 const ADReal & temperature,
405 const ADReal & co2_density,
406 ADReal & fco2,
407 ADReal & fh2o) const
408{
409 using std::log, std::exp, std::pow;
410
411 if (temperature.value() > 373.15)
413 ": fugacityCoefficientsLowTemp() is not valid for T > 373.15K. Use "
414 "fugacityCoefficientsHighTemp() instead");
415
416 // Need pressure in bar
417 const ADReal pbar = pressure * 1.0e-5;
418
419 // Molar volume in cm^3/mol
420 const ADReal V = _Mco2 / co2_density * 1.0e6;
421
422 // Redlich-Kwong parameters
423 const ADReal aCO2 = 7.54e7 - 4.13e4 * temperature;
424 const Real bCO2 = 27.8;
425 const Real aCO2H2O = 7.89e7;
426 const Real bH2O = 18.18;
427
428 const ADReal t15 = pow(temperature, 1.5);
429
430 // The fugacity coefficients for H2O and CO2
431 auto lnPhi = [V, aCO2, bCO2, t15, this](ADReal a, ADReal b)
432 {
433 return log(V / (V - bCO2)) + b / (V - bCO2) -
434 2.0 * a / (_Rbar * t15 * bCO2) * log((V + bCO2) / V) +
435 aCO2 * b / (_Rbar * t15 * bCO2 * bCO2) * (log((V + bCO2) / V) - bCO2 / (V + bCO2));
436 };
437
438 const ADReal lnPhiH2O = lnPhi(aCO2H2O, bH2O) - log(pbar * V / (_Rbar * temperature));
439 const ADReal lnPhiCO2 = lnPhi(aCO2, bCO2) - log(pbar * V / (_Rbar * temperature));
440
441 fh2o = exp(lnPhiH2O);
442 fco2 = exp(lnPhiCO2);
443}
444
445void
447 const ADReal & temperature,
448 const ADReal & co2_density,
449 const ADReal & xco2,
450 const ADReal & yh2o,
451 ADReal & fco2,
452 ADReal & fh2o) const
453{
454 if (temperature.value() <= 373.15)
456 ": fugacityCoefficientsHighTemp() is not valid for T <= 373.15K. Use "
457 "fugacityCoefficientsLowTemp() instead");
458
459 fh2o = fugacityCoefficientH2OHighTemp(pressure, temperature, co2_density, xco2, yh2o);
460 fco2 = fugacityCoefficientCO2HighTemp(pressure, temperature, co2_density, xco2, yh2o);
461}
462
463ADReal
465 const ADReal & temperature,
466 const ADReal & co2_density,
467 const ADReal & xco2,
468 const ADReal & yh2o) const
469{
470 using std::sqrt, std::pow, std::log, std::exp;
471
472 // Need pressure in bar
473 const ADReal pbar = pressure * 1.0e-5;
474 // Molar volume in cm^3/mol
475 const ADReal V = _Mco2 / co2_density * 1.0e6;
476
477 // Redlich-Kwong parameters
478 const ADReal yco2 = 1.0 - yh2o;
479 const ADReal xh2o = 1.0 - xco2;
480
481 const ADReal aCO2 = 8.008e7 - 4.984e4 * temperature;
482 const ADReal aH2O = 1.337e8 - 1.4e4 * temperature;
483 const Real bCO2 = 28.25;
484 const Real bH2O = 15.7;
485 const ADReal KH2OCO2 = 1.427e-2 - 4.037e-4 * temperature;
486 const ADReal KCO2H2O = 0.4228 - 7.422e-4 * temperature;
487 const ADReal kH2OCO2 = KH2OCO2 * yh2o + KCO2H2O * yco2;
488 const ADReal kCO2H2O = KCO2H2O * yh2o + KH2OCO2 * yco2;
489
490 const ADReal aH2OCO2 = sqrt(aCO2 * aH2O) * (1.0 - kH2OCO2);
491 const ADReal aCO2H2O = sqrt(aCO2 * aH2O) * (1.0 - kCO2H2O);
492
493 const ADReal amix = yh2o * yh2o * aH2O + yh2o * yco2 * (aH2OCO2 + aCO2H2O) + yco2 * yco2 * aCO2;
494 const ADReal bmix = yh2o * bH2O + yco2 * bCO2;
495
496 const ADReal t15 = pow(temperature, 1.5);
497
498 ADReal lnPhiH2O = bH2O / bmix * (pbar * V / (_Rbar * temperature) - 1.0) -
499 log(pbar * (V - bmix) / (_Rbar * temperature));
500 ADReal term3 = (2.0 * yh2o * aH2O + yco2 * (aH2OCO2 + aCO2H2O) -
501 yh2o * yco2 * sqrt(aH2O * aCO2) * (kH2OCO2 - kCO2H2O) * (yh2o - yco2) +
502 xh2o * xco2 * sqrt(aH2O * aCO2) * (kH2OCO2 - kCO2H2O)) /
503 amix;
504 term3 -= bH2O / bmix;
505 term3 *= amix / (bmix * _Rbar * t15) * log(V / (V + bmix));
506 lnPhiH2O += term3;
507
508 return exp(lnPhiH2O);
509}
510
511ADReal
513 const ADReal & temperature,
514 const ADReal & co2_density,
515 const ADReal & xco2,
516 const ADReal & yh2o) const
517{
518 using std::sqrt, std::pow, std::log, std::exp;
519
520 // Need pressure in bar
521 const ADReal pbar = pressure * 1.0e-5;
522 // Molar volume in cm^3/mol
523 const ADReal V = _Mco2 / co2_density * 1.0e6;
524
525 // Redlich-Kwong parameters
526 const ADReal yco2 = 1.0 - yh2o;
527 const ADReal xh2o = 1.0 - xco2;
528
529 const ADReal aCO2 = 8.008e7 - 4.984e4 * temperature;
530 const ADReal aH2O = 1.337e8 - 1.4e4 * temperature;
531 const Real bCO2 = 28.25;
532 const Real bH2O = 15.7;
533 const ADReal KH2OCO2 = 1.427e-2 - 4.037e-4 * temperature;
534 const ADReal KCO2H2O = 0.4228 - 7.422e-4 * temperature;
535 const ADReal kH2OCO2 = KH2OCO2 * yh2o + KCO2H2O * yco2;
536 const ADReal kCO2H2O = KCO2H2O * yh2o + KH2OCO2 * yco2;
537
538 const ADReal aH2OCO2 = sqrt(aCO2 * aH2O) * (1.0 - kH2OCO2);
539 const ADReal aCO2H2O = sqrt(aCO2 * aH2O) * (1.0 - kCO2H2O);
540
541 const ADReal amix = yh2o * yh2o * aH2O + yh2o * yco2 * (aH2OCO2 + aCO2H2O) + yco2 * yco2 * aCO2;
542 const ADReal bmix = yh2o * bH2O + yco2 * bCO2;
543
544 const ADReal t15 = pow(temperature, 1.5);
545
546 ADReal lnPhiCO2 = bCO2 / bmix * (pbar * V / (_Rbar * temperature) - 1.0) -
547 log(pbar * (V - bmix) / (_Rbar * temperature));
548
549 ADReal term3 = (2.0 * yco2 * aCO2 + yh2o * (aH2OCO2 + aCO2H2O) -
550 yh2o * yco2 * sqrt(aH2O * aCO2) * (kH2OCO2 - kCO2H2O) * (yh2o - yco2) +
551 xh2o * xco2 * sqrt(aH2O * aCO2) * (kCO2H2O - kH2OCO2)) /
552 amix;
553
554 lnPhiCO2 += (term3 - bCO2 / bmix) * amix / (bmix * _Rbar * t15) * log(V / (V + bmix));
555
556 return exp(lnPhiCO2);
557}
558
559ADReal
560PorousFlowBrineCO2::activityCoefficientH2O(const ADReal & temperature, const ADReal & xco2) const
561{
562 using std::exp;
563
564 if (temperature.value() <= 373.15)
565 return 1.0;
566 else
567 {
568 const ADReal Tref = temperature - 373.15;
569 const ADReal xh2o = 1.0 - xco2;
570 const ADReal Am = -3.084e-2 * Tref + 1.927e-5 * Tref * Tref;
571
572 return exp((Am - 2.0 * Am * xh2o) * xco2 * xco2);
573 }
574}
575
576ADReal
577PorousFlowBrineCO2::activityCoefficientCO2(const ADReal & temperature, const ADReal & xco2) const
578{
579 using std::exp;
580
581 if (temperature.value() <= 373.15)
582 return 1.0;
583 else
584 {
585 const ADReal Tref = temperature - 373.15;
586 const ADReal xh2o = 1.0 - xco2;
587 const ADReal Am = -3.084e-2 * Tref + 1.927e-5 * Tref * Tref;
588
589 return exp(2.0 * Am * xco2 * xh2o * xh2o);
590 }
591}
592
593ADReal
595 const ADReal & temperature,
596 const ADReal & Xnacl) const
597{
598 using std::log, std::exp;
599
600 // Need pressure in bar
601 const ADReal pbar = pressure * 1.0e-5;
602 // Need NaCl molality (mol/kg)
603 const ADReal mnacl = Xnacl / (1.0 - Xnacl) / _Mnacl;
604
605 const ADReal lambda = -0.411370585 + 6.07632013e-4 * temperature + 97.5347708 / temperature -
606 0.0237622469 * pbar / temperature +
607 0.0170656236 * pbar / (630.0 - temperature) +
608 1.41335834e-5 * temperature * log(pbar);
609
610 const ADReal xi = 3.36389723e-4 - 1.9829898e-5 * temperature +
611 2.12220830e-3 * pbar / temperature -
612 5.24873303e-3 * pbar / (630.0 - temperature);
613
614 return exp(2.0 * lambda * mnacl + xi * mnacl * mnacl);
615}
616
617ADReal
619 const ADReal & Xnacl) const
620{
621 using std::exp;
622
623 // Need NaCl molality (mol/kg)
624 const ADReal mnacl = Xnacl / (1.0 - Xnacl) / _Mnacl;
625
626 const ADReal T2 = temperature * temperature;
627 const ADReal T3 = temperature * T2;
628
629 const ADReal lambda = 2.217e-4 * temperature + 1.074 / temperature + 2648.0 / T2;
630 const ADReal xi = 1.3e-5 * temperature - 20.12 / temperature + 5259.0 / T2;
631
632 return (1.0 - mnacl / _invMh2o) * exp(2.0 * lambda * mnacl + xi * mnacl * mnacl);
633}
634
635ADReal
637{
638 using std::pow;
639
640 // Uses temperature in Celsius
641 const ADReal Tc = temperature - _T_c2k;
642 const ADReal Tc2 = Tc * Tc;
643 const ADReal Tc3 = Tc2 * Tc;
644 const ADReal Tc4 = Tc3 * Tc;
645
646 ADReal logK0H2O;
647
648 if (Tc <= 99.0)
649 logK0H2O = -2.209 + 3.097e-2 * Tc - 1.098e-4 * Tc2 + 2.048e-7 * Tc3;
650
651 else if (Tc > 99.0 && Tc < 109.0)
652 {
653 const ADReal Tint = (Tc - 99.0) / 10.0;
654 const ADReal Tint2 = Tint * Tint;
655 logK0H2O = -0.0204026 + 0.0152513 * Tint + 0.417565 * Tint2 - 0.278636 * Tint * Tint2;
656 }
657
658 else // 109 <= Tc <= 300
659 logK0H2O = -2.1077 + 2.8127e-2 * Tc - 8.4298e-5 * Tc2 + 1.4969e-7 * Tc3 - 1.1812e-10 * Tc4;
660
661 return pow(10.0, logK0H2O);
662}
663
664ADReal
666{
667 using std::pow;
668
669 // Uses temperature in Celsius
670 const ADReal Tc = temperature - _T_c2k;
671 const ADReal Tc2 = Tc * Tc;
672 const ADReal Tc3 = Tc2 * Tc;
673
674 ADReal logK0CO2;
675
676 if (Tc <= 99.0)
677 logK0CO2 = 1.189 + 1.304e-2 * Tc - 5.446e-5 * Tc2;
678
679 else if (Tc > 99.0 && Tc < 109.0)
680 {
681 const ADReal Tint = (Tc - 99.0) / 10.0;
682 const ADReal Tint2 = Tint * Tint;
683 logK0CO2 = 1.9462 + 2.25692e-2 * Tint - 9.49577e-3 * Tint2 - 6.77721e-3 * Tint * Tint2;
684 }
685
686 else // 109 <= Tc <= 300
687 logK0CO2 = 1.668 + 3.992e-3 * Tc - 1.156e-5 * Tc2 + 1.593e-9 * Tc3;
688
689 return pow(10.0, logK0CO2);
690}
691
692void
694 const ADReal & temperature,
695 const ADReal & Xnacl,
696 ADReal & xco2,
697 ADReal & yh2o) const
698{
699 if (temperature.value() <= _Tlower)
700 {
701 equilibriumMoleFractionsLowTemp(pressure, temperature, Xnacl, xco2, yh2o);
702 }
703 else if (temperature.value() > _Tlower && temperature.value() < _Tupper)
704 {
705 // Cubic polynomial in this regime
706 const Real Tint = (temperature.value() - _Tlower) / 10.0;
707
708 // Equilibrium mole fractions and derivatives at the lower temperature
709 ADReal Tlower = _Tlower;
710 Moose::derivInsert(Tlower.derivatives(), _Tidx, 1.0);
711
712 ADReal xco2_lower, yh2o_lower;
713 equilibriumMoleFractionsLowTemp(pressure, Tlower, Xnacl, xco2_lower, yh2o_lower);
714
715 const Real dxco2_dT_lower = xco2_lower.derivatives()[_Tidx];
716 const Real dyh2o_dT_lower = yh2o_lower.derivatives()[_Tidx];
717
718 // Equilibrium mole fractions and derivatives at the upper temperature
719 Real xco2_upper, yh2o_upper;
720 Real co2_density_upper = _co2_fp.rho_from_p_T(pressure.value(), _Tupper);
721
723 pressure.value(), _Tupper, Xnacl.value(), co2_density_upper, xco2_upper, yh2o_upper);
724
725 Real A, dA_dp, dA_dT, B, dB_dp, dB_dT, dB_dX;
726 funcABHighTemp(pressure.value(),
727 _Tupper,
728 Xnacl.value(),
729 co2_density_upper,
730 xco2_upper,
731 yh2o_upper,
732 A,
733 dA_dp,
734 dA_dT,
735 B,
736 dB_dp,
737 dB_dT,
738 dB_dX);
739
740 const Real dyh2o_dT_upper =
741 ((1.0 - B) * dA_dT + (A - 1.0) * A * dB_dT) / (1.0 - A * B) / (1.0 - A * B);
742 const Real dxco2_dT_upper = dB_dT * (1.0 - yh2o_upper) - B * dyh2o_dT_upper;
743
744 // The mole fractions in this regime are then found by interpolation
745 Real xco2r, yh2or, dxco2_dT, dyh2o_dT;
747 Tint, xco2_lower.value(), dxco2_dT_lower, xco2_upper, dxco2_dT_upper, xco2r, dxco2_dT);
749 Tint, yh2o_lower.value(), dyh2o_dT_lower, yh2o_upper, dyh2o_dT_upper, yh2or, dyh2o_dT);
750
751 xco2 = xco2r;
752 Moose::derivInsert(xco2.derivatives(), _pidx, xco2_lower.derivatives()[_pidx]);
753 Moose::derivInsert(xco2.derivatives(), _Tidx, dxco2_dT);
754 Moose::derivInsert(xco2.derivatives(), _Xidx, xco2_lower.derivatives()[_Xidx]);
755
756 yh2o = yh2or;
757 Moose::derivInsert(yh2o.derivatives(), _pidx, yh2o_lower.derivatives()[_pidx]);
758 Moose::derivInsert(yh2o.derivatives(), _Tidx, dyh2o_dT);
759 Moose::derivInsert(yh2o.derivatives(), _Xidx, yh2o_lower.derivatives()[_Xidx]);
760 }
761 else
762 {
763 // CO2 density and derivatives wrt pressure and temperature
764 const Real co2_density = _co2_fp.rho_from_p_T(pressure.value(), temperature.value());
765
766 // Equilibrium mole fractions solved using iteration in this regime
767 Real xco2r, yh2or;
769 pressure.value(), temperature.value(), Xnacl.value(), co2_density, xco2r, yh2or);
770
771 // Can use these in funcABHighTemp() to get derivatives analytically rather than by iteration
772 Real A, dA_dp, dA_dT, B, dB_dp, dB_dT, dB_dX;
773 funcABHighTemp(pressure.value(),
774 temperature.value(),
775 Xnacl.value(),
776 co2_density,
777 xco2r,
778 yh2or,
779 A,
780 dA_dp,
781 dA_dT,
782 B,
783 dB_dp,
784 dB_dT,
785 dB_dX);
786
787 const Real dyh2o_dp =
788 ((1.0 - B) * dA_dp + (A - 1.0) * A * dB_dp) / (1.0 - A * B) / (1.0 - A * B);
789 const Real dxco2_dp = dB_dp * (1.0 - yh2or) - B * dyh2o_dp;
790
791 const Real dyh2o_dT =
792 ((1.0 - B) * dA_dT + (A - 1.0) * A * dB_dT) / (1.0 - A * B) / (1.0 - A * B);
793 const Real dxco2_dT = dB_dT * (1.0 - yh2or) - B * dyh2o_dT;
794
795 const Real dyh2o_dX = ((A - 1.0) * A * dB_dX) / (1.0 - A * B) / (1.0 - A * B);
796 const Real dxco2_dX = dB_dX * (1.0 - yh2or) - B * dyh2o_dX;
797
798 xco2 = xco2r;
799 Moose::derivInsert(xco2.derivatives(), _pidx, dxco2_dp);
800 Moose::derivInsert(xco2.derivatives(), _Tidx, dxco2_dT);
801 Moose::derivInsert(xco2.derivatives(), _Xidx, dxco2_dX);
802
803 yh2o = yh2or;
804 Moose::derivInsert(yh2o.derivatives(), _pidx, dyh2o_dp);
805 Moose::derivInsert(yh2o.derivatives(), _Tidx, dyh2o_dT);
806 Moose::derivInsert(yh2o.derivatives(), _Xidx, dyh2o_dX);
807 }
808}
809
810void
812 const ADReal & temperature,
813 const ADReal & Xnacl,
814 ADReal & xco2,
815 ADReal & yh2o) const
816{
817 if (temperature.value() > 373.15)
819 ": equilibriumMoleFractionsLowTemp() is not valid for T > 373.15K. Use "
820 "equilibriumMoleFractions() instead");
821
822 // CO2 density and derivatives wrt pressure and temperature
823 const ADReal co2_density = _co2_fp.rho_from_p_T(pressure, temperature);
824
825 // Assume infinite dilution (yh20 = 0 and xco2 = 0) in low temperature regime
826 ADReal A, B;
827 funcABLowTemp(pressure, temperature, co2_density, A, B);
828
829 // As the activity coefficient for CO2 in brine used in this regime isn't a 'true'
830 // activity coefficient, we instead calculate the molality of CO2 in water, then
831 // correct it for brine, and then calculate the mole fractions.
832 // The mole fraction in pure water is
833 const ADReal yh2ow = (1.0 - B) / (1.0 / A - B);
834 const ADReal xco2w = B * (1.0 - yh2ow);
835
836 // Molality of CO2 in pure water
837 const ADReal mco2w = xco2w * _invMh2o / (1.0 - xco2w);
838 // Molality of CO2 in brine is then calculated using gamma
839 const ADReal gamma = activityCoefficient(pressure, temperature, Xnacl);
840 const ADReal mco2 = mco2w / gamma;
841
842 // Need NaCl molality (mol/kg)
843 const ADReal mnacl = Xnacl / (1.0 - Xnacl) / _Mnacl;
844
845 // Mole fractions of CO2 and H2O in liquid and gas phases
846 const ADReal total_moles = 2.0 * mnacl + _invMh2o + mco2;
847 xco2 = mco2 / total_moles;
848 yh2o = A * (1.0 - xco2 - 2.0 * mnacl / total_moles);
849}
850
851void
853 const ADReal & temperature,
854 const ADReal & co2_density,
855 ADReal & A,
856 ADReal & B) const
857{
858 using std::exp;
859
860 if (temperature.value() > 373.15)
862 ": funcABLowTemp() is not valid for T > 373.15K. Use funcABHighTemp() instead");
863
864 // Pressure in bar
865 const ADReal pbar = pressure * 1.0e-5;
866
867 // Reference pressure and partial molar volumes
868 const Real pref = 1.0;
869 const Real vCO2 = 32.6;
870 const Real vH2O = 18.1;
871
872 const ADReal delta_pbar = pbar - pref;
873 const ADReal Rt = _Rbar * temperature;
874
875 // Equilibrium constants
876 const ADReal K0H2O = equilibriumConstantH2O(temperature);
877 const ADReal K0CO2 = equilibriumConstantCO2(temperature);
878
879 // Fugacity coefficients
880 ADReal phiH2O, phiCO2;
881 fugacityCoefficientsLowTemp(pressure, temperature, co2_density, phiCO2, phiH2O);
882
883 A = K0H2O / (phiH2O * pbar) * exp(delta_pbar * vH2O / Rt);
884 B = phiCO2 * pbar / (_invMh2o * K0CO2) * exp(-delta_pbar * vCO2 / Rt);
885}
886
887void
889 Real temperature,
890 Real Xnacl,
891 Real co2_density,
892 Real xco2,
893 Real yh2o,
894 Real & A,
895 Real & B) const
896{
897 using std::exp;
898
899 if (temperature <= 373.15)
901 ": funcABHighTemp() is not valid for T <= 373.15K. Use funcABLowTemp() instead");
902
903 // Pressure in bar
904 const Real pbar = pressure * 1.0e-5;
905 // Temperature in C
906 const Real Tc = temperature - _T_c2k;
907
908 // Reference pressure and partial molar volumes
909 const Real pref = -1.9906e-1 + 2.0471e-3 * Tc + 1.0152e-4 * Tc * Tc - 1.4234e-6 * Tc * Tc * Tc +
910 1.4168e-8 * Tc * Tc * Tc * Tc;
911 const Real vCO2 = 32.6 + 3.413e-2 * (Tc - 100.0);
912 const Real vH2O = 18.1 + 3.137e-2 * (Tc - 100.0);
913
914 const Real delta_pbar = pbar - pref;
915 const Real Rt = _Rbar * temperature;
916
917 // Equilibrium constants
918 // Use dummy ADReal temperature as derivatives aren't required
919 const ADReal T = temperature;
920 Real K0H2O = equilibriumConstantH2O(T).value();
921 Real K0CO2 = equilibriumConstantCO2(T).value();
922
923 // Fugacity coefficients
924 // Use dummy ADReal variables as derivatives aren't required
925 const ADReal p = pressure;
926 const ADReal rhoco2 = co2_density;
927 const ADReal x = xco2;
928 const ADReal y = yh2o;
929
930 ADReal phiH2O, phiCO2;
931 fugacityCoefficientsHighTemp(p, T, rhoco2, x, y, phiCO2, phiH2O);
932
933 // Activity coefficients
934 const Real gammaH2O = activityCoefficientH2O(T, x).value();
935 const Real gammaCO2 = activityCoefficientCO2(T, x).value();
936
937 // Activity coefficient for CO2 in brine
938 // Use dummy ADReal Xnacl as derivatives aren't required
939 const ADReal X = Xnacl;
940 const Real gamma = activityCoefficientHighTemp(T, X).value();
941
942 A = K0H2O * gammaH2O / (phiH2O.value() * pbar) * exp(delta_pbar * vH2O / Rt);
943 B = phiCO2.value() * pbar / (_invMh2o * K0CO2 * gamma * gammaCO2) * exp(-delta_pbar * vCO2 / Rt);
944}
945
946void
948 Real temperature,
949 Real Xnacl,
950 Real co2_density,
951 Real xco2,
952 Real yh2o,
953 Real & A,
954 Real & dA_dp,
955 Real & dA_dT,
956 Real & B,
957 Real & dB_dp,
958 Real & dB_dT,
959 Real & dB_dX) const
960{
961 funcABHighTemp(pressure, temperature, Xnacl, co2_density, xco2, yh2o, A, B);
962
963 // Use finite differences for derivatives in the high temperature regime
964 const Real dp = 1.0e-2;
965 const Real dT = 1.0e-6;
966 const Real dX = 1.0e-8;
967
968 Real A2, B2;
969 funcABHighTemp(pressure + dp, temperature, Xnacl, co2_density, xco2, yh2o, A2, B2);
970 dA_dp = (A2 - A) / dp;
971 dB_dp = (B2 - B) / dp;
972
973 funcABHighTemp(pressure, temperature + dT, Xnacl, co2_density, xco2, yh2o, A2, B2);
974 dA_dT = (A2 - A) / dT;
975 dB_dT = (B2 - B) / dT;
976
977 funcABHighTemp(pressure, temperature, Xnacl + dX, co2_density, xco2, yh2o, A2, B2);
978 dB_dX = (B2 - B) / dX;
979}
980
981void
983 Real pressure, Real temperature, Real Xnacl, Real co2_density, Real & xco2, Real & yh2o) const
984{
985 // Initial guess for yh2o and xco2 (from Spycher and Pruess (2010))
986 Real y = _brine_fp.vaporPressure(temperature, 0.0) / pressure;
987 Real x = 0.009;
988
989 // Need salt mass fraction in molality
990 const Real mnacl = Xnacl / (1.0 - Xnacl) / _Mnacl;
991
992 // If y > 1, then just use y = 1, x = 0 (only a gas phase)
993 if (y >= 1.0)
994 {
995 y = 1.0;
996 x = 0.0;
997 }
998 else
999 {
1000 // Residual function for Newton-Raphson
1001 auto fy = [mnacl, this](Real y, Real A, Real B)
1002 {
1003 return y -
1004 (1.0 - B) * _invMh2o / ((1.0 / A - B) * (2.0 * mnacl + _invMh2o) + 2.0 * mnacl * B);
1005 };
1006
1007 // Derivative of fy wrt y
1008 auto dfy = [mnacl, this](Real A, Real B, Real dA, Real dB)
1009 {
1010 const Real denominator = (1.0 / A - B) * (2.0 * mnacl + _invMh2o) + 2.0 * mnacl * B;
1011 return 1.0 + _invMh2o * dB / denominator +
1012 (1.0 - B) * _invMh2o *
1013 (2.0 * mnacl * dB - (2.0 * mnacl + _invMh2o) * (dB + dA / A / A)) / denominator /
1014 denominator;
1015 };
1016
1017 Real A, B;
1018 Real dA, dB;
1019 const Real dy = 1.0e-8;
1020
1021 // Solve for yh2o using Newton-Raphson method
1022 unsigned int iter = 0;
1023 const Real tol = 1.0e-12;
1024 const unsigned int max_its = 10;
1025 funcABHighTemp(pressure, temperature, Xnacl, co2_density, x, y, A, B);
1026
1027 while (std::abs(fy(y, A, B)) > tol)
1028 {
1029 funcABHighTemp(pressure, temperature, Xnacl, co2_density, x, y, A, B);
1030 // Finite difference derivatives of A and B wrt y
1031 funcABHighTemp(pressure, temperature, Xnacl, co2_density, x, y + dy, dA, dB);
1032 dA = (dA - A) / dy;
1033 dB = (dB - B) / dy;
1034
1035 y = y - fy(y, A, B) / dfy(A, B, dA, dB);
1036
1037 x = B * (1.0 - y);
1038
1039 // Break if not converged and just use the value
1040 if (iter > max_its)
1041 break;
1042 }
1043 }
1044
1045 yh2o = y;
1046 xco2 = x;
1047}
1048
1049ADReal
1051{
1052 // This correlation uses temperature in C
1053 const ADReal Tc = temperature - _T_c2k;
1054 // The parial molar volume
1055 const ADReal V = 37.51 - 9.585e-2 * Tc + 8.74e-4 * Tc * Tc - 5.044e-7 * Tc * Tc * Tc;
1056
1057 return 1.0e6 * _Mco2 / V;
1058}
1059
1060Real
1062 Real pressure, Real temperature, Real Xnacl, Real saturation, unsigned int qp) const
1063{
1064 // Check whether the input pressure and temperature are within the region of validity
1065 checkVariables(pressure, temperature);
1066
1067 // As we do not require derivatives, we can simply ignore their initialisation
1068 const ADReal p = pressure;
1069 const ADReal T = temperature;
1070 const ADReal X = Xnacl;
1071
1072 // FluidStateProperties data structure
1073 std::vector<FluidStateProperties> fsp(_num_phases, FluidStateProperties(_num_components));
1076
1077 // Calculate equilibrium mass fractions in the two-phase state
1078 ADReal Xco2, Yh2o;
1079 equilibriumMassFractions(p, T, X, Xco2, Yh2o);
1080
1081 // Save the mass fractions in the FluidStateMassFractions object
1082 const ADReal Yco2 = 1.0 - Yh2o;
1083 liquid.mass_fraction[_aqueous_fluid_component] = 1.0 - Xco2;
1084 liquid.mass_fraction[_gas_fluid_component] = Xco2;
1087
1088 // Gas properties
1089 gasProperties(pressure, temperature, fsp);
1090
1091 // Liquid properties
1092 const ADReal liquid_saturation = 1.0 - saturation;
1093 const ADReal liquid_pressure = p - _pc.capillaryPressure(liquid_saturation, qp);
1094 liquidProperties(liquid_pressure, T, X, fsp);
1095
1096 // The total mass fraction of ncg (z) can now be calculated
1097 const ADReal Z = (saturation * gas.density * Yco2 + liquid_saturation * liquid.density * Xco2) /
1098 (saturation * gas.density + liquid_saturation * liquid.density);
1099
1100 return Z.value();
1101}
1102
1103ADReal
1104PorousFlowBrineCO2::henryConstant(const ADReal & temperature, const ADReal & Xnacl) const
1105{
1106 using std::pow;
1107
1108 // Henry's constant for dissolution in water
1109 const ADReal Kh_h2o = _brine_fp.henryConstant(temperature, _co2_henry);
1110
1111 // The correction to salt is obtained through the salting out coefficient
1112 const std::vector<Real> b{1.19784e-1, -7.17823e-4, 4.93854e-6, -1.03826e-8, 1.08233e-11};
1113
1114 // Need temperature in Celsius
1115 const ADReal Tc = temperature - _T_c2k;
1116
1117 ADReal kb = 0.0;
1118 for (unsigned int i = 0; i < b.size(); ++i)
1119 kb += b[i] * pow(Tc, i);
1120
1121 // Need salt mass fraction in molality
1122 const ADReal xmol = Xnacl / (1.0 - Xnacl) / _Mnacl;
1123
1124 // Henry's constant and its derivative wrt temperature and salt mass fraction
1125 return Kh_h2o * pow(10.0, xmol * kb);
1126}
1127
1128ADReal
1129PorousFlowBrineCO2::enthalpyOfDissolutionGas(const ADReal & temperature, const ADReal & Xnacl) const
1130{
1131 // Henry's constant
1132 const ADReal Kh = henryConstant(temperature, Xnacl);
1133
1134 ADReal hdis = -_R * temperature * temperature * Kh.derivatives()[_Tidx] / Kh / _Mco2;
1135
1136 // Derivative of enthalpy of dissolution wrt temperature and xnacl requires the second
1137 // derivatives of Henry's constant. For simplicity, approximate these numerically
1138 const Real dT = temperature.value() * 1.0e-8;
1139 const ADReal T2 = temperature + dT;
1140 const ADReal Kh2 = henryConstant(T2, Xnacl);
1141
1142 const Real dhdis_dT =
1143 (-_R * T2 * T2 * Kh2.derivatives()[_Tidx] / Kh2 / _Mco2 - hdis).value() / dT;
1144
1145 const Real dX = Xnacl.value() * 1.0e-8;
1146 const ADReal X2 = Xnacl + dX;
1147 const ADReal Kh3 = henryConstant(temperature, X2);
1148
1149 const Real dhdis_dX =
1150 (-_R * temperature * temperature * Kh3.derivatives()[_Tidx] / Kh3 / _Mco2 - hdis).value() /
1151 dX;
1152
1153 hdis.derivatives() = temperature.derivatives() * dhdis_dT + Xnacl.derivatives() * dhdis_dX;
1154
1155 return hdis;
1156}
1157
1158ADReal
1160{
1161 // Linear fit to model of Duan and Sun (2003) (in kJ/mol)
1162 const ADReal delta_h = -58.3533 + 0.134519 * temperature;
1163
1164 // Convert to J/kg
1165 return delta_h * 1000.0 / _Mco2;
1166}
1167
1168void
1170 Real temperature, Real f0, Real df0, Real f1, Real df1, Real & value, Real & deriv) const
1171{
1172 // Coefficients of cubic polynomial
1173 const Real dT = _Tupper - _Tlower;
1174
1175 const Real a = f0;
1176 const Real b = df0 * dT;
1177 const Real c = 3.0 * (f1 - f0) - (2.0 * df0 + df1) * dT;
1178 const Real d = 2.0 * (f0 - f1) + (df0 + df1) * dT;
1179
1180 const Real t2 = temperature * temperature;
1181 const Real t3 = temperature * t2;
1182
1183 value = a + b * temperature + c * t2 + d * t3;
1184 deriv = b + 2.0 * c * temperature + 3.0 * d * t2;
1185}
1186
1187void
1188PorousFlowBrineCO2::checkVariables(Real pressure, Real temperature) const
1189{
1190 // The calculation of mass fractions is valid from 12C <= T <= 300C, and
1191 // pressure less than 60 MPa
1192 if (temperature < 285.15 || temperature > 573.15)
1193 mooseException(name() + ": temperature " + Moose::stringify(temperature) +
1194 " is outside range 285.15 K <= T <= 573.15 K");
1195
1196 if (pressure > 6.0e7)
1197 mooseException(name() + ": pressure " + Moose::stringify(pressure) +
1198 " must be less than 60 MPa");
1199}
DualNumber< Real, DNDerivativeType, true > ADReal
const std::vector< double > y
const double tol
const std::vector< double > x
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const Real p
const double T
Point xi
registerMooseObject("PorousFlowApp", PorousFlowBrineCO2)
FluidStatePhaseEnum
Phase state enum.
const std::string name
Definition Setup.h:21
void ErrorVector unsigned int
Brine (NaCl in H2O) fluid properties as a function of pressure (Pa), temperature (K) and NaCl mass fr...
virtual Real mu_from_p_T_X(Real pressure, Real temperature, Real xnacl) const override
virtual Real rho_from_p_T_X(Real pressure, Real temperature, Real xnacl) const override
FPADReal h_from_p_T_X(const FPADReal &pressure, const FPADReal &temperature, const FPADReal &xnacl) const
Real vaporPressure(Real temperature, Real xnacl) const
Brine vapour pressure From Haas, Physical properties of the coexisting phases and thermochemical prop...
Real henryConstant(Real temperature, const std::vector< Real > &coeffs) const
IAPWS formulation of Henry's law constant for dissolution in water (implemented in water FluidPropert...
virtual std::string fluidName() const override
Fluid name.
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
Specialized class for brine and CO2 including calculation of mutual solubility of the two fluids usin...
void liquidProperties(const ADReal &pressure, const ADReal &temperature, const ADReal &Xnacl, std::vector< FluidStateProperties > &fsp) const
Thermophysical properties of the liquid state.
void funcABLowTemp(const ADReal &pressure, const ADReal &temperature, const ADReal &co2_density, ADReal &A, ADReal &B) const
ADReal saturation(const ADReal &pressure, const ADReal &temperature, const ADReal &Xnacl, const ADReal &Z, std::vector< FluidStateProperties > &fsp) const
Gas saturation in the two-phase region.
ADReal fugacityCoefficientCO2HighTemp(const ADReal &pressure, const ADReal &temperature, const ADReal &co2_density, const ADReal &xco2, const ADReal &yh2o) const
ADReal henryConstant(const ADReal &temperature, const ADReal &Xnacl) const
Henry's constant of dissolution of gas phase CO2 in brine.
const Real _Tlower
Temperature below which the Spycher, Pruess & Ennis-King (2003) model is used (K)
void gasProperties(const ADReal &pressure, const ADReal &temperature, std::vector< FluidStateProperties > &fsp) const
Thermophysical properties of the gaseous state.
const Real _Tupper
Temperature above which the Spycher & Pruess (2010) model is used (K)
const Real _invMh2o
Inverse of molar mass of H2O (mol/kg)
ADReal enthalpyOfDissolutionGas(const ADReal &temperature, const ADReal &Xnacl) const
Enthalpy of dissolution of gas phase CO2 in brine calculated using Henry's constant From Himmelblau,...
virtual void checkVariables(Real pressure, Real temperature) const
Check the input variables.
ADReal fugacityCoefficientH2OHighTemp(const ADReal &pressure, const ADReal &temperature, const ADReal &co2_density, const ADReal &xco2, const ADReal &yh2o) const
ADReal partialDensityCO2(const ADReal &temperature) const
Partial density of dissolved CO2 From Garcia, Density of aqueous solutions of CO2,...
const Real _Rbar
Molar gas constant in bar cm^3 /(K mol)
void fugacityCoefficientsHighTemp(const ADReal &pressure, const ADReal &temperature, const ADReal &co2_density, const ADReal &xco2, const ADReal &yh2o, ADReal &fco2, ADReal &fh2o) const
Fugacity coefficients for H2O and CO2 at elevated temperatures (100C < T <= 300C).
ADReal activityCoefficientHighTemp(const ADReal &temperature, const ADReal &Xnacl) const
Activity coefficient for CO2 in brine used in the elevated temperature formulation.
void solveEquilibriumMoleFractionHighTemp(Real pressure, Real temperature, Real Xnacl, Real co2_density, Real &xco2, Real &yh2o) const
Function to solve for yh2o and xco2 iteratively in the elevated temperature regime (T > 100C)
const Real _Mco2
Molar mass of CO2 (kg/mol)
void massFractions(const ADReal &pressure, const ADReal &temperature, const ADReal &Xnacl, const ADReal &Z, FluidStatePhaseEnum &phase_state, std::vector< FluidStateProperties > &fsp) const
Mass fractions of CO2 and H2O in both phases, as well as derivatives wrt PorousFlow variables.
void smoothCubicInterpolation(Real temperature, Real f0, Real df0, Real f1, Real df1, Real &value, Real &deriv) const
Cubic function to smoothly interpolate between the low temperature and elevated temperature models fo...
void funcABHighTemp(Real pressure, Real temperature, Real Xnacl, Real co2_density, Real xco2, Real yh2o, Real &A, Real &B) const
The function A (Eq.
const Real _Zmin
Minimum Z - below this value all CO2 will be dissolved.
const std::vector< Real > _co2_henry
Henry's coefficeients for CO2.
virtual std::string fluidStateName() const override
Name of FluidState.
void equilibriumMoleFractionsLowTemp(const ADReal &pressure, const ADReal &temperature, const ADReal &Xnacl, ADReal &xco2, ADReal &yh2o) const
Mole fractions of CO2 in brine and water vapor in CO2 at equilibrium in the low temperature regime (T...
const BrineFluidProperties & _brine_fp
Fluid properties UserObject for water.
void equilibriumMoleFractions(const ADReal &pressure, const ADReal &temperature, const ADReal &Xnacl, ADReal &xco2, ADReal &yh2o) const
Mole fractions of CO2 in brine and water vapor in CO2 at equilibrium.
PorousFlowBrineCO2(const InputParameters &parameters)
virtual Real totalMassFraction(Real pressure, Real temperature, Real Xnacl, Real saturation, unsigned int qp) const override
Total mass fraction of fluid component summed over all phases in the two-phase state for a specified ...
void equilibriumMassFractions(const ADReal &pressure, const ADReal &temperature, const ADReal &Xnacl, ADReal &Xco2, ADReal &Yh2o) const
Mass fractions of CO2 in brine and water vapor in CO2 at equilibrium.
ADReal equilibriumConstantCO2(const ADReal &temperature) const
Equilibrium constant for CO2 For temperatures 12C <= T <= 99C, uses Spycher, Pruess and Ennis-King (2...
void twoPhaseProperties(const ADReal &pressure, const ADReal &temperature, const ADReal &Xnacl, const ADReal &Z, unsigned int qp, std::vector< FluidStateProperties > &fsp) const
Gas and liquid properties in the two-phase region.
ADReal activityCoefficient(const ADReal &pressure, const ADReal &temperature, const ADReal &Xnacl) const
Activity coefficient for CO2 in brine.
const Real _Mh2o
Molar mass of water (kg/mol)
static InputParameters validParams()
const unsigned int _salt_component
Salt component index.
ADReal activityCoefficientCO2(const ADReal &temperature, const ADReal &xco2) const
Activity coefficient of CO2 Eq.
void fugacityCoefficientsLowTemp(const ADReal &pressure, const ADReal &temperature, const ADReal &co2_density, ADReal &fco2, ADReal &fh2o) const
Fugacity coefficients for H2O and CO2 for T <= 100C Eq.
const SinglePhaseFluidProperties & _co2_fp
Fluid properties UserObject for the CO2.
ADReal enthalpyOfDissolution(const ADReal &temperature) const
Enthalpy of dissolution of CO2 in brine calculated using linear fit to model of Duan and Sun,...
ADReal activityCoefficientH2O(const ADReal &temperature, const ADReal &xco2) const
Activity coefficient of H2O Eq.
void thermophysicalProperties(Real pressure, Real temperature, Real Xnacl, Real Z, unsigned int qp, std::vector< FluidStateProperties > &fsp) const override
Determines the complete thermophysical state of the system for a given set of primary variables.
ADReal equilibriumConstantH2O(const ADReal &temperature) const
Equilibrium constant for H2O For temperatures 12C <= T <= 99C, uses Spycher, Pruess and Ennis-King (2...
const Real _Mnacl
Molar mass of NaCL.
virtual Real capillaryPressure(Real saturation, unsigned qp=0) const
Capillary pressure is calculated as a function of true saturation.
unsigned int _num_components
Number of components.
const PorousFlowCapillaryPressure & _pc
Capillary pressure UserObject.
unsigned int _gas_phase_number
Phase number of the gas phase.
const Real _R
Universal gas constant (J/mol/K)
const unsigned int _aqueous_phase_number
Phase number of the aqueous phase.
FluidStateProperties _empty_fsp
Empty FluidStateProperties object.
const Real _T_c2k
Conversion from C to K.
void clearFluidStateProperties(std::vector< FluidStateProperties > &fsp) const
Clears the contents of the FluidStateProperties data structure.
unsigned int _num_phases
Number of phases.
Real vaporMassFraction(Real Z0, Real K0, Real K1) const
Solves Rachford-Rice equation to provide vapor mass fraction.
Compositional flash routines for miscible multiphase flow classes with multiple fluid components.
const unsigned int _Xidx
Index of derivative wrt salt mass fraction X.
unsigned int _gas_fluid_component
Fluid component number of the gas phase.
const bool _compute_enthalpy
Whether to compute the enthalpy of each phase.
const bool _compute_internal_energy
Whether to compute the internal energy of each phase.
const unsigned int _pidx
Index of derivative wrt pressure.
const unsigned int _Tidx
Index of derivative wrt temperature.
const unsigned int _Zidx
Index of derivative wrt total mass fraction Z.
const unsigned int _aqueous_fluid_component
Fluid component number of the aqueous component.
void phaseState(Real Zi, Real Xi, Real Yi, FluidStatePhaseEnum &phase_state) const
Determines the phase state gven the total mass fraction and equilibrium mass fractions.
Common class for single phase fluid properties.
e e e e s T T T T T rho v v T e p T T virtual T std::string fluidName() const
Fluid name.
virtual void rho_mu_from_p_T(Real p, Real T, Real &rho, Real &mu) const
Combined methods.
std::string stringify(const T &t)
void derivInsert(SemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< N > > &derivs, libMesh::dof_id_type index, Real value)
AD data structure to pass calculated thermophysical properties.
std::vector< ADReal > mass_fraction