33#ifndef DUMUX_PENG_ROBINSON_HH
34#define DUMUX_PENG_ROBINSON_HH
36#include <dune/common/math.hh>
58template <
class Scalar>
65 static void init(Scalar aMin, Scalar aMax,
int na,
66 Scalar bMin, Scalar bMax,
int nb)
73 Scalar VmCrit = 18e-6;
76 for (
int i = 0; i < na; ++i) {
78 for (
int j = 0; j < nb; ++j) {
100 template <
class Params>
103 using Component =
typename Params::Component;
104 if (T >= Component::criticalTemperature())
105 return Component::criticalPressure();
109 const Scalar eps = Component::criticalPressure()*1e-10;
116 for (
int i = 0; i < 5; ++i) {
118 assert(molarVolumes(Vm, params, T, pVap) == 3);
127 Scalar delta = f/df_dp;
130 if (abs(delta/pVap) < 1e-10)
155 template <
class Flu
idState,
class Params>
160 bool handleUnphysicalPhase =
true)
164 Scalar T = fs.temperature(phaseIdx);
165 Scalar p = fs.pressure(phaseIdx);
167 Scalar a = params.a(phaseIdx);
168 Scalar b = params.b(phaseIdx);
171 Scalar Astar = a*p/(RT*RT);
172 Scalar Bstar = b*p/RT;
175 Scalar a2 = - (1 - Bstar);
176 Scalar a3 = Astar - Bstar*(3*Bstar + 2);
177 Scalar a4 = Bstar*(- Astar + Bstar*(1 + Bstar));
187 if (numSol > 1 && Z[0] <= 0.0) {
188 Z[0] = Z[numSol - 1];
192 if (numSol > 0 && Z[0] <= 0)
204 else if (numSol == 1) {
210 if (handleUnphysicalPhase)
214 DUNE_THROW(
NumericalProblem,
"Unexpected number of roots in the equation for compressibility factor: " << numSol);
218 if (!isfinite(Vm) || Vm <= 0)
230 template <
class Params>
248 template <
class Params>
251 Scalar T = params.temperature();
252 Scalar p = params.pressure();
253 Scalar Vm = params.molarVolume();
257 Scalar Bstar = p*params.b() / RT;
260 (Vm + params.b()*(1 + sqrt(2))) /
261 (Vm + params.b()*(1 - sqrt(2)));
262 Scalar expo = - params.a()/(RT * 2 * params.b() * sqrt(2));
266 exp(Z - 1) / (Z - Bstar) *
282 template <
class Params>
284 {
return params.pressure()*computeFugacityCoeff(params); }
294 template <
class Flu
idState,
class Params>
296 const FluidState &fs,
297 const Params ¶ms,
301 Scalar T = fs.temperature(phaseIdx);
312 Scalar Vmin, Vmax, pmin, pmax;
316 params.a(phaseIdx), params.b(phaseIdx), T))
317 return isGasPhase ? max(Vmax, Vm) : min(Vmin, Vm);
322 template <
class Flu
idState,
class Params>
324 const FluidState &fs,
325 const Params ¶ms,
333 return isGasPhase ? max(Vm, Vcrit) : min(Vm, Vcrit);
351 for (
int i = 0; i < 30; ++i) {
352 bool hasExtrema =
findExtrema_(minVm, maxVm, minP, maxP, a, b, Tmin);
362 for (
int i = 0; i < 25; ++i) {
364 Scalar f = maxVm - minVm;
369 pcrit = (minP + maxP)/2;
370 Vcrit = (maxVm + minVm)/2;
378 const Scalar eps = - 1e-8;
379 [[maybe_unused]]
bool hasExtrema =
findExtrema_(minVm, maxVm, minP, maxP, a, b, T + eps);
381 Scalar fStar = maxVm - minVm;
386 Scalar fPrime = (fStar - f)/eps;
389 Scalar delta = f/fPrime;
395 for (
int j = 0; ; ++j) {
398 "Could not determine the critical point for a=" << a <<
", b=" << b);
401 if (
findExtrema_(minVm, maxVm, minP, maxP, a, b, T - delta)) {
431 Scalar a2 = 2*RT*u*b - 2*a;
432 Scalar a3 = 2*RT*w*b*b + RT*u*u*b*b + 4*a*b - u*a*b;
433 Scalar a4 = 2*RT*u*w*b*b*b + 2*u*a*b*b - 2*a*b*b;
434 Scalar a5 = RT*w*w*b*b*b*b - u*a*b*b*b;
444 for (
int i = 0; abs(delta) > 1e-9; ++i) {
445 Scalar f = a5 + V*(a4 + V*(a3 + V*(a2 + V*a1)));
446 Scalar fPrime = a4 + V*(2*a3 + V*(3*a2 + V*4*a1));
448 if (abs(fPrime) < 1e-20) {
469 Scalar b2 = a2 + V*b1;
470 Scalar b3 = a3 + V*b2;
471 Scalar b4 = a4 + V*b3;
479 std::sort(allV + 0, allV + numSol);
482 if (allV[numSol - 2] < b) {
490 Vmin = allV[numSol - 2];
491 Vmax = allV[numSol - 1];
505 template <
class Params>
508 using Component =
typename Params::Component;
510 Scalar Tr = T / Component::criticalTemperature();
512 Scalar omega = Component::acentricFactor();
515 Scalar f0 = (tau*(-5.97616 + sqrt(tau)*(1.29874 - tau*0.60394)) - 1.06841*power(tau, 5))/Tr;
516 Scalar f1 = (tau*(-5.03365 + sqrt(tau)*(1.11505 - tau*5.41217)) - 7.46628*power(tau, 5))/Tr;
517 Scalar f2 = (tau*(-0.64771 + sqrt(tau)*(2.41539 - tau*4.26979)) + 3.25259*power(tau, 5))/Tr;
519 return Component::criticalPressure()*exp(f0 + omega * (f1 + omega*f2));
532 template <
class Params>
538 {
return fugacity(params, T, p, VmLiquid) - fugacity(params, T, p, VmGas); }
545template <
class Scalar>
548template <
class Scalar>
551template <
class Scalar>
Some exceptions thrown in DuMux
Define some often used mathematical functions.
Implements tabulation for a two-dimensional function.
This is a fluid state which allows to set the fluid temperatures and takes all other quantities from ...
Relations valid for an ideal gas.
int invertCubicPolynomial(SolContainer *sol, Scalar a, Scalar b, Scalar c, Scalar d, std::size_t numPostProcessIterations=1)
Invert a cubic polynomial analytically.
Definition: math.hh:252
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
Exception thrown if a fixable numerical problem occurs.
Definition: exceptions.hh:39
Implements tabulation for a two-dimensional function.
Definition: tabulated2dfunction.hh:48
A central place for various physical constants occurring in some equations.
Definition: constants.hh:39
Implements the Peng-Robinson equation of state for liquids and gases.
Definition: pengrobinson.hh:60
static Scalar criticalTemperature(const Params ¶ms)
Returns the critical temperature for a given mix.
Definition: pengrobinson.hh:231
static Scalar handleSingleRoot_(Scalar Vm, const FluidState &fs, const Params ¶ms, int phaseIdx, bool isGasPhase)
Definition: pengrobinson.hh:295
static Scalar fugacityDifference_(const Params ¶ms, Scalar T, Scalar p, Scalar VmLiquid, Scalar VmGas)
Returns the difference between the liquid and the gas phase fugacities in [bar].
Definition: pengrobinson.hh:533
static Scalar computeMolarVolume(const FluidState &fs, Params ¶ms, int phaseIdx, bool isGasPhase, bool handleUnphysicalPhase=true)
Computes molar volumes where the Peng-Robinson EOS is true.
Definition: pengrobinson.hh:156
static Tabulated2DFunction< Scalar > criticalPressure_
Definition: pengrobinson.hh:541
static void init(Scalar aMin, Scalar aMax, int na, Scalar bMin, Scalar bMax, int nb)
Definition: pengrobinson.hh:65
static Tabulated2DFunction< Scalar > criticalMolarVolume_
Definition: pengrobinson.hh:542
static bool findExtrema_(Scalar &Vmin, Scalar &Vmax, Scalar &pMin, Scalar &pMax, Scalar a, Scalar b, Scalar T)
Definition: pengrobinson.hh:415
static void findCriticalPoint_(Scalar &Tcrit, Scalar &pcrit, Scalar &Vcrit, Scalar a, Scalar b)
Definition: pengrobinson.hh:336
static Scalar computeFugacity(const Params ¶ms)
Returns the fugacity coefficient for a given pressure and molar volume.
Definition: pengrobinson.hh:283
static Scalar ambroseWalton_(const Params ¶ms, Scalar T)
The Ambrose-Walton method to estimate the vapor pressure.
Definition: pengrobinson.hh:506
static Scalar handleCriticalFluid_(Scalar Vm, const FluidState &fs, const Params ¶ms, int phaseIdx, bool isGasPhase)
Definition: pengrobinson.hh:323
static Tabulated2DFunction< Scalar > criticalTemperature_
Definition: pengrobinson.hh:540
static Scalar computeVaporPressure(const Params ¶ms, Scalar T)
Predicts the vapor pressure for the temperature given in setTP().
Definition: pengrobinson.hh:101
static Scalar computeFugacityCoeffient(const Params ¶ms)
Returns the fugacity coefficient for a given pressure and molar volume.
Definition: pengrobinson.hh:249