From b86c80fe606750e38c8960d3a60327c69e039986 Mon Sep 17 00:00:00 2001 From: Adam Atia Date: Fri, 8 Dec 2023 13:03:14 -0500 Subject: [PATCH] settle params for TSS and BOD5 --- .../activated_sludge/asm1_properties.py | 29 +++++++++++++------ .../activated_sludge/asm1_reactions.py | 22 +++----------- .../tests/test_asm1_thermo.py | 15 +++++++++- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/watertap/property_models/activated_sludge/asm1_properties.py b/watertap/property_models/activated_sludge/asm1_properties.py index 8b940e839b..8a327b7018 100644 --- a/watertap/property_models/activated_sludge/asm1_properties.py +++ b/watertap/property_models/activated_sludge/asm1_properties.py @@ -125,16 +125,12 @@ def build(self): doc="Reference temperature", units=pyo.units.K, ) - #TODO: f_p exists on the rxn parameter block and duplicating here temporarily; consolidate self.f_p = pyo.Var( initialize=0.08, units=pyo.units.dimensionless, domain=pyo.PositiveReals, doc="Fraction of biomass yielding particulate products, f_p", ) - self.f_p.fix() - - #TODO: i_xb and i_xp exist on rxn param block, duplicating temporarily; consolidate later self.i_xb = pyo.Var( initialize=0.08, units=pyo.units.dimensionless, @@ -147,8 +143,22 @@ def build(self): domain=pyo.PositiveReals, doc="Mass fraction of N per COD in particulates, i_xp", ) - self.i_xb.fix() - self.i_xp.fix() + self.COD_to_SS = pyo.Var( + initialize=0.75, + units=pyo.units.dimensionless, + domain=pyo.PositiveReals, + doc="Conversion factor applied for TSS calculation", + ) + self.BOD5_factor = pyo.Var( + ["raw", "effluent"], + initialize={"raw": 0.65, "effluent": 0.25}, + units=pyo.units.dimensionless, + domain=pyo.PositiveReals, + doc="Conversion factor for BOD5", + ) + # Fix Vars that are treated as Params + for v in self.component_objects(pyo.Var): + v.fix() @classmethod def define_metadata(cls, obj): @@ -387,19 +397,20 @@ def energy_density_expression(self): def _TSS(self): tss = self.conc_mass_comp["X_S"] + self.conc_mass_comp["X_I"] + self.conc_mass_comp["X_BH"] + self.conc_mass_comp["X_BA"] + self.conc_mass_comp["X_P"] - return 0.75*tss + return self.params.COD_to_SS * tss self.TSS = pyo.Expression( rule=_TSS, doc="Total suspended solids (TSS)", ) - def _BOD5(self): + def _BOD5(self, i): bod5 = self.conc_mass_comp["X_S"] + self.conc_mass_comp["X_S"] + (1-self.params.f_p)*(self.conc_mass_comp["X_BH"] + self.conc_mass_comp["X_BA"]) #TODO: 0.25 should be a parameter instead as it changes by influent/effluent - return 0.25*bod5 + return self.params.BOD5_factor[i]*bod5 self.BOD5 = pyo.Expression( + ["raw", "effluent"], rule=_BOD5, doc="Five-day Biological Oxygen Demand (BOD5)", ) diff --git a/watertap/property_models/activated_sludge/asm1_reactions.py b/watertap/property_models/activated_sludge/asm1_reactions.py index e4f09d09bb..d6645fb587 100644 --- a/watertap/property_models/activated_sludge/asm1_reactions.py +++ b/watertap/property_models/activated_sludge/asm1_reactions.py @@ -87,25 +87,11 @@ def build(self): domain=pyo.PositiveReals, doc="Yield of cell COD formed per g COD oxidized, Y_H", ) - self.f_p = pyo.Var( - initialize=0.08, - units=pyo.units.dimensionless, - domain=pyo.PositiveReals, - doc="Fraction of biomass yielding particulate products, f_p", - ) - self.i_xb = pyo.Var( - initialize=0.08, - units=pyo.units.dimensionless, - domain=pyo.PositiveReals, - doc="Mass fraction of N per COD in biomass, i_xb", - ) - self.i_xp = pyo.Var( - initialize=0.06, - units=pyo.units.dimensionless, - domain=pyo.PositiveReals, - doc="Mass fraction of N per COD in particulates, i_xp", - ) + add_object_reference(self, "f_p", self.config.property_package.f_p) + add_object_reference(self, "i_xb", self.config.property_package.i_xb) + add_object_reference(self, "i_xp", self.config.property_package.i_xp) + # Kinetic Parameters self.mu_A = pyo.Var( initialize=0.5, diff --git a/watertap/property_models/activated_sludge/tests/test_asm1_thermo.py b/watertap/property_models/activated_sludge/tests/test_asm1_thermo.py index 3267c4da8c..7c0813e45e 100644 --- a/watertap/property_models/activated_sludge/tests/test_asm1_thermo.py +++ b/watertap/property_models/activated_sludge/tests/test_asm1_thermo.py @@ -161,6 +161,18 @@ def test_build(self, model): "X_ND", ] assert value(model.props[1].conc_mass_comp[i]) == 0.1 + + assert isinstance(model.props[1].params.f_p, Var) + assert value(model.props[1].params.f_p) == 0.08 + assert isinstance(model.props[1].params.i_xb, Var) + assert value(model.props[1].params.i_xb) == 0.08 + assert isinstance(model.props[1].params.i_xp, Var) + assert value(model.props[1].params.i_xp) == 0.06 + assert isinstance(model.props[1].params.COD_to_SS, Var) + assert value(model.props[1].params.COD_to_SS) == 0.75 + assert isinstance(model.props[1].params.BOD5_factor, Var) + assert value(model.props[1].params.BOD5_factor["raw"]) == 0.65 + assert value(model.props[1].params.BOD5_factor["effluent"]) == 0.25 assert isinstance(model.props[1].material_flow_expression, Expression) for j in model.params.component_list: @@ -325,6 +337,7 @@ def check_units(self, model): def test_expressions(self, model): assert value(model.props[1].TSS) == 0.375 assert value(model.props[1].COD) == pytest.approx(0.7999, rel=1e-3) - assert value(model.props[1].BOD5) == 0.096 + assert value(model.props[1].BOD5["effluent"]) == 0.096 + assert value(model.props[1].BOD5["raw"]) == 0.096 *0.65/0.25 assert value(model.props[1].TKN) == pytest.approx(0.328, rel=1e-3) assert value(model.props[1].Total_N) == pytest.approx(0.428, rel=1e-3) \ No newline at end of file