-
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
MCAS w/generic crystallizer #1487
Merged
adam-a-a
merged 54 commits into
watertap-org:main
from
adam-a-a:mcas_generic_crystallizer
Oct 31, 2024
Merged
Changes from all commits
Commits
Show all changes
54 commits
Select commit
Hold shift + click to select a range
1feb735
paste Mayo's surrogate_crystallizer unit in raw form
adam-a-a 3c32230
start code cleanup in surrogate crystallizer, add vapor prop pack con…
adam-a-a db52f1e
git rid of self.vap_prop instances
adam-a-a ba1893c
Merge branch 'main' into mcas_generic_crystallizer
adam-a-a 7d12510
Merge branch 'main' into mcas_generic_crystallizer
adam-a-a 6595daa
paste in seawater relationship for enth_mass_phase
adam-a-a b62cbb4
pass tests for enth_mass_phase implementation in MCAS
adam-a-a e1c99a7
check value of enthalpy in test
adam-a-a 4563e7c
bring in test code
adam-a-a 4424c83
get test crystallizer surrogate file to pass
adam-a-a a6b8159
only construct enthalpy params once
adam-a-a 2531bda
blk
adam-a-a 7d0eb12
add surrogate files
adam-a-a 41832da
clean up imports and other code
adam-a-a 4ce6242
track costing file
adam-a-a 6eafd1d
bk
adam-a-a 5fbd721
raise config error instead of string
adam-a-a 9a7f99b
remove unused imports
adam-a-a edecffc
Merge branch 'main' into mcas_generic_crystallizer
adam-a-a 2f690da
changed filename and started cleanup
adam-a-a 18cd73a
make folder for crystallizer surrogate defaults to test; finish cleanup
adam-a-a a58201f
Merge branch 'mcas_generic_crystallizer' of https://github.com/adam-a…
adam-a-a 86d4fb7
Merge branch 'main' into mcas_generic_crystallizer
adam-a-a b07ace5
blk
adam-a-a 3831b5f
Merge branch 'mcas_generic_crystallizer' of https://github.com/adam-a…
adam-a-a bcddc5f
add folder
adam-a-a 4bc170c
cleanup imports and copyright headers
adam-a-a dd7aac9
fix file path
adam-a-a a039651
updated some var names to make a bit more user friendly and closer to…
adam-a-a 427c635
blk
adam-a-a 4895335
delete erronous code in mcas during initialization of enthalpy
adam-a-a 67e5b54
fix issue with file path?
adam-a-a 5a1d053
blk
adam-a-a 2793edc
black
adam-a-a 5cd9db1
move surrogate defaults
adam-a-a d018429
refine test file
adam-a-a b22c817
add pressure_sat and add some scaling
adam-a-a 1bd2454
black
adam-a-a e2d37e8
add to MCAS tech ref; revise subtlety in sw prop model tech ref
adam-a-a 7a945c7
revise docs
adam-a-a 11ef9d4
fix rst
adam-a-a 21fef31
adjust th equation in rst
adam-a-a 060766b
remove units inclusion for D
adam-a-a 85252da
fix fraction
adam-a-a 788bbef
fix path issue
adam-a-a 1cacd7d
blk
adam-a-a 6d29750
fix relatiosnhip
adam-a-a 275acf7
try to fix path issues now having created init files
adam-a-a fc1a1dc
revise doc
adam-a-a ac847b4
tinker with docs
adam-a-a 71b6e27
cleanup
adam-a-a df3f8b2
add init files!
adam-a-a 55643c9
regression tests for enth flow and pressure sat
adam-a-a 168c9fc
Merge branch 'main' into mcas_generic_crystallizer
OOAmusat File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
################################################################################# | ||
# WaterTAP Copyright (c) 2020-2024, The Regents of the University of California, | ||
# through Lawrence Berkeley National Laboratory, Oak Ridge National Laboratory, | ||
# National Renewable Energy Laboratory, and National Energy Technology | ||
# Laboratory (subject to receipt of any required approvals from the U.S. Dept. | ||
# of Energy). All rights reserved. | ||
# | ||
# Please see the files COPYRIGHT.md and LICENSE.md for full copyright and license | ||
# information, respectively. These files are also available online at the URL | ||
# "https://github.com/watertap-org/watertap/" | ||
################################################################################# | ||
|
||
import pyomo.environ as pyo | ||
from watertap.costing.util import ( | ||
register_costing_parameter_block, | ||
make_capital_cost_var, | ||
) | ||
|
||
|
||
def build_surrogate_crystallizer_cost_param_block(blk): | ||
|
||
blk.steam_pressure = pyo.Var( | ||
initialize=3, | ||
units=pyo.units.bar, | ||
doc="Steam pressure (gauge) for crystallizer heating: 3 bar default based on Dutta example", | ||
) | ||
|
||
blk.efficiency_pump = pyo.Var( | ||
initialize=0.7, | ||
units=pyo.units.dimensionless, | ||
doc="Crystallizer pump efficiency - assumed", | ||
) | ||
|
||
blk.pump_head_height = pyo.Var( | ||
initialize=1, | ||
units=pyo.units.m, | ||
doc="Crystallizer pump head height - assumed, unvalidated", | ||
) | ||
|
||
# Crystallizer operating cost information from literature | ||
blk.fob_unit_cost = pyo.Var( | ||
initialize=675000, | ||
doc="Forced circulation crystallizer reference free-on-board cost (Woods, 2007)", | ||
units=pyo.units.USD_2007, | ||
) | ||
|
||
blk.ref_capacity = pyo.Var( | ||
initialize=1, | ||
doc="Forced circulation crystallizer reference crystal capacity (Woods, 2007)", | ||
units=pyo.units.kg / pyo.units.s, | ||
) | ||
|
||
blk.ref_exponent = pyo.Var( | ||
initialize=0.53, | ||
doc="Forced circulation crystallizer cost exponent factor (Woods, 2007)", | ||
units=pyo.units.dimensionless, | ||
) | ||
|
||
blk.iec_percent = pyo.Var( | ||
initialize=1.43, | ||
doc="Forced circulation crystallizer installed equipment cost (Diab and Gerogiorgis, 2017)", | ||
units=pyo.units.dimensionless, | ||
) | ||
|
||
blk.steam_cost = pyo.Var( | ||
initialize=0.004, | ||
units=pyo.units.USD_2018 / (pyo.units.meter**3), | ||
doc="Steam cost, Panagopoulos (2019)", | ||
) | ||
|
||
costing = blk.parent_block() | ||
costing.register_flow_type("steam", blk.steam_cost) | ||
|
||
|
||
def cost_surrogate_crystallizer(blk): | ||
""" | ||
Function for costing the surrogate crystallizer by the mass flow of produced crystals. | ||
The operating cost model assumes that heat is supplied via condensation of saturated steam (see Dutta et al.) | ||
""" | ||
cost_crystallizer_by_crystal_mass(blk) | ||
|
||
|
||
def _cost_crystallizer_flows(blk): | ||
blk.costing_package.cost_flow( | ||
pyo.units.convert( | ||
(blk.unit_model.heat_required / _compute_steam_properties(blk)), | ||
to_units=pyo.units.m**3 / pyo.units.s, | ||
), | ||
"steam", | ||
) | ||
|
||
|
||
@register_costing_parameter_block( | ||
build_rule=build_surrogate_crystallizer_cost_param_block, | ||
parameter_block_name="surrogate_crystallizer", | ||
) | ||
def cost_crystallizer_by_crystal_mass(blk): | ||
""" | ||
Mass-based capital cost for FC crystallizer | ||
""" | ||
make_capital_cost_var(blk) | ||
blk.costing_package.add_cost_factor(blk, "TIC") | ||
blk.cost_factor = 1 # blk.costing_package.add_cost_factor(blk, "TIC") | ||
blk.capital_cost_constraint = pyo.Constraint( | ||
expr=blk.capital_cost | ||
== blk.cost_factor | ||
* pyo.units.convert( | ||
( | ||
blk.costing_package.surrogate_crystallizer.iec_percent | ||
* blk.costing_package.surrogate_crystallizer.fob_unit_cost | ||
* ( | ||
blk.unit_model.flow_mass_sol_total | ||
/ blk.costing_package.surrogate_crystallizer.ref_capacity | ||
) | ||
** blk.costing_package.surrogate_crystallizer.ref_exponent | ||
), | ||
to_units=blk.costing_package.base_currency, | ||
) | ||
) | ||
_cost_crystallizer_flows(blk) | ||
|
||
|
||
def _compute_steam_properties(blk): | ||
""" | ||
Function for computing saturated steam properties for thermal heating estimation. | ||
|
||
Args: | ||
pressure_sat: Steam gauge pressure in bar | ||
|
||
Out: | ||
Steam thermal capacity (latent heat of condensation * density) in kJ/m3 | ||
""" | ||
pressure_sat = blk.costing_package.surrogate_crystallizer.steam_pressure | ||
# 1. Compute saturation temperature of steam: computed from El-Dessouky expression | ||
tsat_constants = [ | ||
42.6776 * pyo.units.K, | ||
-3892.7 * pyo.units.K, | ||
1000 * pyo.units.kPa, | ||
-9.48654 * pyo.units.dimensionless, | ||
] | ||
psat = ( | ||
pyo.units.convert(pressure_sat, to_units=pyo.units.kPa) | ||
+ 101.325 * pyo.units.kPa | ||
) | ||
temperature_sat = tsat_constants[0] + tsat_constants[1] / ( | ||
pyo.log(psat / tsat_constants[2]) + tsat_constants[3] | ||
) | ||
|
||
# 2. Compute latent heat of condensation/vaporization: computed from Sharqawy expression | ||
t = temperature_sat - 273.15 * pyo.units.K | ||
enth_mass_units = pyo.units.J / pyo.units.kg | ||
t_inv_units = pyo.units.K**-1 | ||
dh_constants = [ | ||
2.501e6 * enth_mass_units, | ||
-2.369e3 * enth_mass_units * t_inv_units**1, | ||
2.678e-1 * enth_mass_units * t_inv_units**2, | ||
-8.103e-3 * enth_mass_units * t_inv_units**3, | ||
-2.079e-5 * enth_mass_units * t_inv_units**4, | ||
] | ||
dh_vap = ( | ||
dh_constants[0] | ||
+ dh_constants[1] * t | ||
+ dh_constants[2] * t**2 | ||
+ dh_constants[3] * t**3 | ||
+ dh_constants[4] * t**4 | ||
) | ||
dh_vap = pyo.units.convert(dh_vap, to_units=pyo.units.kJ / pyo.units.kg) | ||
|
||
# 3. Compute specific volume: computed from Affandi expression (Eq 5) | ||
t_critical = 647.096 * pyo.units.K | ||
t_red = temperature_sat / t_critical # Reduced temperature | ||
sp_vol_constants = [ | ||
-7.75883 * pyo.units.dimensionless, | ||
3.23753 * pyo.units.dimensionless, | ||
2.05755 * pyo.units.dimensionless, | ||
-0.06052 * pyo.units.dimensionless, | ||
0.00529 * pyo.units.dimensionless, | ||
] | ||
log_sp_vol = ( | ||
sp_vol_constants[0] | ||
+ sp_vol_constants[1] * (pyo.log(1 / t_red)) ** 0.4 | ||
+ sp_vol_constants[2] / (t_red**2) | ||
+ sp_vol_constants[3] / (t_red**4) | ||
+ sp_vol_constants[4] / (t_red**5) | ||
) | ||
sp_vol = pyo.exp(log_sp_vol) * pyo.units.m**3 / pyo.units.kg | ||
|
||
# 4. Return specific energy: density * latent heat | ||
return dh_vap / sp_vol |
Empty file.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Just a note for everyone's awareness: The crystallizer cost for steam (including steam properties) and the pump is being removed in PR #1482 . These costs are now broken down into the steam heater (which uses the water vapor property package) and the pump unit model costs. This means steam and pump flows are calculated at the flowsheet level, with their respective costs corresponding to the unit models.
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.
Good to know--will leave here in this PR and let your PR take care of this.