This is Part 6 of a series.
In Part 5, I implemented a basic flash algorithm and applied it to around 130 pTxy literature data for (methane + helium), with 90% of cases giving acceptable results. Before addressing the failures in the flash, I want to investigate modifying the critical constants of helium and how that affects the Helmholtz EOS.
In [1], we found that changing the critical constants of helium in the Peng-Robinson EOS improved significantly the predictions of fluid phase equilibria of mixtures involving helium. In [2], Messerly et al. calculated the critical parameters of 'classical' helium but didn't investigate the effect on mixture predictions. The alternate parameter sets are given below.
Reference | pc /MPa | Tc /K | ρc /kmol.m−3 |
---|---|---|---|
Kunz et al. [3] | 0.226 | 5.1953 | 17.399 |
Rowland et al. [1] | 0.568 | 11.73 | — |
Messerly et al. [2] | 0.93 | 13.0 | 28.4 |
Critical density and critical temperature are key quantities in the GERG-2008 EOS [3].
In the first part of this series
I implemented models for the Helmholtz energy of pure fluids from the GERG-2008 EOS.
For pure fluids, these models depend on critical parameters through
δ = ρ/ρc and τ = Tc/T.
The k-th polynomial-type term contributes to the Helmholtz energy
like this:
nk ×
(ρ/ρc)^dk ×
(Tc/T)^tk
If a different set of critical parameters are used, say ρe
and Te, new EOS parameters (nk, dk,
tk) must be found. However, altering dk or
tk would alter the functional form and mean that the amounts
contributed to the Helmholtz energy would differ at the same ρ and T.
Therefore the only change must come from nk. I find the new
coefficients n*k by rearranging the following equation
nk ×
(ρ/ρc)^dk ×
(Tc/T)^tk =
n*k ×
(ρ/ρe)^dk ×
(Te/T)^tk
to arrive at a relationship giving the new coefficients in terms of old:
n*k = nk ×
(ρe/ρc)^dk ×
(Tc/Te)^tk
The other key expressions in the residual Helmholtz energy are of exponential-type:
nk ×
(ρ/ρc)^dk ×
(Tc/T)^tk ×
exp[−(ρ/ρc)^ck]
As before, the introduction of new critical parameters must not change
the Helmholtz energy. Due to the presence of the exponential function, this
is more complicated than above and requires introducing a
new parameter γ*k:
n*k ×
(ρ/ρe)^dk ×
(Te/T)^tk ×
exp[−γ*k(ρ/ρe)^ck]
where n*k and nk are related as above and
γ*k = (ρe/ρc)^ck.
To accomodate this new parameter, I'll add it to the FluidComponent
struct and set it to unity for unmodified fluids. Then the function for the
reduced residual Helmholtz energy due to exponential-type terms changes from
function αʳ(δ,τ,n,d,t,c)
return sum(@.(n*δ^d*τ^t*exp(-δ^c)))
end
to
function αʳ(δ,τ,n,d,t,γ,c)
return sum(@.(n*δ^d*τ^t*exp(-γ*δ^c)))
end
As I'm relying on Automatic Differentiation to compute the
derivatives, that's practically the only change required. With the changes in,
the existing unit tests pass as before :).
The final pure component parameters to deal with occur
in the ideal contribution to the Helmholtz energy. For helium, the functional
form is simple [3]:
log(ρ/ρc)
+ n1
+ n2Tc/T
+ n3log(Tc/T)
which will become
log(ρ/ρe)
+ n*1
+ n*2Te/T
+ n3log(Te/T)
upon substitution of n*1 = log(ρe/ρc)
+ n1 + n3log(Tc/Te), and
n*2 = n2Tc/Te.
Fluids other than helium have a more complicated ideal contribution to
the Helmholtz energy, including terms like [3]
nk ×
ln[|sinh(vkTc/T)|]
These are dealt with by setting v*k = vkTc/Te
and leaving nk as-is.
At last, the function that sets new critical parameters and adjusts the parameters in the
EOS for a pure fluid looks like:
function new_critical!(fluid::FluidComponent,pc,Tc,ρc)
ρr = ρc/fluid.ρc
Tr = fluid.Tc/Tc
fluid.pc = pc
fluid.Tc = Tc
fluid.ρc = ρc
# ideal contribution
fluid.ni[1] += log(ρr) + fluid.ni[3]*log(Tr)
fluid.ni[2] *= Tr
@. fluid.vi *= Tr
# residual contribution
@. fluid.np *= ρr^fluid.dp * Tr^fluid.tp
@. fluid.ne *= ρr^fluid.de * Tr^fluid.te
@. fluid.γe *= ρr^fluid.ce
return fluid
end
and the following unit tests confirm things are working correctly:
@testset "critical parameters (helium)" begin
T = 300.0
p = 1.e5
x = [1.0]
helium = AdvancedThermo.get_fluid_component("helium")
m = AdvancedThermo.create_mixture([helium])
da = AdvancedThermo.derivatives_of_a(m,AdvancedThermo.ρ(m,p,T,x),T,x)
pc = 0.93e6
Tc = 13.0
ρc = 28.4e3
helium_new = AdvancedThermo.get_fluid_component("helium")
helium_new = AdvancedThermo.new_critical!(helium_new,pc,Tc,ρc)
m_new = AdvancedThermo.create_mixture([helium_new])
da_new = AdvancedThermo.derivatives_of_a(m_new,AdvancedThermo.ρ(m_new,p,T,x),T,x)
# compare Helmholtz energy and derivatives (new vs. old)
tol = 1.e-13
val = DiffResults.value(da)
val_new = DiffResults.value(da_new)
grad = DiffResults.gradient(da)
grad_new = DiffResults.gradient(da_new)
hess = DiffResults.hessian(da)
hess_new = DiffResults.hessian(da_new)
@test abs((val-val_new)/val)<tol
@test abs((grad[1]-grad_new[1])/grad[1])<tol
@test abs((grad[2]-grad_new[2])/grad[2])<tol
@test abs((grad[3]-grad_new[3])/grad[3])<tol
@test abs((hess[1,1]-hess_new[1,1])/hess[1,1])<tol
@test abs((hess[1,2]-hess_new[1,2])/hess[1,2])<tol
@test abs((hess[1,3]-hess_new[1,3])/hess[1,3])<tol
@test abs((hess[2,2]-hess_new[2,2])/hess[2,2])<tol
@test abs((hess[2,3]-hess_new[2,3])/hess[2,3])<tol
@test abs((hess[3,3]-hess_new[3,3])/hess[3,3])<tol
end
@testset "critical parameters (methane)" begin
T = 300.0
p = 1.e5
x = [1.0]
methane = AdvancedThermo.get_fluid_component("methane")
m = AdvancedThermo.create_mixture([methane])
da = AdvancedThermo.derivatives_of_a(m,AdvancedThermo.ρ(m,p,T,x),T,x)
pc = 5.0e6
Tc = 192.0
ρc = 10.0e3
methane_new = AdvancedThermo.get_fluid_component("methane")
methane_new = AdvancedThermo.new_critical!(methane_new,pc,Tc,ρc)
m_new = AdvancedThermo.create_mixture([methane_new])
da_new = AdvancedThermo.derivatives_of_a(m_new,AdvancedThermo.ρ(m_new,p,T,x),T,x)
# compare Helmholtz energy and derivatives (new vs. old)
tol = 5.e-13
val = DiffResults.value(da)
val_new = DiffResults.value(da_new)
grad = DiffResults.gradient(da)
grad_new = DiffResults.gradient(da_new)
hess = DiffResults.hessian(da)
hess_new = DiffResults.hessian(da_new)
@test abs((val-val_new)/val)<tol
@test abs((grad[1]-grad_new[1])/grad[1])<tol
@test abs((grad[2]-grad_new[2])/grad[2])<tol
@test abs((grad[3]-grad_new[3])/grad[3])<tol
@test abs((hess[1,1]-hess_new[1,1])/hess[1,1])<tol
@test abs((hess[1,2]-hess_new[1,2])/hess[1,2])<tol
@test abs((hess[1,3]-hess_new[1,3])/hess[1,3])<tol
@test abs((hess[2,2]-hess_new[2,2])/hess[2,2])<tol
@test abs((hess[2,3]-hess_new[2,3])/hess[2,3])<tol
@test abs((hess[3,3]-hess_new[3,3])/hess[3,3])<tol
end
I call this a great success! The code so far can be obtained by downloading the zip file. Now that I have a proven way to modify the critical parameters for a pure fluid, the next part of the series will examine the effect on mixtures with helium.
[1] Rowland et al., J. Chem. Eng. Data, 2017, 62, 2799 (link to publisher)
[2] Messerly et al., J. Chem. Eng. Data, 2020, 65, 1028 (link to publisher)
[3] Kunz et al., GERG Technical Monograph 15: The GERG-2004 Wide-Range Equation of State for Natural Gases and Other Mixtures, Groupe Européen de Recherches Gazières, 2007
Go to Home | How to cite this page | Permalink to this page |