BSM2-base plant documentation¶
This documentation of BSM2-Python's base class bsm2_base.py will guide you through the source code and help you to better understand the wastewater treatment plant layout of BSM2-Python.
Initialization¶
The initialization of the wastewater treatment plant objects and variables takes place in the definition of the __init__.
def __init__(
self,
data_in: np.ndarray | str | None = None,
timestep: float | None = None,
endtime: float | None = None,
evaltime: int | np.ndarray | None = None,
*,
tempmodel: bool = False,
activate: bool = False,
data_out: str | None = None,
):
super().__init__(
data_in=data_in,
timestep=timestep,
endtime=endtime,
evaltime=evaltime,
data_out=data_out,
)
- Initiates the
BSM2Baseobject with default parameters, setting up the simulation environment for the BSM2 model
# definition of the objects:
self.input_splitter = Splitter(sp_type=2)
self.bypass_plant = Splitter()
self.combiner_primclar_pre = Combiner()
self.primclar = PrimaryClarifier(
primclarinit.VOL_P,
primclarinit.YINIT1,
primclarinit.PAR_P,
asm1init.PAR1,
primclarinit.XVECTOR_P,
tempmodel=tempmodel,
activate=activate,
)
self.combiner_primclar_post = Combiner()
- Initiates Splitter
input_splitter - Initiates Splitter
bypass_plant - Initiates Combiner
combiner_primclar_pre - Initiates PrimaryClarifier
primclarwith initial parameters ofprimclarinit_bsm2andasm1init_bsm2 - Initiates Combiner
combiner_primclar_post
self.bypass_reactor = Splitter()
self.combiner_reactor = Combiner()
self.reactor1 = ASM1Reactor(
reginit.KLA1,
asm1init.VOL1,
asm1init.YINIT1,
asm1init.PAR1,
reginit.CARB1,
reginit.CARBONSOURCECONC,
tempmodel=tempmodel,
activate=activate,
)
self.reactor2 = ASM1Reactor(
reginit.KLA2,
asm1init.VOL2,
asm1init.YINIT2,
asm1init.PAR2,
reginit.CARB2,
reginit.CARBONSOURCECONC,
tempmodel=tempmodel,
activate=activate,
)
self.reactor3 = ASM1Reactor(
reginit.KLA3,
asm1init.VOL3,
asm1init.YINIT3,
asm1init.PAR3,
reginit.CARB3,
reginit.CARBONSOURCECONC,
tempmodel=tempmodel,
activate=activate,
)
self.reactor4 = ASM1Reactor(
reginit.KLA4,
asm1init.VOL4,
asm1init.YINIT4,
asm1init.PAR4,
reginit.CARB4,
reginit.CARBONSOURCECONC,
tempmodel=tempmodel,
activate=activate,
)
self.reactor5 = ASM1Reactor(
reginit.KLA5,
asm1init.VOL5,
asm1init.YINIT5,
asm1init.PAR5,
reginit.CARB5,
reginit.CARBONSOURCECONC,
tempmodel=tempmodel,
activate=activate,
)
self.splitter_reactor = Splitter()
self.settler = Settler(
settler1dinit.DIM,
settler1dinit.LAYER,
asm1init.QR,
asm1init.QW,
settler1dinit.settlerinit,
settler1dinit.SETTLERPAR,
asm1init.PAR1,
tempmodel,
settler1dinit.MODELTYPE,
)
self.combiner_effluent = Combiner()
- Initiates Splitter
bypass_reactor - Initiates Combiner
combiner_reactor - Initiates first, second, third, fourth and fifth ASM1Reactor
reactor1,reactor2,reactor3,reactor4andreactor5with initial parameters ofasm1init_bsm2andreginit_bsm2 -
Initiates Splitter
splitter_reactor -
Initiates Settler
settlerwith initial parameters ofsettler1dinit_bsm2andasm1init_bsm2 - Initiates Combiner
combiner_effluent
self.thickener = Thickener(thickenerinit.THICKENERPAR)
self.splitter_thickener = Splitter()
self.combiner_adm1 = Combiner()
self.adm1_reactor = ADM1Reactor(
adm1init.DIGESTERINIT, adm1init.DIGESTERPAR, adm1init.INTERFACEPAR, adm1init.DIM_D
)
self.dewatering = Dewatering(dewateringinit.DEWATERINGPAR)
self.storage = Storage(storageinit.VOL_S, storageinit.ystinit, tempmodel, activate)
self.splitter_storage = Splitter()
- Initiates Thickener
thickenerwith initial parameters ofthickenerinit_bsm2 -
Initiates Splitter
splitter_thickener -
Initiates Combiner
combiner_adm1 -
Initiates ADM1Reactor
adm1_reactorwith initial parameters ofadm1init_bsm2 -
Initiates Dewatering
dewateringwith initial parameters ofdewateringinit_bsm2 -
Initiates Storage
storagewith initial parameters ofstorageinit_bsm2 - Initiates Splitter
splitter_storage
Initialization of evaluation objects and variables to collect data for later evaluation.
self.performance = PlantPerformance(pp_init.PP_PAR)
- Initializes a PlantPerformance object
performancewith initial parameters ofplantperformanceinit_bsm2
self.y_in = self.data_in[:, 1:]
self.ys_tss_internal = np.zeros(settler1dinit.LAYER[1])
self.yd_out = np.zeros(51)
self.yst_vol = 0
(
self.yst_sp_p,
self.yt_sp_p,
self.y_out1,
self.y_out2,
self.y_out3,
self.y_out4,
self.y_out5,
self.ys_r,
self.ys_was,
self.ys_of,
self.yp_uf,
self.yp_of,
self.yp_internal,
self.yt_uf,
self.yd_in,
self.yi_out2,
self.ydw_s,
self.yst_out,
self.yst_sp_as,
self.yt_sp_as,
self.y_out5_r,
self.y_eff,
) = self._create_copies(self.y_in[0], 22)
- Initializes arrays and variables for the wastewater or sludge streams that flow between the wastewater treatment plant objects
At first for every wastewater and sludge stream the influent stream y_in is used to prevent that negative flow rates are calculated.
self.y_in_all = np.zeros((len(self.simtime), 21))
self.y_eff_all = np.zeros((len(self.simtime), 21))
self.y_in_bp_all = np.zeros((len(self.simtime), 21))
self.to_primary_all = np.zeros((len(self.simtime), 21))
self.prim_in_all = np.zeros((len(self.simtime), 21))
self.qpass_plant_all = np.zeros((len(self.simtime), 21))
self.qpassplant_to_as_all = np.zeros((len(self.simtime), 21))
self.qpassAS_all = np.zeros((len(self.simtime), 21))
self.to_as_all = np.zeros((len(self.simtime), 21))
self.feed_settler_all = np.zeros((len(self.simtime), 21))
self.qthick2AS_all = np.zeros((len(self.simtime), 21))
self.qthick2prim_all = np.zeros((len(self.simtime), 21))
self.qstorage2AS_all = np.zeros((len(self.simtime), 21))
self.qstorage2prim_all = np.zeros((len(self.simtime), 21))
self.sludge_all = np.zeros((len(self.simtime), 21))
self.y_out1_all = np.zeros((len(self.simtime), 21))
self.y_out2_all = np.zeros((len(self.simtime), 21))
self.y_out3_all = np.zeros((len(self.simtime), 21))
self.y_out4_all = np.zeros((len(self.simtime), 21))
self.y_out5_all = np.zeros((len(self.simtime), 21))
self.ys_r_all = np.zeros((len(self.simtime), 21))
self.ys_was_all = np.zeros((len(self.simtime), 21))
self.ys_of_all = np.zeros((len(self.simtime), 21))
self.ys_tss_internal_all = np.zeros((len(self.simtime), settler1dinit.LAYER[1]))
self.yp_uf_all = np.zeros((len(self.simtime), 21))
self.yp_of_all = np.zeros((len(self.simtime), 21))
self.yi_out2_all = np.zeros((len(self.simtime), 21))
self.yst_out_all = np.zeros((len(self.simtime), 21))
self.yst_vol_all = np.zeros((len(self.simtime), 2))
self.ydw_s_all = np.zeros((len(self.simtime), 21))
self.yt_uf_all = np.zeros((len(self.simtime), 21))
self.yp_internal_all = np.zeros((len(self.simtime), 21))
self.yd_out_all = np.zeros((len(self.simtime), 51))
self.yt_uf_all = np.zeros((len(self.simtime), 21))
- Initializes arrays to collect data from the wastewater or sludge streams
self.klas = np.array([reginit.KLA1, reginit.KLA2, reginit.KLA3, reginit.KLA4, reginit.KLA5])
# scenario 5, 75th percentile, 50% reduction when S_NH below 4g/m3
# self.controller = ControllerOxygen(self.timestep[0], 0.75, klas, 0.5, 4)
self.sludge_height = 0
self.ae = 0
self.pe = 0
self.me = 0
self.heat_demand = 0
self.iqi_all = np.zeros(len(self.simtime))
self.eqi_all = np.zeros(len(self.simtime))
self.oci_all = np.zeros(len(self.simtime))
self.perf_factors_all = np.zeros((len(self.simtime), 12))
self.violation_all = np.zeros(len(self.simtime))
self.qintr = asm1init.QINTR
self.y_out5_r[14] = self.qintr
-
Initializes
klasarray with all the KLa values for every activated sludge reactor with initial parameters ofreginit_bsm2 -
Initializes
sludge_heightvariable for the continuous signal of sludge blanket level of the Settler objectsettler -
Initializes variable
ae,pe,meandheat_demandfor collection of aeration energy, pumping energy, mixing energy and heat demand data -
Initializes array
iqi_all,eqi_all,oci_all,perf_factors_all, andviolation_allfor the collection of the influent quality index, effluent quality index, operation cost index, performance factors and violation data -
Defines
y_out5_r[14], the flow rate of the internal recirculation after the fifth activated sludge reactor with initial parameters ofasm1init_bsm2
Simulation loop¶
The simulation loop is defined in the step method, where wastewater treatment plant objects are connected with each other through wastewater and sludge streams.
Most wastewater and sludge flows in BSM2 are represented in the ASM1 (Activated Sludge Model No. 1) format as an array, containing 21 standard parameters (concentrations, flow rate, temperature and dummy states) to describe the stream. For more information visit the documentation of the combiner and splitter.
def step(self, i: int, *args, **kwargs):
- Defines the
stepmethod for the simulation loop
It simulates one time step of the BSM2 model with the index of the current time step i.
# timestep = timesteps[i]
step: float = self.simtime[i]
stepsize: float = self.timesteps[i]
self.reactor1.kla, self.reactor2.kla, self.reactor3.kla, self.reactor4.kla, self.reactor5.kla = self.klas
-
Sets up the current simulation time
stepand the time step sizestepsizefor theith iteration of the simulation -
Updates all five reactors with the corresponding oxygen transfer coefficients (
klaattributes) from theklasarray
# get influent data that is smaller than and closest to current time step
y_in_timestep = self.y_in[np.where(self.data_time <= step)[0][-1], :]
iqi = self.performance.iqi(y_in_timestep)[0]
self.iqi_all[i] = iqi
-
Defines the wastewater stream
y_in_timestepthat goes into the plant influent -
Collects data of the
iqifor every time step in theiqi_allarray
Method PlantPerformance.iqi calculates the influent quality index
| I/O | Variable | Description |
|---|---|---|
| Input | y_in_timestep | Wastewater stream that goes into the plant influent |
| Output | iqi | Influent quality index of the plant influent y_in_timestep |
yp_in_c, y_in_bp = self.input_splitter.output(y_in_timestep, (0.0, 0.0), float(reginit.QBYPASS))
y_plant_bp, y_in_as_c = self.bypass_plant.output(y_in_bp, (1 - reginit.QBYPASSPLANT, reginit.QBYPASSPLANT))
yp_in = self.combiner_primclar_pre.output(yp_in_c, self.yst_sp_p, self.yt_sp_p)
self.yp_uf, self.yp_of, self.yp_internal = self.primclar.output(stepsize, step, yp_in)
y_c_as_bp = self.combiner_primclar_post.output(self.yp_of[:21], y_in_as_c)
Splitters of type 1 (default) separate streams into multiple by a given split ratio and splitters of type 2 separate single streams into two, if a given flow rate threshold is exceeded.
Method Splitter.output; Splitter after plant influent, that splits when plant influent is overflowing; Type 2 Splitter with flow rate threshold of 60000 m³/d from reginit_bsm2
| I/O | Variable | Description |
|---|---|---|
| Input | y_in_timestep | Wastewater stream that goes into the plant influent |
| Output | yp_in_c | Wastewater stream that goes to the primary clarifier Combiner combiner_primclar_pre |
| Output | y_in_bp | Bypassed wastewater stream that goes to the Splitter bypass_plant |
Method Splitter.output; Bypass splitter, that directs the overflow either to the activated sludge system or directly to the plant effluent, in case of an overflowing plant influent (default: activated sludge system); Type 1 Splitter with split ratio from reginit_bsm2
| I/O | Variable | Description |
|---|---|---|
| Input | y_in_bp | Bypassed wastewater stream from the plant influent Splitter input_splitter |
| Output | y_plant_bp | Bypassed wastewater stream that goes to the plant effluent Combiner combiner_effluent |
| Output | y_in_as_c | Bypassed wastewater stream that goes to activated sludge system Combiner combiner_primclar_post |
Method Combiner.output; Combiner before primary clarifier
| I/O | Variable | Description |
|---|---|---|
| Input | yp_in_c | Wastewater stream from the plant influent Splitter input_splitter |
| Input | yst_sp_p | Wastewater stream from the wastewater storage Splitter splitter_storage |
| Input | yt_sp_p | Wastewater stream from the thickener Splitter splitter_thickener |
| Output | yp_in | Combined wastewater stream that goes into the PrimaryClarifier primclar |
Method PrimaryClarifier.output; Separates wastewater into two streams - primary effluent (overflow) and primary sludge (underflow); Further information in the Primary Clarifier documentation
| I/O | Variable | Description |
|---|---|---|
| Input | yp_in | Combined wastewater stream from the plant influent Combiner combiner_primclar_pre |
| Output | yp_uf | Primary sludge (underflow) that goes to the anaerobic digester Combiner combiner_adm1 |
| Output | yp_of | Primary effluent (overflow) that goes to the activated sludge system Combiner combiner_primclar_post |
| - | yp_internal | Internal wastewater for evaluation purposes |
Method Combiner.output; Combiner after primary clarifier
| I/O | Variable | Description |
|---|---|---|
| Input | yp_of | Primary effluent (overflow) from the PrimaryClarifier primclar |
| Input | y_in_as_c | Bypassed wastewater stream from the plant influent Splitter bypass_plant |
| Output | y_c_as_bp | Wastewater stream that goes to the Splitter bypass_reactor |
y_bp_as, y_as_bp_c_eff = self.bypass_reactor.output(y_c_as_bp, (1 - reginit.QBYPASSAS, reginit.QBYPASSAS))
y_in1 = self.combiner_reactor.output(self.ys_r, y_bp_as, self.yst_sp_as, self.yt_sp_as, self.y_out5_r)
self.y_out1 = self.reactor1.output(stepsize, step, y_in1)
self.y_out2 = self.reactor2.output(stepsize, step, self.y_out1)
self.y_out3 = self.reactor3.output(stepsize, step, self.y_out2)
self.y_out4 = self.reactor4.output(stepsize, step, self.y_out3)
self.y_out5 = self.reactor5.output(stepsize, step, self.y_out4)
ys_in, self.y_out5_r = self.splitter_reactor.output(
self.y_out5, (max(self.y_out5[14] - self.qintr, 0.0), float(self.qintr))
)
self.ys_r, self.ys_was, self.ys_of, _, self.ys_tss_internal = self.settler.output(stepsize, step, ys_in)
Method Splitter.output; Bypass splitter before activated sludge system, that bypasses the entire primary clarifier effluent to the plant effluent if activated (default: not activated); Type 1 Splitter with split ratio from reginit_bsm2
| I/O | Variable | Description |
|---|---|---|
| Input | y_c_as_bp | Combined wastewater stream from the post primary clarifier Splitter combiner_primclar_post |
| Output | y_bp_as | Wastewater stream that goes to the activated sludge system Combiner combiner_reactor |
| Output | y_as_bp_c_eff | Bypassed wastewater stream that goes to the plant effluent Combiner combiner_effluent |
Method Combiner.output; Combiner before activated sludge system
| I/O | Variable | Description |
|---|---|---|
| Input | ys_r | Returned sludge stream from the Settler settler |
| Input | y_bp_as | Wastewater stream from the post primary clarifier Splitter combiner_primclar_post |
| Input | yst_sp_as | Wastewater stream from wastewater storage Splitter splitter_storage |
| Input | yt_sp_as | Wastewater stream from the thickener Splitter splitter_thickener |
| Input | y_out5_r | Wastewater stream from the post activated sludge system Splitter splitter_reactor |
| Output | y_in1 | Wastewater stream that goes into the first ASM1Reactor reactor1 |
Method ASM1Reactor.output; Activated sludge reactor with anoxic conditions (KLa = 0) for removal of nitrogen (denitrification); Further information in the Activated Sludge Reactor documentation
| I/O | Variable | Description |
|---|---|---|
| Input | y_in1 | Combined wastewater stream from the Combiner combiner_reactor |
| Output | y_out1 | Wastewater stream that goes into the second ASM1Reactor reactor2 |
Method ASM1Reactor.output; Activated sludge reactor with anoxic conditions (KLa = 0) for denitrification; Further information in the Activated Sludge Reactor documentation
| I/O | Variable | Description |
|---|---|---|
| Input | y_out1 | Wastewater stream from the first ASM1Reactor reactor1 |
| Output | y_out2 | Wastewater stream that goes into the third ASM1Reactor reactor3 |
Method ASM1Reactor.output; Activated sludge reactor with aerobic conditions (KLa = 120) for carbon decomposition and nitrification; Further information in the Activated Sludge Reactor documentation
| I/O | Variable | Description |
|---|---|---|
| Input | y_out2 | Wastewater stream from the second ASM1Reactor reactor2 |
| Output | y_out3 | Wastewater stream that goes into the fourth ASM1Reactor reactor4 |
Method ASM1Reactor.output; Activated sludge reactor with aerobic conditions (KLa = 120) for carbon decomposition and nitrification; Further information in the Activated Sludge Reactor documentation
| I/O | Variable | Description |
|---|---|---|
| Input | y_out3 | Wastewater stream from the third ASM1Reactor reactor3 |
| Output | y_out4 | Wastewater stream that goes into the fifth ASM1Reactor reactor5 |
Method ASM1Reactor.output; Activated sludge reactor with aerobic conditions (KLa = 60) for carbon decomposition and nitrification; Further information in the Activated Sludge Reactor documentation
| I/O | Variable | Description |
|---|---|---|
| Input | y_out4 | Wastewater stream from the fourth ASM1Reactor reactor4 |
| Output | y_out5 | Wastewater stream that goes to the post activated sludge Splitter splitter_reactor |
Method Splitter.output; Splitter after activated sludge system, for internal sludge recirculation; Type 1 Splitter with split ratio from qintr
| I/O (21) | Variable | Description |
|---|---|---|
| Input | y_out5 | Wastewater stream from the fifth ASM1Reactor reactor5 |
| Output | ys_in | Wastewater stream that goes into the Settler settler |
| Output | y_out5_r | Internal recirculation stream that goes back to the activated sludge system Combiner combiner_reactor |
Method Settler.output; Separates wastewater into two streams - effluent (overflow) and sludge (underflow); Further information in the Settler documentation
| I/O | Variable | Description |
|---|---|---|
| Input | ys_in | Wastewater stream from the post activated sludge Splitter splitter_reactor |
| Output | ys_r | Returned sludge stream that goes to the activated sludge system Combiner combiner_reactor |
| Output | ys_was | Waste sludge stream that goes into the Thickener thickener |
| Output | ys_of | Wastewater stream that goes to the plant effluent Combiner combiner_effluent |
| Output | _ | Sludge height for evaluation purposes (not used) |
| Output | ys_tss_internal | Internal total suspended solids (TSS) states of the settler for evaluation purposes |
self.y_eff = self.combiner_effluent.output(y_plant_bp, y_as_bp_c_eff, self.ys_of)
eqi = self.performance.eqi(self.ys_of, y_plant_bp, y_as_bp_c_eff)[0]
self.eqi_all[i] = eqi
self.yt_uf, yt_of = self.thickener.output(self.ys_was)
self.yt_sp_p, self.yt_sp_as = self.splitter_thickener.output(
yt_of, (1 - reginit.QTHICKENER2AS, reginit.QTHICKENER2AS)
)
- Collects data of the
eqifor every time step in theeqi_allarray
Method Combiner.output; Combiner before the plant effluent
| I/O (27) | Variable | Description |
|---|---|---|
| Input | y_plant_bp | Bypassed wastewater stream from the plant influent Splitter bypass_plant |
| Input | y_as_bp_c_eff | Bypassed wastewater stream from the pre activated sludge system Splitter bypass_reactor |
| Input | ys_of | Wastewater stream from the Settler settler |
| Output | y_eff | Wastewater stream that goes in the plant effluent |
Method PlantPerformance.eqi calculates the effluent quality index
| I/O | Variable | Description |
|---|---|---|
| Input | ys_of | Wastewater stream from the Settler settler |
| Input | y_plant_bp | Bypassed wastewater stream from the plant influent Splitter bypass_plant |
| Input | y_as_bp_c_eff | Bypassed wastewater stream from the pre activated sludge system Splitter bypass_reactor |
| Output | eqi | Effluent quality index of the plant effluent |
Method Thickener.output; Separates the stream into residual effluent (overflow) and thickened sludge (underflow); Further information in the Thickener documentation
| I/O | Variable | Description |
|---|---|---|
| Input | ys_was | Waste sludge stream from the Settler settler |
| Output | yt_uf | Thickened sludge (underflow) that goes to the anaerobic digester Combiner combiner_adm1 |
| Output | yt_of | Residual effluent (overflow) that goes to the post thickener Splitter splitter_thickener |
Method Splitter.output; Splitter after thickener, that directs the entire flow either to the primary clarifier or to the activated sludge system (default: primary clarifier); Type 1 Splitter with split ratio from reginit_bsm2
| I/O | Variable | Description |
|---|---|---|
| Input | yt_of | Residual effluent (overflow) from the Thickener thickener |
| Output | yt_sp_p | Residual effluent (overflow) that goes to the pre primary clarifier Combiner combiner_primclar_pre |
| Output | yt_sp_as | Residual effluent (overflow) that goes to the pre activated sludge system Combiner combiner_reactor |
self.yd_in = self.combiner_adm1.output(self.yt_uf, self.yp_uf)
self.yi_out2, self.yd_out, _ = self.adm1_reactor.output(stepsize, step, self.yd_in, reginit.T_OP)
self.ydw_s, ydw_r = self.dewatering.output(self.yi_out2)
self.yst_out, self.yst_vol = self.storage.output(stepsize, step, ydw_r, reginit.QSTORAGE)
self.yst_sp_p, self.yst_sp_as = self.splitter_storage.output(
self.yst_out, (1 - reginit.QSTORAGE2AS, reginit.QSTORAGE2AS)
)
Method Combiner.output; Combiner before anaerobic digester
| I/O | Variable | Description |
|---|---|---|
| Input | yt_uf | Thickened sludge (underflow) from the Thickener thickener |
| Input | yp_uf | Primary sludge (underflow) from the PrimaryClarifier primclar |
| Output | yd_in | Combined sludge stream that goes into the ADM1Reactor adm1_reactor |
Method ADM1Reactor.output; Breaks down sewage sludge to produce methane gas; Further information in the Anaerobic Digester documentation
| I/O | Variable | Description |
|---|---|---|
| Input | yd_in | Combined sludge stream from the anaerobic digester Combiner combiner_adm1 |
| Output | yi_out2 | Fermented sludge stream (ASM1 format) that goes into the Dewatering dewatering |
| Output | yd_out | Fermented sludge stream (ADM1 format) for evaluation purposes |
| Output | _ | Combined sludge stream (turned in ADM1 format) from the anaerobic digester Combiner combiner_adm1 (not used) |
Method Dewatering.output; Separates the stream into reject wastewater (overflow) and dewatered/waste sludge (underflow); Further information in the Dewatering documentation
| I/O | Variable | Description |
|---|---|---|
| Input | yi_out2 | Fermented sludge stream from the ADM1Reactor adm1_reactor |
| Output | ydw_s | Dewatered/waste sludge (underflow) that leaves the plant |
| Output | ydw_r | Reject wastewater (overflow) that goes into the Storage storage |
Method Storage.output; Holds reject wastewater before recycling it back to either primary clarifier or the activated sludge system; Further information in the Storage documentation
| I/O | Variable | Description |
|---|---|---|
| Input | ydw_r | Reject wastewater (overflow) from the Dewatering dewatering |
| Output | yst_out | Stored wastewater that goes to the post storage Splitter splitter_storage |
| Output | yst_vol | Volume of the storage tank for evaluation purposes |
Method Splitter.output; Splitter after wastewater storage, that directs the entire flow either to the primary clarifier or to the activated sludge system (default: primary clarifier); Type 1 Splitter with split ratio from reginit_bsm2
| I/O | Variable | Description |
|---|---|---|
| Input | yst_out | Stored wastewater from the Storage storage |
| Output | yst_sp_p | Stored wastewater that goes to the pre primary clarifier Combiner combiner_primclar_pre |
| Output | yst_sp_as | Stored wastewater that goes to the activated sludge system Combiner combiner_reactor |
In the simulation loop data is also collected from each time step to evaluate the plant performance and wastewater treatment parameters.
vol = np.array(
[
self.reactor1.volume,
self.reactor2.volume,
self.reactor3.volume,
self.reactor4.volume,
self.reactor5.volume,
self.adm1_reactor.volume_liq,
]
)
sosat = np.array([asm1init.SOSAT1, asm1init.SOSAT2, asm1init.SOSAT3, asm1init.SOSAT4, asm1init.SOSAT5])
self.ae = self.performance.aerationenergy_step(self.klas, vol[0:5], sosat)
flows = np.array([self.qintr, asm1init.QR, asm1init.QW, self.yp_uf[14], self.yt_uf[14], self.ydw_s[14]])
self.pe = self.performance.pumpingenergy_step(flows, pp_init.PP_PAR[10:16])
self.me = self.performance.mixingenergy_step(self.klas, vol, pp_init.PP_PAR[16])
-
Initializes
volarray with the volume for each activated sludge reactor and the anaerobic digester -
Initializes
sosatarray with the saturated oxygen concentrations for each activated sludge reactor -
Initializes
flowsarray with all flow rates that are operated by a pump
Method PlantPerformance.aerationenergy_step evaluates the aeration energy of the plant during the evaluation time
| I/O | Variable | Description |
|---|---|---|
| Input | klas | Array with all the KLa values for the activated sludge reactors |
| Input | vol[0:5] | Array with all the volumes of the activated sludge reactors |
| Input | sosat | Array with the saturated oxygen concentrations for the activated sludge reactors |
| Output | ae | Aeration energy during the evaluation time |
Method PlantPerformance.pumpingenergy_step evaluates the pumping energy of the plant during the evaluation time
| I/O | Variable | Description |
|---|---|---|
| Input | flows | Array with all the KLa values for the activated sludge reactors |
| Input | pp_init.PP_PAR[10:16] | Array with the pumping energy factors for the individual flows from plantperformanceinit_bsm2 |
| Output | pe | Pumping energy during the evaluation time |
Method PlantPerformance.mixingenergy_step evaluates the mixing energy of the plant during the evaluation time
| I/O | Variable | Description |
|---|---|---|
| Input | klas | Array with all the KLa values for the activated sludge reactors and the anaerobic digester |
| Input | vol | Array with the volume for each activated sludge reactor and the anaerobic digester |
| Input | pp_init.PP_PAR[16] | Mixing energy factor for anaerobic digester unit from plantperformanceinit_bsm2 |
| Output | me | Pumping energy during the evaluation time |
tss_mass = self.performance.tss_mass_bsm2(
self.yp_of,
self.yp_uf,
self.yp_internal,
self.y_out1,
self.y_out2,
self.y_out3,
self.y_out4,
self.y_out5,
self.ys_tss_internal,
self.yd_out,
self.yst_out,
self.yst_vol,
)
Method PlantPerformance.tss_mass_bsm2 calculates the sludge production of the BSM2 plant setup
| I/O | Variable | Description |
|---|---|---|
| Input | yp_of | Primary clarifier overflow (effluent) concentrations |
| Input | yp_uf | Primary clarifier underflow (sludge) concentrations |
| Input | yp_internal | Primary clarifier internal (basically influent) concentrations |
| Input | y_out1 | Concentrations of the 21 components after the first ASM reactor |
| Input | y_out2 | Concentrations of the 21 components after the second ASM reactor |
| Input | y_out3 | Concentrations of the 21 components after the third ASM reactor |
| Input | y_out4 | Concentrations of the 21 components after the fourth ASM reactor |
| Input | y_out5 | Concentrations of the 21 components after the fifth ASM reactor |
| Input | ys_tss_internal | Total suspended solids (TSS) concentrations of the internals of the settler |
| Input | yd_out | Concentrations of the 51 components and gas phase parameters after the digester |
| Input | yst_out | Concentrations of the 21 components in the effluent of the storage tank |
| Input | yst_vol | Current volume of the storage tank |
| Output | tss_mass | Sludge production of the BSM2 plant setup |
ydw_s_tss_flow = self.performance.tss_flow(self.ydw_s)
y_eff_tss_flow = self.performance.tss_flow(self.y_eff)
carb = reginit.CARB1 + reginit.CARB2 + reginit.CARB3 + reginit.CARB4 + reginit.CARB5
added_carbon_mass = self.performance.added_carbon_mass(carb, reginit.CARBONSOURCECONC)
self.heat_demand = self.performance.heat_demand_step(self.yd_in, reginit.T_OP)[0]
ch4_prod, h2_prod, co2_prod, q_gas = self.performance.gas_production(self.yd_out, reginit.T_OP)
- Calculates float variable
carbwith the sum of external carbon flow rate that goes into the activated sludge system fromreginit_bsm2
Method PlantPerformance.tss_flow calculates the total suspended solids (TSS) flow out of a reactor
| I/O | Variable | Description |
|---|---|---|
| Input | ydw_s | Waste sludge (underflow) concentrations of the dewatering unit |
| Output | ydw_s_tss_flow | Total suspended solids (TSS) flow of the dewatering waste sludge stream |
Method PlantPerformance.tss_flow calculates the total suspended solids (TSS) flow out of a reactor
| I/O | Variable | Description |
|---|---|---|
| Input | y_eff | Effluent wastewater stream |
| Output | y_eff_tss_flow | Total suspended solids (TSS) flow of the effluent stream |
Method PlantPerformance.added_carbon_mass calculates the total added carbon mass
| I/O | Variable | Description |
|---|---|---|
| Input | carb | Sum of external carbon flow rate that goes in AS system |
| Input | reginit.CARBONSOURCECONC | External carbon source concentration from reginit_bsm2 |
| Output | added_carbon_mass | Total carbon mass added into the AS system |
Method PlantPerformance.heat_demand_step calculates the heating demand of the sludge flow to the anaerobic digester
| I/O | Variable | Description |
|---|---|---|
| Input | yd_in | Sludge stream that goes into the anaerobic digester |
| Input | reginit.T_OP | Operating temperature of the anaerobic digester from reginit_bsm2 |
| Output | heat_demand | Heat demand of the sludge flow that goes into the anaerobic digester |
Method PlantPerformance.gas_production calculates the gas production of the anaerobic digester
| I/O | Variable | Description |
|---|---|---|
| Input | yd_out | Sludge stream that goes out of the anaerobic digester |
| Input | reginit.T_OP | Operating temperature of the anaerobic digester from reginit_bsm2 |
| Output | ch4_prod | Methane production of the anaerobic digester |
| Output | h2_prod | Hydrogen production of the anaerobic digester |
| Output | co2_prod | Carbon dioxide production of the anaerobic digester |
| Output | q_gas | Total gas flow rate of the anaerobic digester |
# This calculates an approximate oci value for each time step,
# neglecting changes in the tss mass inside the whole plant
self.oci_all[i] = self.performance.oci(
self.pe * 24,
self.ae * 24,
self.me * 24,
ydw_s_tss_flow,
added_carbon_mass,
self.heat_demand * 24,
ch4_prod,
)
- Collects
ocidata for every time step in theoci_allarray
Method PlantPerformance.oci calculates the operational cost index of the plant
| I/O | Variable | Description |
|---|---|---|
| Input | pe * 24 | Pumping energy of the BSM2 plant setup |
| Input | ae * 24 | Aeration energy of the BSM2 plant setup |
| Input | me * 24 | Mixing energy of the BSM2 plant setup |
| Input | ydw_s_tss_flow | Total suspended solids (TSS) flow of the dewatering waste sludge stream |
| Input | added_carbon_mass | Total carbon mass added into the AS system |
| Input | heat_demand * 24 | Heat demand of the sludge flow that goes into the anaerobic digester |
| Input | ch4_prod | Methane production of the anaerobic digester |
| Input | q_gas | Total gas flow rate of the anaerobic digester |
| Output | oci_all[i] | Operational cost index of the plant |
# These values are used to calculate the exact performance values at the end of the simulation
self.perf_factors_all[i, :12] = [
self.pe * 24,
self.ae * 24,
self.me * 24,
ydw_s_tss_flow,
y_eff_tss_flow,
tss_mass,
added_carbon_mass,
self.heat_demand * 24,
ch4_prod,
h2_prod,
co2_prod,
q_gas,
]
- Collects all performance values for each time step in
perf_factors_allarray
self.y_in_all[i] = y_in_timestep
self.y_eff_all[i] = self.y_eff
self.y_in_bp_all[i] = y_in_bp
self.to_primary_all[i] = yp_in_c
self.prim_in_all[i] = yp_in
self.qpass_plant_all[i] = y_plant_bp
self.qpassplant_to_as_all[i] = y_in_as_c
self.qpassAS_all[i] = y_as_bp_c_eff
self.to_as_all[i] = y_bp_as
self.feed_settler_all[i] = ys_in
self.qthick2AS_all[i] = self.yt_sp_as
self.qthick2prim_all[i] = self.yt_sp_p
self.qstorage2AS_all[i] = self.yst_sp_as
self.qstorage2prim_all[i] = self.yst_sp_p
self.sludge_all[i] = self.ydw_s
# data for calculation of final oci
self.violation_all[i] = self.performance.violation_step(self.y_eff[SNH], 4)[0]
self.y_out1_all[i] = self.y_out1
self.y_out2_all[i] = self.y_out2
self.y_out3_all[i] = self.y_out3
self.y_out4_all[i] = self.y_out4
self.y_out5_all[i] = self.y_out5
self.ys_r_all[i] = self.ys_r
self.ys_was_all[i] = self.ys_was
self.ys_of_all[i] = self.ys_of
self.ys_tss_internal_all[i] = self.ys_tss_internal
self.yp_uf_all[i] = self.yp_uf
self.yp_of_all[i] = self.yp_of
self.yt_uf_all[i] = self.yt_uf
self.yd_out_all[i] = self.yd_out
self.yi_out2_all[i] = self.yi_out2
self.yst_out_all[i] = self.yst_out
self.yst_vol_all[i] = self.yst_vol, step
self.ydw_s_all[i] = self.ydw_s
self.yp_internal_all[i] = self.yp_internal
- Collecting all wastewater and sludge stream data for every time step in arrays
Also see the full source code
modbsm2_base.py