Skip to content

Commit

Permalink
Dewatering and thickener unit models BSM2 (#1010)
Browse files Browse the repository at this point in the history
* dewtering unit model

* removing imports

* black

* black and doc error

* testing scaling

* pylint errors 1

* change blk to self

* pylint errors 2

* adding test and list error

* thickener unit model

* unit consistency check

* applying comments

* fix typo

* fix typo 2

* Update watertap/unit_models/thickener.py

Co-authored-by: Adam Atia <[email protected]>

* Update watertap/unit_models/dewatering.py

Co-authored-by: Adam Atia <[email protected]>

* chaine unit name in tests

* changing class name

* cleanup unused imports and add time index to TSS in dewaterer

* remove unused imports from test_dewatering

* more cleanup

---------

Co-authored-by: agarciadiego <>
Co-authored-by: Adam Atia <[email protected]>
  • Loading branch information
agarciadiego and adam-a-a authored Apr 27, 2023
1 parent a4fed99 commit a305488
Show file tree
Hide file tree
Showing 5 changed files with 881 additions and 0 deletions.
2 changes: 2 additions & 0 deletions watertap/unit_models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@
from .electrodialysis_1D import Electrodialysis1D
from .gac import GAC
from .ion_exchange_0D import IonExchange0D
from .thickener import Thickener
from .dewatering import DewateringUnit
163 changes: 163 additions & 0 deletions watertap/unit_models/dewatering.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
###############################################################################
# WaterTAP Copyright (c) 2021, 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/"
#
###############################################################################
"""
Dewatering unit model for BSM2. Based on IDAES separator unit
Model based on
J. Alex, L. Benedetti, J.B. Copp, K.V. Gernaey, U. Jeppsson,
I. Nopens, M.N. Pons, C. Rosen, J.P. Steyer and
P. A. Vanrolleghem
Benchmark Simulation Model no. 2 (BSM2)
"""
# Import IDAES cores
from idaes.core import (
declare_process_block_class,
)
from idaes.models.unit_models.separator import SeparatorData, SplittingType

from idaes.core.util.tables import create_stream_table_dataframe
import idaes.logger as idaeslog

from pyomo.environ import (
Param,
units as pyunits,
Set,
)

from idaes.core.util.exceptions import (
ConfigurationError,
)

__author__ = "Alejandro Garciadiego"


# Set up logger
_log = idaeslog.getLogger(__name__)


@declare_process_block_class("DewateringUnit")
class DewateringData(SeparatorData):
"""
Dewatering unit block for BSM2
"""

CONFIG = SeparatorData.CONFIG()
CONFIG.outlet_list = ["underflow", "overflow"]
CONFIG.split_basis = SplittingType.componentFlow

def build(self):
"""
Begin building model.
Args:
None
Returns:
None
"""

# Call UnitModel.build to set up dynamics
super(DewateringData, self).build()

if "underflow" and "overflow" not in self.config.outlet_list:
raise ConfigurationError(
"{} encountered unrecognised "
"outlet_list. This should not "
"occur - please use overflow "
"and underflow as outlets.".format(self.name)
)

self.p_dewat = Param(
initialize=0.28,
units=pyunits.dimensionless,
mutable=True,
doc="Percentage of suspended solids in the underflow",
)

self.TSS_rem = Param(
initialize=0.98,
units=pyunits.dimensionless,
mutable=True,
doc="Percentage of suspended solids removed",
)

@self.Expression(self.flowsheet().time, doc="Suspended solid concentration")
def TSS(blk, t):
return 0.75 * (
blk.inlet.conc_mass_comp[t, "X_I"]
+ blk.inlet.conc_mass_comp[t, "X_P"]
+ blk.inlet.conc_mass_comp[t, "X_BH"]
+ blk.inlet.conc_mass_comp[t, "X_BA"]
+ blk.inlet.conc_mass_comp[t, "X_S"]
)

@self.Expression(self.flowsheet().time, doc="Dewatering factor")
def f_dewat(blk, t):
return blk.p_dewat * (10 / (blk.TSS[t]))

@self.Expression(self.flowsheet().time, doc="Remove factor")
def f_q_du(blk, t):
return blk.TSS_rem / (pyunits.kg / pyunits.m**3) / 100 / blk.f_dewat[t]

self.non_particulate_components = Set(
initialize=[
"S_I",
"S_S",
"S_O",
"S_NO",
"S_NH",
"S_ND",
"H2O",
"S_ALK",
]
)

self.particulate_components = Set(
initialize=["X_I", "X_S", "X_P", "X_BH", "X_BA", "X_ND"]
)

@self.Constraint(
self.flowsheet().time,
self.particulate_components,
doc="particulate fraction",
)
def overflow_particulate_fraction(blk, t, i):
return blk.split_fraction[t, "overflow", i] == 1 - blk.TSS_rem

@self.Constraint(
self.flowsheet().time,
self.non_particulate_components,
doc="soluble fraction",
)
def non_particulate_components(blk, t, i):
return blk.split_fraction[t, "overflow", i] == 1 - blk.f_q_du[t]

def _get_performance_contents(self, time_point=0):
var_dict = {}
for k in self.split_fraction.keys():
if k[0] == time_point:
var_dict[f"Split Fraction [{str(k[1:])}]"] = self.split_fraction[k]
return {"vars": var_dict}

def _get_stream_table_contents(self, time_point=0):
outlet_list = self.create_outlet_list()

io_dict = {}
if self.config.mixed_state_block is None:
io_dict["Inlet"] = self.mixed_state
else:
io_dict["Inlet"] = self.config.mixed_state_block

for o in outlet_list:
io_dict[o] = getattr(self, o + "_state")

return create_stream_table_dataframe(io_dict, time_point=time_point)
Loading

0 comments on commit a305488

Please sign in to comment.