#################################################################################
# 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/"
#################################################################################
__author__ = "Paul Vecchiarelli, Adam Atia"
from pyomo.environ import (
units as pyunits,
ConcreteModel,
assert_optimal_termination,
)
from idaes.core import FlowsheetBlock, MaterialFlowBasis
from idaes.core.util.scaling import calculate_scaling_factors
from idaes.core.solvers import get_solver
from watertap.property_models.multicomp_aq_sol_prop_pack import MCASParameterBlock
from watertap.tools.oli_api.util.watertap_to_oli_helper_functions import (
get_molar_mass,
get_charge,
)
[docs]def create_state_block(source_water):
"""
Creates a state block using the Multi Component Aqueous Solution (MCAS) property model.
:param source_water: dictionary containing state variables and units
:return m: ConcreteModel containing MCAS state block
"""
solver = get_solver()
m = ConcreteModel()
m.fs = FlowsheetBlock(dynamic=False)
props = create_property_model_input(
source_water["components"], property_model_type="mcas"
)
m.fs.properties = MCASParameterBlock(
**props, material_flow_basis=MaterialFlowBasis.mass
)
stream = m.fs.stream = m.fs.properties.build_state_block([0])
for comp, conc in stream[0].flow_mass_phase_comp.items():
m.fs.properties.set_default_scaling(
"flow_mass_phase_comp", 1 / conc.value, index=comp
)
for comp, conc in stream[0].conc_mass_phase_comp.items():
m.fs.properties.set_default_scaling(
"conc_mass_phase_comp", 1 / conc.value, index=comp
)
m.fs.properties.set_default_scaling(
"flow_vol_phase", 1 / stream[0].flow_vol_phase["Liq"].value, index=("Liq")
)
calculate_scaling_factors(m)
convert_to_state_block_units(stream[0].temperature, source_water, "temperature")
convert_to_state_block_units(stream[0].pressure, source_water, "pressure")
stream[0].conc_mass_phase_comp
convert_conc = lambda conc: pyunits.convert_value(
conc,
from_units=source_water["units"]["components"],
to_units=stream[0].conc_mass_phase_comp._units,
)
# TODO: enable customization
conc_basis = "conc_mass_phase_comp"
vol_basis = "flow_vol_phase"
phase = "Liq"
var_args = {}
for comp in source_water["components"]:
var_args[(conc_basis, (phase, comp))] = convert_conc(
source_water["components"][comp]
)
var_args.update({(vol_basis, phase): 1e-3})
stream.calculate_state(var_args=var_args, hold_state=True)
stream.initialize()
result = solver.solve(m)
assert_optimal_termination(result)
return m
[docs]def convert_to_state_block_units(state_variable, source: dict, key):
"""
Converts state variable values from input source to state block units.
:param state_variable: state block attribute (i.e. temperature, pressure, concentration) to convert
:param source: input source with initial value
:param key: lookup key in input source for specified state variable
"""
converted_value = pyunits.convert_value(
source[key], from_units=source["units"][key], to_units=state_variable._units
)
state_variable.fix(converted_value)