Skip to content

Commit 730c37a

Browse files
authored
improve stability of crit_pure (#501)
* add modification to crit_pure * support multicomponent BACKSAFT * change serialized model to eos_repr created model * improve x0_sat_pure_virial when b constant is less than lb_volume
1 parent 9a659cf commit 730c37a

File tree

10 files changed

+325
-122
lines changed

10 files changed

+325
-122
lines changed
Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,47 @@
11
Clapeyron Database File
22
BACKSAFT Like Parameters
3-
species,DIPPR Number,Mw,segment,c,vol,epsilon,alpha,source
4-
argon,,16,1.0,1.0,12.08,149.2,1.0,
5-
nitrogen,,30,1.0,1.0,14.05,128.9,1.031,
6-
oxygen,,44,1.0,1.0,11.8,155.9,1.017,
7-
carbon dioxide,,44,1.348,10.0,10.95,324.3,1.067,
8-
methane,,44,1.0,1.0,15.93,191.2,1.012,
9-
ethane,,44,1.07,10.0,21.43,308.4,1.028,
10-
propane~|~n-propane,,44,1.24,10.0,25.46,387.4,1.051,
11-
butane~|~n-butane,,44,1.34,10.0,29.88,457.9,1.071,
12-
pentane~|~n-pentane,,44,1.446,10.0,33.8,517.6,1.083,
13-
hexane~|~n-hexane,,44,1.573,10.0,36.64,570.7,1.097,
14-
heptane~|~n-heptane,,44,1.682,10.0,39.65,617.8,1.108,
15-
octane~|~n-octane,,44,1.814,10.0,42.05,659.7,1.117,
16-
nonane~|~n-nonane,,44,1.905,10.0,45.06,698.0,1.123,
17-
decane~|~n-decane,,44,2.018,10.0,47.37,732.0,1.13,
18-
dodecane~|~n-dodecane,,44,2.255,10.0,55.1,787.5,1.137,
19-
tetradecane~|~n-tetradecane,,44,2.434,10.0,60.0,841.4,1.148,
20-
hexadecane~|~n-hexadecane,,44,2.524,10.0,65.61,893.9,1.157,
21-
octadecane~|~n-octadecane,,44,2.786,10.0,71.14,926.5,1.162,
22-
eicosane~|~n-eicosane,,44,3.039,10.0,84.15,950.9,1.163,
23-
isobutane~|~2-methylpropane,,44,1.319,10.0,30.69,435.8,1.066,
24-
isopentane~|~methylbutane~|~2-methylbutane,,44,1.411,10.0,34.33,501.0,1.073,
25-
"neopentane~|~2,2-dimethylpropane",,44,1.353,10.0,36.55,463.9,1.06,
26-
isohexane~|~2-methylpentane,,44,1.541,10.0,37.41,553.3,1.088,
27-
"2,2-dimethylbutane",,44,1.433,10.0,39.68,533.3,1.074,
28-
"2,3-dimethylbutane",,44,1.474,10.0,38.29,550.3,1.081,
29-
3-methylhexane~|~3-methyl-hexane,,44,1.64,10.0,39.68,606.0,1.1,
30-
3-ethylpentane,,44,1.623,10.0,40.02,609.0,1.096,
31-
"2,2-dimethylpentane",,44,1.563,10.0,41.93,581.1,1.09,
32-
"2,2,3-trimethylbutane~|~2,2,3-trimethyl-butane",,44,1.488,10.0,43.04,585.0,1.08,
33-
3-methylheptane,,44,1.742,10.0,43.01,647.4,1.11,
34-
"3,3-dimethylhexane",,44,1.645,10.0,44.35,635.5,1.096,
35-
2-methyl-3-ethylpentane~|~3-ethyl-2-methylpentane,,44,1.661,10.0,43.73,642.4,1.097,
36-
"2,2,3-trimethylpentane",,44,1.6,10.0,45.4,630.5,1.086,
37-
"2,3,3-trimethylpentane",,44,1.575,10.0,45.92,640.6,1.087,
38-
cyclopropane,,44,1.171,10.0,21.99,416.0,1.052,
39-
ethylcyclopentane,,44,1.55,10.0,38.48,632.4,1.085,
40-
ethene~|~ethylene~|~1-ethylene,,44,1.039,10.0,20.03,283.4,1.034,
41-
propene~|~propylene,,44,1.202,10.0,24.22,379.5,1.047,
42-
pentene~|~1-pentene,,44,1.424,10.0,32.21,510.3,1.082,
43-
ethine~|~ethyne~|~acetylene,,44,1.254,10.0,14.18,326.6,1.064,
44-
propyne~|~1-propyne~|~methylacetylene,,44,1.355,10.0,18.63,435.5,1.076,
45-
benzene,,44,1.403,10.0,28.7,615.8,1.078,
46-
toluene,,44,1.503,10.0,33.34,655.9,1.076,
47-
"pxylene~|~p-xylene~|~1,4-dimethylbenzene",,44,1.576,10.0,37.15,703.4,1.101,
3+
species,segment,c,vol,epsilon,alpha,source
4+
argon,1.0,1.0,12.08,149.2,1.0,10.1016/S0378-3812(01)00521-0
5+
nitrogen,1.0,1.0,14.05,128.9,1.031,10.1016/S0378-3812(01)00521-0
6+
oxygen,1.0,1.0,11.8,155.9,1.017,10.1016/S0378-3812(01)00521-0
7+
carbon dioxide,1.348,10.0,10.95,324.3,1.067,10.1016/S0378-3812(01)00521-0
8+
methane,1.0,1.0,15.93,191.2,1.012,10.1016/S0378-3812(01)00521-0
9+
ethane,1.07,10.0,21.43,308.4,1.028,10.1016/S0378-3812(01)00521-0
10+
propane~|~n-propane,1.24,10.0,25.46,387.4,1.051,10.1016/S0378-3812(01)00521-0
11+
butane~|~n-butane,1.34,10.0,29.88,457.9,1.071,10.1016/S0378-3812(01)00521-0
12+
pentane~|~n-pentane,1.446,10.0,33.8,517.6,1.083,10.1016/S0378-3812(01)00521-0
13+
hexane~|~n-hexane,1.573,10.0,36.64,570.7,1.097,10.1016/S0378-3812(01)00521-0
14+
heptane~|~n-heptane,1.682,10.0,39.65,617.8,1.108,10.1016/S0378-3812(01)00521-0
15+
octane~|~n-octane,1.814,10.0,42.05,659.7,1.117,10.1016/S0378-3812(01)00521-0
16+
nonane~|~n-nonane,1.905,10.0,45.06,698.0,1.123,10.1016/S0378-3812(01)00521-0
17+
decane~|~n-decane,2.018,10.0,47.37,732.0,1.13,10.1016/S0378-3812(01)00521-0
18+
dodecane~|~n-dodecane,2.255,10.0,55.1,787.5,1.137,10.1016/S0378-3812(01)00521-0
19+
tetradecane~|~n-tetradecane,2.434,10.0,60.0,841.4,1.148,10.1016/S0378-3812(01)00521-0
20+
hexadecane~|~n-hexadecane,2.524,10.0,65.61,893.9,1.157,10.1016/S0378-3812(01)00521-0
21+
octadecane~|~n-octadecane,2.786,10.0,71.14,926.5,1.162,10.1016/S0378-3812(01)00521-0
22+
eicosane~|~n-eicosane,3.039,10.0,84.15,950.9,1.163,10.1016/S0378-3812(01)00521-0
23+
isobutane~|~2-methylpropane,1.319,10.0,30.69,435.8,1.066,10.1016/S0378-3812(01)00521-0
24+
isopentane~|~methylbutane~|~2-methylbutane,1.411,10.0,34.33,501.0,1.073,10.1016/S0378-3812(01)00521-0
25+
"neopentane~|~2,2-dimethylpropane",1.353,10.0,36.55,463.9,1.06,10.1016/S0378-3812(01)00521-0
26+
isohexane~|~2-methylpentane,1.541,10.0,37.41,553.3,1.088,10.1016/S0378-3812(01)00521-0
27+
"2,2-dimethylbutane",1.433,10.0,39.68,533.3,1.074,10.1016/S0378-3812(01)00521-0
28+
"2,3-dimethylbutane",1.474,10.0,38.29,550.3,1.081,10.1016/S0378-3812(01)00521-0
29+
3-methylhexane~|~3-methyl-hexane,1.64,10.0,39.68,606.0,1.1,10.1016/S0378-3812(01)00521-0
30+
3-ethylpentane,1.623,10.0,40.02,609.0,1.096,10.1016/S0378-3812(01)00521-0
31+
"2,2-dimethylpentane",1.563,10.0,41.93,581.1,1.09,10.1016/S0378-3812(01)00521-0
32+
"2,2,3-trimethylbutane~|~2,2,3-trimethyl-butane",1.488,10.0,43.04,585.0,1.08,10.1016/S0378-3812(01)00521-0
33+
3-methylheptane,1.742,10.0,43.01,647.4,1.11,10.1016/S0378-3812(01)00521-0
34+
"3,3-dimethylhexane",1.645,10.0,44.35,635.5,1.096,10.1016/S0378-3812(01)00521-0
35+
2-methyl-3-ethylpentane~|~3-ethyl-2-methylpentane,1.661,10.0,43.73,642.4,1.097,10.1016/S0378-3812(01)00521-0
36+
"2,2,3-trimethylpentane",1.6,10.0,45.4,630.5,1.086,10.1016/S0378-3812(01)00521-0
37+
"2,3,3-trimethylpentane",1.575,10.0,45.92,640.6,1.087,10.1016/S0378-3812(01)00521-0
38+
cyclopropane,1.171,10.0,21.99,416.0,1.052,10.1016/S0378-3812(01)00521-0
39+
ethylcyclopentane,1.55,10.0,38.48,632.4,1.085,10.1016/S0378-3812(01)00521-0
40+
ethene~|~ethylene~|~1-ethylene,1.039,10.0,20.03,283.4,1.034,10.1016/S0378-3812(01)00521-0
41+
propene~|~propylene,1.202,10.0,24.22,379.5,1.047,10.1016/S0378-3812(01)00521-0
42+
pentene~|~1-pentene,1.424,10.0,32.21,510.3,1.082,10.1016/S0378-3812(01)00521-0
43+
ethine~|~ethyne~|~acetylene,1.254,10.0,14.18,326.6,1.064,10.1016/S0378-3812(01)00521-0
44+
propyne~|~1-propyne~|~methylacetylene,1.355,10.0,18.63,435.5,1.076,10.1016/S0378-3812(01)00521-0
45+
benzene,1.403,10.0,28.7,615.8,1.078,10.1016/S0378-3812(01)00521-0
46+
toluene,1.503,10.0,33.34,655.9,1.076,10.1016/S0378-3812(01)00521-0
47+
"pxylene~|~p-xylene~|~1,4-dimethylbenzene",1.576,10.0,37.15,703.4,1.101,10.1016/S0378-3812(01)00521-0

docs/src/api/parameters.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,8 @@ Clapeyron.xlogx
9494
## Model Exporting
9595

9696
```@docs
97+
Clapeyron.eos_repr
9798
Clapeyron.export_model
98-
Clapeyron.FluidCorrelation
99-
Clapeyron.GammaPhi
100-
Clapeyron.ECS
10199
```
102100

103101
## Model Citing

src/base/eosshow.jl

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,79 @@ function show_reference_state(io::IO,ref,model::EoSModel,space)
115115
end
116116
end
117117

118-
export eosshow
118+
"""
119+
eos_repr(io::IO,model,newlines = true)
120+
eos_repr(model;newlines = true)::String
121+
122+
Given a `model::EoSModel`, returns a copy-pastable text representation of that model, designed to be parseable julia code.
123+
By default, `eos_repr` inserts some newlines for easier human reading of the output, that can be disabled via the `newlines` keyword argument.
124+
125+
## Examples:
126+
127+
```julia-repr
128+
julia> model = PCSAFT("methane")
129+
PCSAFT{BasicIdeal, Float64} with 1 component:
130+
"methane"
131+
Contains parameters: Mw, segment, sigma, epsilon, epsilon_assoc, bondvol
132+
133+
julia> push!(model.references,"test")
134+
3-element Vector{String}:
135+
"10.1021/ie0003887"
136+
"10.1021/ie010954d"
137+
"test"
138+
139+
julia> s = eos_repr(model);
140+
141+
julia> model2 = eval(Meta.parse(s)) #exactly the same model
142+
PCSAFT{BasicIdeal, Float64} with 1 component:
143+
"methane"
144+
Contains parameters: Mw, segment, sigma, epsilon, epsilon_assoc, bondvol
145+
146+
julia> model2.references
147+
3-element Vector{String}:
148+
"10.1021/ie0003887"
149+
"10.1021/ie010954d"
150+
"test"
151+
```
152+
"""
153+
function eos_repr(io::IO,model;inside = false,newlines = true)
154+
M = typeof(model)
155+
n = fieldnames(M)
156+
newlines && print(io,"\n")
157+
print(io,M)
158+
print(io,"(")
159+
if !inside && newlines
160+
print(io,"\n")
161+
end
162+
k = 0
163+
nf = length(n)
164+
for i in n
165+
k += 1
166+
f = getfield(model,i)
167+
F = typeof(f)
168+
if F.name.module == Clapeyron || F isa EoSModel
169+
eos_repr(io,f,inside = true)
170+
elseif f isa PackedVofV
171+
print(io,"Clapeyron.PackedVofV(")
172+
show(io,f.p)
173+
print(io,", ")
174+
show(io,f.v)
175+
print(io,")")
176+
else
177+
show(io,f)
178+
end
179+
k != nf && print(io,", ")
180+
end
181+
print(io,")")
182+
183+
184+
return nothing
185+
end
186+
187+
function eos_repr(model;newlines = false)
188+
io = IOBuffer()
189+
eos_repr(io,model;newlines)
190+
return String(take!(io))
191+
end
192+
193+
export eosshow, eos_repr

src/methods/initial_guess.jl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ function x0_sat_pure_virial(model,T)
267267
=#
268268

269269
a,b = vdw_coefficients(vl,pl0,vv_virial,pv_eos,T)
270+
if b < lb_v
271+
b = lb_v
272+
a = RT*(b - B)
273+
end
270274
= RT*b/a
271275
T̃max = 0.2962962962962963 # Ωb/Ωa = 8/27
272276
T̃min = 0.1*T̃max
@@ -381,8 +385,13 @@ function x0_sat_pure_near0(model, T, vl0 = volume(model,zero(T),T,phase = :l);B
381385
ares = a_res(model, vl0, T, z)
382386
lnϕ_liq0 = ares - 1 + log(RT/vl0)
383387
p = exp(lnϕ_liq0)
384-
vv = volume_virial(B,p,T)
385388
pB = -0.25*RT/B
389+
if lnϕ_liq0 < log(eps(eltype(T)))
390+
p = oneunit(p)*0.5*pB
391+
vl0 = volume(model,p,T,z,vol0 = vl0,phase = :l)
392+
end
393+
vv = volume_virial(B,p,T)
394+
386395
if refine_vl && pB/p > 10
387396
vl = volume(model,p,T,z,vol0 = vl0,phase = :l)
388397
else

src/methods/property_solvers/singlecomponent/crit_pure.jl

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,44 +19,67 @@ function crit_pure(model::EoSModel)
1919
end
2020
end
2121

22+
23+
function crit_x_to_v(lbv,x)
24+
lo = 0.001
25+
hi = 1.0
26+
η = lo + (hi - lo)/(exp(-x) + 1)
27+
return lbv/η
28+
end
29+
30+
function crit_v_to_x(lbv,v)
31+
η = lbv/v
32+
lo = 0.001
33+
hi = 1.0
34+
return -log((hi - lo)/- lo) - 1)
35+
end
36+
2237
function crit_pure(model::EoSModel,x0,z = SA[1.0];options = NEqOptions())
2338
check_arraysize(model,z)
2439
#f! = (F,x) -> obj_crit(model, F, x[1]*T̄, exp10(x[2]))
40+
zp = primalval(z)
41+
primalmodel = primalval(model)
2542
if x0 === nothing
26-
x0 = x0_crit_pure(model,z)
43+
x0 = x0_crit_pure(primalmodel,zp)
2744
end
2845
x01,x02 = x0
29-
= T_scale(model,z)*one(x01*one(x02))
30-
#if type !== nothing
31-
# T̄ = T̄*oneunit(type)
32-
#end
46+
= T_scale(primalmodel,zp)*one(x01*one(x02))
47+
Tc0 = x01*
48+
lbv0 = lb_volume(primalmodel,Tc0,zp)
3349
_1 = oneunit(T̄)
34-
#x0 = SVector(_1*x01,_1*x02)
35-
x0 = vec2(primalval(x01),primalval(x02*log(10)),primalval(_1))
36-
primalmodel = primalval(model)
50+
Tx0 = primalval(x01)
51+
vc0 = exp10(primalval(x02))
52+
x0 = vec2(Tx0,crit_v_to_x(lbv0,vc0),_1)
3753
zz = z/sum(z)
3854
f!(F,x) = ObjCritPure(primalmodel,F,primalval(T̄),x,zz)
3955
solver_res = Solvers.nlsolve(f!, x0, TrustRegion(Newton(), NLSolvers.NWI()), options)
40-
#display(solver_res)
4156
r = Solvers.x_sol(solver_res)
57+
!all(<(solver_res.options.f_abstol),solver_res.info.best_residual) && (r .= NaN)
4258
T_c = r[1]*
43-
V_c = exp(r[2])
59+
lbv = lb_volume(primalmodel,T_c,z)
60+
V_c = crit_x_to_v(lbv,r[2])
4461
p_c = pressure(model, V_c, T_c, zz)
62+
if p_c < 0
63+
p_c *= NaN
64+
V_c *= NaN
65+
T_c *= NaN
66+
end
4567
crit = (T_c, p_c, V_c)
4668
return crit_pure_ad(model,crit,z)
4769
end
4870

4971
function crit_pure_ad(model,crit,z)
50-
if has_dual(model)
72+
if has_dual(model) || has_dual(z)
5173
T_c_primal, p_c_primal, V_c_primal = crit
5274
= T_scale(model)
53-
x = SVector(T_c_primal/T̄,log(V_c_primal))
54-
f(zz) = __ObjCritPure(model,T̄,z,zz)
75+
lbv = lb_volume(model,T̄,z)
76+
x = SVector(T_c_primal/T̄,crit_v_to_x(lbv,V_c_primal))
77+
f(zz) = __ObjCritPure(model,T̄,z,zz,lbv)
5578
F,J = Solvers.J2(f,x)
5679
∂x = J\F
5780
r = x .- ∂x
5881
T_c = r[1]*
59-
V_c = exp(r[2])
82+
V_c = crit_x_to_v(lbv,r[2])
6083
P_c = pressure(model,V_c,T_c,z)
6184
return (T_c,P_c,V_c)
6285
else
@@ -71,9 +94,10 @@ function ObjCritPure(model::T,F,T̄,x,z) where T
7194
return F
7295
end
7396

74-
function __ObjCritPure(model::T,T̄,x,z) where T
97+
function __ObjCritPure(model::T,T̄,x,z,) where T
7598
T_c = x[1]*
76-
V_c = exp(x[2])
99+
lbv = lb_volume(model,T_c,z)
100+
V_c = crit_x_to_v(lbv,x[2])
77101
RT = Rgas(model)*T_c
78102
∂²A∂V²_scale = V_c*V_c/RT
79103
∂³A∂V³_scale = ∂²A∂V²_scale*V_c

src/methods/property_solvers/singlecomponent/saturation/ChemPotV.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
atol = 1e-8,
1111
rtol = 1e-12,
1212
max_iters = 10^4)
13-
Default `saturation_pressure` Saturation method used by `Clapeyron.jl`. It uses equality of Chemical Potentials with a volume basis. If no volumes are provided, it will use [`x0_sat_pure`](@ref).
14-
If those initial guesses fail and the specification is near critical point, it will try one more time, using Corresponding States instead.
15-
when `crit_retry` is true, if the initial solve fail, it will try to obtain a better estimate by calculating the critical point.
13+
Default `saturation_pressure` Saturation method used by `Clapeyron.jl`.
14+
It uses equality of Chemical Potentials with a volume basis.
15+
If no volumes are provided, it will use [`x0_sat_pure`](@ref).
16+
When `crit_retry` is true, if the initial solve fail, it will try to obtain a better estimate by calculating the critical point.
1617
`f_limit`, `atol`, `rtol`, `max_iters` are passed to the non linear system solver.
1718
"""
1819
struct ChemPotVSaturation{T,C} <: SaturationMethod

0 commit comments

Comments
 (0)