-
Notifications
You must be signed in to change notification settings - Fork 62
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
Calculate state method #178
Conversation
@TimBartholomew What is the actual use case for this method, and how do you see it being used? I can see some potential issues with this, and it would help to know exactly what you intend this for. I will also note that as it stands this would only affect the ProteusLib specific property packages, so would hardly be general, which might be confusing to some users. Also, will ask the question of how this would differ from initializing the properties at some known state (hopefully close to the final requirement), and then fixing/specifying the required properties after initialization. For example, this is how the isentropic pressure changer works (and actually even the energy balances). We start by initializng the isentropic state at a condition close to the final solution, and then add a constraints that fix pressure and entropy for the actual solve. |
def test_calculate_state(self, frame_stateblock): | ||
m = frame_stateblock | ||
|
||
# check if calculate_state runs and solves rather than how its used |
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.
Can you add a test that demonstrates how supplying volumetric feed flow rate and mass concentration to calculate_state
would lead to some expected set of results?
After all, in my view, that is the main point for introducing this method--we want to be able to specify flow_vol_phase
and conc_mass_phase_comp
when fixing variables instead of being restricted to fixing component mass flow rates only, which is less straightforward.
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.
Yes, I haven't finished the PR yet. I'm planning on adding an individual test class in the property test harness for calculate_state cases. I'm also going to use it in the RO with energy recovery flowsheet.
@andrewlee94 I see this method being used before initialization routines in a variety of cases.
Cases 1 and 2 will be demonstrated in this PR soon for the RO with energy recovery flowsheet, this was still a work in progress. |
@TimBartholomew So, the first thing I can see is that a tool like this is going to be very property-package specific - i.e. I do not think it will be possible to build a generalised version of this. This means that any implementation is going to be case-specific, and it does mean that users might be confused when only certain property packages support this behaviour (and only for certain properties). There may still be value in doing this, but I do see a lot of caveats and edge cases that will arise from this (and I do mean will). To put somethings in writing and allow some thought/discussion (note that these are written from a general stand point, many of these could be trivial for specific examples):
In terms of the specific case studies you mentioned, I would suggest that in all cases you would get more reliable results by initializing the state block first at your best current guess (even if that is the inlet conditions), and then switching to your preferred definition of the system. Yes, it is one more step, but it avoids a lot of potential problems as the model constraints are generally written explicitly in terms of the state variables (that is what makes them state variables). Otherwise, you are now trying to solve a model based on implicit relationships which is much harder. As I mentioned before, this is how the isentropic pressure changer model works. The isentropic state should be solved based on the inlet flowrate and composition, inlet specific entropy and outlet pressure. However, specific entropy is very rarely a state variable, so instead we initialize at the inlet flow, composition and temperature and outlet pressure. This is not correct, but is generally very close enough such that we can then just solve the entire unit with the isentropic constraint. A similar argument holds for the actual outlet condition (where the outlet specific enthalpy, pressure, flow and composition is known). Of your listed use cases, case 1 is probably the most important as it is often the case that the user knows the inlet in one set of properties, but the calculations are better performed using a different set of state variables. However, even here my gut feeling is that it would be better to initialize the state block using the best guesses of the actual state variables, and to only apply the desired specification once the state is initialised. In terms of case 2 and 3, I very much think that is the case - just initialize using simple guesses based on the state variables and then apply the actual spec. Unless you have some really weird system, I cannot see your best guess being too far off the mark. TLDR: It is almost always easier to initialize at a set of initial guesses for the state variable first and get a feasible solution which is close to your desired conditions, and to then move to the actual state you want rather than to try to directly solve for the condition you want by specifying properties derived from the state variables. |
…roteuslib into calculate_state
Codecov Report
@@ Coverage Diff @@
## main #178 +/- ##
==========================================
- Coverage 90.11% 90.10% -0.01%
==========================================
Files 21 21
Lines 3611 3649 +38
==========================================
+ Hits 3254 3288 +34
- Misses 357 361 +4
Continue to review full report at Codecov.
|
…roteuslib into calculate_state
@adam-a-a @bknueven @lbianchi-lbl have we seen these test failures before?
|
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.
Despite our collective comments related to the API discussion, I think all of that can be saved for another issue/PR. This looks good to me.
self.solver = 'ipopt' | ||
self.optarg = {'nlp_scaling_method': 'user-scaling'} | ||
|
||
self.scaling_args = {('flow_mass_phase_comp', ('Liq', 'H2O')): 1e-1, |
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.
EDIT: I only noticed the full API discussion after writing this. No need to respond.
This would be tedious, would apply to all dictionaries related to PropertyTestHarness
objects, and would be for a future PR, but I think we may want to consider reformatting how the variable dicts are entered. Unless there's a reason for why things were written this way, I think we should change it to be more consistent with the way things are usually written in IDAES/Proteuslib. (@TimBartholomew @andrewlee94 Please correct me if I am wrong.)
For example, instead of
('flow_mass_phase_comp', ('Liq', 'H2O')): 1e-1
replace with
{'flow_mass_phase_comp[Liq, 'H2O']: 1e-1
The difference is subtle, but I could see future developers/users getting confused between the different formats.
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.
@adam-a-a so you are advocating for form 4 described above, right?
Fixes/Addresses:
Fixes #57
Summary/Motivation:
Oftentimes users want to fix properties on a stateblock and while this is possible it frequently causes errors in initialization. This happens because stateblock initialization routines assume the state variables should be fixed before the solve call. This PR creates another method called
calculate_state
, where a stateblock is solved for user provided variables and values (that can be properties).Changes proposed in this PR:
Legal Acknowledgement
By contributing to this software project, I agree to the following terms and conditions for my contribution: