You are on page 1of 37

Whats New in STOAT 4.

2
Introduction .................................................................................................................. 3
New Process Models..................................................................................................... 5
Screening .............................................................................................................................. 5
Grit trap ............................................................................................................................... 6
Sand filtration ...................................................................................................................... 7
UV disinfection .................................................................................................................... 9
Chlorination ....................................................................................................................... 13
Reactive settlers ................................................................................................................. 14
Collocation biofilm models ............................................................................................... 14
Instrumentation ................................................................................................................. 15

Graphical Process Reporting ..................................................................................... 17


User-defined Models................................................................................................... 20
STOAT ASM............................................................................................................... 20
APPENDIX - User-defined Models ........................................................................... 21
File location ........................................................................................................................ 21
Program file ....................................................................................................................... 22
Menu files ........................................................................................................................... 22
Example.............................................................................................................................. 23
Contents of USER.DAT file.............................................................................................. 24
Contents of menu file (menu.txt).................................................................................. 24
Fortran routines ................................................................................................................ 27

Introduction
STOAT 4.1 was released in May 1999. This version, STOA4.2, was released
in August 2001. This release contains many small enhancements and
corrections that have been made in the intervening two years. In addition to
these there have been the following:
There have been several new process models added, and extensions to
existing process models. The range of preliminary and tertiary treatment
models has been increased, and there is now support for reactive
secondary clarifiers. In addition, there is a new process model, NIVAPlant,
available from the Norwegian Water Research Institute, NIVA. NIVAPlant
encompasses the Norwegian knowledge of chemically-assisted
sedimentation, both to enhance the removal of TSS and BOD/COD and
also to remove phosphorus. If you wish to add NIVAPlant to your STOAT
please contact Harsha Ratnaweera of NIVA at the following e-mail
address: Harsha.Ratnaweera@niva.no. We would be interested in
knowing about your interest in NIVAPlant, or if you have models that you
would like advertised as being available through STOAT. You can e-mail
us at STOAT@wrcplc.co.uk. This guide includes information on how you
can write your own models to work with STOAT.
At the end of a simulation you can now view the results from the process
models graphically, as well as tables of summary statistics and time
series. Where the process has a single stage the results will be displayed
as line plots, and multiple stage processes will be displayed as threedimensional graphs. At present the biofilm models do not support
graphical output, as this requires four-dimensional graphs time (T),
distance into the biofilm (Y), distance along the reactor (X), and the value
at this (T, Y, X) point.
Support for the DHI/WRc Integrated Catchment Simulator (ICS) and
improved support for Wallingford Softwares InfoWorks system.
The ICS allows you to run simulations using sewer models (MOUSE),
sewage works models (STOAT) and river models (MIKE), with data
exchange between the three programs. This provides for a great
improvement in the support for modelling the feasibility of real-time
control of the entire catchment. More information on the ICS can be
found by e-mailing WRc at ICS@wrcplc.co.uk
InfoWorks allows you to carry out similar integrated modelling, using
STOAT along with Wallingford Softwares sewer model HydroWorks
and their river model ISIS. These two enhancements further position
STOAT as the tool designed for ease of use when studying catchmentwide decision modelling.
A spin-off from the DHI ICS system is that there is now a COM
interface that allows STOAT To be controlled by other programs. This
is currently being used as part of a research project by NIVA to send
3

SCADA data to STOAT to examine real-time output as part of online


control investigations. If you wish to pursue this aspect of STOAT
please e-mail us at STOAT@wrcplc.co.uk. We will be delighted to help
you implement controlling STOAT through your own applications,
extending this interface as necessary to ensure that you get the best
out of STOAT to meet your own needs.
You can now write your own process models and integrate them into
STOAT. Details are given in the section introducing user-defined models.
We are willing to assist you in getting your first model to work within the
STOAT framework. One valuable feature of the STOAT approach to userdefined models is that they can be written in any computer language of
your choice, providing that the language can produce dynamic link libraries
(DLLs). This means that you can easily use C, C++, Fortran, Pascal/Delphi
and some versions of Basic, and even Lisp, SmallTalk or Prolog!
Finally, we will be using our web site, http://www.wrcplc.co.uk/software, to
provide ongoing support. On the web site we will post future upgrades for
STOAT 4.2 what Microsoft refers to as Service Packs and also later
releases of STOAT.

New Process Models


Screening

The data entry forms are shown below. The bar spacing affects the
screenings production. The screenings production1 can also be changed
under sewage calibration, by choosing either Average or Maximum.
Screenings are assumed to be gross solids that are not captured by traditional
sampling methods and therefore the screening model has no effect on the
sewage quality passing through it.

The model is based on curves of screening production published in RL Droste,


Theory and Practice of Water and Wastewater Treatment, Wiley

Grit trap

The grit trap data entry forms are shown below. At present the volume of the
grit trap has no process significance all that is required is that be a value
greater than zero. The grit removal is specified as g/l, and is the removal of
nonvolatile suspended solids from the influent stream.

Sand filtration
Bypass
Influent
Backwash

Effluent

There are two sand filtration models, Simple and Time varying. Both are
mass-balance based models.
The Simple model is a steady-state approximation to the back-wash
performance. The bypass stream is never used. You must connect an outlet
stream to this connector, but there is never any flow down it. For this model
performance is defined by specifying what fraction of the incoming flow is
diverted as the backwash, and what is the efficiency of solids removal the
recovery fraction. There is a continuous flow through both the backwash and
effluent streams.
The Time varying model also uses a simple equation to calculate the
efficiency of solids removal, but now that efficiency may vary over time, and
you also specify a backwash frequency and period during the backwash
period all flow is diverted through the bypass line, the backwash stream only
has a flow during the backwash period and the effluent stream only has a flow
outside the backwash period. The backwash flow is assumed to come from a
clean source, and is not explicitly modelled.

Operational data entry for the simple model

Operational data entry for the time varying model

The clean efficiency is the efficiency at the start of each operating cycle. The
efficiency falls off with time, but will never fall off below the worst efficiency.
The equation relating the fall-off in performance with time is given by
Efficiency = Best efficiency exp(-fouling coefficient time)
The phase time is used to set up an operating stagger when several sand
filters are present on the flowsheet.

UV disinfection

The UV disinfection model is based on a correlation2 from the US Water


Environment Research Foundation (WERF). This model uses the UV
intensity, which is dependent on the number of UV tubes, their spacing, power
output, assumptions about fouling coefficients, etc. The model predicts the
coliform count in the final effluent, not the log removal of coliforms.

The UV intensity in a uniform lamp array can be estimated from the following
chart:

FJ Loge et al, 1996, Water Environment Research 68(5) 900-916. Original work in
WEF, 1995, Comparison of UV irradiation to chlorination: Guidance for achieving
optimal UV performance, ISBN 95-060880, WEF # 91-WWD-1

An example of its use is given in the following figure: Start at the spacing axis.
Move horizontally left to the UV density in the reactor. Move down until you
intersect the appropriate UV absorbance coefficient, . Move left until you
intersect the UV intensity. The UV absorbance coefficient is calculated using
%UV transmittance over 1 cm at 254 nm
= 2.303 log 10

100

10

11

The model can be calibrated by adjusting the WERF parameters, but this will
obviously require access to coliform count results.

A:

The WERF model uses the equation


Count = 10 A TSS a UFT b D n
where Count = coliform count
TSS = total suspended solids, mg/l
UFT = unfiltered UV transmissivity, %
D = UV dose, mWs/cm2
Because STOAT does not predict the unfiltered UV transmittance this is
approximated by a further correlation on suspended solids, as
UFT = Atransmittance - Btransmittance TSS

12

Chlorination

The chlorination model is a simple representation of chlorine kill, using the


equation
% Survival = 100 exp(-kill rate dose time)

13

Reactive settlers
STOAT has added the following reactive settlers for the secondary settling
tank:
ASAL 1
ASAL 2
ASAL 3
ASAL 5
ASM 1
ASM 2d
ASM 2w3
ASM 3

This should be used with the ASAL 1/1A and OXID 1 aeration tanks
This should be used with the ASAL 2/2A and OXID 2 aeration tanks
This should be used with the ASAL 3/3A and OXID 3 aeration tanks
This should be used with the ASAL 5/5A and OXID 5 aeration tanks
This should be used with the IAWQ #1 aeration tanks
This should be used with the IAWQ #2d aeration tanks
This should be used with the IAWQ #2w aeration tanks
This should be used with the IAWQ #3aeration tanks

When selecting a reactive settler model we recommend that you adopt the
following procedure:
1. Set up all the aeration tanks to use the required kinetic model (ASAL 1,
IAWWQ #1, etc.)
2. Set up the secondary settlers to use the desired matching kinetic model
3. Close the settler Name and dimensions dialogue, then re-open. On the
second page of the dialogue you are asked to enter the name of the
activated sludge tank that will be used to pick up the kinetic data. The list
of allowable names will be filtered to display only those that are valid for
the chosen settling tank reaction model.
The models ASL 1, ASAL 2 and ASAL 5 are sufficiently simple on their data
needs that this is repeated under Sewage Calibration rather than being taken
from the corresponding aeration tank. For the models ASAL 3, ASM 1, ASM
2d, ASM 2w and ASM 3 the reaction kinetic parameters are always taken
from the associated aeration basin.
Collocation biofilm models
New biofilm models have been added, based loosely on collocation equations
for the soluble components. These models are referred to as BOD coll (1) and

The ASM 2w model is a variant of ASM 2d developed by WRc. The model differs
from the standard ASM 2d model in the handling of the switching function for
heterotrophic usage of VFA and fermentable COD. Where the standard model uses
the term (for VFA) of

SA
SA

, the WRc modification uses


KK + SA SA + SF

SA
. This change has better mathematical consistency than
K A + SA + SF K A / KF
the standard ASM 2 version. The ASM 2w model will only show a difference
compared to ASM 2d when there are substantial quantities of VFA in the aerobic
section of the aeration tank.

14

COD coll (1). They usually give the same results as the standard finitedifference models, but with substantially reduced computation times4. We
would recommend that the standard model be used first, and if computation
speed is an issue then you should switch to the collocation method. There will
be small differences between the two models - usually this is negligible,
unless the biofilm is close to a nitrifying/non-nitrifying position, when the full
model will be more accurate.
Instrumentation

There are two new instrumentation models: noisy probe and delay sampler.

Noisy probe is a generalisation of the first-order probe, but allowing you to


specify that a random amount of noise should be added to the measurements.
The noise is calculated from a Normal distribution, and you can use a mixture
of constant noise (independent of the magnitude of the measurement) and
variable noise (related to the size of the measurement).
Delay sampler is a representation of a wet-chemistry type of sampler, where
there is a large delay between taking a sample and the sample results being
available. This model also supports noisy measurements.

We are developing further collocation models, where the collocation


method will also be applied to the particulate components. These
models will be made available in a later release of STOAT.
15

Operational data for the noisy probe

The measurement has a level of noise added to it, using two Normal
functions. The first adds noise independent of the measured value:
For white noise the mean, , has the value zero.
Noise = N ( , )
The second noise function allows the mean and standard deviation to be
dependent on the measured value:

= measured value x relative mean


= measured value x relative standard deviation
Operational data for the delay sampler

16

Graphical Process Reporting


At the end of a simulation you can look at process results graphically. On
selecting the results you will first be presented with a menu allowing you to
select what parameters you want displayed. (In previous versions of STOAT
you were always given tabular values of all available parameters, with no
choice.)

After this you can then choose how the data should be displayed graphically
or in tables.

17

The results will then be displayed. For most processes the graphs will be
displayed as a three-dimensional plot. For some processes, that only ever
have one stage, the results will be presented as simple line graph. Staged
processes display one parameter per graph, with a series of tabs allowing you
to quickly switch between different parameters.

By right-clicking over the graph you will get a series of menus that allow you
to rotate and modify the graph.

18

The most useful are likely to be View 3D, which allows you to experiment with
rotation and view angles, and Plot cube, which allows you to distort the
different axes to better view the image.

19

User-defined Models
You can now add your own models to STOAT. More details are given in the
appendix.

STOAT ASM
STOAT .2 has a partner product, STOAT ASM Activated Sludge Model.
Many wastewater modellers focus only on activated sludge. For those people
we have STOAT ASM as a lower-priced entry into the STOAT world. Any
models developed by STOAT ASM are fully compatible with the full STOAT
package, and can easily be upgraded to STOAT later. If you need to deliver a
copy of your STOAT models to your clients then STOAT ASM may be a lowcost way of handing over a working version for them to use.

20

APPENDIX - User-defined Models


This appendix explains the procedure for adding your own models to STOAT. There
are several steps:
Create your model and compile it in a DLL. The DLL must, in its turn, be called by
a DLL that has the name and entry points defined by STOAT. Details are given
below.
Create a file that contains all the menu information needed by your model.
Create a bitmap that will be used to display your model.
Update a file used by STOAT that tells STOAT that you have added a new
process model. Details are given below.
File location
STOAT looks for a file called USER.DAT in the same directory as the project
database. USER.DAT should contain the following:
[USER_MODELS]
NAME = <Model name>, CODE = <Model code>, FILE = <Model file>
The NAME = line can be repeated for as many models as you wish to use.
<Model name> is the name that will be associated with the model. If the name
contains any spaces or commas then it should be enclosed in double quotes (")
<Model code> is a positive integer that will be used to identify the model in the userwritten program files.
<Model file> is the location of the dialogue text for this model. If no path is given then
the file must be in the same directory as USER.DAT. If there are spaces or commas
in the filename/path then the entire name should be enclosed in double quotes (").
Note that Standard Windows will treat commas in a filename/file path as an illegal
character.
The model is compiled and placed in a DLL, or a DLL called from a DLL. The master
DLL that STOAT looks for must be called STOAT_USER.DLL and must be on the
executable path - this is most commonly achieved by placing the DLL either in
\WINDOWS\SYSTEM or in the same place as the STOAT32.EXE file. If you have
multiple copies of this file then Windows normally locates the files in the following
order: the same place as STOAT32.EXE; any directories specified in the PATH
environment variable - these directories are searched in the order defined in the
PATH statement; or the \WINDOS and \WINDOWS\SYSTEM directories. We
recommend not keeping multiple copies of STOAT_USER.DLL on your computer.

21

Program file
For an example of the contents of a program file please study the file BULK1.F90.
This indicates

What parameters are passed from STOAT to STOAT_USER.DLL

The two entry points that STOAT is looking for: USER and USERS

How to declare that these entry points are to be made available. Note that the
syntax is specific to Digital/Compaq Visual Fortran and would have to be modified
if you are using a different Fortran compiler, or a compiler for another language
(e.g. C or C++). Also note that the entry points USER and USERS are defined
using an ALIAS command to be exported in 'undecorated' format.

What parameters can be adjusted, specified using the Fortran attributes


intent(in) for parameters that you should not alter and intent(out) for parameters
that are undefined by STOAT and for which you must specify a value - the
performance of STOAT is undefined if you do not set values for these
parameters.

Menu files
The menu file contains information about the screen representation of your model.
When no model is specified STOAT will display a question mark in a box. When you
specify a model this will change to the symbol that you have defined for the model. If
you add streams to a screen symbol and subsequently change the process to a
different model with a different number of inlets or outlets then the performance of
STOAT may be unpredictable. Always settle for the models before adding
streams.
The menu file contains the following information:
[CONNECTIONS]
IMAGE = <image file name, usually an icon, but possibly a bitmap>
INLETn, NAME = <Name>, X = <X>, Y = <Y>
OUTLETn, NAME = <Name>, X = <X>, Y = <Y>
Where n is 1-3: up to 3 inlets and 3 outlets per process.
<Name> is a name that will be used to help users identify connections.
<X> and <Y> are the X and Y co-ordinates for the connections on your image.
[UNIT SPECIFICATION]
This must be specified, even if empty, for STOAT to automatically add an entry for
the number of stages and, optionally, an entry for the number of recycle streams.
NAME = <Name>, MAX = <Max>, MIN = <Min>, DEFUALT = <Default value>
[KINETICS CALIBRATION]
22

[INITIAL CONDITIONS]
These follow the same format as above
[RECYCLES]
ENABLED
No [RECYCLES] entry means that there will be no user prompts for internal recycle
streams.
[DISTRIBUTION]
This has the same format as for unit specification, but with an optional SUM =
<Sum> keyword if the sum of values for a stage must equal some defined number typically 1, where the values are fractional distributions across the stages (e.g.,
volume fractions).
[DERIVED PARAMETERS]
NAME = <Name>
The derived parameters are defined for each stage.
Example
The following material gives an example of implementing a model for bulking
activated sludge (See Low F/M bulking model of J. Kapeller and R.Brodman, 1995,
Water Science and technology 31(2), 225 ff. for more details) . Sample output from
the model is given in the following figure.

23

Contents of USER.DAT file


;
; USER.DAT -- master user model file
;
[USER_MODELS]
NAME = "Bulking model", CODE = 100, FILE = "menu.txt"

Contents of menu file (menu.txt)


;
; Dialog data for bulking model
;
[CONNECTIONS]
IMAGE = "bulk1.ico"
INLET1, NAME = "Sewage", X = 0, Y = 7
INLET2, NAME = "RAS",
X = 0, Y = 15
OUTLET1, NAME = "Outlet", X = 31, Y = 10
[UNIT SPECIFICATION]
; Nothing to add to defaults.
; Must be defined (even empty) to indicate that
; this menu option is wanted
[KINETICS CALIBRATION]
NAME = "Mu max floc formers @ 15C", MIN = 0, MAX = 1, DEFAULT = 0.125
NAME = "Temp coeff.", MIN = 0, MAX = 0, DEFAULT = 0
NAME = "Mu max filaments @ 15C", MIN = 0, MAX = 1, DEFAULT = 0.08333
NAME = "Temp coeff.", MIN = 0, MAX = 1, DEFAULT = 0
NAME = "Mu max Nitrosomonas", MIN = 0, MAX = 1, DEFAULT = 0.0333
NAME = "Temp coeff.", MIN = 0, MAX = 1, DEFAULT = 0
NAME = "Mu max Nitrobacter", MIN = 0, MAX = 1, DEFAULT = 0.05
NAME = "Temp coeff.", MIN = 0, MAX = 1, DEFAULT = 0
NAME = "Death rate, floc formers", MIN = 0, MAX = 10, DEFAULT = 0.021
NAME = "Temp coeff.", MIN = 0, MAX = 1, DEFAULT = 0
NAME = "Deat rate, filaments", MIN = 0, MAX = 1, DEFAULT = 0.0125
NAME = "Temp coeff.", MIN = 0, MAX = 1, DEFAULT = 0
NAME = "Death rate, Nitrosomonas", MIN = 0, MAX = 1, DEFAULT = 0.00417
NAME = "Temp coeff.", MIN = 0, MAX = 1, DEFAULT = 0
NAME = "Death rate, Nitrobacter", MIN = 0, MAX = 1, DEFAULT = 0.00625
NAME = "Temp coeff.", MIN = 0, MAX = 1, DEFAULT = 0
NAME = "Yield, floc formers", MIN = 0, MAX = 1, DEFAULT = 0.63
NAME = "Yield, filaments", MIN = 0, MAX = 1, DEFAULT = 0.63
NAME = "Yield, Nitrosomonas", MIN = 0, MAX = 1, DEFAULT = 0.21
NAME = "Yield, Nitrobacter", MIN = 0, MAX = 1, DEFAULT = 0.03
NAME = "O2 switch, floc formers", MIN = 0, MAX = 1, DEFAULT = 0.25
NAME = "O2 switch, filaments", MIN = 0, MAX = 1, DEFAULT = 0.1
NAME = "O2 switch, Nitrosomonas", MIN = 0, MAX = 1, DEFAULT = 0.5
NAME = "O2 switch, Nitrobacter", MIN = 0, MAX = 1, DEFAULT = 0.5
NAME = "O2 suppression on NO2", MIN = 0, MAX = 1, DEFAULT = 0.1
NAME = "O2 supression on NO", MIN = 0, MAX = 1, DEFAULT = 0.05
NAME = "Switch for growth on SH", MIN = 0, MAX = 10, DEFAULT = 1
NAME = "Switch for nitrite growth on SH", MIN = 0, MAX = 10, DEFAULT = 5
NAME = "Switch, flocs, on SL", MIN = 0, MAX = 10, DEFAULT = 5
NAME = "Switch, filaments, on SL", MIN = 0, MAX = 10, DEFAULT = 1
NAME = "Switch, flocs, on SL and nitrite", MIN = 0, MAX = 10, DEFAULT = 10
NAME = "Switch, flocs, on NH4", MIN = 0, MAX = 10, DEFAULT = 0.01
NAME = "Switch, filaments, on NH4", MIN = 0, MAX = 10, DEFAULT = 0.01
NAME = "Switch, Nitrosomonas, on NH4", MIN = 0, MAX = 10, DEFAULT = 0.01
NAME = "Switch, Nitrobacter, on NH4", MIN = 0, MAX = 10, DEFAULT = 0.01
NAME = "Switch on NO", MIN = 0, MAX = 10, DEFAULT = 0.5
NAME = "Switch on NO3", MIN = 0, MAX = 10, DEFAULT = 0.5
NAME = "Switch on NO2, flocs", MIN = 0, MAX = 10, DEFAULT = 0.5
NAME = "Switch on NO2, Nitrobacter", MIN = 0, MAX = 10, DEFAULT = 0.5
NAME = "beta1", MIN = 0, MAX = 10, DEFAULT = 1
NAME = "beta2", MIN = 0, MAX = 10, DEFAULT = 0.8
NAME = "beta3", MIN = 0, MAX = 10, DEFAULT = 0.8

24

NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME
NAME

=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=

"beta4", MIN = 0, MAX = 10, DEFAULT = 1


"beta5", MIN = 0, MAX = 10, DEFAULT = 1
"beta6", MIN = 0, MAX = 10, DEFAULT = 1.67
"beta7", MIN = 0, MAX = 10, DEFAULT = 1.67
"O2 consumed per NO2", MIN = 0, MAX = 10, DEFAULT = 3.22
"O2 consumed per NO3", MIN = 0, MAX = 10, DEFAULT = 1.11
"N/COD, floc", MIN = 0, MAX = 1, DEFAULT = 0.06
"N/COD, filament", MIN = 0, MAX = 1, DEFAULT = 0.06
"N/COD, Nitrosomonas", MIN = 0, MAX = 1, DEFAULT = 0.06
"N/COD, Nitrobacter", MIN = 0, MAX = 1, DEFAULT = 0.06
"N/COD in lysis, floc", MIN = 0, MAX = 1, DEFAULT = 0.054
"N/COD in lysis, filament", MIN = 0, MAX = 1, DEFAULT = 0.054
"N/COD in lysis, Nitrosomonas", MIN = 0, MAX = 1, DEFAULT = 0.054
"N/COD in lysis, Nitrobacter", MIN = 0, MAX = 1, DEFAULT = 0.054
"N/COD in XH", MIN = 0, MAX = 1, DEFAULT = 0.05
"N/COD in XL", MIN = 0, MAX = 1, DEFAULT = 0.02
"Release of SH by lysis, floc", MIN = 0, MAX = 1, DEFAULT = 0.8
"Release of SH by lysis, filament", MIN = 0, MAX = 1, DEFAULT = 0.8
"Release of SH by lysis, Nitrosomonas", MIN = 0, MAX = 1, DEFAULT = 0.8
"Release of SH by lysis, Nitrobacter", MIN = 0, MAX = 1, DEFAULT = 0.8
"Release of SL by lysis, floc", MIN = 0, MAX = 1, DEFAULT = 0.1
"Release of SL by lysis, filament", MIN = 0, MAX = 1, DEFAULT = 0.1
"Release of SL by lysis, Nitrosomonas", MIN = 0, MAX = 1, DEFAULT = 0.1
"Release of SL by lysis, Nitrobacter", MIN = 0, MAX = 1, DEFAULT = 0.1
"Release of Xsurf by lysis, floc", MIN = 0, MAX = 1, DEFAULT = 0.02
"Release of Xsurf by lysis, filament", MIN = 0, MAX = 1, DEFAULT = 0.02
"Release of Xsurf by lysis, Nitrosomonas", MIN = 0, MAX = 1, DEFAULT = 0.02
"Release of Xsurf by lysis, Nitrobacter", MIN = 0, MAX = 1, DEFAULT = 0.02
"Release of XI by lysis, floc", MIN = 0, MAX = 1, DEFAULT = 0.08
"Release of XI by lysis, filament", MIN = 0, MAX = 1, DEFAULT = 0.08
"Release of XI by lysis, Nitrosomonas", MIN = 0, MAX = 1, DEFAULT = 0.08
"Release of XI by lysis, Nitrobacter", MIN = 0, MAX = 1, DEFAULT = 0.08
"Hydrolysis rate, XH", MIN = 0, MAX = 10, DEFAULT = 0.208
"Temp. coeff", MIN = 0, MAX = 10, DEFAULT = 0, DEFAULT = 0
"Hydrolysis rate, XL", MIN = 0, MAX = 10, DEFAULT = 0.208
"Temp coeff.", MIN = 0, MAX = 10, DEFAULT = 0, DEFAULT = 0
"Degradation rate, XSurf", MIN = 0, MAX = 10, DEFAULT = 0.208
"Temp coeff.", MIN = 0, MAX = 10, DEFAULT = 0, DEFAULT = 0
"betaH", MIN = 0, MAX = 10, DEFAULT = 0.4
"betaL", MIN = 0, MAX = 10, DEFAULT = 0.4
"beta_surf", MIN = 0, MAX = 10, DEFAULT = 0.4
"KXSurf", MIN = 0, MAX = 10, DEFAULT = 0.5
"TSS to COD ratio, biomass", MIN = 0, MAX = 1, DEFAULT = 0.75
"XI released by hydrolysis of XH", MIN = 0, MAX = 1, DEFAULT = 0
"XI released by hydrolysis of XL", MIN = 0, MAX = 1, DEFAULT = 0
"KO2Hyd", MIN = 0, MAX = 10, DEFAULT = 0.25
"KNO3Hyd", MIN = 0, MAX = 10, DEFAULT = 0.5
"KO2Surf", MIN = 0, MAX = 10, DEFAULT = 0.25
"KNO3Surf", MIN = 0, MAX = 10, DEFAULT = 0.5

[INITIAL CONDITIONS]
NAME = "Temperature", MIN = 0, MAX = 30
NAME = "Oxygen", MIN=0, MAX = 10
NAME = "SH", MIN = 0, MAX = 1E6
NAME = "SL", MIN = 0, MAX = 1E6
NAME = "SI", MIN = 0, MAX = 1E6
NAME = "NH4", MIN = 0, MAX = 1E6
NAME = "NO3", MIN = 0, MAX = 1E6
NAME = "NO2", MIN = 0, MAX = 1E6
NAME = "NO", MIN = 0, MAX = 1E6
NAME = "XF", MIN = 0, MAX = 1E6, DEFAULT = 100
NAME = "XB", MIN = 0, MAX = 1E6, DEFAULT = 100
NAME = "XNS", MIN = 0, MAX = 1E6, DEFAULT = 10
NAME = "XNB", MIN = 0, MAX = 1E6, DEFAULT = 10
NAME = "XH", MIN = 0, MAX = 1E6
NAME = "XL", MIN = 0, MAX = 1E6
NAME = "XSurf", MIN = 0, MAX = 1E6

25

NAME = "XI", MIN = 0, MAX = 1E6


NAME = "XNVS", MIN = 0, MAX = 1E6
NAME = "Integral error", MIN = 0, MAX = 1E6
[RECYCLES]
ENABLED
; indicates that recycles are to be used.
[DISTRIBUTION]
NAME = "Volume", MIN=0, MAX = 1E6
NAME = "Sewage distribution", MIN = 0, MAX = 1, SUM = 1
NAME = "RAS distribution", MIN = 0, MAX = 1, SUM = 1
NAME = "Alpha value", MIN = 0.5, MAX = 1.2, DEFAULT = 1
NAME = "Beta value", MIN = 0.5, MAX = 1.2, DEFAULT = 1
NAME = "Theta value", MIN = 1, MAX = 2, DEFAULT = 1.024
NAME = "Min KLa", MIN = 0, MAX = 20, DEFAULT = 0
NAME = "Max KLa", MIN = 0, MAX = 20, DEFAULT = 10
NAME = "DO setpoint", MIN = 0, MAX = 10, DEFAULT = 2
NAME = "Gain", MIN = 0, MAX = 10, DEFAULT = 1
NAME = "Integral time", MIN = 1, MAX = 10, DEFAULT = 1
[DERIVED PARAMETERS]
NAME = "KLa"
NAME = "O2 demand"
NAME = "OUR"
NAME = "NUR"

26

Fortran routines
!
!
!
!
!
!
!
!

In these two routines, USER is used to specify the values for the
differential equations DY()/dy = f(Y(), ...)
USER should NOT be used to assign values to the streams.
USERS is used to specify values for the outlet streams.
It should not be used to specify values for any other parameters,
with the possible exception of DERIVED().

!DEC$ ATTRIBUTES DLLEXPORT:: User


!DEC$ ATTRIBUTES ALIAS: 'USER':: User
subroutine user(in1, in2, in3, out1, out2, out3, &
model, NoStages, NoRecycles, &
CalibUnit, CalibSwg, Calibswitch, CalibStoic, &
Recycles, Distribution, Operation, &
y, dy, derived, s1, s2, t)
include 'stream.fi'
record /Stream/
in1, in2, in3
record /Stream/
out1, out2, out3
integer
model
integer
NoStages
integer
NoRecycles
double precision
CalibUnit(*)
double precision
CalibSwg(*)
double precision
CalibStoic(*)
double precision
CalibSwitch(*)
double precision
Recycles(3,*)
double precision
Distribution(NoStages, *)
double precision
Operation(*)
double precision
y(NoStages, *)
double precision
dy(NoStages, *)
double precision
derived(NoStages, *)
double precision
s1
double precision
s2
double precision
t
intent (in)
:: in1, in2, in3, out1, out2, out3
intent (in)
:: model, NoStages, NoRecycles
intent (in)
:: CalibUnit, CalibSwg, CalibStoic, CalibSwitch
intent (in)
:: Recycles, Distribution, Operation
intent (in)
:: y
intent (out)
:: dy
intent (inout) :: derived
intent (in)
:: s1, s2, t
!
! Up to 3 inlet streams and 3 outlet streams. If a user model does
! not use a stream then the value for that stream is undefined, and
! should not be accessed by that model.
!
! MODEL contains the user-specified ID number.
! NoStages is the number of stages.
! Norecycles is the number of recycles.
! CalibUnit() contains the unit calibration data in the order specified
!
by the dialogue data file.
! CalibSwg() contains the main sewage calibration data in the order
!
specified by the dialogue data file.
! CalibStoic() contains additional stoichiometric data if specified
!
by the dialogue data file.
! Calibswitch() contains additional switching data if specified
!
by the dialogue data file.
! Recycles() contains the recycle data, in the form of triplets:
!
From stage, To stage, Stage flow.
! Distribution() contains the stage distribution data.
! Operation() contains operational data in the order specified by
!
the dialogue data file. If any operational data was listed as

27

!
!
!
!
!
!
!
!
!
!
!
!
!
!

being staged, then this will be repeated NoStages times.


Y() contains the current computed values for the model.
DY() should, on exit from this routine, contain the current values
for the time derivative.
Derived() contains computed values. These may have been set in the
companion routine USERS or may be set here. Derived() is
used to pass information that is not specified by differential
equations.
s1 is the ratio of BOD removed per unit of volatile solids, excluding
biomass, removed. The BOD removed may be converted to soluble
BOD rather than being oxidised.
s2 is the ratio of BOD removed per unit of biomass removed.
t is the current integration time.

select case (model)


case (100)
! Call the appropriate routine
call bulk1(in1, in2, NoStages, NoRecycles, &
CalibSwg, Recycles, Distribution, &
y, dy, Derived, s2)
end select
end
!DEC$ ATTRIBUTES DLLEXPORT:: Users
!DEC$ ATTRIBUTES ALIAS: 'USERS':: Users
subroutine users(in1, in2, in3, out1, out2, out3, &
model, NoStages, NoRecycles, &
CalibUnit, CalibSwg, Calibswitch, CalibStoic, &
Recycles, Distribution, Operation, &
y, derived, s1, s2, t)
include 'stream.fi'
record /Stream/
in1, in2, in3
record /Stream/
out1, out2, out3
integer
model
integer
NoStages
integer
NoRecycles
double precision
CalibUnit(*)
double precision
CalibSwg(*)
double precision
CalibStoic(*)
double precision
CalibSwitch(*)
double precision
Recycles(3,*)
double precision
Distribution(NoStages, *)
double precision
Operation(*)
double precision
y(NoStages, *)
double precision
derived(NoStages, *)
double precision
s1
double precision
s2
double precision
t
intent
intent
intent
intent
intent
intent
intent
intent

(in)
(in )
(in)
(in)
(in)
(in)
(inout)
(in)

::
::
::
::
::
::
::
::

in1, in2, in3


out1, out2, out3
model, NoStages, NoRecycles
CalibUnit, CalibSwg, CalibStoic, CalibSwitch
Recycles, Distribution, Operation
y
derived
s1, s2, t

select case (model)


case (100)
! Call the appropriate routine
call bulk1_output(NoStages, in1, in2, out1, CalibSwg, y, s1)
end select
end
!
! Low F/M bulking model of J. Kapeller and R.Brodman, 1995

28

! Water Science and technology 31(2), 225 ff.


!
! The Kapeller model has been extended by adding a term for nonvolatile
solids
!
! Contents of p()
! Number of stages
[NS]
! Number of MLSS recycles
[NR]
! NR FROM recycle stage
! NR TO recycle stage
! NR recycle flow
! NS stage volumes
! NS feed distribution (sums to 1.0)
! NS RAS distribution (sums to 1.0)
! NS alpha values
! NS beta values
! NS theta values
! NS minimum KLa values
! NS maximum KLa values
! NS DO setpoints
! NS proportional gains
! NS integral times
! (Start of reaction parameters)
!
subroutine bulk1(in1, in2, NumberOfStages, NumberOfRecycles, &
CalibSwg, Recycles, Distribution, y, dy, x, s2)
implicit none
include 'stream.fi'
record /stream/ in1, in2
integer:: NumberOfStages, NumberOfRecycles
double precision:: CalibSwg(*), Recycles(3, NumberOfRecycles), &
Distribution(NumberOfStages, 11), &
y(NumberofStages, 19), dy(NumberofStages, 19), &
x(NumberOfStages, 4), s2
! Internal variables
double precision, dimension(NumberofStages):: KLa20
integer:: Stage
KLa20 = Distribution(:, 10) * ( (Distribution(:, 9) - y(:, 2)) &
+ Distribution(:, 11) * y(:, 19))
dy(:, 19) = Distribution(:, 9) - y(:, 2)
do Stage = 1, NumberOfStages
if (
KLa20(Stage) > Distribution(Stage, 8) &
.and. dy(Stage, 19) > 0) then
KLa20(Stage) = Distribution(Stage, 8)
dy(Stage, 19) = 0d0
elseif (
KLa20(Stage) < Distribution(Stage, 7) &
.and. dy(Stage, 19) < 0) then
KLa20(Stage) = Distribution(Stage, 7)
dy(Stage, 19) = 0d0
end if
end do
call bulk1_hydraulics(in1, in2, y(1,1), dy(1,1), &
y(:, 2:18), dy(:, 2:18), &
NumberOfStages, &
Distribution(:, 1), &
Distribution(:, 2), &
Distribution(:, 3), &
s2, Recycles(1, :), &
Recycles(2, :), &
Recycles(3, :), &
NumberOfRecycles)
x(:, 1) = KLa20
dy(:, 1) = dy(1, 1)

29

call bulk1_kinetics(NumberOfStages, y(1,1), y(:, 2:18), dy(:, 2:18), &


Distribution(:, 1), KLa20, &
Distribution(:, 6), &
Distribution(:, 4), &
Distribution(:, 5), &
CalibSwg, &
x(:, 2), x(:, 3), x(:, 4), s2)
end
subroutine bulk1_output(NumberofStages, in1, in2, out, p, y, s1)
implicit none
include 'stream.fi'
integer:: NumberofStages
record /stream/ in1, in2, out
double precision:: p(*), y(NumberOfStages, 19)
double precision:: iTSSBM, s1
out.flow = in1.flow + in2.flow
iTSSBM = p(85)
out.t = y(1, 1)
out.pH = 7d0
out.c.o2
out.c.sbod
out.c.vfa
out.c.scod
out.c.nh3
out.c.no3
out.c.no2
out.c.son
out.c.xvih
out.c.xnvh
out.c.xvia
out.c.xnva
out.c.xbod
out.c.phb1
out.c.phb2
out.c.xcod
out.c.xnvs
out.c.xvs
+

= y(NumberOfStages, 2)
= y(NumberOfStages, 3)
= y(NumberOfStages, 4)
= y(NumberOfStages, 5)
= y(NumberOfStages, 6)
= y(NumberOfStages, 7)
= y(NumberOfStages, 8)
= y(NumberOfStages, 9)
= y(NumberOfStages, 10) * iTSSBM
= y(NumberOfStages, 11) * iTSSBM
= y(NumberOfStages, 12) * iTSSBM
= y(NumberOfStages, 13) * iTSSBM
= Sum(y(NumberOfStages, 10:14))
= y(NumberOfStages, 15) ! 'low' MW
= y(NumberOfStages, 16) ! 'surfactants'
= y(NumberOfStages, 17) ! 'inerts'
= y(NumberOfStages, 18)
= out.c.xvih + out.c.xnvh + out.c.xvia + out.c.xnva &
Sum(y(NumberOfStages, 14:17)) / s1

end
subroutine bulk1_hydraulics(sin, sRAS, T, dT, y, dy, NumberOfStages, &
Volume, Feed, RASFeed, s2, From, To, Q, &
NumberOfRecycles)
implicit none
include 'stream.fi'
record /stream/ sin, sRAS
integer:: NumberOfStages
integer:: NumberOfRecycles
double precision:: T, dT
double precision:: s2 ! biomass COD:VSS ratio
double precision, dimension(NumberOfStages, 17):: y, dy
double precision, dimension(NumberOfStages):: Volume, Feed, RASFeed, &
From, To, Q
! Local variables
double precision:: Qin, QRAS, QSewage
double precision:: XBOD1, XBOD2
integer:: Stage, FromStage, ToStage, i
double precision:: QMLSS, Q1, Q2

30

QSewage = sin.flow
QRAS
= sRAS.flow
dT = QSewage * sin.T + QRAS * sRAS.T - (QRAS + QSewage) * T
dT = dT / sum(Volume)
dy = 0d0
Qin = 0d0
do Stage = 1, NumberOfStages
Q1 = Qsewage * Feed(Stage)
Q2 = QRAS * RASFeed(Stage)
dy(Stage, 1) = Q1 * sin.c.o2
+ Q2 * sRAS.c.o2
dy(Stage, 2) = Q1 * sin.c.sbod + Q2 * sRAS.c.sbod
! Volatile fatty acid term in STOAT used to hold the low molecular weight
soluble
! degradable COD fraction in Kapeller's model.
dy(Stage, 3) = Q1 * sin.c.vfa + Q2 * sRAS.c.vfa
dy(Stage, 4) = Q1 * sin.c.scod + Q2 * sRAS.c.scod
dy(Stage, 5) = Q1 * sin.c.nh3 + Q2 * sRAS.c.nh3
dy(Stage, 6) = Q1 * sin.c.no3 + Q2 * sRAS.c.no3
dy(Stage, 7) = Q1 * sin.c.no2 + Q2 * sRAS.c.no2
! Soluble degradable organic nitrogen fraction in STOAT used to hold the
! dissolved nitrous oxide (NO) component in Kapeller's model
dy(Stage, 8) = Q1 * sin.c.son + Q2 * sRAS.c.son
! Mapping STOAT components to Kapeller's model::
! Viable heterotrophs (XVIH)
: Floc formers
! Nonviable heterotrophs (XNVH)
: 'Bulking' biomass
! Viable autotrophs (XVIA)
: Nitrosomonas
! Nonviable autotrophs (XNVA)
: Nitrobacter
! Degradable particulate COD (XBOD): High-molecular weight particulate cOD
! Stored PHB (PHB1)
: Low-molecular weight particulate COD
! Stored PHB (PHB2)
: Surfactant COD
! Nondegradable COD (XCOD)
: Nondegradable COD
dy(Stage, 9) = Q1 * s2 * sin.c.XVIH + Q2 * s2 * sRAS.c.XVIH
dy(Stage, 10) = Q1 * s2 * sin.c.XNVH + Q2 * s2 * sRAS.c.XNVH
dy(Stage, 11) = Q1 * s2 * sin.c.XVIA + Q2 * s2 * sRAS.c.XVIA
dy(Stage, 12) = Q1 * s2 * sin.c.XNVA + Q2 * s2 * sRAS.c.XNVA
!
! Biomass COD was added to XBOD to ensure that the COD balance is correctly
! reported. In STOAT the biomass terms are reported as having units
! of suspended solids, not COD. We must subtract the
! biomass COD from XBOD before assigning it to the
! XH fraction in kapeller's model
!
XBOD1 = sin.c.xbod &
- s2 * (sin.c.xvih + sin.c.xnvh + sin.c.xvia + sin.c.xnva)
XBOD2 = sRAS.c.xbod &
- s2 * (sRAS.c.xvih + sRAS.c.xnvh + sRAS.c.xvia + sRAS.c.xnva)
dy(Stage, 13) = Q1 * XBOD1 + Q2 * XBOD2
dy(Stage, 14) = Q1 * sin.c.phb1 + Q2 * sRAS.c.phb1
dy(Stage, 15) = Q1 * sin.c.phb2 + Q2 * sRAS.c.phb2
dy(Stage, 16) = Q1 * sin.c.xcod + Q2 * sRAS.c.xcod
dy(Stage, 17) = Q1 * sin.c.xnvs + Q2 * sRAS.c.xnvs
if (Stage > 1) then
dy(Stage, :) = dy(Stage, :) + Qin * y(Stage - 1, :)
end if
! Add internal recycle flows
Qin = Q1 + Q2 + Qin
do i = 1, NumberOfRecycles
FromStage = From(i)
ToStage
= To(i)
QMLSS
= Q(i)
if (QMLSS < 0) QMLSS = abs(QMLSS) * Qsewage
if (FromStage .eq. Stage) then
Qin = Qin - QMLSS

31

dy(Stage, :) = dy(Stage, :) - QMLSS * y(Stage, :)


elseif (ToStage .eq. Stage) then
Qin = Qin + QMLSS
dy(Stage, :) = dy(Stage, :) + QMLSS * y(FromStage, :)
end if
end do
dy(Stage, :) = dy(Stage, :) - Qin * y(Stage, :)
end do
! Now divide by volumes
do Stage = 1, NumberOfStages
dy(Stage,:) = dy(Stage,:) / Volume(Stage)
end do
end

subroutine bulk1_kinetics(NumberOfStages, T, y, dy, &


Volume, KLa20, Theta, Alpha, Beta, p, &
QO2, OUR, NUR, s2)
implicit none
integer, parameter:: NumberOfComponents = 17
integer, parameter:: NumberOfReactions = 21
integer:: NumberOfStages
double precision:: T
double precision, dimension(NumberOfStages, NumberofComponents):: y, dy
double precision, dimension(NumberOfStages):: Volume, Alpha, Beta, &
KLa20, Theta, QO2, OUR, NUR
double precision:: p(82)
double precision:: s2
! Local variables
double precision:: Rho(NumberOfReactions) = 0d0
double precision:: S(NumberOfComponents, NumberOfReactions) = 0d0
double precision, dimension (NumberOfStages):: KLa
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double

precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::
precision::

mumaxF, mumaxB, mumaxNS, mumaxNB


bF, bB, bNS, bNB
YF, YB, YNS, YNB
KO2F, KO2B, KO2NS, KO2NB, KO2NO, KO2NO2
KH, KHNO2
KLF, KLB, KLFNO2
KNH4F, KNH4B, KNH4NS, KNH4NB
KNO, KNO3, KNO2, KNO2NB
beta1, beta2, beta3, beta4, beta5, beta6, beta7
betaH, betaL, beta_surf
iNO2, iNO3
iXBF, iXBB, iXBNS, iXBNB
iLysF, iLysB, iLysNS, iLysNB
iNH
iNL
fLHF, fLHB, fLHNS, fLHNB
fLLF, fLLB, fLLNS, fLLNB
fLSF, fLSB, fLSNS, fLSNB
fIF, fIB, fINS, fINB
kHi, kLo, kS, kXSurf
iTSSBM
fH, fL
KO2Hyd, KNO3Hyd, KO2Surf, KNO3Surf

integer:: Stage, Reaction, Comp


double precision:: SO2, SH, SL, SI, SNH4, SNO3, SNO2, SNO
double precision:: XF, XB, XNS, XNB, XH, XL, XS, XI
KLa = KLa20 * Theta**(T - 20d0)

32

!
! Assign kinetic values
!
mumaxF = p( 1) * exp(p( 2)
mumaxB = p( 3) * exp(p( 4)
mumaxNS = p( 5) * exp(p( 6)
mumaxNB = p( 7) * exp(p( 8)
bF
= p( 9) * exp(p(10)
bB
= p(11) * exp(p(12)
bNS
= p(13) * exp(p(14)
bNB
= p(15) * exp(p(16)
YF
= p(17)
YB
= p(18)
YNS
= p(19)
YNB
= p(20)
KO2F
= p(21)
KO2B
= p(22)
KO2NS
= p(23)
KO2NB
= p(24)
KO2NO2 = p(25)
KO2NO
= p(26)
KH
= p(27)
KHNO2
= p(28)
KLF
= p(29)
KLB
= p(30)
KLFNO2 = p(31)
KNH4F
= p(32)
KNH4B
= p(33)
KNH4NS = p(34)
KNH4NB = p(35)
KNO
= p(36)
KNO3
= p(37)
KNO2
= p(38)
KNO2NB = p(39)
beta1
= p(40)
beta2
= p(41)
beta3
= p(42)
beta4
= p(43)
beta5
= p(44)
beta6
= p(45)
beta7
= p(46)
iNO2
= p(47)
iNO3
= p(48)
iXBF
= p(49)
iXBB
= p(50)
iXBNS
= p(51)
iXBNB
= p(52)
iLysF
= p(53)
iLysB
= p(54)
iLysNS = p(55)
iLysNB = p(56)
iNH
= p(57)
iNL
= p(58)
fLHF
= p(59)
fLHB
= p(60)
fLHNS
= p(61)
fLHNB
= p(62)
fLLF
= p(63)
fLLB
= p(64)
fLLNS
= p(65)
fLLNB
= p(66)
fLSF
= p(67)
fLSB
= p(68)
fLSNS
= p(69)
fLSNB
= p(70)
fIF
= p(71)
fIB
= p(72)

*
*
*
*
*
*
*
*

(T
(T
(T
(T
(T
(T
(T
(T

15d0))
15d0))
15d0))
15d0))
15d0))
15d0))
15d0))
15d0))

33

fINS
= p(73)
fINB
= p(74)
kHi
= p(75) * exp(p(76) * (T - 15d0))
KLo
= p(77) * exp(p(78) * (T - 15d0))
KS
= p(78) * exp(p(80) * (T - 15d0))
betaH
= p(81)
betaL
= p(82)
beta_surf
= p(83)
KXSurf = p(84)
iTSSBM = p(85)
fH
= p(86)
fL
= p(87)
KO2Hyd = p(88)
KNO3Hyd = p(89)
KO2Surf = p(90)
KNO3Surf = p(91)
!
! Define stoichiometry matrix
!
! O2
s( 1, 1) = -(1d0
s( 1, 2) = -(1d0
s( 1, 10) = -(1d0
s( 1, 12) = -iNO2
s( 1, 14) = -iNO3

/
/

YF) / YF
YF) / YF
YB) / YB
YNS
YNB

! SH -- high molecular wieght, soluble


s( 2, 1) = -1d0 / YF
s( 2, 3) = -1d0 / YF
s( 2, 5) = -1d0 / YF
s( 2, 7) = -1d0 / YF
s( 2, 9) = fLHF
s( 2, 11) = fLHB
s( 2, 13) = fLHNS
s( 2, 15) = fLHNB
s( 2, 16) = 1d0 - fH
s( 2, 18) = 1d0 - fH
! SL -- low
s( 3, 2) =
s( 3, 4) =
s( 3, 6) =
s( 3, 8) =
s( 3, 9) =
s( 3, 11) =
s( 3, 13) =
s( 3, 15) =
s( 3, 17) =
s( 3, 19) =

molecular weight, soluble


-1d0 / YF
-1d0 / YF
-1d0 / YF
-1d0 / YF
fLLF
fLLB
fLLNS
fLLNB
1d0 - fL
1d0 - fL

! SI -- nondegradable, soluble
s( 4, 16) = fH
s( 4, 17) = fL
s( 4, 18) = fH
s( 4, 19) = fL
! SNH4
s( 5, 1)
s( 5, 2)
s( 5, 3)
s( 5, 4)
s( 5, 5)
s( 5, 6)
s( 5, 7)
s( 5, 8)
s( 5, 9)
s( 5, 10)

=
=
=
=
=
=
=
=
=
=

-iXBF
-iXBF
-iXBF
-iXBF
-iXBF
-iXBF
-iXBF
-iXBF
iLysF
-iXBB

34

s(
s(
s(
s(
s(
s(
s(
s(
s(

5,
5,
5,
5,
5,
5,
5,
5,
5,

11)
12)
13)
14)
15)
16)
17)
18)
19)

=
=
=
=
=
=
=
=
=

iLysB
-1d0 / YNS - iXBNS
iLysNS
-iXBNB
iLysNB
iNH
iNL
iNH
iNL

! SNO2
s( 6, 3)
s( 6, 4)
s( 6, 5)
s( 6, 6)
s( 6, 12)
s( 6, 14)

=
=
=
=
=
=

(1d0 - YF)
(1d0 - YF)
-(1d0 - YF)
-(1d0 - YF)
1d0 / YNS
-1d0 / YNB

/
/
/
/

(1.14d0
(1.14d0
(0.57d0
(0.57d0

*
*
*
*

YF)
YF)
YF)
YF)

! SNO3
s( 7, 3) = -(1d0 - YF) / (1.14d0 * YF)
s( 7, 4) = -(1d0 - YF) / (1.14d0 * YF)
s( 7, 14) = 1d0 / YNB
! SNO
s( 8,
s( 8,
s( 8,
s( 8,

5)
6)
7)
8)

= (1d0 = (1d0 = -(1d0 = -(1d0 -

YF)
YF)
YF)
YF)

/
/
/
/

(0.57d0
(0.57d0
(1.14d0
(1.14d0

*
*
*
*

YF)
YF)
YF)
YF)

! XF -- floc formers
s( 9, 1) = 1d0
s( 9, 2) = 1d0
s( 9, 3) = 1d0
s( 9, 4) = 1d0
s( 9, 5) = 1d0
s( 9, 6) = 1d0
s( 9, 7) = 1d0
s( 9, 8) = 1d0
s( 9, 9) = -1d0
! XB -- bulking biomass
s(10, 10) = 1d0
s(10, 11) = -1d0
! XNS -- Nitrosomonas
s(11, 12) = 1d0
s(11, 13) = -1d0
! XNB -- Nitrobacter
s(12, 14) = 1d0
s(12, 15) = -1d0
! XH -- high molecular weight, particulate
s(13, 16) = -1d0
s(13, 18) = -1d0
s(13, 20) = 1d0
s(13, 21) = 1d0
! XL -- low molecular weight, particulate
s(14, 17) = -1d0
s(14, 19) = -1d0
! XS -- surfactant, particulate
s(15, 9) = fLSF
s(15, 11) = fLSB
s(15, 13) = fLSNS
s(15, 15) = fLSNB
s(15, 20) = -1d0

35

s(15, 21) = -1d0


! XI -- nondegradable, particulate
s(16, 9) = fIF
s(16, 11) = fIB
s(16, 13) = fINS
s(16, 15) = fINB
! Nonvolatile solids
! iTSSBM is the ratio between biomass as COD and biomass as TSS
! s2 is the ratio between biomass as COD and biomass as VSS
! We assume that dditions to nonvolatile solids are a result
! of the difference between these two ratios only.
s(17, :) = s( 9, :) * (iTSSBM - 1d0 / s2) &
+ s(10, :) * (iTSSBM - 1d0 / s2) &
+ s(11, :) * (iTSSBM - 1d0 / s2) &
+ s(12, :) * (iTSSBM - 1d0 / s2)
!
! Evaluate kinetics
!
do Stage = 1, NumberOfStages
SO2
= y(Stage, 1)
SH
= y(Stage, 2)
SL
= y(Stage, 3)
SI
= y(Stage, 4)
SNH4 = y(Stage, 5)
SNO3 = y(Stage, 6)
SNO2 = y(Stage, 7)
SNO
= y(Stage, 8)
XF
= y(Stage, 9)
XB
= y(Stage, 10)
XNS
= y(Stage, 11)
XNB
= y(Stage, 12)
XH
= y(Stage, 13)
XL
= y(Stage, 14)
XS
= y(Stage, 15)
XI
= y(Stage, 16)
rho( 1) =
mumaxF*ON(SO2,KO2F)
*ON(SH,KH)
*ON(SNH4,KNH4F)*OFF(SNO,KNO) *XF
rho( 2) = beta1*mumaxF*ON(SO2,KO2F)
*ON(SL,KLF)
*ON(SNH4,KNH4F)*OFF(SNO,KNO) *XF
rho( 3) = beta2*mumaxF*OFF(SO2,KO2F) *ON(SH,KH)
*ON(SNH4,KNH4F)*ON(SNO3,KNO3)*XF
rho( 4) = beta3*mumaxF*OFF(SO2,KO2F) *ON(SL,KLF)
*ON(SNH4,KNH4F)*ON(SNO3,KNO3)*XF
rho( 5) = beta4*mumaxF*OFF(SO2,KO2NO2)*ON(SH,KHNO2)
*ON(SNH4,KNH4F)*ON(SNO2,KNO2)*XF
rho( 6) =
beta5*mumaxF*OFF(SO2,KO2NO2)*ON(SL,KLFNO2)*ON(SNH4,KNH4F)*ON(SNO2,KNO2)*XF
rho( 7) = beta6*mumaxF*OFF(SO2,KO2NO) *ON(SH,KHNO2)
*ON(SNH4,KNH4F)*ON(SNO,KNO) *XF
rho( 8) = beta7*mumaxF*OFF(SO2,KO2NO)
*ON(SL,KLFNO2)*ON(SNH4,KNH4F)*ON(SNO,KNO) *XF
rho( 9) = bF*XF
rho(10) = mumaxB*ON(SO2,KO2B)*ON(SL,KLB)*ON(SNH4,KNH4B)*XB
rho(11) = bB*XB
rho(12) = mumaxNS*ON(SO2,KO2NS)*ON(SNH4,KNH4NS)*XNS
rho(13) = bNS*XNS
rho(14) = mumaxNB*ON(SO2,KO2NB)*ON(SNH4,KNH4NB)*ON(SNO2,KNO2NB)*XNB
rho(15) = bNB*XNB
rho(16) = kHi*ON(SO2,KO2Hyd)*XH
rho(17) = kLo*ON(SO2,KO2Hyd)*ON(XS,KXSurf*XL)*XL
rho(18) = betaH*kHi*OFF(SO2,KO2Hyd)*ON(SNO3,KNO3Hyd)*XH
rho(19) = betaL*kLo*OFF(SO2,KO2Hyd)*ON(SNO3,KNO3Hyd)*ON(XS,KXSurf*XL)*XL
rho(20) = kS*ON(SO2,KO2Surf)*XS
rho(21) = beta_surf*OFF(SO2,KO2Surf)*ON(SNO3,KNO3Surf)*XS

36

OUR(Stage) = 0d0
NUR(Stage) = 0d0
do Reaction = 1, NumberofReactions
do Comp = 1, NumberOfComponents
if (s(Comp, Reaction) <> 0) then
dy(Stage, Comp) = dy(Stage, Comp) &
+ Rho(Reaction) * s(Comp, Reaction)
end if
end do
OUR(Stage) = Sum(Rho * s(1, :))
NUR(Stage) = Sum(Rho * s(6, :)) + Sum(Rho * s(7, :)) + Sum(Rho * s(8,
:))
end do
dy(Stage, 1) = dy(Stage, 1) + KLa(Stage) * Alpha(Stage) * (Beta(Stage) *
SatO2(T) - SO2)
QO2(Stage) = KLa(Stage) * Alpha(Stage) * (Beta(Stage) * SatO2(T) - SO2) *
Volume(Stage) * 1d-3 ! kg/h
end do
contains
double precision function ON(S, K)
double precision:: S, K
if (K == 0 .and. S == 0) then
ON = 0
else
ON = S / (K + abs(S))
endif
end function ON
double precision function OFF(S, K)
double precision:: S, K
OFF = K / (abs(S) + K)
end function OFF
double precision function SatO2(T)
double precision:: T
SatO2 = exp(1d0/(t*0.004065d0 + 0.372017d0))
end function SatO2
end

37

You might also like