GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/material/components/heavyoil.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 72 79 91.1%
Functions: 5 9 55.6%
Branches: 42 76 55.3%

Line Branch Exec Source
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 //
4 // SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 /*!
8 * \file
9 * \ingroup Components
10 * \brief Properties of the component heavyoil.
11 */
12 #ifndef DUMUX_HEAVYOIL_HH
13 #define DUMUX_HEAVYOIL_HH
14
15 #include <algorithm>
16
17 #include <dune/common/math.hh>
18
19 #include <dumux/material/constants.hh>
20 #include <dumux/material/components/base.hh>
21 #include <dumux/material/components/gas.hh>
22 #include <dumux/material/components/liquid.hh>
23 #include <dumux/material/idealgas.hh>
24
25 namespace Dumux::Components {
26
27 /*!
28 * \ingroup Components
29 * \brief Properties of the component heavyoil
30 *
31 * \tparam Scalar The type used for scalar values
32 */
33 template <class Scalar>
34 class HeavyOil
35 : public Components::Base<Scalar, HeavyOil<Scalar> >
36 , public Components::Liquid<Scalar, HeavyOil<Scalar> >
37 , public Components::Gas<Scalar, HeavyOil<Scalar> >
38 {
39 using Consts = Dumux::Constants<Scalar>;
40 using IdealGas = Dumux::IdealGas<Scalar>;
41 public:
42 /*!
43 * \brief A human readable name for heavyoil
44 */
45 static std::string name()
46
34/66
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 1 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 1 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 1 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 1 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 1 times.
✗ Branch 71 not taken.
✓ Branch 73 taken 1 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 1 times.
✗ Branch 77 not taken.
✓ Branch 79 taken 1 times.
✗ Branch 80 not taken.
✓ Branch 82 taken 1 times.
✗ Branch 83 not taken.
✓ Branch 85 taken 1 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 1 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 1 times.
✗ Branch 92 not taken.
✓ Branch 94 taken 1 times.
✗ Branch 95 not taken.
26 { return "heavyoil"; }
47
48 /*!
49 * \brief The molar mass in \f$\mathrm{[kg/mol]}\f$ of heavyoil
50 */
51 constexpr static Scalar molarMass()
52 { return .350; }
53
54 /*!
55 * \brief The MolecularWeight in \f$\mathrm{[kg/mol]}\f$ of refComponent
56 */
57 constexpr static Scalar refComponentMolecularWeight()
58 { return .400; }
59
60 /*!
61 * \brief The molar mass in \f$\mathrm{[kg/mol]}\f$ of heavyoil
62 */
63
64 constexpr static Scalar molecularWeight()
65 { return .350; }
66
67 /*!
68 * \brief The Specific Gravity \f$\mathrm{[ ]}\f$ of heavyoil
69 */
70 constexpr static Scalar specificGravity()
71 { return 0.91; }
72
73 /*!
74 * \brief Returns the temperature \f$\mathrm{[K]}\f$ at heavyoil's triple point.
75 */
76 static Scalar tripleTemperature()
77 {
78 DUNE_THROW(Dune::NotImplemented, "tripleTemperature for heavyoil");
79 }
80
81 /*!
82 * \brief Returns the pressure \f$\mathrm{[Pa]}\f$ at heavyoil's triple point.
83 */
84 static Scalar triplePressure()
85 {
86 DUNE_THROW(Dune::NotImplemented, "triplePressure for heavyoil");
87 }
88
89 static Scalar refComponentSpecificGravity()
90 {
91 constexpr Scalar A = 0.83;
92 constexpr Scalar B = 89.9513;
93 constexpr Scalar C = 139.6612;
94 constexpr Scalar D = 3.2033;
95 constexpr Scalar E = 1.0564;
96
97 const Scalar mW = refComponentMolecularWeight() *1000. ; // in [g/mol];
98
99 using std::pow;
100 return A+(B/mW)-(C/pow((mW+D),E));
101 }
102
103 static Scalar perbutationFactorBoilingTemperature()
104 {
105 constexpr Scalar A = -7.4120e-2; //All factors for 1 atm / 101325 pascals [760 mmHg]
106 constexpr Scalar B = -7.5041e-3;
107 constexpr Scalar C = -2.6031;
108 constexpr Scalar D = 9.0180e-2;
109 constexpr Scalar E = -1.0482;
110
111 using std::log;
112 const Scalar deltaSpecificGravity = log(refComponentSpecificGravity()/specificGravity());
113 const Scalar deltaMolecularWeight = log(refComponentMolecularWeight()/molecularWeight());
114
115 using Dune::power;
116 7710114 return A*power(deltaSpecificGravity,2) + B*deltaSpecificGravity + C*power(deltaMolecularWeight,2) + D*deltaMolecularWeight
117 7710114 + E*deltaSpecificGravity*deltaMolecularWeight;
118 }
119
120 static Scalar perbutationFactorCriticalTemperature()
121 {
122 constexpr Scalar A = -6.1294e-2;
123 constexpr Scalar B = -7.0862e-2;
124 constexpr Scalar C = 6.1976e-1;
125 constexpr Scalar D = -5.7090e-2;
126 constexpr Scalar E = -8.4583e-2;
127
128 using std::log;
129 const Scalar deltaSpecificGravity = log(refComponentSpecificGravity()/specificGravity());
130 const Scalar deltaMolecularWeight = log(refComponentMolecularWeight()/molecularWeight());
131
132 using Dune::power;
133 30840456 return A*power(deltaSpecificGravity,2) + B*deltaSpecificGravity + C*power(deltaMolecularWeight,2) + D*deltaMolecularWeight
134 30840456 + E*deltaSpecificGravity*deltaMolecularWeight;
135 }
136
137 static Scalar perbutationFactorCriticalPressure()
138 {
139 constexpr Scalar A = 1.8270e-1;
140 constexpr Scalar B = -2.4864e-1;
141 constexpr Scalar C = 8.3611;
142 constexpr Scalar D = -2.2389e-1;
143 constexpr Scalar E = 2.6984;
144
145 using std::log;
146 const Scalar deltaSpecificGravity = log(refComponentSpecificGravity()/specificGravity());
147 const Scalar deltaMolecularWeight = log(refComponentMolecularWeight()/molecularWeight());
148
149 using Dune::power;
150 7710114 return A*power(deltaSpecificGravity,2) + B*deltaSpecificGravity + C*power(deltaMolecularWeight,2) + D*deltaMolecularWeight
151 7710114 + E*deltaSpecificGravity*deltaMolecularWeight;
152 }
153
154 static Scalar refComponentBoilingTemperature()
155 {
156 3855057 constexpr Scalar A = 477.63; //All factors for 1 atm / 101325 pascals [760 mmHg]
157 3855057 constexpr Scalar B = 88.51;
158 3855057 constexpr Scalar C = 1007;
159 3855057 constexpr Scalar D = 1214.40;
160
161 using std::log;
162 return A*log((1000.*refComponentMolecularWeight() + B)/(1000.*refComponentMolecularWeight()+C)) + D;
163 }
164
165 static Scalar refComponentCriticalTemperature()
166 {
167 15420228 constexpr Scalar A = 226.50;
168 15420228 constexpr Scalar B = 6.78;
169 15420228 constexpr Scalar C = 1.282e6;
170 15420228 constexpr Scalar D = 2668;
171
172 using std::log;
173 return A*log((1000.*refComponentMolecularWeight() + B)/(1000.*refComponentMolecularWeight()+C)) + D ;
174 }
175
176 static Scalar refComponentCriticalPressure()
177 {
178 3855057 constexpr Scalar A = 141.20;
179 3855057 constexpr Scalar B = 45.66e-2;
180 3855057 constexpr Scalar C = 16.59e-3;
181 3855057 constexpr Scalar D = 2.19;
182
183 using std::pow;
184 return (A*1000.*molecularWeight())/(pow(B + (C*1000.*molecularWeight()),D)) ;
185 }
186
187 /*!
188 * \brief Returns the temperature \f$\mathrm{[K]}\f$ at heavyoil's boiling point (1 atm)
189 */
190 3855057 static Scalar boilingTemperature()
191 {
192 using Dune::power;
193 11565171 return refComponentBoilingTemperature() * power((1 + 2*perbutationFactorBoilingTemperature())/(1 - 2*perbutationFactorBoilingTemperature()),2);
194 }
195
196 /*!
197 * \brief Returns the critical temperature \f$\mathrm{[K]}\f$ of heavyoil
198 */
199 15420228 static Scalar criticalTemperature()
200 {
201 using Dune::power;
202 46260684 return refComponentCriticalTemperature() * power((1 + 2*perbutationFactorCriticalTemperature())/(1 - 2*perbutationFactorCriticalTemperature()),2);
203 }
204
205 /*!
206 * \brief Returns the critical pressure \f$\mathrm{[Pa]}\f$ of heavyoil
207 */
208 3855057 static Scalar criticalPressure()
209 {
210 using Dune::power;
211 11565171 return refComponentCriticalPressure() * power((1 + 2*perbutationFactorCriticalPressure())/(1 - 2*perbutationFactorCriticalPressure()),2);
212 }
213
214 /*!
215 * \brief The saturation vapor pressure in \f$\mathrm{[Pa]}\f$ of
216 *
217 * \param temperature temperature of component in \f$\mathrm{[K]}\f$
218 */
219 static Scalar vaporPressure(Scalar temperature)
220 {
221 7711000 constexpr Scalar A = 8.25990;
222 7711000 constexpr Scalar B = 2830.065;
223 7711000 constexpr Scalar C = 42.95101;
224
225 7711000 const Scalar T = temperature - 273.15;
226
227 using std::pow;
228 7711000 return 100*1.334*pow(10.0, (A - (B/(T + C)))); // in [Pa]
229 }
230
231 static Scalar vaporTemperature(Scalar pressure)
232 {
233 370 constexpr Scalar A = 8.25990;
234 370 constexpr Scalar B = 2830.065;
235 370 constexpr Scalar C = 42.95101;
236
237 370 const Scalar P = pressure;
238
239 using std::log10;
240 370 return Scalar ((B/(A-log10(P/100*1.334)))-C);
241 }
242
243 /*!
244 * \brief Specific enthalpy of liquid heavyoil \f$\mathrm{[J/kg]}\f$.
245 *
246 * \param temperature temperature of component in \f$\mathrm{[K]}\f$
247 * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
248 */
249 static Scalar liquidEnthalpy(const Scalar temperature,
250 const Scalar pressure)
251 {
252 // Gauss quadrature rule:
253 // Interval: [0K; temperature (K)]
254 // Gauss-Legendre-Integration with variable transformation:
255 // \int_a^b f(T) dT \approx (b-a)/2 \sum_i=1^n \alpha_i f( (b-a)/2 x_i + (a+b)/2 )
256 // with: n=2, legendre -> x_i = +/- \sqrt(1/3), \apha_i=1
257 // here: a=273.15K, b=actual temperature in Kelvin
258 // \leadsto h(T) = \int_273.15^T c_p(T) dT
259 // \approx 0.5 (T-273.15) * (cp( 0.5(temperature-273.15)sqrt(1/3) ) + cp(0.5(temperature-273.15)(-1)sqrt(1/3))
260
261 // Enthalpy may have arbitrary reference state, but the empirical/fitted heatCapacity function needs Kelvin as input and is
262 // fit over a certain temperature range. This suggests choosing an interval of integration being in the actual fit range.
263 // I.e. choosing T=273.15K as reference point for liquid enthalpy.
264 using std::sqrt;
265 7710114 const Scalar sqrt1over3 = sqrt(1./3.);
266 7710114 const Scalar TEval1 = 0.5*(temperature-273.15)* sqrt1over3 + 0.5*(273.15+temperature) ; // evaluation points according to Gauss-Legendre integration
267 7710114 const Scalar TEval2 = 0.5*(temperature-273.15)* (-1)* sqrt1over3 + 0.5*(273.15+temperature) ; // evaluation points according to Gauss-Legendre integration
268
269 3855057 const Scalar h_n = 0.5 * (temperature-273.15) * ( liquidHeatCapacity(TEval1, pressure) + liquidHeatCapacity(TEval2, pressure) ) ;
270
271 return h_n;
272 }
273
274 /*!
275 * \brief Latent heat of vaporization for heavyoil \f$\mathrm{[J/kg]}\f$.
276 *
277 * source : Reid et al. (fourth edition): Chen method (chap. 7-11, Delta H_v = Delta H_v (T) according to chap. 7-12)
278 *
279 * \param temperature temperature of component in \f$\mathrm{[K]}\f$
280 * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
281 */
282 3855057 static Scalar heatVap(Scalar temperature,
283 const Scalar pressure)
284 {
285 using std::clamp;
286
1/2
✓ Branch 0 taken 3855057 times.
✗ Branch 1 not taken.
3855057 temperature = clamp(temperature, 0.0, criticalTemperature()); // regularization
287
288 3855057 const Scalar T_crit = criticalTemperature();
289 3855057 const Scalar Tr1 = boilingTemperature()/criticalTemperature();
290 3855057 const Scalar p_crit = criticalPressure();
291
292 // Chen method, eq. 7-11.4 (at boiling)
293 using std::log;
294 7710114 const Scalar DH_v_boil = Consts::R * T_crit * Tr1
295 3855057 * (3.978 * Tr1 - 3.958 + 1.555*log(p_crit * 1e-5 /*Pa->bar*/ ) )
296 3855057 / (1.07 - Tr1); /* [J/mol] */
297
298 /* Variation with temp according to Watson relation eq 7-12.1*/
299 using std::pow;
300 3855057 const Scalar Tr2 = temperature/criticalTemperature();
301 3855057 const Scalar n = 0.375;
302 3855057 const Scalar DH_vap = DH_v_boil * pow(((1.0 - Tr2)/(1.0 - Tr1)), n);
303
304 3855057 return (DH_vap/molarMass()); // we need [J/kg]
305 }
306
307
308 /*!
309 * \brief Specific enthalpy of heavyoil vapor \f$\mathrm{[J/kg]}\f$.
310 *
311 * This relation is true on the vapor pressure curve, i.e. as long
312 * as there is a liquid phase present.
313 *
314 * \param temperature temperature of component in \f$\mathrm{[K]}\f$
315 * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
316 */
317 static Scalar gasEnthalpy(Scalar temperature, Scalar pressure)
318 {
319 3855057 return liquidEnthalpy(temperature,pressure) + heatVap(temperature, pressure);
320 }
321
322 /*!
323 * \brief The (ideal) gas density of heavyoil vapor at a given temperature and pressure \f$\mathrm{[kg/m^3]}\f$.
324 *
325 * \param temperature temperature of component in \f$\mathrm{[K]}\f$
326 * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
327 */
328 static Scalar gasDensity(Scalar temperature, Scalar pressure)
329 {
330
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
7710120 return IdealGas::density(molarMass(), temperature, pressure);
331 }
332
333 /*!
334 * \brief The molar density of pure heavyoil in \f$\mathrm{[mol/m^3]}\f$,
335 * depending on pressure and temperature.
336 * \param temperature The temperature of the gas
337 * \param pressure The pressure of the gas
338 */
339 static Scalar gasMolarDensity(Scalar temperature, Scalar pressure)
340 7709894 { return IdealGas::molarDensity(temperature, pressure); }
341
342 /*!
343 * \brief The density of pure heavyoil at a given pressure and temperature \f$\mathrm{[kg/m^3]}\f$.
344 *
345 * \param temperature temperature of component in \f$\mathrm{[K]}\f$
346 * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
347 */
348 static Scalar liquidDensity(Scalar temperature, Scalar pressure)
349 {
350
351 /* according to Lashanizadegan et al (2008) in Chemical Engineering Communications: */
352 /* Simultaneous Heat and Fluid Flow in Porous Media: Case Study: Steam Injection for Tertiary Oil Recovery */
353 7710010 constexpr Scalar rhoReference = 906.; // [kg/m^3] at reference pressure and temperature
354 7710010 constexpr Scalar compressCoeff = 1.e-8; // just a value without justification
355 7710010 constexpr Scalar expansCoeff = 1.e-7; // also just a value
356
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3855060 return rhoReference * (1. + (pressure - 1.e5)*compressCoeff) * (1. - (temperature - 293.)*expansCoeff);
357 }
358
359 /*!
360 * \brief The molar density of pure heavyoil in \f$\mathrm{[mol/m^3]}\f$ at a given pressure and temperature.
361 *
362 * \param temperature temperature of component in \f$\mathrm{[K]}\f$
363 * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
364 *
365 */
366 static Scalar liquidMolarDensity(Scalar temperature, Scalar pressure)
367 3854947 { return liquidDensity(temperature, pressure)/molarMass(); }
368
369 /*!
370 * \brief Returns true if the gas phase is assumed to be compressible
371 */
372 static constexpr bool gasIsCompressible()
373 { return true; }
374
375 /*!
376 * \brief Returns true if the gas phase is assumed to be ideal
377 */
378 static constexpr bool gasIsIdeal()
379 { return true; }
380
381 /*!
382 * \brief Returns true if the liquid phase is assumed to be compressible
383 */
384 static constexpr bool liquidIsCompressible()
385 { return true; }
386
387 /*!
388 * \brief The dynamic viscosity \f$\mathrm{[Pa*s]}\f$ of heavyoil vapor
389 *
390 * \param temperature temperature of component in \f$\mathrm{[K]}\f$
391 * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
392 */
393 3855057 static Scalar gasViscosity(Scalar temperature, Scalar pressure)
394 {
395 using std::clamp;
396
1/2
✓ Branch 0 taken 3855057 times.
✗ Branch 1 not taken.
3855057 temperature = clamp(temperature, 250.0, 500.0); // regularization
397
398 // reduced temperature
399 3855057 const Scalar Tr = temperature/criticalTemperature();
400
401 using std::pow;
402 using std::exp;
403 3855057 constexpr Scalar Fp0 = 1.0;
404 3855057 constexpr Scalar xi = 0.00474;
405 3855057 const Scalar eta_xi =
406 3855057 Fp0*(0.807*pow(Tr,0.618)
407 3855057 - 0.357*exp(-0.449*Tr)
408 3855057 + 0.34*exp(-4.058*Tr)
409 + 0.018);
410
411 3855057 return eta_xi/xi/1e7; // [Pa s]
412 }
413
414 /*!
415 * \brief The dynamic viscosity \f$\mathrm{[Pa*s]}\f$ of pure heavyoil.
416 *
417 * Lashanizadegan et al. (2008) \cite lashanizadegan2008 <BR>
418 *
419 * \param temperature temperature of component in \f$\mathrm{[K]}\f$
420 * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
421 */
422 static Scalar liquidViscosity(Scalar temperature, Scalar pressure)
423 {
424
425 /* according to Lashanizadegan et al (2008) in Chemical Engineering Communications: */
426 /* Simultaneous Heat and Fluid Flow in Porous Media: Case Study: Steam Injection for Tertiary Oil Recovery */
427
428 //using std::exp;
429 //return 1027919.422*exp(-0.04862*temperature); // [Pa s]
430
431 //according to http://www.ecltechnology.com/subsur/reports/pvt_tgb.pdf [Page 10]
432 3855057 const Scalar temperatureFahrenheit = (9/5)*(temperature-273.15)+32;
433 3855057 constexpr Scalar API = 9;
434
435 using std::pow;
436 using Dune::power;
437 3855057 return ((pow(10,0.10231*power(API,2)-3.9464*API+46.5037))*(pow(temperatureFahrenheit,-0.04542*power(API,2)+1.70405*API-19.18)))*0.001;
438
439 }
440 /*!
441 * \brief Specific heat cap of liquid heavyoil \f$\mathrm{[J/kg]}\f$.
442 *
443 * Lashanizadegan et al. (2008) \cite lashanizadegan2008 <BR>
444 *
445 * \param temperature temperature of component in \f$\mathrm{[K]}\f$
446 * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
447 *
448 */
449 static Scalar liquidHeatCapacity(const Scalar temperature,
450 const Scalar pressure)
451 {
452 return 618.; // J/(kg K)
453 }
454
455 /*!
456 * \brief Thermal conductivity \f$\mathrm{[[W/(m*K)]}\f$ of heavy oil
457 *
458 * Lashanizadegan et al. (2008) \cite lashanizadegan2008 <BR>
459 *
460 * \param temperature absolute temperature in \f$\mathrm{[K]}\f$
461 * \param pressure of the phase in \f$\mathrm{[Pa]}\f$
462 */
463 static Scalar liquidThermalConductivity( Scalar temperature, Scalar pressure)
464 {
465 return 0.127;
466 }
467 };
468
469 } // end namespace Dumux::Components
470
471 #endif
472