-
Notifications
You must be signed in to change notification settings - Fork 59
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
Fix bubblepoint function and unit inconsistency in OLI API #1388
Conversation
…itymatrix results; reminder to check diff and remove debugging bits and finalized fixedkeysdict changes
… bubblepoint; test fixedkeysdict funcitonality with resolved units issue
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1388 +/- ##
==========================================
- Coverage 95.25% 95.23% -0.02%
==========================================
Files 335 335
Lines 35727 35621 -106
==========================================
- Hits 34033 33925 -108
- Misses 1694 1696 +2 ☔ View full report in Codecov by Sentry. |
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 am not sure about the automatic units conversion piece of this.
In the original conception, I imaged using the "pyomo_unit" attribute so the user could convert whatever input they had to units which will work with OLI by using the existing units conversion in Pyomo, and then back to those units after OLI returns the data.
It could be the answer is to restructure this so that the "pyomo_unit" and "oli_unit" are read-only attributes so as not to confuse the user.
@@ -25,7 +27,48 @@ def __setitem__(self, k, v): | |||
raise RuntimeError(f" Key {k} not in dictionary.") | |||
# also check for valid value if a list of values is given in the default dictionary | |||
else: | |||
self.data[k] = v | |||
# if user setting value in pyomo units |
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 we should have a sub-class of FixedKeysDict
just for the units?
"oli_unit": "Pa-s", | ||
"pyomo_unit": pyunits.Pa * pyunits.second, | ||
}, | ||
"alkalinity": {"oli_unit": "mg HCO3/L", "pyomo_unit": pyunits.mg / pyunits.L}, |
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.
This example, among others, is why Paul and I gave up on an automatic approach. It seemed like you could be working forever on every edge case and still miss some.
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.
Right- we'd need to set valid units accepted for each property, which is documented. We may catch bugs along the way (i.e., what's documented may not match reality in some cases).
So, I am not completely sure about the utility of pyomo_unit since we technically haven't applied it yet. Nevertheless, assuming that it might come in handy later and aiming to maintain what you guys put together, I decided to implement in this fashion, primarily because the immediate priority is to allow for the user to be able change units for inputs/outputs readily. I suppose this wasn't the original intent for FixedKeysDict, but that is what is most important to start with. These changes should make that possible. I think we can decide on totally reworking this later, but for now, i want to use it for a subsequent PR that will involve the need to toggle units of inputs and outputs. |
Maybe "pyomo unit" should be replaced with "pint unit". The idea of the existing mapping is if the user wants to change the units on the input / output they can do that in a standard way through Python, instead of needing to deal with the units in OLI at all. |
Ah, so say I want to alter the units for "molecularConcentration" to mol/L, which happens to be set to mg/L by default. How would you imagine that would go? Would it be something like the following? Or do you have a different example in mind?
|
So, for this particular issue, I would suggest we mirror what we already do in other parts of IDAES / WaterTAP: force the user to tell us up-front if they want an molar or mass basis and select the appropriate mapping for them. |
That could be problematic given the way properties are passed/returned in OLI. We can think about changing this entirely. In any case, the current code resolved the issue that I identified. Now, if you overwrite either oli_unit or pyomo_unit with string or pint unit (all options are compatible), pyomo_unit would automatically match the newly set oli_unit; conversely, setting the pyomo_unit to a new value (string or pint units), would automatically update the corresponding oli_unit. I think we can decide to accept as an incremental change and revisit in subsequent PRs, or I can strip that segment from this PR. If I do the latter, I will likely reintroduce those mods in a subsequent PR which would illustrate an example of why the user might need to change units for certain workflows in a non-obvious way. In the longer-term, we can think about a total refactor of the related code to better match practical user needs. Most importantly, I want to have some treatment of this before it ends up in 1.0. |
My issue is that this does not work for all cases because the OLI units are bespoke, e.g., #1388 (comment), and that issue aside, according to the documentation OLI will only take a fixed set of units for each parameter. Because of this, I would suggest if the user wants different units to go to OLI we make them specify them as OLI unit / pint unit pair. |
Right- so, I think I have a solution for this, but that would come as a later PR if we decided to handle that way. Essentially, the same way we have But on this PR- it sounds like you'd opt to strip the changes to FixedKeysDict from here. I would reinject it in a subsequent PR for a common use case that WaterTAP users (myself included) might want to run often, and we can take it from there. How does that sound? |
@OOAmusat @avdudchenko I think you two are the only ones who could add reviews to this PR at this point. Please take a look if you have a chance. If this is something you don't think you'll have time for this quarter, let me know, and I will merge without reviews (because we really should have the major fix included in this PR as part of 1.0). |
…into fix_oli_client
if invalid_phases: | ||
raise RuntimeError( | ||
"Failed DBS file generation. " | ||
+ f"Unexpected phase(s): {invalid_phases}" | ||
) | ||
dbs_file_inputs["phases"] = phases | ||
else: | ||
dbs_file_inputs["phases"] = ["liquid1", "solid"] | ||
dbs_file_inputs["phases"] = ["liquid1", "solid", "vapor"] |
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 Is there a reason why we do not have "liquid2" here?
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.
For now, because we haven't experimented with it enough and I didn't want to open up more cans of worms until we get the more fundamental bits of code working, I think it is safer to add liquid2 as part of the default in a later PR, which would need to include some thorough testing to see how various OLI functions may or may not be impacted.
I have tests passing for OLI. @TimBartholomew @OOAmusat @avdudchenko - just a reminder that I would like to get this merged for the June release since it fixes some issues that needed repair. Hoping to get your reviews in time; otherwise, we may just end up merging without the full 2 reviews. |
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.
LGTM.
Would have liked to test the units switching myself to check for edge cases, but in the absence of OLI access, I guess this is the best we can do.
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.
This looks good to me - nothing really popped out that would cause issues. LTMG
Fixes/Resolves:
Summary/Motivation:
In an attempt to call the bubblepoint function, I discovered that it doesn't work as intended and the user would not be able to run the function. Along the way, I also noticed that input and/or output units provided for OLI properties have
oli_unit
andpyomo_unit
attributes, and when one sets one or the other, there would be inconsistencies between the two (see #1369).Changes proposed in this PR:
pyomo_unit
oroli_unit
, the other will automatically update via__setitem__
and using nested FixedKeysDictsLegal Acknowledgement
By contributing to this software project, I agree to the following terms and conditions for my contribution: