-
Notifications
You must be signed in to change notification settings - Fork 11
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
Multi-effect crystallizer unit model #121
Conversation
@Zhuoran29 can you run black so we can see the results of the GH tests please? |
Sure, it seems the cost package is not adjusted well and I'll look into it. |
def test_initialize(self, Crystallizer_frame): | ||
# Add costing function, then initialize | ||
m = Crystallizer_frame | ||
# m.fs.costing = WaterTAPCosting() |
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.
@Zhuoran29 just skimming this from my phone, but maybe the failed tests are due to the costing lines being commented out 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.
In any case, I’d recommend just having a separate test_costing test rather than bundle it up in the initialization test.
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.
Now the costing package is rebuilt in REFLO and tested separately.
…to crystallizers
…-reflo into crystallizers
I added the costing package from the WaterTAP repo and a test file for the flowsheet, where both simulation and optimization modes were tested. |
Hey @kurbansitterley @adam-a-a , forgot to tag you when I updated this PR. |
opt = get_solver(solver, optarg) | ||
for n, eff in self.effects.items(): | ||
if n == 1: | ||
assert degrees_of_freedom(eff.effect) == 0 |
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 should raise an exception if DOF do not equal 0
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.
addressed
return m | ||
|
||
|
||
class TestMultiEffectCrystallizer_4Effects: |
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.
So 4 effects is the default, and you test for 4 effects and 3 effects. What happens if the user tries entering 1 effect? Similarly, what about 2 effects? I went scanned through the core code quickly, so I know I missed this. I just wonder if we should just add two quick, shortened versions of these tests just to ensure that we get what we'd expect from entering 1 effect or 2 effects. For example, in 2 effects, I might expect some special handling of the first and last effect, hence interest in this case. For 1 effect, I would expect the code to handle this case or throw an exception if the multieffect model is not setup to handle specification of 1 effect.
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.
addressed in e0b5b44.
Added test for 2 effects.
If the user tries to use MultiEffectCrystallizer
with a single effect, it will raise ConfigurationError
and they will be directed to use the CrystallizerEffect
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.
Nice. One thought I have--say you wanted to run optimization cases across a range of conditions and a range of number of effects, including a single effect. You'd need to add some logic in to such a script to toggle between the CrystallizerEffect model for the case where a single effect is optimized, and then toggle to the MultiEffectCrystallizer model for all other cases.
All that just to say, it might be useful to actually allow for a single effect via MultiEffectCrystallizer too. Definitely not something to consider for this PR--just food for thought.
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.
Thinking about this now, I don't think it would be very hard to implement, maybe a little clunky, but I do like the idea of having all the functionality for a unit model within a single model rather than directing the user to use a different unit model. A consideration for the future.
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.
Quite an impressive bit of work here that I know must've taken a lot of thought and effort! Well done! I just have a couple of comments from a quick scan.
My other general comment is we definitely want to document the single and multieffect models thoroughly--though that can happen in a subsequent PR down the line and shouldn't hold this up. |
…-reflo into pr/Zhuoran29/121
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 - I had another comment or two to consider but I think this should be good to merge. We can make issues on any other gaps identified here.
Co-authored-by: Adam Atia <[email protected]>
I ran a few cases and the results are looking good to me! Also I added a test for an optimization scenario in case it's helpful to the case study. If the additions look good to you then I think it's good to go, but please feel free to not include it. @kurbansitterley |
This PR adds:
CrystallizerEffect
unit modelMultiEffectCrystallizer
unit model that is comprised of nCrystallizerEffect
unit models connected via constraintsMultiEffectCrystallizer
andCrystallizerEffect
watertap==1.0.0rc0
in setup.pyTODO:
CrystallizerEffect
flow_vol_phase['Vap']
is the proper flow to cost for steam