-
Couldn't load subscription status.
- Fork 65
HELD Implementation #371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
HELD Implementation #371
Conversation
|
The vscode examples are out of date and need the tp_flash_impl added I will push an update later. |
src/methods/property_solvers/multicomponent/tp_flash/HELD_flash.jl
Outdated
Show resolved
Hide resolved
src/methods/property_solvers/multicomponent/tp_flash/HELD_flash.jl
Outdated
Show resolved
Hide resolved
src/methods/property_solvers/multicomponent/tp_flash/HELD_flash.jl
Outdated
Show resolved
Hide resolved
| μ₀ = VT_chemical_potential(model,v₀,T,z₀) | ||
| λ₀ = (μ₀[1:nc-1] .- μ₀[nc])/R̄/T | ||
| # calculate reference volume based on Kays rule and vc[i] and scale to give water a vref/v ~ 1 | ||
| pure = split_model.(model) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| pure = split_model.(model) | |
| pure = split_pure_model(model) |
|
|
||
| function Projection(x,lb,ub) | ||
| n = size(x)[1] | ||
| p = Vector{Float64}(undef,n) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| p = Vector{Float64}(undef,n) | |
| p = Vector{Base.promote_eltype(x,lb,ub)}(undef,n) |
|
Hello, Some comments.
|
|
Yes I think the trust region stuff could easily go into the solvers. But note there is some specific structures to the projections for HELD and Gibbs's that are unique to the HELD code. If those are defined in the HELD code then it will work. As for JuMP if there is a way to change it that would be fine. We really only need a simplex method. I used a canned code from numerical recipes c++ that worked Any advice on optimisations appreciated. |
|
some specific optimization tips, some specific to Clapeyron, others more general:
Also, the specific return type for |
|
It looks like you can implement HiGHS without using JuMP: Not as pretty, but more reasonable? |
|
I will try to use the HiGHS API and remove JuMP I also found an annoying issue. I tested something that I thought as simple and it failed. This was air and water at 1.5 bar and 20 deg C. After a lot of frustration it turned out HELD could only solve it as water first then the air components. If the system was set up as air first then water at a certain moderately low water fraction the solver fails. It's comes up with an invalid lambda solution from the HiGHs solver that prevents the global solution. Once the components are rearranged in increasing mole fraction order it all works as expected. Finally the trust region solver loops is prefect for parallel solution. I'd like to implement that but it can be a future update. |
|
This is something I've noticed with our other solvers as well. When you have two phases with very low concentrations, it typically prefers solving for the compositions with the order of the species in a certain order. Aside from giving guidance in the docs, I don't quite know how to handle this best? |
|
You could sort the model in the following way: ix = sortperm(z)
model_sort = each_split_model(model, ix)An equivalent way is to, instead of doing |
|
Usingthe sorted model works but so far I have only one case where that needed to be done. Would be good to understand why its needed and if there are any other test cases that have a similar issue that we can test. For that same problematic case if you increase the water molefraction eventually it all works with no sorting. I have found that the associating components need to come first. This seems to be robust. However we may need some scaling as hessian can become ill conditioned for systems with small mole fractions. |
|
probably, one way check if the model sort is even necessary is to check the initial K-values, and if, for example , |
|
If have going through some testing that the statement in the original HELD paper that the initial M set can be proven to be all that's required to initiate the method is practically not true. There are some cases where for larger component sets this does not provide a good enough cutting plane. Also in the early phase of the solution when UB and LB are far apart you need all the LB solutions below the current UB otherwise you can get very poor cutting planes that case the method to fail. Once things are tighter to the approaching hyper plane solution the stated algorithm works robustly. |
|
Ok what I have found is during the OPxv phase the Lambdas are very loose early on. As such for small mole fraction components you can get a sudden large Lambda that prevents the IPxv phase from finding a minimum. The solution is to provide an upper and lower bound on the lambdas in the OPxv phase. This works but I have no way yet of knowing how to set this at the start. Certainly (G0 -Gi)/(x0 - xi) for the initial M set is a poor estimate. It's easy once I know the answer. |
|
Hello, I saw in some of your recent commits that you had some problems with the density solver used by GERG2008, is that right? i was just debugging #376, and there was indeed a problem with the initial value suggestions, but I'm interested if the cases are still failing (to add those cases into the test infrastructure) |
|
Hi I stopped using the Clapeyron volume solution and made my own. The issue I had was water at 28 barg and 30 deg C. The Clapeyron solver could not identify the correct volume. It turns out you need to identify the spinodal points and use these as criteria to select the correct root. The issue is the many Maxwell loops with water and selecting what looks like the minimum Gibbs and mechanically stable solution but they are inside the spinodal metastable region. I will post the test. |
|
Also I have made many improvements to HELD Code since my original PR. Not sure if you get these updates. Let me know if I need to do another PR so you can get them. The main one is moving the Trust Region to Clapeyron solvers and adding a trust region sub-problem solver that is more robust. It was make this update that I saw the issue with GERG2008 volumes. |
|
This is code that fails to solve using Clapeyron
components = ["carbon dioxide","nitrogen","water"]
model = GERG2008(components)
p = 64.0e5
T = 30+273.15
zs=[0.4975080785711593, 0.0049838428576813995]
z=append!(zs,1.0 - zs[1] - zs[2])
vol = volume(model,p,T,z)
mw = Clapeyron.molecular_weight(model,z)
println("mw = $(mw)")
rho = mw/vol
println("Volume = $(vol) rho = $(rho)")
rhom = mass_density(model,p,T,z)
println("rhom = $(rhom)")gives |
|
The answer should be Volume by HELD = 3.710503849983332e-5 m3/mol |
|
It was absolutely related, it works with with the most recent commit. an easier way to test this is to check if the value of Before: After |
|
Just as an observation for GERG2008. If you try to look at water at say 30 degrees C and 28 bar you will find the most stable volume including mechanical stability is a false root, at least from the reality of the required solution. This is because for compressed liquids the spinodal vapour root eventually disappears. For GERG2008 they probably don't care as it's a natural gas eos. But it's a pain if you want consistency across all pure components in a mixture. It means you can't dehydrate CO2 with compression and cooling. BTW false volume solutions cause a major problem to held as the initial M set is not on the true surface so the hyperplane solution comes up with a bad lambda solution. Saft eos,s seem to work well. My only issue is they are poor near the critical region and for CO2 this is important as we need to correctly predict near critical and super critical phase behaviour. I'm hoping for a cross over correction to SAFTVRMie may become available. |
|
Note the Clapeyron Volume solution seems to be OK. So its my solution method that is getting the wrong root. |
|
hmmm, if i remember correctly, false roots are vapour phases, right? if that is the case, and you are far from the mechanical critical point, maybe this criteria could help: function return_true_root(model,v_liquid,v_vapour,T,x)
gl = Clapeyron.VT0.gibbs_free_energy(model,v_liquid,T,x)
gv = Clapeyron.VT0.gibbs_free_energy(model,v_vapour,T,x)
if gv < gl
B = second_virial_coefficient(model,T,x)
if v_vapour < -2B #approximation of the spinodal, point when second order virial model diverges
#for low temps (< 0.9Tc) this should be true. for high temps, false roots tend to disappear.
return v_liquid
else
return v_vapour
end
else
return v_liquid
end
endAnother way would be to approximate the gas gibbs energy by a virial model, check if the gibbs energy of the tentative phase is within reasonable bounds. |
|
For the simplex method, I found this in julia: https://github.com/davidagold/simplex.jl/blob/master/simplex.jl Looks abandoned and coded in a very interesting way. Could we adapt it? |
clean_solution for vector norms
…x as this wasn't working for 8 comp water meoh
better vref method (neta like for all eos)
Need to add a_cr = fnc(T/Tc)*(ac/V + bc/V^2 + cc/V^3) to ares
HELD Implementation with vscode example cases. Note this current only implements tp_flash_impl in HELD_flash.jl and needs integrating into the flash code particularly tpflash and tpflash2 in PT.jl.
tp_flash_impl returns beta,xp,vp,Gsol which can be placed in the flash returns for tpflash and tpflash2
beta,xp,vp,Gsol = Clapeyron.tp_flash_impl(model,p,T,z, HELDTPFlash(verbose = verbose))
Please test and feed back any comments or improvements