-
Notifications
You must be signed in to change notification settings - Fork 301
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
Catch singular explosions in saturation_PHSU_pure #2250
Conversation
Sometimes, the Akasaka solver has issues. This is usually caught and then it is retried with a new omega. However, sometimes it goes bad because the J matrix is singular, and this is not caught because the error is not recalculated. This commit recalculates the error term to prevent a bad result.
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.
Maybe it would be a good idea to explain your intent of recomputing the error as a code comment? I don't fully understand the problem, but based on the message in your PR, it sounds like this extra check is superfluous provided that the Akasaka solver's Jacobian works as expected. When that issue is addressed in the future, I'm hoping that my proposed comment could be a reminder that the changes you made here could be omitted to cut out the extra error calculation you described. Just a thought.
Those additional checks should be very cheap, so if this fixes the iteration failures then I would say we should merge them. |
But I also agree with @danielkwalsh that a few comments would be good |
I added a comment which I hope captures what you think should be communicated. If I am off, please let me know. |
@msaitta-mpr yeah, I think this looks great. Thanks for adding this! |
@ibell @msaitta-mpr Seems like there are two tests that are failing. Is that expected? |
These also fail in the master branch. I have been meaning to track down the cause and fix it, but I haven't had a chance. |
Should I go ahead and merge, or wait? |
On a hunch, I reran my test case with much greater point density and found that there are still a few points that do not behave. So, while the PR has so far fixed a lot of these issues, there is still some underlying issue. I will try to look into it. I think it makes sense to leave the PR open for the moment. Hopefully these commits can serve as an interim patch for users who need a quick fix. |
Hmm that's weird. I wonder what is going on. If this improves this, it might be worth it to merge it. But I also wonder whether there is something wrong with the ancillary functions it fails so hard. I don't recall similar problems with other EOS. |
@ibell @msaitta-mpr Have we assessed whether this is an ammonia-specific issue, or does it exist for other fluids as well? |
Surprisingly, I do not think that it is the ancillary. Looking at a couple of the failing points, the ancillary is within 0.01% of the correct solution. The issue seems to be in the update of |
I don't understand how the pressure can be not correct for input
temperature and density. Can you figure out what is going on? Could a
derivative be not correct somehow?
… Message ID: ***@***.***>
|
During saturated PHSU flash calculations, SatL and SatV states have an imposed phase. This is good for stability, but there is a small chance that they can both up up with a matching third variable (e.g., pressure) that is not actually at the saturation point. This commit forces a final DT update without this requirement. If an actual solution has been found, the the error term will still be small. If not, then we throw an exception and try again. This continues work on CoolProp#2245.
In saturation_PHSU_pure, we unspecify the phase of SatL and SatV to perform a final check. However, for any future updates, these states *must* be set with specified phase. This commit ensures that no matter what happens (exception, etc.) the phase is always specified again.
The "error" in the DT update seems to be due to the imposed phase on |
This doesn't make any sense. The phases should always be set to liquid and
vapor to avoid a nested phase equilibrium calculation. It doesn't make
sense to not impose the phase. Can you see whether the obtained pressures
are very different when doing a calc with and without the imposing of
phase? I may need to dig in a bit here. It could be a problem with the
EOS I fear.
|
That is what I would have thought as well, but you can get some strange results even when doing DT updates. Here is some example Python: import CoolProp
rho = 16425.375470309176
t = 337.43858705452624
state = CoolProp.AbstractState("HEOS", "AMMONIA")
state.update(CoolProp.DmolarT_INPUTS, rho, t)
print(state.p())
state.specify_phase(CoolProp.iphase_liquid)
state.update(CoolProp.DmolarT_INPUTS, rho, t)
print(state.p()) This prints
whereas I would have expected the same value to be printed in either case. Is the issue in the equation of state, or in the way that the pressure is found with some underlying phase assumption? I will try to take a look into the intermediate derivative values. |
Well, in your test case, the first set of inputs are two-phase, so that is why the results are different: import CoolProp
rho = 16425.375470309176
t = 337.43858705452624
state = CoolProp.AbstractState("HEOS", "AMMONIA")
state.update(CoolProp.DmolarT_INPUTS, rho, t)
print(state.p(), state.Q())
state.specify_phase(CoolProp.iphase_liquid)
state.update(CoolProp.DmolarT_INPUTS, rho, t)
print(state.p(), state.Q()) yielding
and this is general true. If the inputs are two-phase you should expect different answers. |
Hey, all. What's the status on this? |
@danielkwalsh Sorry for the slow progress on this, but I am a bit stuck. In short, the current version of the PR fixes the immediate issue, but it does so in an awkward way that might not be best for merging into master. If you need a short term fix, you can probably just use this branch as it seems to make all of my tests work. To elaborate a bit further, there seem to have been two issues at play:
|
@msaitta-mpr Perhaps I am missing something, but the saturation pressure applies to any point under the dome. Any isobar here will also be an isotherm, since the liquid and gaseous phases are in equilibrium. While I don't know the exact behavior of the solver being used here, nor do I understand the exact issue you are seeing, I could imagine that due to this degeneracy, asking for a state at a given pressure on the phase line could be multivalued due to this degeneracy, and consequently, the solver may give different results under different circumstances corresponding to different enthalpies. This is fine, since we are only interested in determining for a fluid at a given pressure, its corresponding vapor temperature, or vice versa. I'm happy to help try to debug this issue with you if you'd like, but unfortunately I don't understand the backend of the code well enough to do so on my own. Perhaps @ibell has some thoughts? On the CoolProp low-level API page, I find the following:
|
@danielkwalsh The low-level API page that you linked is key to this issue. We want to find the phase boundary. To do so, we perform repeated evaluations with two different states with imposed phases: one assumed liquid and the other gas. This works well, until they are evaluated within the two phase region. As the documentation states, they may return incorrect results in this region. The trick is that I do not have a good way to detect the phase to verify that they are not in the two phase region without recursing to another attempt at finding the phase boundary. |
@msaitta-mpr @ibell It seems that a common approach used is to pre-calculate the phase boundary. See the "Vapor-Liquid Equilibrium" section of this link for more details. |
This reverts commit c6b650b. The commit caused potential recursive lookups and did not solve the issue at hand.
The rhoV ancillary gave somewhat wrong results. This commit provides a closer fit that prevents errors downstream.
@ibell Looking at this again, I think that the issue actually is with the ancillary function. I went ahead and quickly remade the ancillary and things seem to be better now. |
Hey, @msaitta-mpr, does this mean the issue is fixed? |
// Recalculate error | ||
// The result has changed since the last error calculation. | ||
// In rare scenarios, the final step can become unstable due to solving a singular | ||
// J matrix. This final error check verifies that the solution is still good. | ||
// Furthermore, the forced phase of SatL and SatV may have caused errors. We will recalculate them without this assumption. |
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.
Does the singular J matrix still crop up with the fixed ancillary? I'm wondering if this part of the code is still needed?
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.
I never actually checked whether it is still needed. I figure that it is a cheap enough check that it is probably worth leaving in.
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.
Okay, great. I'm satisfied with that.
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.
@msaitta-mpr @ibell, so what are the next steps to get this merged?
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.
If everyone agrees we are ready I can merge it
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.
I believe that in its current state that it fixes the known issue and does not introduce any others. It raises the question of whether there are other ancillary issues hidden elsewhere, but I think that we should merge for now and reevaluate the ancillaries some other time.
@msaitta-mpr @danielkwalsh please feel free to introduce yourselves here: #2206 |
@ibell, @msaitta-mpr, thanks for merging! When do we get a new release as a new version? |
No idea. It will depend on getting some other
bugfixes/improvements together, enough that we can justify the time it
takes to put together a release.
|
Description of the Change
Sometimes, the Akasaka solver has issues. This is usually caught and then it is retried with a new omega. However, sometimes it goes bad because the J matrix is singular, and this is not caught because the error is not recalculated.
This PR recalculates the error term to prevent a bad result.
Benefits
This prevents saturation_PHSU_pure from providing wrong answers.
This closes #2245.
Possible Drawbacks
This slows calculations because it requires that the error term be recalculated an extra time for each update. However, it prevents bad results, which is usually worth it.
This does not solve the underlying issue of a singular matrix forming in the Akasaka solver. Therefore, we may want to look into that in the future.
Verification Process
I ran the following C++ code and verified that the results look smooth.
Applicable Issues
Closes #2245