Skip to content

Commit

Permalink
Replacing Expr_if & Changing Bio_P Default (#1362)
Browse files Browse the repository at this point in the history
* Import smooth max into translator block

* Replace Expr_ifs with smooth_max or smooth_min

* differentiate between the eps smoothing function and the eps used elsewhere

* Adjust the value of eps_smooth from 1e-10 to 1e-4

* Temporarily add diagnostic toolbox and scaling checks

* Continue playing around with scaling and tear guesses

* Reset flowsheet to the version in main

* Reset flowsheet to the version in main

* Change bio_P default to False

* Replace separators with clarifiers and modify tear guesses

* Update test

* Add bio_P config option to Extended BSM2 flowsheet and testing

* Minor adjustments to test solutions

* Minor improvements to bio_P=True tear guesses

* Clean up code
  • Loading branch information
MarcusHolly authored May 10, 2024
1 parent 27ee4d8 commit ac04ca7
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
stream_table_dataframe_to_string,
)
from watertap.unit_models.cstr_injection import CSTR_Injection
from watertap.unit_models.clarifier import Clarifier
from watertap.property_models.anaerobic_digestion.modified_adm1_properties import (
ModifiedADM1ParameterBlock,
)
Expand Down Expand Up @@ -79,16 +80,16 @@
_log = idaeslog.getLogger(__name__)


def main():
m = build()
def main(bio_P=True):
m = build(bio_P=bio_P)
set_operating_conditions(m)
for mx in m.fs.mixers:
mx.pressure_equality_constraints[0.0, 2].deactivate()
m.fs.MX3.pressure_equality_constraints[0.0, 2].deactivate()
m.fs.MX3.pressure_equality_constraints[0.0, 3].deactivate()
print(f"DOF before initialization: {degrees_of_freedom(m)}")

initialize_system(m)
initialize_system(m, bio_P=bio_P)
for mx in m.fs.mixers:
mx.pressure_equality_constraints[0.0, 2].deactivate()
m.fs.MX3.pressure_equality_constraints[0.0, 2].deactivate()
Expand Down Expand Up @@ -118,7 +119,7 @@ def main():
return m, results


def build():
def build(bio_P=False):
m = pyo.ConcreteModel()

m.fs = FlowsheetBlock(dynamic=False)
Expand All @@ -139,7 +140,7 @@ def build():

# ====================================================================
# Primary Clarifier
m.fs.CL = Separator(
m.fs.CL = Clarifier(
property_package=m.fs.props_ASM2D,
outlet_list=["underflow", "effluent"],
split_basis=SplittingType.componentFlow,
Expand Down Expand Up @@ -185,8 +186,7 @@ def build():
property_package=m.fs.props_ASM2D, outlet_list=["underflow", "overflow"]
)
# Secondary Clarifier
# TODO: Replace with more detailed model when available
m.fs.CL2 = Separator(
m.fs.CL2 = Clarifier(
property_package=m.fs.props_ASM2D,
outlet_list=["underflow", "effluent"],
split_basis=SplittingType.componentFlow,
Expand Down Expand Up @@ -233,6 +233,7 @@ def build():
outlet_reaction_package=m.fs.rxn_props_ADM1,
has_phase_equilibrium=False,
outlet_state_defined=True,
bio_P=bio_P,
)

# Anaerobic digester
Expand Down Expand Up @@ -515,7 +516,7 @@ def scale_variables(m):
iscale.calculate_scaling_factors(m)


def initialize_system(m):
def initialize_system(m, bio_P=False):
# Initialize flowsheet
# Apply sequential decomposition - 1 iteration should suffice
seq = SequentialDecomposition()
Expand All @@ -530,58 +531,113 @@ def initialize_system(m):
for o in order:
print(o[0].name)

# Initial guesses for flow into first reactor
tear_guesses = {
"flow_vol": {0: 1.2368},
"conc_mass_comp": {
(0, "S_A"): 0.0007,
(0, "S_F"): 0.000429,
(0, "S_I"): 0.05745,
(0, "S_N2"): 0.0534,
(0, "S_NH4"): 0.0092,
(0, "S_NO3"): 0.00403,
(0, "S_O2"): 0.00192,
(0, "S_PO4"): 0.0123,
(0, "S_K"): 0.373,
(0, "S_Mg"): 0.023,
(0, "S_IC"): 0.135,
(0, "X_AUT"): 0.1382,
(0, "X_H"): 3.6356,
(0, "X_I"): 3.2611,
(0, "X_PAO"): 3.3542,
(0, "X_PHA"): 0.089416,
(0, "X_PP"): 1.1127,
(0, "X_S"): 0.059073,
},
"temperature": {0: 308.15},
"pressure": {0: 101325},
}

tear_guesses2 = {
"flow_vol": {0: 0.003},
"conc_mass_comp": {
(0, "S_A"): 0.10,
(0, "S_F"): 0.16,
(0, "S_I"): 0.05745,
(0, "S_N2"): 0.039,
(0, "S_NH4"): 0.034,
(0, "S_NO3"): 0.0028,
(0, "S_O2"): 0.00136,
(0, "S_PO4"): 0.0254,
(0, "S_K"): 0.379,
(0, "S_Mg"): 0.0267,
(0, "S_IC"): 0.078,
(0, "X_AUT"): 0.342,
(0, "X_H"): 23.4,
(0, "X_I"): 11.5,
(0, "X_PAO"): 10.3,
(0, "X_PHA"): 0.0044,
(0, "X_PP"): 2.76,
(0, "X_S"): 3.83,
},
"temperature": {0: 308.15},
"pressure": {0: 101325},
}
if bio_P:
# Initial guesses for flow into first reactor
tear_guesses = {
"flow_vol": {0: 1.2368},
"conc_mass_comp": {
(0, "S_A"): 0.0009,
(0, "S_F"): 0.00042,
(0, "S_I"): 0.05745,
(0, "S_N2"): 0.0534,
(0, "S_NH4"): 0.0089,
(0, "S_NO3"): 0.0046,
(0, "S_O2"): 0.0046,
(0, "S_PO4"): 0.0118,
(0, "S_K"): 0.373,
(0, "S_Mg"): 0.023,
(0, "S_IC"): 0.1366,
(0, "X_AUT"): 0.135,
(0, "X_H"): 3.647,
(0, "X_I"): 3.314,
(0, "X_PAO"): 2.984,
(0, "X_PHA"): 0.083,
(0, "X_PP"): 0.9907,
(0, "X_S"): 0.05823,
},
"temperature": {0: 308.15},
"pressure": {0: 101325},
}

tear_guesses2 = {
"flow_vol": {0: 0.003},
"conc_mass_comp": {
(0, "S_A"): 0.10,
(0, "S_F"): 0.16,
(0, "S_I"): 0.05745,
(0, "S_N2"): 0.039,
(0, "S_NH4"): 0.035,
(0, "S_NO3"): 0.0032,
(0, "S_O2"): 0.00314,
(0, "S_PO4"): 0.0238,
(0, "S_K"): 0.379,
(0, "S_Mg"): 0.026,
(0, "S_IC"): 0.078,
(0, "X_AUT"): 0.342,
(0, "X_H"): 23.95,
(0, "X_I"): 11.9,
(0, "X_PAO"): 9.62,
(0, "X_PHA"): 0.0033,
(0, "X_PP"): 2.51,
(0, "X_S"): 3.92,
},
"temperature": {0: 308.15},
"pressure": {0: 101325},
}

else:
# Initial guesses for flow into first reactor
tear_guesses = {
"flow_vol": {0: 1.235},
"conc_mass_comp": {
(0, "S_A"): 0.0007,
(0, "S_F"): 0.0004,
(0, "S_I"): 0.0575,
(0, "S_N2"): 0.05,
(0, "S_NH4"): 0.007,
(0, "S_NO3"): 0.0035,
(0, "S_O2"): 0.00192,
(0, "S_PO4"): 0.02,
(0, "S_K"): 0.37,
(0, "S_Mg"): 0.02,
(0, "S_IC"): 0.11,
(0, "X_AUT"): 0.12,
(0, "X_H"): 3.3,
(0, "X_I"): 3.0,
(0, "X_PAO"): 2.3,
(0, "X_PHA"): 0.06,
(0, "X_PP"): 0.75,
(0, "X_S"): 0.050,
},
"temperature": {0: 308.15},
"pressure": {0: 101325},
}

tear_guesses2 = {
"flow_vol": {0: 0.0027},
"conc_mass_comp": {
(0, "S_A"): 0.044,
(0, "S_F"): 0.15,
(0, "S_I"): 0.0575,
(0, "S_N2"): 0.035,
(0, "S_NH4"): 0.03,
(0, "S_NO3"): 0.002,
(0, "S_O2"): 0.0012,
(0, "S_PO4"): 0.02,
(0, "S_K"): 0.38,
(0, "S_Mg"): 0.023,
(0, "S_IC"): 0.063,
(0, "X_AUT"): 0.31,
(0, "X_H"): 24.8,
(0, "X_I"): 11.8,
(0, "X_PAO"): 8.5,
(0, "X_PHA"): 0.086,
(0, "X_PP"): 2.1,
(0, "X_S"): 4.2,
},
"temperature": {0: 308.15},
"pressure": {0: 101325},
}

# Pass the tear_guess to the SD tool
seq.set_guesses_for(m.fs.R3.inlet, tear_guesses)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
# Some more information about this module
__author__ = "Chenyu Wang"

import pytest
import pytest

from pyomo.environ import assert_optimal_termination, value
Expand All @@ -29,15 +28,93 @@

from watertap.examples.flowsheets.case_studies.full_water_resource_recovery_facility.BSM2_P_extension import (
main,
solve,
)


class TestFullFlowsheet:
@pytest.mark.requires_idaes_solver
@pytest.fixture(scope="class")
def system_frame(self):
m, res = main()
m, res = main(bio_P=False)
m.results = res
return m

@pytest.mark.requires_idaes_solver
@pytest.mark.integration
def test_structure(self, system_frame):
assert_units_consistent(system_frame)
assert degrees_of_freedom(system_frame) == 0
assert_optimal_termination(system_frame.results)

@pytest.mark.requires_idaes_solver
@pytest.mark.component
def test_solve(self, system_frame):
m = system_frame

assert value(m.fs.Treated.properties[0].flow_vol) == pytest.approx(
0.2422, rel=1e-3
)
assert value(m.fs.Treated.properties[0].conc_mass_comp["S_A"]) == pytest.approx(
5.21698e-07, rel=1e-3
)
assert value(m.fs.Treated.properties[0].conc_mass_comp["S_F"]) == pytest.approx(
0.00029232, rel=1e-3
)
assert value(m.fs.Treated.properties[0].conc_mass_comp["S_I"]) == pytest.approx(
0.057450, rel=1e-3
)
assert value(
m.fs.Treated.properties[0].conc_mass_comp["S_N2"]
) == pytest.approx(0.058906, rel=1e-3)
assert value(
m.fs.Treated.properties[0].conc_mass_comp["S_NH4"]
) == pytest.approx(0.00012576, rel=1e-3)
assert value(
m.fs.Treated.properties[0].conc_mass_comp["S_NO3"]
) == pytest.approx(0.0097215, rel=1e-3)
assert value(
m.fs.Treated.properties[0].conc_mass_comp["S_O2"]
) == pytest.approx(0.00772288, rel=1e-3)
assert value(
m.fs.Treated.properties[0].conc_mass_comp["S_PO4"]
) == pytest.approx(0.495041, rel=1e-3)
assert value(m.fs.Treated.properties[0].conc_mass_comp["S_K"]) == pytest.approx(
0.37011, rel=1e-2
)
assert value(
m.fs.Treated.properties[0].conc_mass_comp["S_Mg"]
) == pytest.approx(0.01912677, rel=1e-3)
assert value(
m.fs.Treated.properties[0].conc_mass_comp["S_IC"]
) == pytest.approx(0.130732, rel=1e-3)
assert value(
m.fs.Treated.properties[0].conc_mass_comp["X_AUT"]
) == pytest.approx(0.00053442, rel=1e-3)
assert value(m.fs.Treated.properties[0].conc_mass_comp["X_H"]) == pytest.approx(
0.012031, rel=1e-3
)
assert value(m.fs.Treated.properties[0].conc_mass_comp["X_I"]) == pytest.approx(
0.0116256, rel=1e-3
)
assert value(
m.fs.Treated.properties[0].conc_mass_comp["X_PAO"]
) == pytest.approx(0.00805345, rel=1e-3)
assert value(
m.fs.Treated.properties[0].conc_mass_comp["X_PHA"]
) == pytest.approx(2.632e-06, rel=1e-3)
assert value(
m.fs.Treated.properties[0].conc_mass_comp["X_PP"]
) == pytest.approx(0.0027335, rel=1e-3)
assert value(m.fs.Treated.properties[0].conc_mass_comp["X_S"]) == pytest.approx(
0.00018726, rel=1e-3
)


class TestFullFlowsheetBioPTrue:
@pytest.mark.requires_idaes_solver
@pytest.fixture(scope="class")
def system_frame(self):
m, res = main(bio_P=True)
m.results = res
return m

Expand Down
Loading

0 comments on commit ac04ca7

Please sign in to comment.