https://mooseframework.inl.gov
Loading...
Searching...
No Matches
BrineFluidProperties.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
13
16{
18 params.addParam<UserObjectName>("water_fp",
19 "The name of the FluidProperties UserObject for water");
20 params.addClassDescription("Fluid properties for brine");
21 return params;
22}
23
26{
27 // There are two possibilities to consider:
28 // 1) No water_fp has been supplied (in which case one is constructed)
29 // 2) A water_fp hase been supplied (in which case it is used)
30 // In both cases, though, a Water97FluidProperties UserObject must be added
31 // Note: this UserObject is only used to gain access to the Henry's constant
32 // formulation. All property calculations are performed using _water_fp
33 const std::string water_name = name() + ":water";
34 {
35 const std::string class_name = "Water97FluidProperties";
36 InputParameters params = _app.getFactory().getValidParams(class_name);
37 if (_tid == 0)
38 _fe_problem.addUserObject(class_name, water_name, params);
39 }
41
42 if (parameters.isParamSetByUser("water_fp"))
43 {
44 // SinglePhaseFluidPropertiesPT UserObject for water
45 _water_fp = &getUserObject<SinglePhaseFluidProperties>("water_fp");
46
47 // Check that a water userobject has actually been supplied
48 if (_water_fp->fluidName() != "water")
49 paramError("water_fp", "A water FluidProperties UserObject must be supplied");
50 }
51 else
52 {
53 // Construct a SinglePhaseFluidProperties UserObject for water
55 }
56
57 // SinglePhaseFluidProperties UserObject for NaCl
58 const std::string nacl_name = name() + ":nacl";
59 {
60 const std::string class_name = "NaClFluidProperties";
61 InputParameters params = _app.getFactory().getValidParams(class_name);
62 if (_tid == 0)
63 _fe_problem.addUserObject(class_name, nacl_name, params);
64 }
66
67 // Molar mass of NaCl and H20
70}
71
73
75BrineFluidProperties::getComponent(unsigned int component) const
76{
77 switch (component)
78 {
79 case WATER:
80 return *_water_fp;
81
82 case NACL:
83 return *_nacl_fp;
84
85 default:
86 mooseError("BrineFluidProperties::getComponent has been provided an incorrect component");
87 }
88}
89
90std::string
92{
93 return "brine";
94}
95
98{
99 return 1.0 / (xnacl / _Mnacl + (1.0 - xnacl) / _Mh2o);
100}
101
102Real
104{
105 return 1.0 / (xnacl / _Mnacl + (1.0 - xnacl) / _Mh2o);
106}
107
108Real
110{
111 return _Mnacl;
112}
113
114Real
116{
117 return _Mh2o;
118}
119
122 const FPADReal & temperature,
123 const FPADReal & xnacl) const
124{
125 using std::exp, std::sqrt;
126 // The correlation requires the pressure in bar, not Pa.
127 FPADReal pbar = pressure * 1.0e-5;
128 FPADReal pbar2 = pbar * pbar;
129 FPADReal pbar3 = pbar2 * pbar;
130
131 // The correlation requires mole fraction
132 const FPADReal Xnacl = massFractionToMoleFraction(xnacl);
133
134 const FPADReal n11 = -54.2958 - 45.7623 * exp(-9.44785e-4 * pbar);
135 const FPADReal n21 = -2.6142 - 2.39092e-4 * pbar;
136 const FPADReal n22 = 0.0356828 + 4.37235e-6 * pbar + 2.0566e-9 * pbar2;
137 const FPADReal n1x1 =
138 330.47 + 0.942876 * sqrt(pbar) + 0.0817193 * pbar - 2.47556e-8 * pbar2 + 3.45052e-10 * pbar3;
139 const FPADReal n2x1 = -0.0370751 + 0.00237723 * sqrt(pbar) + 5.42049e-5 * pbar +
140 5.84709e-9 * pbar2 - 5.99373e-13 * pbar3;
141 const FPADReal n12 = -n1x1 - n11;
142 const FPADReal n20 = 1.0 - n21 * sqrt(n22);
143 const FPADReal n23 = n2x1 - n20 - n21 * sqrt(1.0 + n22);
144
145 // The temperature Tv where the brine has the same molar volume as pure water
146 // Note: correlation uses temperature in Celcius
147 const FPADReal n1 = n1x1 + n11 * (1.0 - Xnacl) + n12 * (1.0 - Xnacl) * (1.0 - Xnacl);
148 const FPADReal n2 = n20 + n21 * sqrt(Xnacl + n22) + n23 * Xnacl;
149 const FPADReal Tv = n1 + n2 * (temperature - _T_c2k);
150
151 // The density of water at temperature Tv
152 // Note: convert Tv to Kelvin to calculate water density
153 Real rho, drho_dp, drho_dT;
154 _water_fp->rho_from_p_T(pressure.value(), Tv.value() + _T_c2k, rho, drho_dp, drho_dT);
155 FPADReal water_density = rho;
156 water_density.derivatives() = pressure.derivatives() * drho_dp + Tv.derivatives() * drho_dT;
157
158 // The brine density is given by the water density scaled by the ratio of
159 // brine molar mass to pure water molar mass
160 return water_density * molarMass(xnacl) / _Mh2o;
161}
162
163Real
164BrineFluidProperties::rho_from_p_T_X(Real pressure, Real temperature, Real xnacl) const
165{
166 // Initialise the AD value (no derivatives required)
167 FPADReal p = pressure;
168 FPADReal T = temperature;
169 FPADReal x = xnacl;
170
171 FPADReal ad_rho = this->rho_from_p_T_X(p, T, x);
172
173 return ad_rho.value();
174}
175
176void
178 Real temperature,
179 Real xnacl,
180 Real & rho,
181 Real & drho_dp,
182 Real & drho_dT,
183 Real & drho_dx) const
184{
185 // Initialise the AD value and derivatives
186 FPADReal p = pressure;
187 Moose::derivInsert(p.derivatives(), 0, 1.0);
188 FPADReal T = temperature;
189 Moose::derivInsert(T.derivatives(), 1, 1.0);
190 FPADReal x = xnacl;
191 Moose::derivInsert(x.derivatives(), 2, 1.0);
192
193 FPADReal ad_rho = this->rho_from_p_T_X(p, T, x);
194
195 rho = ad_rho.value();
196 drho_dp = ad_rho.derivatives()[0];
197 drho_dT = ad_rho.derivatives()[1];
198 drho_dx = ad_rho.derivatives()[2];
199}
200
201Real
202BrineFluidProperties::mu_from_p_T_X(Real pressure, Real temperature, Real xnacl) const
203{
204 // Correlation requires molal concentration (mol/kg)
205 const Real mol = massFractionToMolalConc(xnacl);
206 const Real mol2 = mol * mol;
207 const Real mol3 = mol2 * mol;
208
209 // Correlation requires temperature in C
210 const Real Tc = temperature - _T_c2k;
211
212 const Real a = 1.0 + 0.0816 * mol + 0.0122 * mol2 + 0.128e-3 * mol3 +
213 0.629e-3 * Tc * (1.0 - std::exp(-0.7 * mol));
214
215 const Real water_viscosity = _water_fp->mu_from_p_T(pressure, temperature);
216
217 return a * water_viscosity;
218}
219
220void
222 Real temperature,
223 Real xnacl,
224 Real & mu,
225 Real & dmu_dp,
226 Real & dmu_dT,
227 Real & dmu_dx) const
228{
229 // Viscosity of water and derivatives wrt pressure and temperature
230 Real muw, dmuw_dp, dmuw_dT;
231 _water_fp->mu_from_p_T(pressure, temperature, muw, dmuw_dp, dmuw_dT);
232
233 // Correlation requires molal concentration (mol/kg)
234 Real mol = massFractionToMolalConc(xnacl);
235 Real dmol_dx = 1.0 / ((1.0 - xnacl) * (1.0 - xnacl) * _Mnacl);
236 Real mol2 = mol * mol;
237 Real mol3 = mol2 * mol;
238
239 // Correlation requires temperature in C
240 Real Tc = temperature - _T_c2k;
241
242 Real a = 1.0 + 0.0816 * mol + 0.0122 * mol2 + 0.128e-3 * mol3 +
243 0.629e-3 * Tc * (1.0 - std::exp(-0.7 * mol));
244 Real da_dx =
245 (0.0816 + 0.0244 * mol + 3.84e-4 * mol2 + 4.403e-4 * Tc * std::exp(-0.7 * mol)) * dmol_dx;
246 Real da_dT = 0.629e-3 * (1.0 - std::exp(-0.7 * mol));
247
248 mu = a * muw;
249 dmu_dp = a * dmuw_dp;
250 dmu_dx = da_dx * muw;
251 dmu_dT = da_dT * muw + a * dmuw_dT;
252}
253
256 const FPADReal & temperature,
257 const FPADReal & xnacl) const
258{
259 using std::sqrt;
260
261 FPADReal q1, q2, q10, q11, q12, q20, q21, q22, q23, q1x1, q2x1, Th;
262
263 // The correlation requires the pressure in bar, not Pa.
264 const FPADReal pbar = pressure * 1.0e-5;
265 const FPADReal pbar2 = pbar * pbar;
266
267 // The correlation requires mole fraction
268 const FPADReal Xnacl = massFractionToMoleFraction(xnacl);
269
270 q11 = -32.1724 + 0.0621255 * pbar;
271 q21 = -1.69513 - 4.52781e-4 * pbar - 6.04279e-8 * pbar2;
272 q22 = 0.0612567 + 1.88082e-5 * pbar;
273
274 q1x1 = 47.9048 - 9.36994e-3 * pbar + 6.51059e-6 * pbar2;
275 q2x1 = 0.241022 + 3.45087e-5 * pbar - 4.28356e-9 * pbar2;
276
277 q12 = -q11 - q1x1;
278 q10 = q1x1;
279
280 q20 = 1.0 - q21 * sqrt(q22);
281 q23 = q2x1 - q20 - q21 * sqrt(1.0 + q22);
282
283 q1 = q10 + q11 * (1.0 - Xnacl) + q12 * (1.0 - Xnacl) * (1.0 - Xnacl);
284 q2 = q20 + q21 * sqrt(Xnacl + q22) + q23 * Xnacl;
285 // The temperature Th where the brine has the same enthalpy as pure water
286 // Note: correlation uses temperature in Celcius
287 Th = q1 + q2 * (temperature - _T_c2k);
288
289 // The brine enthalpy is then given by the enthalpy of water at temperature Th
290 // Note: water enthalpy requires temperature in Kelvin
291 Real h, dh_dp, dh_dT;
292 _water_fp->h_from_p_T(pressure.value(), Th.value() + _T_c2k, h, dh_dp, dh_dT);
293 FPADReal enthalpy = h;
294 enthalpy.derivatives() = pressure.derivatives() * dh_dp + Th.derivatives() * dh_dT;
295
296 return enthalpy;
297}
298
299Real
300BrineFluidProperties::h_from_p_T_X(Real pressure, Real temperature, Real xnacl) const
301{
302 // Initialise the AD value (no derivatives required)
303 FPADReal p = pressure;
304 FPADReal T = temperature;
305 FPADReal x = xnacl;
306
307 return h_from_p_T_X(p, T, x).value();
308}
309
310void
312 Real temperature,
313 Real xnacl,
314 Real & h,
315 Real & dh_dp,
316 Real & dh_dT,
317 Real & dh_dx) const
318{
319 // Initialise the AD value and derivatives
320 FPADReal p = pressure;
321 Moose::derivInsert(p.derivatives(), 0, 1.0);
322 FPADReal T = temperature;
323 Moose::derivInsert(T.derivatives(), 1, 1.0);
324 FPADReal x = xnacl;
325 Moose::derivInsert(x.derivatives(), 2, 1.0);
326
327 FPADReal ad_h = h_from_p_T_X(p, T, x);
328
329 h = ad_h.value();
330 dh_dp = ad_h.derivatives()[0];
331 dh_dT = ad_h.derivatives()[1];
332 dh_dx = ad_h.derivatives()[2];
333}
334
335Real
336BrineFluidProperties::cp_from_p_T_X(Real pressure, Real temperature, Real xnacl) const
337{
338 Real q1, q2, q10, q11, q12, q20, q21, q22, q23, q1x1, q2x1, Th;
339
340 // The correlation requires the pressure in bar, not Pa.
341 Real pbar = pressure * 1.0e-5;
342 Real pbar2 = pbar * pbar;
343
344 // The correlation requires mole fraction
345 Real Xnacl = massFractionToMoleFraction(xnacl);
346
347 q11 = -32.1724 + 0.0621255 * pbar;
348 q21 = -1.69513 - 4.52781e-4 * pbar - 6.04279e-8 * pbar2;
349 q22 = 0.0612567 + 1.88082e-5 * pbar;
350
351 q1x1 = 47.9048 - 9.36994e-3 * pbar + 6.51059e-6 * pbar2;
352 q2x1 = 0.241022 + 3.45087e-5 * pbar - 4.28356e-9 * pbar2;
353
354 q12 = -q11 - q1x1;
355 q10 = q1x1;
356
357 q20 = 1.0 - q21 * std::sqrt(q22);
358 q23 = q2x1 - q20 - q21 * std::sqrt(1.0 + q22);
359
360 q1 = q10 + q11 * (1.0 - Xnacl) + q12 * (1.0 - Xnacl) * (1.0 - Xnacl);
361 q2 = q20 + q21 * std::sqrt(Xnacl + q22) + q23 * Xnacl;
362 // The temperature Th where the brine has the same isobaric heat capacity
363 // as pure water. Note: correlation uses temperature in Celcius
364 Th = q1 + q2 * (temperature - _T_c2k);
365
366 // The brine isobaric heat capacity is then given by the isobaric heat
367 // capacity of water at temperature Th multiplied by q2
368 // Note: water isobaric heat capacity requires temperature in Kelvin
369 return q2 * _water_fp->cp_from_p_T(pressure, Th + _T_c2k);
370}
371
374 const FPADReal & temperature,
375 const FPADReal & xnacl) const
376{
377 FPADReal enthalpy = h_from_p_T_X(pressure, temperature, xnacl);
378 FPADReal density = rho_from_p_T_X(pressure, temperature, xnacl);
379
380 return enthalpy - pressure / density;
381}
382
383Real
384BrineFluidProperties::e_from_p_T_X(Real pressure, Real temperature, Real xnacl) const
385{
386 Real enthalpy = h_from_p_T_X(pressure, temperature, xnacl);
387 Real density = rho_from_p_T_X(pressure, temperature, xnacl);
388
389 return enthalpy - pressure / density;
390}
391
392void
394 Real temperature,
395 Real xnacl,
396 Real & e,
397 Real & de_dp,
398 Real & de_dT,
399 Real & de_dx) const
400{
401 // Initialise the AD value and derivatives
402 FPADReal p = pressure;
403 Moose::derivInsert(p.derivatives(), 0, 1.0);
404 FPADReal T = temperature;
405 Moose::derivInsert(T.derivatives(), 1, 1.0);
406 FPADReal x = xnacl;
407 Moose::derivInsert(x.derivatives(), 2, 1.0);
408
409 FPADReal ad_e = e_from_p_T_X(p, T, x);
410
411 e = ad_e.value();
412 de_dp = ad_e.derivatives()[0];
413 de_dT = ad_e.derivatives()[1];
414 de_dx = ad_e.derivatives()[2];
415}
416
417Real
418BrineFluidProperties::k_from_p_T_X(Real pressure, Real temperature, Real xnacl) const
419{
420 // Correlation requires molal concentration (mol/kg)
421 Real mol = massFractionToMolalConc(xnacl);
422 // Correlation requires temperature in C
423 Real Tc = temperature - _T_c2k;
424
425 Real S = 100.0 * _Mnacl * mol / (1.0 + _Mnacl * mol);
426 Real lambdaw = _water_fp->k_from_p_T(pressure, temperature);
427 Real lambda = 1.0 - (2.3434e-3 - 7.924e-6 * Tc + 3.924e-8 * Tc * Tc) * S +
428 (1.06e-5 - 2.0e-8 * Tc - 1.2e-10 * Tc * Tc) * S * S;
429
430 return lambda * lambdaw;
431}
432
433Real
434BrineFluidProperties::vaporPressure(Real temperature, Real xnacl) const
435{
436 // Correlation requires molal concentration (mol/kg)
437 Real mol = massFractionToMolalConc(xnacl);
438 Real mol2 = mol * mol;
439 Real mol3 = mol2 * mol;
440
441 Real a = 1.0 + 5.93582e-6 * mol - 5.19386e-5 * mol2 + 1.23156e-5 * mol3;
442 Real b = 1.1542e-6 * mol + 1.41254e-7 * mol2 - 1.92476e-8 * mol3 - 1.70717e-9 * mol * mol3 +
443 1.0539e-10 * mol2 * mol3;
444
445 // The temperature of pure water at the same pressure as the brine is given by
446 Real th20 = std::exp(std::log(temperature) / (a + b * temperature));
447
448 // The brine vapour pressure is then found by evaluating the saturation pressure for pure water
449 // using this effective temperature
450 return _water_fp->vaporPressure(th20);
451}
452
453Real
455{
456 // This correlation requires temperature in Celcius
457 Real Tc = temperature - _T_c2k;
458
459 return (26.18 + 7.2e-3 * Tc + 1.06e-4 * Tc * Tc) / 100.0;
460}
461
462Real
464{
465 return xnacl / ((1.0 - xnacl) * _Mnacl);
466}
467
468Real
470{
471 // The average molar mass of brine from the mass fraction
472 Real Mbrine = molarMass(xnacl);
473 // The mole fraction is then
474 return xnacl * Mbrine / _Mnacl;
475}
476
479{
480 // The average molar mass of brine from the mass fraction
481 FPADReal Mbrine = molarMass(xnacl);
482 // The mole fraction is then
483 return xnacl * Mbrine / _Mnacl;
484}
485
486Real
487BrineFluidProperties::henryConstant(Real temperature, const std::vector<Real> & coeffs) const
488{
489 return _water97_fp->henryConstant(temperature, coeffs);
490}
491
492void
494 const std::vector<Real> & coeffs,
495 Real & Kh,
496 Real & dKh_dT) const
497{
498 _water97_fp->henryConstant(temperature, coeffs, Kh, dKh_dT);
499}
500
501ADReal
503 const std::vector<Real> & coeffs) const
504{
505 Real Kh, dKh_dT;
506 henryConstant(temperature.value(), coeffs, Kh, dKh_dT);
507
508 ADReal henry = Kh;
509 henry.derivatives() = temperature.derivatives() * dKh_dT;
510
511 return henry;
512}
DualNumber< Real, DNDerivativeType, true > ADReal
registerMooseObject("FluidPropertiesApp", BrineFluidProperties)
const std::vector< double > x
DualNumber< Real, DNDerivativeSize< 5 > > FPADReal
const double mu
const double rho
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
Real massFractionToMolalConc(Real xnacl) const
Conversion from mass fraction to molal concentration (molality)
FPADReal e_from_p_T_X(const FPADReal &pressure, const FPADReal &temperature, const FPADReal &xnacl) const
const SinglePhaseFluidProperties * _nacl_fp
NaClFluidProperties UserObject.
Real molarMassNaCl() const
NaCl molar mass.
FPADReal h_from_p_T_X(const FPADReal &pressure, const FPADReal &temperature, const FPADReal &xnacl) const
virtual Real k_from_p_T_X(Real pressure, Real temperature, Real xnacl) const override
Real massFractionToMoleFraction(Real xnacl) const
Conversion from mass fraction to mole fraction.
Real _Mh2o
Molar mass of water (H2O) (kg/mol)
Real haliteSolubility(Real temperature) const
Solubility of halite (solid NaCl) in water Originally from Potter et al., A new method for determinin...
static const unsigned int NACL
BrineFluidProperties(const InputParameters &parameters)
Real vaporPressure(Real temperature, Real xnacl) const
Brine vapour pressure From Haas, Physical properties of the coexisting phases and thermochemical prop...
const SinglePhaseFluidProperties * _water_fp
Water97FluidProperties UserObject.
Real molarMassH2O() const
H2O molar mass.
static InputParameters validParams()
static const unsigned int WATER
Fluid component numbers for water and NaCl.
virtual Real cp_from_p_T_X(Real pressure, Real temperature, Real xnacl) const override
virtual const SinglePhaseFluidProperties & getComponent(unsigned int component) const override
Get UserObject for specified component.
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...
Real molarMass(Real xnacl) const
Average molar mass of brine.
const Water97FluidProperties * _water97_fp
Water97FluidProperties UserObject (for Henry's law)
Real _Mnacl
Molar mass of NaCl (kg/mol)
virtual std::string fluidName() const override
Fluid name.
T & getUserObject(const std::string &name, unsigned int tid=0) const
virtual std::vector< std::shared_ptr< UserObject > > addUserObject(const std::string &user_object_name, const std::string &name, InputParameters &parameters)
InputParameters getValidParams(const std::string &name) const
const Real _T_c2k
Conversion of temperature from Celsius to Kelvin.
bool isParamSetByUser(const std::string &name) const
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)
Factory & getFactory()
const InputParameters & parameters() const
const std::string & name() const
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
Common class for multiple component fluid properties using a pressure and temperature formulation.
Common class for single phase fluid properties.
virtual Real vaporPressure(Real T) const
Vapor pressure.
virtual Real molarMass() const
Molar mass [kg/mol].
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.
FEProblemBase & _fe_problem
Water (H2O) fluid properties as a function of pressure (Pa) and temperature (K) from IAPWS-IF97: Revi...
Real henryConstant(Real temperature, const std::vector< Real > &coeffs) const
IAPWS formulation of Henry's law constant for dissolution in water From Guidelines on the Henry's con...
void derivInsert(SemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< N > > &derivs, libMesh::dof_id_type index, Real value)