Skip to content
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

To merge MED only files to main branch #10

Merged
merged 56 commits into from
Dec 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
988d0a3
Add files via upload
nazia-ga Dec 13, 2024
f563bab
Rename 3MED.rst to 3MED.rst
nazia-ga Dec 13, 2024
4c32d93
Delete src/watertap_contrib/rENRTL/examples/flowsheets/med directory
nazia-ga Dec 13, 2024
2aced17
Add files via upload
nazia-ga Dec 13, 2024
8e1871a
Add files via upload
nazia-ga Dec 13, 2024
3eeebce
Delete src/watertap_contrib/rENRTL/examples/flowsheets/med_with_refin…
nazia-ga Dec 13, 2024
b0e630c
Delete src/watertap_contrib/rENRTL/examples/flowsheets/med_with_refin…
nazia-ga Dec 13, 2024
8dd4758
Delete src/watertap_contrib/rENRTL/examples/flowsheets/med_with_refin…
nazia-ga Dec 13, 2024
01ab68a
Create placeholder file.py
nazia-ga Dec 13, 2024
de6ec78
Add files via upload
nazia-ga Dec 13, 2024
a666d36
Rename 3MED_eNRTL-2.py to 3MED_eNRTL.py
nazia-ga Dec 13, 2024
1b16f4c
Rename enrtl_config_FpcTP-2.py to enrtl_config_FpcTP.py
nazia-ga Dec 13, 2024
8d89f09
Rename renrtl_multi_config-6.py to renrtl_multi_config.py
nazia-ga Dec 13, 2024
0cf98e4
Delete src/watertap_contrib/rENRTL/examples/flowsheets/med_with_refin…
nazia-ga Dec 13, 2024
1e687e6
Rename 3MED_Only.png to 3MED.png
nazia-ga Dec 13, 2024
64fe0c4
Add files via upload
nazia-ga Dec 13, 2024
6a71c56
Rename refined_enrtl-5.py to refined_enrtl.py
nazia-ga Dec 13, 2024
0fac7c7
Rename refined_enrtl_multi-3.py to refined_enrtl_multi.py
nazia-ga Dec 13, 2024
ad73c70
Create placeholder.py
nazia-ga Dec 13, 2024
35ed90d
Add files via upload
nazia-ga Dec 13, 2024
ca1845d
Rename refined_enrtl-5.py to refined_enrtl.py
nazia-ga Dec 13, 2024
eddc8f1
Rename refined_enrtl_multi-3.py to refined_enrtl_multi.py
nazia-ga Dec 13, 2024
e5619a0
Delete src/watertap_contrib/rENRTL/examples/flowsheets/med_ahp_with_r…
nazia-ga Dec 13, 2024
9f8af4c
Add files via upload
nazia-ga Dec 13, 2024
3532241
Delete src/watertap_contrib/rENRTL/examples/flowsheets/med_ahp_with_r…
nazia-ga Dec 13, 2024
2d7e59e
Do the black
Pengfei-Xu-1993 Dec 13, 2024
308e544
Rename 3MED_eNRTL.py to MED_eNRTL.py
nazia-ga Dec 13, 2024
c3c6f6e
Update 3MED_eNRTL_test.py
nazia-ga Dec 13, 2024
d898da7
Update 3MED_eNRTL_test.py
nazia-ga Dec 18, 2024
539976e
Update 3MED_eNRTL_test.py
nazia-ga Dec 18, 2024
7f996f4
Update 3MED_eNRTL_test.py
nazia-ga Dec 18, 2024
8b70d87
Update 3MED_eNRTL_test.py
Pengfei-Xu-1993 Dec 18, 2024
4710393
Update 3MED_eNRTL_test.py
Pengfei-Xu-1993 Dec 19, 2024
974af01
Create pytest.ini
Pengfei-Xu-1993 Dec 19, 2024
83dab60
Uploaded a trial file for MED eNRTL
Pengfei-Xu-1993 Dec 19, 2024
ec037e1
Reach optimality of t he MED_eNRTL_test.py
Pengfei-Xu-1993 Dec 19, 2024
e3e8f0c
trial
Pengfei-Xu-1993 Dec 19, 2024
5c8c310
Remove unnecessary files
Pengfei-Xu-1993 Dec 19, 2024
159a381
Rename 3MED.png to threeeffect_med.png
nazia-ga Dec 19, 2024
3140caf
Rename 3MED.rst to threeeffect_med.rst
nazia-ga Dec 19, 2024
0307cbc
Rename 3MED_eNRTL_test.py to Test_MED_eNRTL.py
nazia-ga Dec 19, 2024
03859e5
Add files via upload
nazia-ga Dec 19, 2024
374e201
Update threeeffect_med.rst
nazia-ga Dec 19, 2024
114944d
Update and rename MED_eNRTL_rev.py to threeeffect_med_eNRTL.py
nazia-ga Dec 19, 2024
5e0efcb
Delete src/watertap_contrib/rENRTL/examples/flowsheets/med_with_refin…
nazia-ga Dec 19, 2024
efa6aca
Add files via upload
nazia-ga Dec 19, 2024
9a7923d
Update Test_MED_eNRTL.py
nazia-ga Dec 19, 2024
61ccadf
Delete src/watertap_contrib/rENRTL/examples/flowsheets/med_with_refin…
nazia-ga Dec 19, 2024
f5cd214
Update enrtl_config_FpcTP.py
nazia-ga Dec 19, 2024
66a098e
Update renrtl_multi_config.py
nazia-ga Dec 19, 2024
687b654
Delete src/watertap_contrib/rENRTL/examples/flowsheets/med_with_refin…
nazia-ga Dec 19, 2024
cfb98d7
Delete src/watertap_contrib/rENRTL/examples/flowsheets/med_with_refin…
nazia-ga Dec 19, 2024
5a058e0
Update Test_MED_eNRTL.py
nazia-ga Dec 19, 2024
af65d55
Executed black
Pengfei-Xu-1993 Dec 20, 2024
6e06f4c
fix the problems that can not be run again in windows spyder app
Pengfei-Xu-1993 Dec 20, 2024
0417d78
delete the init
Pengfei-Xu-1993 Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,349 @@
#################################################################################
# WaterTAP Copyright (c) 2020-2023, 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.
#
# Copyright 2023-2024, National Technology & Engineering Solutions of Sandia,
# LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the
# U.S. Government retains certain rights in this software.
#
# Copyright 2024, Nazia Aslam, Matthew D. Stuber, George M. Bollas, and the University of Connecticut.
#
# 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: Nazia Aslam from the University of Connecticut
#################################################################################

"""
References:
[1] Robinson, R. A., & Stokes, R. H. Electrolyte Solutions. Academic Press, New York, 1959. xv + 559 pp.

[2] Stuber, M. D., Sullivan, C., Kirk, S. A., Farrand, J. A., Schillaci, P. V., Fojtasek, B. D., & Mandell, A. H. (2015).
Pilot demonstration of concentrated solar-powered desalination of subsurface agricultural drainage water and
other brackish groundwater sources. Desalination, 355, 186-196. https://doi.org/10.1016/j.desal.2014.10.037

This is a close loop 3MED-only model configuration.
The model uses experimental conditions from [2] and validates well at a water recovery of 60%.
"""
import logging
import pytest

# Import Pyomo components
import pyomo.environ as pyo
from pyomo.environ import (
ConcreteModel,
TransformationFactory,
Block,
Constraint,
Expression,
Objective,
minimize,
Param,
value,
Set,
RangeSet,
log,
exp,
Var,
assert_optimal_termination,
)
from pyomo.network import Arc
from pyomo.environ import units as pyunits
from pyomo.util.check_units import assert_units_consistent

# Import IDAES components
import idaes.core.util.scaling as iscale
import idaes.logger as idaeslog
from idaes.core import FlowsheetBlock
from idaes.models.properties.modular_properties.base.generic_property import (
GenericParameterBlock,
)
from idaes.models.unit_models import Feed

from idaes.core.solvers.get_solver import get_solver
from idaes.core.util.model_statistics import degrees_of_freedom
from idaes.core.util.initialization import propagate_state
from idaes.models.unit_models import Pump, Heater

# Import property packages and WaterTAP components
import watertap.property_models.seawater_prop_pack as props_sw
import watertap.property_models.water_prop_pack as props_w

from watertap.unit_models.mvc.components import Evaporator, Condenser

# Import configuration dictionary
import enrtl_config_FpcTP # single electrolyte
import renrtl_multi_config # multi electrolytes

module = __import__("threeeffect_med_eNRTL")

# Access the functions from the module
populate_enrtl_state_vars = module.populate_enrtl_state_vars
populate_enrtl_state_vars_multi = module.populate_enrtl_state_vars_multi
create_model = module.create_model
create_arcs = module.create_arcs
add_enrtl_method_single = module.add_enrtl_method_single
add_enrtl_method_multi = module.add_enrtl_method_multi
set_scaling = module.set_scaling
set_model_inputs = module.set_model_inputs
initialize = module.initialize
add_bounds = module.add_bounds
model_analysis = module.model_analysis

logging.basicConfig(level=logging.INFO)
logging.getLogger("pyomo.repn.plugins.nl_writer").setLevel(logging.ERROR)

# solve_nonideal gives the option to solve an ideal and nonideal system
# If solve_nonideal is set to true, eNRTL is used to calculate the activity coefficients of solvent and solutes;
# when set to False, the model is solved assuming an ideal system with an activity coefficient of 1 for the solvent
solve_nonideal = True
run_multi = True


class TestMED:
@pytest.fixture(scope="class")
def MED_eNRTL(self):
m = create_model()
return m

@pytest.fixture(scope="class")
def Initialize_fixture(self):
optarg = {"max_iter": 500, "tol": 1e-8}
solver = get_solver("ipopt", optarg)

m = create_model()

set_scaling(m)

set_model_inputs(m)

initialize(m, solver=solver)

add_bounds(m)

return m

@pytest.mark.unit
def test_build_model(self, MED_eNRTL):
m = MED_eNRTL

# test model set up
assert isinstance(m, ConcreteModel)
assert isinstance(m.fs, FlowsheetBlock)
assert isinstance(m.fs.properties_vapor, props_w.WaterParameterBlock)
assert isinstance(m.fs.properties_feed, props_sw.SeawaterParameterBlock)

# test unit models
assert isinstance(m.fs.feed, Feed)
assert isinstance(m.fs.evaporator, Evaporator)
assert isinstance(m.fs.condenser, Condenser)
assert isinstance(m.fs.pump, Pump)
assert isinstance(m.fs.steam_generator, Heater)

@pytest.mark.unit
def test_create_arcs(self, MED_eNRTL):
m = MED_eNRTL
create_arcs(m)

arc_dict = {
m.fs.evap1brine_to_evap2feed: (
m.fs.evaporator[1].outlet_brine,
m.fs.evaporator[2].inlet_feed,
),
m.fs.evap1vapor_to_cond2: (
m.fs.evaporator[1].outlet_vapor,
m.fs.condenser[2].inlet,
),
m.fs.evap2vapor_to_cond3: (
m.fs.evaporator[2].outlet_vapor,
m.fs.condenser[3].inlet,
),
m.fs.evap2brine_to_evap3feed: (
m.fs.evaporator[2].outlet_brine,
m.fs.evaporator[3].inlet_feed,
),
m.fs.evap3vapor_to_condenser: (
m.fs.evaporator[3].outlet_vapor,
m.fs.condenser[4].inlet,
),
m.fs.condenser_to_pump: (m.fs.condenser[1].outlet, m.fs.pump.inlet),
m.fs.pump_to_generator: (m.fs.pump.outlet, m.fs.steam_generator.inlet),
m.fs.generator_to_condenser: (
m.fs.steam_generator.outlet,
m.fs.condenser[1].inlet,
),
}
for arc, port_tpl in arc_dict.items():
assert arc.source is port_tpl[0]
assert arc.destination is port_tpl[1]

# units
assert_units_consistent(m.fs)

@pytest.mark.component
def test_set_model_inputs(self, MED_eNRTL):
m = MED_eNRTL
set_scaling(m)
set_model_inputs(m)

# check fixed variables
# Feed
assert (
m.fs.evaporator[1]
.inlet_feed.flow_mass_phase_comp[0, "Liq", "H2O"]
.is_fixed()
)
assert (
value(m.fs.evaporator[1].inlet_feed.flow_mass_phase_comp[0, "Liq", "H2O"])
== 0.15
)
assert (
m.fs.evaporator[1]
.inlet_feed.flow_mass_phase_comp[0, "Liq", "TDS"]
.is_fixed()
)
assert (
value(m.fs.evaporator[1].inlet_feed.flow_mass_phase_comp[0, "Liq", "TDS"])
== 0.0035
)
assert m.fs.evaporator[1].inlet_feed.temperature[0].is_fixed()
assert value(m.fs.evaporator[1].inlet_feed.temperature[0]) == 27 + 273.15
assert m.fs.evaporator[1].inlet_feed.pressure[0].is_fixed()
assert value(m.fs.evaporator[1].inlet_feed.pressure[0]) == 101325

# Condenser[1]
assert m.fs.condenser[1].outlet.temperature[0].is_fixed()
assert value(m.fs.condenser[1].outlet.temperature[0]) == 69 + 273.15
assert m.fs.condenser[1].inlet.flow_mass_phase_comp[0, "Liq", "H2O"].is_fixed()
assert (
value(m.fs.condenser[1].inlet.flow_mass_phase_comp[0, "Liq", "H2O"]) == 0.00
)

# Pressure changer
assert m.fs.pump.outlet.pressure[0].is_fixed()
assert value(m.fs.pump.outlet.pressure[0]) == 30000
assert m.fs.pump.efficiency_pump[0].is_fixed()
assert value(m.fs.pump.efficiency_pump[0]) == 0.8

# Steam generator
assert m.fs.steam_generator.outlet.temperature[0].is_fixed()
assert value(m.fs.steam_generator.outlet.temperature[0]) == 69.1 + 273.15
assert m.fs.steam_generator.control_volume.heat[0].is_fixed()
assert value(m.fs.steam_generator.control_volume.heat[0]) == 96370

# Evaporator[1]
assert m.fs.evaporator[1].outlet_brine.temperature[0].is_fixed()
assert value(m.fs.evaporator[1].outlet_brine.temperature[0]) == 65 + 273.15
assert m.fs.evaporator[1].U.is_fixed()
assert value(m.fs.evaporator[1].U) == 500
assert m.fs.evaporator[1].area.is_fixed()
assert value(m.fs.evaporator[1].area) == 10
assert m.fs.evaporator[1].delta_temperature_in.is_fixed()
assert value(m.fs.evaporator[1].delta_temperature_in) == 10
assert m.fs.evaporator[1].delta_temperature_out.is_fixed()
assert value(m.fs.evaporator[1].delta_temperature_out) == 8

# Condenser[2]
assert m.fs.condenser[2].outlet.temperature[0].is_fixed()
assert value(m.fs.condenser[2].outlet.temperature[0]) == 64 + 273.15

# Evaporator[2]
assert m.fs.evaporator[2].U.is_fixed()
assert value(m.fs.evaporator[2].U) == 500
assert m.fs.evaporator[2].area.is_fixed()
assert value(m.fs.evaporator[2].area) == 10
assert m.fs.evaporator[2].outlet_brine.temperature[0].is_fixed()
assert value(m.fs.evaporator[2].outlet_brine.temperature[0]) == 64 + 273.15
assert m.fs.evaporator[2].delta_temperature_in.is_fixed()
assert value(m.fs.evaporator[2].delta_temperature_in) == 10
assert m.fs.evaporator[2].delta_temperature_out.is_fixed()
assert value(m.fs.evaporator[2].delta_temperature_out) == 8

# Condenser[3]
assert m.fs.condenser[3].outlet.temperature[0].is_fixed()
assert value(m.fs.condenser[3].outlet.temperature[0]) == 60 + 273.15

# Evaporator[3]
assert m.fs.evaporator[3].U.is_fixed()
assert value(m.fs.evaporator[3].U) == 500
assert m.fs.evaporator[3].area.is_fixed()
assert value(m.fs.evaporator[3].area) == 10
assert m.fs.evaporator[3].outlet_brine.temperature[0].is_fixed
assert value(m.fs.evaporator[3].outlet_brine.temperature[0]) == 63 + 273.15
assert m.fs.evaporator[3].delta_temperature_in.is_fixed()
assert value(m.fs.evaporator[3].delta_temperature_in) == 10
assert m.fs.evaporator[3].delta_temperature_out.is_fixed()
assert value(m.fs.evaporator[3].delta_temperature_out) == 8

# Condenser[4]
assert m.fs.condenser[4].outlet.temperature[0].is_fixed()
assert value(m.fs.condenser[4].outlet.temperature[0]) == 55 + 273.15

@pytest.mark.component
@pytest.mark.requires_idaes_solver
def test_initialize(self, Initialize_fixture):

m = Initialize_fixture

assert value(m.fs.evaporator[1].U) == pytest.approx(500, rel=1e-3)
assert value(m.fs.evaporator[1].delta_temperature_out) == pytest.approx(
8, rel=1e-3
)
assert value(m.fs.evaporator[2].U) == pytest.approx(500, rel=1e-3)
assert value(m.fs.evaporator[2].delta_temperature_out) == pytest.approx(
8, rel=1e-3
)
assert value(m.fs.evaporator[3].U) == pytest.approx(500, rel=1e-3)
assert value(m.fs.evaporator[3].delta_temperature_out) == pytest.approx(
8, rel=1e-3
)
assert value(m.fs.pump.outlet.pressure[0]) == pytest.approx(30000, rel=1e-3)
assert value(m.fs.steam_generator.outlet.temperature[0]) == pytest.approx(
69.1 + 273.15, rel=1e3
)
assert value(m.fs.steam_generator.control_volume.heat[0]) == pytest.approx(
96370, rel=1e-3
)

assert degrees_of_freedom(m) == 0

@pytest.mark.component
@pytest.mark.requires_idaes_solver
def test_model_analysis(self, Initialize_fixture):
optarg = {"max_iter": 500, "tol": 1e-8}
solver = get_solver("ipopt", optarg)

m = Initialize_fixture

model_analysis(m, water_rec=0.6)

results = solver.solve(m, tee=False)

assert_optimal_termination(results)

# additional constraints, variables, and expressions
assert isinstance(m.fs.gen_heat_bound, Constraint)
assert isinstance(m.fs.eq_upper_bound_evaporators_pressure, Constraint)
assert isinstance(m.fs.eq_specific_energy_consumption, Constraint)
assert isinstance(m.fs.rule_water_recovery, Constraint)
assert isinstance(m.fs.water_recovery_ub, Constraint)
assert isinstance(m.fs.water_recovery_lb, Constraint)
assert isinstance(m.fs.UA_term, Expression)
assert isinstance(m.fs.total_water_produced_gpm, Expression)
assert isinstance(m.fs.performance_ratio, Expression)

assert m.fs.steam_generator.outlet.temperature[0].value == pytest.approx(
69.1 + 273.15, rel=1e-3
)
assert m.fs.steam_generator.outlet.pressure[0].value == pytest.approx(
30000, rel=1e-3
)
assert value(m.fs.total_water_produced_gpm) == pytest.approx(1.4598, rel=1e-3)
assert m.fs.specific_energy_consumption.value == pytest.approx(
331.7649, rel=1e-3
)
assert value(m.fs.performance_ratio) == pytest.approx(1.9417, rel=1e-3)
Loading
Loading