Documente Academic
Documente Profesional
Documente Cultură
Niels Holst
niels.holst@agrsci.dk
www.ecolmod.org
8 June 2015
Draft in progress
Department of Agroecology
Aarhus University
Denmark
Contents
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
ii
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Chapter 1. Installation
1.1. Installing Universal Simulator
.. .. .. .. .. .. .. .. .. .. .. ..
1.2. Running simulations .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
1
1
1
Writing recipes .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Recipe structure and context
.. .. .. .. .. .. .. .. .. .. ..
References to parameters and variables .. .. .. .. .. .. .. .. ..
Parameter elements
.. .. .. .. .. .. .. .. .. .. .. .. .. ..
The integrator element
.. .. .. .. .. .. .. .. .. .. .. .. ..
Model elements
.. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Additional input files
.. .. .. .. .. .. .. .. .. .. .. .. ..
Output and trace elements
.. .. .. .. .. .. .. .. .. .. .. ..
Applications .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
2.8.1. Application 1. Life stage sequence
.. .. .. .. .. .. ..
2.8.2. Application 2. Random parameter values
.. .. .. .. ..
2.8.3. Application 3. Stage-structured population dynamics
.. ..
2.8.4. Application 4. Stage-structured SEIR epidemics model .. ..
2.8.5. Application 5. Functional response: predation, parasitisation,
fection .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
2.8.6. Application 6. Multi-way functional response
.. .. .. ..
2.9. Advanced handling of many models
.. .. .. .. .. .. .. .. ..
..
..
..
..
..
..
..
..
..
..
..
..
..
in..
..
..
3
3
4
6
6
7
8
8
11
11
14
18
20
..
..
..
..
..
..
..
..
43
43
44
47
51
53
57
62
.. .. .. .. .. .. .. .. .. .. .. .. .. ..
Chapter 4. The BtButTox model
4.1. Scenario simulations .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
4.2. Scenario recipes .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
64
64
65
Chapter 2.
2.1.
2.2.
2.3.
2.4.
2.5.
2.6.
2.7.
2.8.
Chapter 3.
3.1.
3.2.
3.3.
3.4.
3.5.
3.6.
3.7.
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
28
32
36
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Conductance model
Plant model
.. ..
Community model
Weather model
..
Running the model
Discussion
.. ..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
65
..
..
..
..
..
..
70
70
75
78
78
80
.. .. .. .. .. .. .. .. .. .. .. .. ..
.. .. .. .. .. .. .. .. .. .. .. .. ..
.. .. .. .. .. .. .. .. .. .. .. .. ..
82
82
93
.. .. .. .. .. .. .. ..
Chapter 7. Student projects
7.1. Lake oxygen model .. .. .. .. .. .. .. ..
7.1.1. Introduction
.. .. .. .. .. .. ..
7.1.2. Calculations
.. .. .. .. .. .. ..
7.1.3. Predicting NCP in Real Lakes
.. ..
7.1.4. Unit of output .. .. .. .. .. .. ..
7.1.5. Setting the stochastic sampling number
7.1.6. Plotting .. .. .. .. .. .. .. .. ..
7.1.7. Output from the model
.. .. .. ..
7.2. Microbial community model
.. .. .. .. ..
7.2.1. Introduction
.. .. .. .. .. .. ..
7.2.2. Population model .. .. .. .. .. ..
7.2.3. Population Growth
.. .. .. .. ..
7.2.4. Competition Model
.. .. .. .. ..
7.2.5. Reaction Models
.. .. .. .. .. ..
7.2.6. GeneralEffect Model .. .. .. .. ..
7.2.7. Community Model
.. .. .. .. ..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
94
94
94
94
96
97
97
97
98
99
99
99
99
100
102
106
108
.. ..
Appendix A. Plug-ins Reference
A.1. awe plugin
.. .. .. .. ..
A.2. conductance plugin .. .. ..
A.3. dynamic_photosynthesis plugin
A.4. ecotox plugin
.. .. .. ..
A.5. intercom plugin .. .. .. ..
A.6. MicrobialCommunity plugin
A.7. mussel_bed plugin
.. .. ..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
111
111
117
119
120
124
132
137
iv
.. .. .. ..
.. .. .. ..
.. .. .. ..
.. .. ..
.. .. .. ..
.. .. .. ..
.. .. .. ..
.. .. .. ..
..
..
..
..
..
..
..
..
..
..
..
..
..
141
143
144
145
162
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
181
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
183
References
Index
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
Chapter 1. Installation
This chapter takes you through the steps of downloading and installing Universal Simulator from
Internet and running your first simulations with Universal Simulator.
1.1. Installing Universal Simulator
First you must install the necessary software. Download the Universal Simulator installation file
from www.ecolmod.org. Execute this installation file and accept all default suggestions. After
installation you should be able to find the flying squirrel icon of Universal Simulator among
your programs.
Universal Simulator is installed in a folder inside your standard folder for programs, for
example C:/Program Files/UniSim-1-37, where 1-37, or something similar, refers to
the version of Universal Simulator. If different versions of Universal Simulator are installed, they
will simply occupy different folders and will not interfere with each other.
Inside
the
Universal
Simulator
program
folder,
for
example
C:/Program Files/UniSim-1-37, there will be a folder with the GraphViz program which
Chapter 1. Installation
change parameter values, or what is shown as output (in plots on screen or in tab-separated text
files), you always do this in three steps:
1.
Edit the recipe in the XML file using a text or XML editor.
2.
3.
In Universal Simulator, open the XML file again using File|Open or File|Reopen.
After opening (or re-opening) an XML recipe file you can run the simulation with Simulation|Run. This will result in a display of output plots on the screen and maybe some files in the
output folder. If you forgot where the output folder is, you can check the File|Locations menu.
Instructions on how to read and edit XML recipe files can be found in the next chapter.
When the user provides a recipe (an XML file selected through the File|Open menu), Universal
Simulator creates live versions of the models listed in the recipe, as objects living in the
3
simulation environment. The recipe specifies, by name and type, which models will take part
in the simulation and with which parameter values. To create the live models, the simulation
environment finds their code in the plug-in libraries. Some recipes may specify additional input,
such as weather data, provided as text file records.
When the user selects Simulation|Run on the menu, all the model objects created in the
simulation environment go into gear, each carrying out its specific behaviour (or logic,
if you prefer). Interaction with other model objects present in the simulation environment is
usually an important part of model behaviour. This allows, for example, leaf models to access
daily irradiation readings from a weather model, and predator models to feed on prey models.
Finally, when the simulations ends (as determined by the recipe, or when the user interrupts the
simulation), output is produced from the simulation environment, in terms of plots on the screen
and records in text files. Which output to produce is also described in the recipe.
The recipe is written in a much reduced subset of the XML language (see sections 2.1-2.7).
To edit XML files you can use a general purpose text editor or a dedicated XML editor. On MS
Windows, Notepad will do, but NotePad++ with its XML syntax highlighting is a better choice.
The most complete, free tool for XML editing seems to be Komodo Edit, which helps you even
more writing correct XML code.
The general structure of a recipe written in XML looks like this
<?xml version="1.0" encoding="ISO-8859-1"?>
<simulation name="Forest">
... one integrator ...
... one or more models ...
... one or more outputs ...
</simulation>
The root of the XML document must be a simulation element. You should give the simulation
a meaningfull name with the name attribute, in this case Forest. The simulation element
must contain in order: an integrator element, one or more model elements, and one or more
output elements. The integrator and model elements may hold additional model elements
inside. In addition, integrator, model and output elements may hold parameter elements.
The trace element can only be used inside output elements.
Elements may be given various attributes, such as name above, to provide detailed information. The elements that can be used in recipes, their attributes and their meaning are all described
below. First, however, comes an explanation of parameter and variable references, because we
often need to refer to a parameter or variable from one place in the recipe to another.
2.2. References to parameters and variables
The logic of a model is not accessible from the recipe. It is behind closed doors, written in C++
not XML. Models, however, provide a public interface which allows outsiders (the recipe and
other models) to set their parameters and to query the current value of their parameters and
variables. Note, however, that only the model itself (in its C++ code) can change its variables.
The syntax for referring to a parameter and a variable is the same. You supply a model name,
that is unique within the recipe, followed by the name of the parameter or variable in brackets.
Here is a reference to the parameter or variable named lossRate inside the mass model:
mass[lossRate]
If mass is not unique inside the recipe, i.e. more than one model has the name mass, then you
must nail it down more precisely by providing its location. For instance, if you have a mass
model inside both a larva and a pupa model, you can refer to the latter by writing
pupa/mass[lossRate]
You can provide as a long a path as needed to make the reference unique:
drosophila/pupa/mass[lossRate]
All the examples above are examples of references. They can be used in the ref attribute of
parameter (2.3) and trace (2.7) elements.
A common usage of references is when several parameters logically must have the same
value, or when the parameter of one model is referring to the current value of a state variable
in another model. This example demonstrates this and also shows how to make use of relative
references, which are refences starting with one or two periods:
<model name="colony">
<model name="egg" type="Vespa::Egg">
<parameter name="newEggs" ref="../queen[eggsLaid"/>
<parameter name="newFertilisedEggs" ref=".[newEggs]"/>
<model name="mass" type="UniSim::Stage">
<parameter name="duration" value="2"/>
<parameter name="k" value="30"/>
</model>
<model name="number" type="UniSim::Stage">
<parameter name="duration" ref="../mass[duration]"/>
<parameter name="k" ref="../mass[k]"/>
</model>
</model>
<model name="queen" type="Vespa::Queen">
</model>
</model>
Here, the parameter newEggs is referring to the eggsLaid variable, which is maintained by
the model named queen. The double-period notation means, go one step up, in the hierarchy. In
this case to the colony model. Thus one double-period (../) takes you to a sibling model, two
(../../) to an uncle model and so forth.
The single-period (./) refers to the element itself. Hence, newFertilisedEggs will take
on the same value as the newEggs parameter in the same model.
The value of parameters duration and k are fixed in the mass model. Because they
must have the same values in the number model, the number model defines its parameters by
reference to the mass model. Note that references may refer to models anywhere, upwards or
downwards, in the recipe.
2.3. Parameter elements
The parameter element is used to set the value of a parameter. Here the k parameter is set to
the value 30:
<parameter name="k" value="30"/>
Note the XML syntax: Since a parameter element never holds another element inside, it
will always end with a slash (/) before the closing sharp parenthesis (>). The format of the
parameters value attribute depends on the type of the parameter:
Parameter type
Examples
Integer
-11, 0, 30
Floating point
-2.4, 1e6
String
paris_1919.txt
Boolean
Date
18/8/2011, 2011/8/18
Time
21:48:10, 9:13
Dates follow the European (dd/mm/yyyy) or international (yyyy/mm/dd) convention. Since year
must be given with four digits, it is clear which convention is meant. Time of day can be given
with (hh:mm:ss) or without seconds (hh:mm).
The parameters available for each model can be looked up in the Plug-ins Reference. For
example, if you look up the k parameter of the Stage model in the UniSim plug-in (page 157),
you find both an explanation of its use and its default value. All models come with default values
for their parameters. Unless you change the parameter value in the recipe, the parameter will keep
its default value.
If you use the ref attribute instead of the value attribute, the parameter value will be
retrieved from another parameter or a variable. For example:
<parameter name="mortality" ref="herbicide[effect]"/>
In this example, you cannot tell whether effect in the model named herbicide is a parameter
or a variable but the result will be the same: mortality will take on the current value of
effect.
2.4. The integrator element
An integrator element should always be the first element inside the simulation element,
which makes up the outermost element, also called the root element. Moreover there can only
be one integrator element. The integrator is, in fact, just a model with a special role: it
determines for how may time steps the simulation should be running. For example,
<integrator type="UniSim::Steps">
<parameter name="maxSteps" value="365"/>
</integrator>
The type attribute is used to select the kind of integrator needed, here the Steps integrator,
which belongs to the Universal Simulator standard plug-in, named UniSim. Currently, this is
the only type of integrator available but one for sensitivity analysis is under development
(autumn 2013).
The duration of the simulation is given in terms of time steps. In this example, it has been
set to 365 which suggest that the length of a time step is one day. Time step length, however, is
not determined by the integrator. Most UniSim XML documents will have a calender model
(page 145) to manage the time scale.
If the simulation contains stochastic models, it is useful to run the simulation for several
iterations. This is specified by including a child model named runIterator:
<integrator type="UniSim::Steps">
<parameter name="maxSteps" value="365"/>
<model name="runIterator" type="UniSim::RunIteratorFixed">
<parameter name="numIterations" value="30"/>
</model>
</integrator>
The question is where the file ngorongoro.txt should be located? The Records model,
and other models that need text file input, will look for input files in various locations in the
following order:
1.
2.
3.
4.
5.
The last two steps are repeated for the grandparent folder and levels further up
This allows you to place input files where they can be shared by the relevant recipes.
2.7. Output and trace elements
The trace element is used only inside output elements where it used to define the model
parameter or variable to show in the output, for example, as a curve in a plot or a column in a
table. For output plots, the first trace defines the x-axis. The subsequent traces each define a
curve to display:
<output type="plot">
<parameter name="title" value ="Larva population dynamics"/>
<trace label="Day" ref="calendar[dayInYear]"/>
Here the type attribute has been set to plot to show this output as a plot on the screen, and the
ensuing parameter element sets the title of that plot. The label attribute of the first-coming
trace element (here, Day) is used to label the x-axis. The label attribute of subsequent trace
elements are used to label each curve. In this case, two curves labelled Mass and Number. The
ref attributes of the trace elements refers to variables (dayInYear, value and value) found
in the respective models (calendar, larva/mass and larva/number). Similar output, sent
to a text file named larva_pop_dyn.txt, and with three columns, labelled Day, Mass and
Number, would be produced by this code:
<output type="table">
<parameter name="fileName" value ="larva_pop_dyn.txt"/>
<trace label="Day" ref="calendar[dayInYear]"/>
<trace label="Mass" ref="larva/mass[value]"/>
<trace label="Number" ref="larva/number[value]"/>
</output>
Currently, only floating point variables and parameters (C++ type double) will be shown
correctly in output. If the ref attribute inside a trace cannot be resolved then that trace
element will silently by ignored. If less than two traces are found for a plot output or no traces
are found for a table output, an error message will appear.
Sometimes you may want to log-transform the y-axis or to set the minimum and maximum
value of the y-axis. The following example shows how to achieve this through the parameters
logy, ymin and ymax. You can use one or more of these parameters in any combination. Here,
they are used in concert:
<output type="plot">
<parameter name="title" value ="Larva population dynamics"/>
<parameter name="logy" value ="true"/>
<parameter name="ymin" value ="0.01"/>
<parameter name="ymax" value ="1e7"/>
<trace label="Day" ref="calendar[dayInYear]"/>
<trace label="Mass" ref="larva/mass[value]"/>
<trace label="Number" ref="larva/number[value]"/>
</output>
With these parameter values, the y-axis will be shown as log10-transformed values; zero-valued
y-values will be ignored. The minimum and maximum values always refer to the original scale.
You can scale an axis by using the multiplier or divisor attributes. Here time is
divided by 7 and mass is multiplied by 1000, before they are shown on the axes:
<output type="plot">
<parameter name="title" value ="Growth"/>
<trace label="Week" ref="calendar[totalTimeSteps]"
divisor=7/>
10
Traces will be shown as lines by default but they can also be shown as symbols, or both line and
symbols. This is set by the type attribute of trace elements:
<output type="plot">
<parameter name="title" value ="Larva population dynamics"/>
<parameter name="logy" value ="true"/>
<parameter name="ymin" value ="0.01"/>
<parameter name="ymax" value ="1e7"/>
<trace label="Day" ref="calendar[dayInYear]"/>
<trace label="Number" ref="larva/number[k]" type="Line"/>
<trace label="Mass" ref="larva/mass[value]" type="Symbols"/>
<trace label="Number" ref="larva/number[value]" type="Both"/>
</output>
If you put a run iterator inside the integrator element (page 6) to run the simulation multiple
times, then output will be produced for every simulation run. For output elements of type plot,
additional output will simply be added producing a trace in the plot for every run. For output
elements of type table, the output from each run will go into a separate file; the files will be
numbered from 1 and onwards.
You can also request for additional output to summarise the result of multiple simulation
runs. For example, you might want to see a plot with the maximum population density, achieved
in each simulation run, plotted against some parameter. For this purpose you use summary plots.
To request summary output, you use the summary attribute of the trace element. For instance,
if you set a fecundity parameter to some random value before each simulation run, and you want
to see the simulated response in terms of maximum larval density, you could write
<output type="plot" >
<parameter name="title" value ="Max. larva mass"/>
<trace label="Fecundity" ref="adult[fecundity]"/>
<trace label="Mass" ref="larva/mass[value]" summary="max"/>
</output>
The default type of a trace element that holds a summary attribute is Symbol. So this code
will show a plot with as many symbols as the number of simulation runs. You can include more
than one summary trace in a plot, although in practice you most often have just one. You can also
use the summary attribute for trace elements to produce file output, i.e. for output elements
with type attribute set to table.
Different values for the summary attribute results in different values:
11
Summary
Meaning
max
min
avg
sum
final
xAtMax
X-value (e.g. time) at which the maximum value was achieved during a
simulation run
X-value (e.g. time) at which the minimum value was achieved during a
simulation run
xAtMin
2.8. Applications
This section shows a selection of recipes for various applications. The recipes can all be found
in the recipes/unisim_explained/writing_recipes folder.
2.8.1. Application 1. Life stage sequence
If you work with stage-structured models of populations dynamics, you often need to string
life stages together, transferring individuals from one stage to the next as they develop. The
Stage model of the UniSim plug-in can be used to model the development in each individual
stage. To pass individuals on to the following stage, you use outflow (a variable of the Stage
model) and inflow (a parameter of the Stage model). Naturally, the outflow from a life stage
must be modelled and computed by the life stage itself, whereas the inflow to it is coming
from outside and is thus a parameter for the life stage. This recipe simulates the life stages of a
holometabolous insect:
<?xml version="1.0" encoding="ISO-8859-1"?>
<simulation name="insect">
<integrator type="UniSim::Steps">
<parameter name="maxSteps" value="100"/>
</integrator>
<model name="calendar" type="UniSim::Calendar">
</model>
<model name="weather" type="UniSim::Weather">
<model name="records" type="UniSim::Records">
<parameter name="fileName" value="Harlingen2008.txt"/>
</model>
</model>
12
2.8. Applications
13
<output type="plot">
<parameter name="title" value ="Harlingen weather log"/>
<trace label="Day" ref="calendar[totalTime]"/>
<trace label="Temperature" ref="weather[Tavg]"/>
</output>
<output type="plot">
<parameter name="title" value ="Insect numbers"/>
<trace label="Day" ref="calendar[totalTime]"/>
<trace label="Eggs" ref="egg/number[value]"/>
<trace label="Larvae" ref="larva/number[value]"/>
<trace label="Pupae" ref="pupa/number[value]"/>
<trace label="Adults" ref="adult/number[value]"/>
</output>
</simulation>
The integrator of the simulation tells it to run for 100 time steps. A Calendar model
keeps track of time, and a Weather model reads weather records from a weather log file. The
Stage models runs on different time scales, either days or day-degrees, as given by the sibling
model named time. The DayDegrees models will automatically search for a model named
weather and will pull daily temperature readings from the weather model. At the end, one plot
shows the daily temperature reading, and another plot shows the resulting insect development:
14
Note that several models simply acts as containers of other models: insect, egg, larva,
pupa and adult. These models add no behaviour of their own. Consequently, they have no
type attribute.
2.8.2. Application 2. Random parameter values
If some parameters are uncertain, or if you want to explore the sensitivity of the model to
variance in some parameters, you need to run the simulation repeatedly to assess the possible
outcomes. In this continuation of the example above, we want to explore the sensitivity of the
model to the lower temperature threshold for development of the three immature life stages:
<?xml version="1.0" encoding="ISO-8859-1"?>
<simulation name="SHBmodel">
<integrator type="Steps">
<parameter name="maxSteps" value="100"/>
<model name="runIterator" type="RunIteratorFixed">
<parameter name="numIterations" value="100"/>
</model>
</integrator>
<model name="calendar" type="Calendar">
</model>
<model name="weather" type="UniSim::Weather">
<model name="records" type="UniSim::Records">
<parameter name="fileName" value="Harlingen2008.txt"/>
</model>
</model>
<model name="random">
<model name="eggT0" type="UniSim::RandomUniform">
<parameter name="minValue" value="0"/>
<parameter name="maxValue" value="8"/>
</model>
<model name="larvaT0" type="UniSim::RandomUniform">
<parameter name="minValue" value="0"/>
<parameter name="maxValue" value="8"/>
</model>
<model name="pupaT0" type="UniSim::RandomUniform">
<parameter name="minValue" value="0"/>
<parameter name="maxValue" value="8"/>
</model>
</model>
<model name="insect">
<model name="egg">
<model name="time" type="UniSim::DayDegrees">
2.8. Applications
<parameter name="T0" ref="random/eggT0[value]"/>
</model>
<model name="number" type="UniSim::Stage">
<parameter name="duration" value="41"/>
<parameter name="k" value="30"/>
<parameter name="initialInflow" value="100"/>
</model>
</model>
<model name="larva">
<model name="time" type="UniSim::DayDegrees">
<parameter name="T0" ref="random/larvaT0[value]"/>
</model>
<model name="number" type="UniSim::Stage">
<parameter name="duration" value="205"/>
<parameter name="k" value="30"/>
<parameter name="inflow"
ref="egg/number[outflow]"/>
</model>
</model>
<model name="pupa">
<model name="time" type="UniSim::DayDegrees">
<parameter name="T0" ref="random/pupaT0[value]"/>
</model>
<model name="number" type="UniSim::Stage">
<parameter name="duration" value="98"/>
<parameter name="k" value="30"/>
<parameter name="inflow"
ref="larva/number[outflow]"/>
</model>
</model>
<model name="adult">
<model name="time" type="UniSim::Days"/>
<model name="number" type="UniSim::Stage">
<parameter name="duration" value="30"/>
<parameter name="k" value="10"/>
<parameter name="inflow"
ref="pupa/number[outflow]"/>
</model>
</model>
</model>
<output type="plot">
<parameter name="title" value ="Harlingen weather log"/>
15
16
We have added a model named runIterator inside the iterator element to achieve
repeated simulations. In this case, we have sete numIterations to achieve 100 repeated runs
of the model.
The random model is simply a container for three models producing random numbers.
The numbers are uniformly distributed between the minimum and maximum values, yielding
evenly distributed values in the range 0 to 8 from all three models. The RandomUniform model
produces a new random value immediately before each simulation run.
2.8. Applications
17
The parameter values for T0 which were previously set to fixed values by the value
attribute have now been set to refer to the pertinent random values. This has been effectuated by
replacing the value attribute with a ref attribute.
Three plots have been added at then end to show the sensitivity of the model to the lower
temperature thresholds of each of the three immature life stages. Each plot shows the value of the
temperature threshold on the x-axis and the time, at which the adult density peaked, on the y-axis.
These plots are constructed by using the summary attribute for the second trace element in
the plot. Here, the summary has been set to xAtMax. For other possible values of the summary
attribute, see page 10.
As can be seen in the plots, weather was the same all simulations (there is only one temperature curve), while the 100 sets of curves showing population numbers illustrate the variability
caused by the random temperature threshold values:
18
In conclusion, the model was most sensitive to variability in the lower temperature threshold
of the larvae, probably because they had the longest development time. Note that all three
parameters varied at the same time. If you want to see the effect of just one random threshold,
you must set the other two threshold to fixed values using the value attribute instead of the
ref attribute.
2.8.3. Application 3. Stage-structured population dynamics
In Application 1 we modelled only the phenology of one generation of an insect. To include
population dynamics, we must add insect reproduction to the recipe. We achieve this be
introducing a Stage model called eggsToBeLaid with a growthRate corresponding to the
life time fecundity of an adult:
2.8. Applications
19
<model name="adult">
<model name="time" type="UniSim::Days"/>
<model name="number" type="UniSim::Stage">
<parameter name="duration" value="30"/>
<parameter name="k" value="10"/>
<parameter name="inflow" ref="pupa/number[outflow]"/>
</model>
<model name="eggsToBeLaid" type="UniSim::Stage">
<parameter name="duration" value="10"/>
<parameter name="k" value="20"/>
<parameter name="inflow" ref="pupa/number[outflow]"/>
<parameter name="growthRate" value="60"/>
</model>
</model>
For every unit that flows into eggsToBelaid, 60 units will eventually flow out; These are the
eggs laid, and they are added as inflow to the egg stage:
<model name="egg">
<model name="time" type="UniSim::DayDegrees">
<parameter name="T0" value="4.5"/>
</model>
<model name="number" type="UniSim::Stage">
<parameter name="duration" value="41"/>
<parameter name="k" value="30"/>
<parameter name="initialInflow" value="100"/>
<parameter name="inflow"
ref="adult/eggsToBeLaid[outflow]"/>
</model>
</model>
With these settings, the adult will live 30 days on average, and eggs will be laid by females at
the age of 10 days on average. If the population has a sex ratio of 50% then a growthRate
of 60 means, that the life time fecundity of a female is 120 eggs. If the model is later extended
with a mortality factor on adults, one should remember to effectuate mortality on both stages,
number and eggsToBeLaid inside adult. In the simulation output, it is difficult to discern the
generations on a linear scale:
20
However, on a log-scale we can see that two new generations result from the original cohort
of 100 eggs:
2.8. Applications
21
The host has two stages J)uvenile and A)dult but only the adult stage can become infected
and, after infection, eventually becomes resistent. The adults only die from old age; their
expected lifespan is unaffected by the disease. The juvenile stage receives inflows from all four
adult sub-populations, irrespective of which phase of infection they are in. It should be noted
that adults of the S, E and I sub-populations can leave their current either by ageing (they die) or
22
their phase (they proceed to the next step of infection). The disease is not promoted from mother
to child, hence all offspring enter as susceptible juveniles. Only adults can become infected, and
the infection rate depends on the density of infectious adult vectors.
The vector is an insect with four life stages: E)gg, L)arva, P)upa and A)dult. Only the adults
can be infected; the infection rate depends on the density of infectious adult hosts. In addition,
all eggs laid by infectious adults will eventually themselves become infectious adults, whereas
eggs laid by exposed adults go into the egg stage of the susceptible sub-population. Just as for
the host population, adult vectors in the S and E stages have two possible fates: either they die or
they pass on to the next phase of infection.
We will begin with the part of the recipe that describes the host model. For the susceptible
phase S we have
<model name="host">
<model name="time" type="UniSim::Days"/>
<model name="S">
<model name="juvenile" type="UniSim::Stage">
<parameter name="initialInflow" value="80"/>
<parameter name="inflow" ref="../toBeBorn[outflow]"/>
<parameter name="duration" value="1095"/>
<parameter name="k" value="30"/>
</model>
<model name="adult" type="UniSim::Stage">
<parameter name="initialInflow" value="50"/>
<parameter name="inflow" ref="../juvenile[outflow]"/>
<parameter name="duration" value="3650"/>
<parameter name="k" value="30"/>
<parameter name="phaseOutflowProportion" value="0.01"/>
</model>
<model name="toBeBorn" type="UniSim::Stage">
<parameter name="inflow" ref="../juvenile[outflow]"/>
<parameter name="duration" value="730"/>
<parameter name="k" value="30"/>
<parameter name="growthRate" value="2.5"/>
</model>
</model>
<...>
</model>
We apply the technique from the previous application (2.8.3) to model reproduction.We introduce
a Stage model called toBeBorn which takes the same inflow as the adult stage. In this case,
where adults in all phases produce juveniles in the susceptible phase, it simplifies matters: the
toBeBorn model is only needed here, as a sub-model of the susceptible phase S. Host development is measured in days, as set by the time model. The parameter values correspond to some
2.8. Applications
23
imaginary vertebrate species. For simplicity, the toBeBorn model is not shown in the figure.
The adult stage has a parameter which defines the proportion of the adults that will
bchanging phase in the next time step. The name of this parameter is phaseOutflowProportion. In a more complete version of the e model, this proportion would be dynamic, varying
with the attack rate of the infectious vector population. In this first version, it is kept simple as a
fixed rate of 1% per day.
The adult stage has two outflows, which can be accessed through the variables outflow
and phaseOutflow. In this case, outflow simply is the loss due to old age while the phaseOutflow must be taken up by the adult stage in the subsequent, exposed phase (E). To link the
flow between phases, the phaseInflow parameter is used, as seen in the subsequent phases of
the host model E, I and R:
<model name="E">
<model name="adult" type="UniSim::StageAndPhase">
<parameter name="duration" ref="../S/adult[duration]"/>
<parameter name="k" ref="../S/adult[k]"/>
<parameter name="timeStep" ref="../time[step]"/>
<parameter name="phaseInflow"
ref="../S/adult[phaseOutflow]"/>
<parameter name="phaseDuration" value="10"/>
<parameter name="phaseK" value="15"/>
<parameter name="phaseTimeStep" ref="../time[step]"/>
</model>
</model>
<model name="I">
<model name="adult" type="UniSim::StageAndPhase">
<parameter name="duration" ref="../S/adult[duration]"/>
<parameter name="k" ref="../S/adult[k]"/>
<parameter name="timeStep" ref="../time[step]"/>
<parameter name="phaseInflow"
ref="../E/adult[phaseOutflow]"/>
<parameter name="phaseDuration" value="20"/>
<parameter name="phaseK" value="15"/>
</model>
</model>
<model name="R">
<model name="adult" type="UniSim::Stage">
<parameter name="duration" ref="../S/adult[duration]"/>
<parameter name="k" ref="../S/adult[k]"/>
<parameter name="phaseInflow"
ref="../I/adult[phaseOutflow]"/>
24
</model>
</model>
There are several linkages between different models defined here. To start with the simple ones,
the parameters duration and k of the adult models in the E, I and R phases, all refer back to
the same parameters in the S phase. Thus adult ageing is not affected by the infection.
Next, the models for the E and I phases are of type StageAndPhase, instead of Stage. A
StageAndPhase model has two development processes going on simultaneously: development
by ageing (vertical arrows in the figure) and development to the next phase of the infection
(rightwards arrows in the figure). Both processes need parameters to characterise the average
duration and dispersion of development time: duration and k for life stage development, and
phaseDuration and phaseK for phase development.
Parameters specifying the inflow and the duration of the time step, are supplied as
parameters, inflow and timeStep, and phaseInflow and phaseTimeStep, respectively.
Note, that for models of Stage type, we did not specify the timeStep parameter. This is not
necessary because Stage models automatically look up the nearest model called time and pulls
the step variable from that. But for StageAndPhase model we have to specify the time step
parameter for both directions of development.
In the final phase (R), the adult model again is a Stage model because development only
occurs in one direction, which is ageing.
The vector model is more complicated than the host model, because it has more life
stages. In the host model, we introduced a toBeBorn stage to model reproduction. Likewise,
we introduce a toBeLaid stage in each of the three vector phases. The recipe for the susceptible phase is simply a series of Stage models, one for each life stage and one for the toBeLaid stage:
<model name="vector">
<model name="time" type="UniSim::DayDegrees">
<parameter name="T0" value="8"/>
</model>
<model name="S">
<model name="egg" type="UniSim::Stage">
<model name="inflows" type="UniSim::Sum">
<parameter name="toAdd" value="(../toBeBorn[outflow]
vector/E/toBeBorn[outflow])"/>
</model>
<parameter name="initialInflow" value="100"/>
<parameter name="inflow" ref="./inflows[value]"/>
<parameter name="duration" value="50"/>
<parameter name="k" value="30"/>
</model>
<model name="larva" type="UniSim::Stage">
<parameter name="inflow" ref="../egg[outflow]"/>
<parameter name="duration" value="250"/>
<parameter name="k" value="30"/>
2.8. Applications
25
</model>
<model name="pupa" type="UniSim::Stage">
<parameter name="inflow" ref="../larva[outflow]"/>
<parameter name="duration" value="80"/>
<parameter name="k" value="30"/>
</model>
<model name="adult" type="UniSim::Stage">
<parameter name="inflow" ref="../pupa[outflow]"/>
<parameter name="duration" value="100"/>
<parameter name="k" value="30"/>
<parameter name="phaseOutflowProportion" value="0.04"/>
</model>
<model name="toBeLaid" type="UniSim::Stage">
<parameter name="inflow" ref="../pupa[outflow]"/>
<parameter name="duration" ref="../adult[duration]"/>
<parameter name="k" ref="../adult[k]"/>
<parameter name="growthRate" value="50"/>
<parameter name="phaseOutflowProportion"
ref="../adult[phaseOutflowProportion]"/>
</model>
</model>
<...>
</model>
Since the egg model takes input from two models, toBeLaid both in the S and E phase, we use
a Sum type model to add the outflows from these. A Sum model has just one parameter toAdd
which contains a list of references to add.
The other Stage models are standard in their parameter settings, except for the toBeBorn
stage for which we must remember to set the same phaseOutflowProportion as for the
adult stage. Biologically, we should think of the eggs to be laid as developing inside the adults.
Then it follows logically that adult and toBeBorn populations should walk hand in hand
through the phases of infection.
All vector stages run on a day-degree scale as set by the time model. The life history
parameters settings suggest that the vector is an invertebrate species, for example, a mosquito.
The phaseOutflowProportion has been set to a fixed value of 4% per day. In a complete
model this parameter would be dynamic depending on the attack rate of susceptible vectors on
infectious hosts.
The exposed phase of the vector only contains the adults. Hence we should expect a simple
recipe for that phase. However we must remember to include a toBeLaid stage:
<model name="E">
<model name="adult" type="UniSim::StageAndPhase">
<parameter name="duration" ref="../S/adult[duration]"/>
<parameter name="k" ref="../S/adult[k]"/>
<parameter name="timeStep" ref="vector/time[step]"/>
26
Both of the models in the exposed phase undergo development in two directions. Followingly
they are modelled as StageAndPhase models. It is worth noticing that the only parameters
particular to the exposed phase are phaseDuration (20) and phaseK (15). Moreover, as adults
and eggs to be laid go hand in hand, the two parameters are set to the same values in the adult
and toBeLaid models.
The remaining parameters are set by reference to those parameters, that they are logically
equivalent to. There are no inflows set by the inflow parameter but the phaseInflow parameter links both the adult and toBeLaid models to their similar models in the susceptible phase.
In the final, infectious phase there is only one direction of development. So, all life stage
models are back to the Stage type:
<model name="I">
<model name="egg" type="UniSim::Stage">
<parameter name="inflow" ref="../toBeLaid[outflow]"/>
<parameter name="duration" ref="vector/S/egg[duration]"/>
<parameter name="k" ref="vector/S/egg[k]"/>
</model>
<model name="larva" type="UniSim::Stage">
<parameter name="inflow" ref="../egg[outflow]"/>
<parameter name="duration"
ref="vector/S/larva[duration]"/>
<parameter name="k" ref="vector/S/larva[k]"/>
</model>
2.8. Applications
27
The recipe is straightforward, except for all the references that must be set to reflect the correct
biological bindings. No new parameter values are needed.
When a recipe contains many information flows between models, it is always a good idea to
test that the plumbing is correct. In this case, the initial inflow marked a in the figure should equal
the sum of the two outflows marked b and c, provided that there is no reproduction. To check this
assertion we make a special version of the recipe, in which no reproduction occurs. All in all, we
expect these balance equations to hold (with reference to the figure): a=b+c, c=d+e, e=f . This
is what we see for 1 years simulation:
28
The final values of flows a-f can be read off the plot by clicking the curves but they can
also be retrieved from the output file produced by the recipe. We find a=100, b=65.17, c=34.82,
d=5.71, e=29.11, f =29.11 from which we confirm that all balances hold as expected.
Next we can add reproduction back into the recipe and follow the dynamics of hosts and
vectors. We should remember though that the epidemics are still not modelled realistically, since
we still hold the infection rates of susceptible hosts and susceptible vectors at fixed values (1 and
4% per day, respectively).The host population shows a steady increase in the resistent population,
while the first juveniles of the next generation are on their way (as the toBeborn population):
The initial 100 eggs of the vector population resulted in two generations of adult vectors:
The population of exposed vectors continues to increase at the end of the year, but this is
an artifact of the model: the rate of susceptible adults turning exposed is 4% per day, while the
development rate of exposed adults into infectious runs on a day-degree scale, that by the end of
the year has come to a halt due to falling temperatures. Clearly, the infection rates should not be
fixed but rely on some biologically realistic model.
2.8.5. Application 5. Functional response: predation, parasitisation, infection
In Universal Simulator, the FunctionalResponseGB model implements the GutierrezBaumgrtner functional response model:
2.8. Applications
29
X
S = D 1 exp
D
This model works with the concepts demand (D), supply (S) and ressource apparancy () with
populations denoted as consumer/predator/parasite/patogen (Y) and resource/prey/host (X). For
a predator-prey system with a time step of one day, the demand and supply could be modelled
in units of, for example, biomass per m2 per day. The demand will be time-varying, as it will
increase with the density of the predator population. For a predator working on a day-degree
scale, the demand will moreover increase with temperature. The demand is often calculated as
D = dY t
where d is the per capita demand rate per time unit, Y is the predator density and t is the time
step measured on the predator time scale.
Demand is a possibly multi-layered concept. If a predator needs a certain input for
growth, it will need to eat more than this to satisfy that demand, because it also spends energy on metabolism. Moreover, it needs to kill more prey than the total demand for growth and
metabolism: Part of the prey will go unutilised, either because it was never eaten (for example,
the skeleton), or because it was quickly ejected (for example, the honey dew excreted by aphids).
One should be aware of these demands at different physiological levels when using the functional
response model.
The demand puts an upper limit on the supply rate; the predator population cannot acquire
more than it needs. How close the supply (S) gets to the demand (D) depends on prey density
and the search efficiency of the predator. In the (G-B) functional response, this is parameterised
as the apparancy () of the prey, a number between zero and one (inclusive). Search behaviour
is difficult to measure, and it makes sense that this difficult aspect is translated into a single
parameter, which usually must be determined by calibration (i.e. fitting of model output to
observed field data).
In
this
example
(the
recipe
can
be
found
in
the
recipes/unisim_explained/writing_recipes folder), apparancy has been set to = 0
.8 and demand to D = 10 with prey density in the range X = 0..100:
Egestion and base metabolic rate have both been set to zero. Supply can be seen to reach
30
The supply curve now increases less steeply with increasing prey density, because the
predator needs to kill more to obtain the same net supply. In a final step we add basic metabolic
rate as a constant with the value 1. Again, we see the supply curve slacken; an even higher prey
density is needed to obtain the same net supply::
The allocation of the acquired net supply lies outside the logic of the FunctionalResponseGB model. Further losses my incur, for example the cost of growth respiration (i.e., conversion costs of food intake).
Energy budget considerations can have a dramatic effect on the predicted number of prey
killed. The three models above all have an asymptote of net supply equal to 10, but by including
losses first to egestion and then to basic metabolism, the potential number of prey killed rises:
2.8. Applications
31
In this last graph the variable totalSupply is shown, whereas the previous three graphs
showed the supply, egestion and respiration variables of the FunctionalResponseGB model. Hence supply denotes the net supply, which is the totalSupply corrected for
egestion and respiration.
A final variable that is commonly calculated is the supply/demand ratio. The example shows
how this is decreasing when losses to egestion and base respiration are included:
32
the average number of attacks per host,
m = S
X
Commonly we would be interested in knowing the number of hosts attacked (X a), which we
can infer from the zero term of the Poisson distribution,
X a = X 1 exp( m)
Prey apparancy
Predator
Demand
Gazella
Gnu
Zebra
Leopard
Leopard
12
0.05
0.001
0.02
Lion
18
0.08
0.01
0.04
0.0005
Prey density
100
200
150
The single zero occuring among the apparancy values implies that leopards are not cannibalistic.
Whatever applies in nature, the Predation model would accept cannibalism too.
application_6_predation.xml
The
recipe
(found
in
the
recipes/unisim_explained/writing_recipes folder) calculates the predation rates
that would result from the table above. However, in this recipe only the the Predation model
is truely functional, whereas the five animal models are just mockups with fixed values for Density and Demand. In a realistic model Density and Demand would be time-varying. Here, the
model keeps calculating the same predation rates, without any kills being effectuated:
<simulation version="1.0">
<integrator type="Steps">
<parameter name="maxSteps" value="10"/>
</integrator>
2.8. Applications
33
The apparancy parameters are provided as the parameter apparancyMatrix to the Predation
model as a tab-separated, text file with the following format:
34
Leopard[demand]
Lion[demand]
Gazella[density]
Gnu[density]
Zebra[density]
Leopard[density]
0.05
0.001
0.02
0.08
0.01
0.04
0.0005
The first column contains references to predator demands. A column label is optional and
inconsequential. The following columns all bear column headings that are references to the
variables holding the density of prey. Both prey densities and predator demands can obviously
be time-varying, so the model needs references to keep track of them. The entries in the main
body of the table shows the apparancy values for each predator-prey combination. The apparancy
values are constant.
With the apparancy matrix above and the prey densities shown in the earlier table, the
Predation model will yield these predation rates when updated:
Gazella
Gnu
Zebra
Leopard
Supply
Leopard
3.410
0.169
2.241
0.000
5.821
Lion
5.000
1.491
3.990
0.002
10.481
Loss
8.410
1.660
6.230
0.002
16.302
model
reference
in
the
apparancy
matrix
contains
slashes,
as
in
2.8. Applications
35
Host apparancy
Parasitoid
Demand
io
levana
paphia
io/fly
Fly
12
0.05
0.001
0.02
Wasp
18
0.08
0.01
0.04
0.0005
Host density
100
200
150
For the Infection model, the demand denotes the potential egg-laying rate of a parasitoid, or
for a vector, the potential rate of encounters between vector and host. The number of interactions
can grow dramatically as parasitoids, vectors and hosts are added to the system, because host
populations may need to be split into different sub-populations. Thus sub-populations may be
needed to keep separate, parasitised and non-parasitised hosts, and different phases of infection
(susceptible, exposed, infectious and recovered). Here we include only one such sub-population
named io/fly which denotes io butterflies parasitised by the fly. According to the apparancy
matrix above, fly-parasitised io cannot be attacked by the fly again, but it can be attacked by the
wasp (at a very low rate).
The application_6_infection.xml recipe yields this simulation output:
io
levana
paphia
io/fly
Attacks
Fly
3.500
0.170
2.272
0.000
5.941
Wasp
5.088
1.491
4.020
0.002
10.601
Attacks
8.588
1.661
6.291
0.002
16.542
The outcome of the Infection model is shown here in terms of the number of attacks. If you
compare this outcome with that of the Predation model, you will find that the Infection
model yields slightly higher numbers. This is because infections can overlap; one host can
receive more than one parasitoid egg or encounter more than vector during a time step. For many
purposes you would also be interested in the number of hosts attacked, in addition to the number
of attacks. The number of hosts attacked will be slightly smaller than the number of attacks,
because a few hosts by chance will have been attacked more than once:
36
io
levana
paphia
io/fly
Attacked
Fly
3.439
0.170
2.255
0.000
5.863
Wasp
4.961
1.486
3.966
0.002
10.415
Attacked
8.400
1.655
6.221
0.002
16.278
These rates, denoting the number of hosts attacked, are inbetween those of predation and number
of attacks, as you can verify by comparing the three respective tables above. The last table still
contains some overlap, as hosts can be attacked by both fly and wasp. For instance, for the io
population the 3.500 attacks (eggs laid) by the fly population led to 3.439 io indivuals being
attacked (having 1 on or more parasitoid eggs inside), and the 5.088 attacks (eggs laid) by the
wasp population led to 4.961 individuals being attacked. Of those individuals attacked some
would have been attacked coincidentally by both fly and wasp. How to sort this out depends on
the biology of the involved species.
The Infection model computes more variables than the Predation model. These variables are named parasitoid-host or vector-host. For the number of attacks, attacks is appended to the name, for example, infection[Fly-paphia-attacks] (equal to 2.272) or infection[Wasp-io_fly-attacks] (equal to 0.002). As noted for the Predation model,
slashes (/) are not allowed in variable names and will be replaced by underscores by the Infection model; here we must write io_fly, instead of io/fly. For the number of hosts attacked, attacked is appended to the name, for example infection[Fly-paphia-attacked]
(equal to 2.255). The totals are named by just the parasitoid, vector or host followed by attacks or attacked, for example infection[Wasp-attacks] (equal to 10.601) or infection[paphia-attacked] (equal to 6.221).
2.9. Advanced handling of many models
Suppose you need several instances of the same model; they have the exact same settings for
parameters and any child models. Then you use the instances attribute:
<model name="generation" type="Insect" instances="3">
...
</model>
I this example you would get three instance of the Insect model. They would be named
generation(1), generation(2) and generation(3). You would need these names, for
instance, when referring to the models in an output element.
In other cases you may need several instances but with different parameter values. Maybe
you have got hundreds of farms each represented by a Farm model. Specifying all these in an
XML recipe would be very cumbersome. Just imagine the first four out of many hundreds:
<model name="landscape" type="My::Landscape">
<model name="A" type="My::Farm">
<parameter name="FarmType" value="Cattle"/>;
<parameter name="SoilType" value="Sand"/>;
37
In this example the plug-in called My defines models of type Landscape and Farm. In the above,
one Landscape model with four Farm models inside is created.
Usually such information would stem from a spreadsheet or database. If you export the
information into a tab-separated text file then you can get the same result as above much more
conveniently, irrespectively of the number of models you want to create:
<model name="landscape" type="My::Landscape">
<model type="My::Farm" table="farms.txt">
</model>
</model>
Where the farms.txt file has this content (with tab-seperated columns):
*My::Farm
FarmType
SoilType
Economy
Cattle
Sand
Business
Cattle
Sand
Leisure
Plant
Sand
Business
Plant
Clay
Business
Note that the parameter values are taken from the columns, identified by the column heading.
These column headings function like the usual name attribute. The name of the model itself is
taken from the column with a heading that matches the models type, in this case My::Farm.
To mark this special functionality it must be preceeded by an asterisc *My::Farm.
The next level of complexity arises once we realize that the farms differ in their acreage of
38
different crops, and we need a Crop model for each of these on each farm. Could we somehow
use the same syntax?
<model name="landscape" type="My::Landscape">
<model type="My::Farm" table="farms.txt">
<model type="My::Crop" table="crops_on_farms.txt">
</model>
</model>
</model>
That certainly does look neat. Now, the crops_on_farms.txt file must hold columns both for
the farm and the crop to specify the parameters for each farm x crop combination:
*My::Farm
*My::Crop
Area
Oats
10
SBarley
30
Oats
20
WBarley
40
SBarley
15
WBarley
25
Oats
55
Here farms A and B each have two crops, farm C has none, and farm D has three. In this
example, the Crop model only has one parameter called Area. Or, if the Crop model holds more
parameters, they will keep their default value as defined in the C++ code for the Crop class.
You can re-apply this principle to any level. In this case, you could for example add a field
operations level telling the date when different operations were carried out in each crop on
each farm:
<model name="landscape" type="My::Landscape">
<model type="My::Farm" table="farms.txt">
<model type="My::Crop" table="crops_on_farms.txt">
<model type="My::Operation"
table="operations_on_crops_on_farms.txt"/>
</model>
</model>
</model>
39
*My::Farm
*My::Crop
*My::Operation
Date
Oats
Sowing
20/4/2010
Oats
Harvest
15/8/2010
SBarley
Sowing
21/4/2010
SBarley
Harvest
16/8/2010
Oats
Sowing
22/4/2010
Oats
Harvest
17/8/2010
WBarley
Sowing
15/9/2009
WBarley
Spraying
1/10/2009
WBarley
Harvest
25/7/2010
SBarley
Sowing
23/4/2010
SBarley
Harvest
18/8/2010
WBarley
Sowing
16/9/2009
WBarley
Spraying
2/10/2009
WBarley
Harvest
26/7/2010
Oats
Sowing
24/4/2010
Oats
Harvest
19/8/2010
But now we realize this does not solve the problem completely, because when we look at the
Operation model it has two more parameters besides Date. These parameters are Cost and
IsOrganic. In fact, we have them in this table:
*My::Operation
Cost
IsOrganic
Sowing
100
yes
Harvest
350
yes
Spraying
20
no
It would be a bad design to duplicate these values into the table above but, of course, if all
these tables are maintained by database software that could be an option. However, we can also
formulate this more succinctly in the XML recipe:
<model name="landscape" type="My::Landscape">
<model type="My::Farm" table="farms.txt">
<model type="My::Crop" table="crops_on_farms.txt">
<model type="My::Operation"
table="operations_on_crops_on_farms.txt"/>
<parameter table="operations.txt"/>
40
</model>
</model>
</model>
One should take note of the two different functionalities of the table attribute exposed here.
When a table is attributed to a model element, one model instance will be created for each line
in the table; parameter values will be set from those given in the table columns. When a table
is attributed to a parameter element, it is simply used to look up parameter values for the parent
model. In this example, when an Operation instance with the name Harvest is created, then
its Cost parameter will be set to 350 and its IsOrganic parameter to yes.
If you need to build a model with a complex data structure like in this example, you should
not try to build it all at once. Start from the outermost level and work yourself inwards. You
should also notice that your C++ coding will look just the same whether you create models
and set parameters with the table attribute, or whether you use the much simpler method of
specifying each model and each parameter individually in the XML code. This is only natural.
Your C++ code should work the same, no matter how many objects of type Farm, Crop and
Operation are present in the simulation. You can find an example of C++ code implementing
Farm, Crop and Operation in src/plugins/test_models.
There are a few more possibilities to cover. Suppose you have the data on crop acreage
represented in cross-tabular format as in this file crops_area_on_farms.txt:
*My::Farm
Oats
SBarley
WBarley
10
30
20
40
55
15
25
This is also readable by Universal Simulator if you use the crosstab attribute in stead of the
table attribute. In addition you must supply the parameter name (Area, in this case) in the
parameter attribute:
<model name="landscape" type="My::Landscape">
<model type="My::Farm" table="farms.txt">
<model type="My::Crop" name="Area"
crosstab="crops_area_on_farms.txt">
</model>
</model>
</model>
Note that with this method all farms get the full complement of crops. In this case the missing
crops are given an area of zero. You are only allowed to specify one key column with this method.
Each entry in the table is identified by the value in the first column and the name of the parent in
the column heading.
41
If you have additional parameter values in the same form, these can be added as a parameter element. For example, if you have the number of fields for each farm x crop combination:
<model name="landscape" type="My::Landscape">
<model type="My::Farm" table="farms.txt">
<model type="My::Crop" name="Area"
crosstab="crops_area_on_farms.txt">
<parameter name="numFields"
crosstab="crops_num_fields_on_farms.txt">
</model>
</model>
</model>
*My::Farm
Oats
SBarley
WBarley
You can add as many as you need of these parameter tables and, indeed, combine this method
with any of the above.
In all of the examples above, key columns were used to define the context of the table by
the name of one or more ancestors (parent, grandparent, ) of the parameter. However, you
can also define the context by the value of one of the ancestors parameters. This is easiest to
understand by example: Lets say that nitrogenNorm is a parameter of Crop. But the value of
nitrogenNorm depends both on the Crop and on the soilType of the Farm. This is easy to
define in a table:
*SoilType
Oats
SBarley
WBarley
Clay
90
110
120
Sandy
105
130
145
When Universal Simulator searches for the key value named SoilType in the column heading,
it will find it as a parameter of the Farm, and the value will be extracted from there. The XML
code is straightforward:
<model name="landscape" type="My::Landscape">
<model type="My::Farm" table="farms.txt">
<model type="My::Crop" name="Area"
42
crosstab="crops_area_on_farms.txt">
<parameter name="numFields"
crosstab="crops_num_fields_on_farms.txt">
<parameter name="nitrogenNorm"
crosstab="nitrogen_norms.txt">
</model>
</model>
</model>
Do not clutter your folder structure. You can, for example, easily find yourself in this situation
after unpacking:
43
44
Keep your folder structure as simple as possible. In this case, delete the unnecessary duplication
of UniSim folders. Otherwise, confusion is imminent. You will soon have plenty of folders and
files to keep track of.
If you later on download newer versions of the source code, you can end up with several
versions in sibling folders:
This developer seemingly chose to keep a folder for each of three different versions of the source
code: versions 1.36 and 1.37 and then maybe the newest version. This will cause no problems
(other than, potentially, your own confusion). At any time you can delete folders with outdated
versions of the source code but always consider whether some files should be salvaged first.
Maybe your own XML files, or even C++ files, are hiding inside those older folders.
3.2. Navigating source code
The folder, where you unpacked the source code, is called the root folder of Universal Simulator.
In this example, the root folder is located in C:/dev/UniSim:
45
The C++ files are found in the src folder. To enable different modellers to program in welldefined work spaces, the source code is split into modules called plug-ins, which are found in the
src/plugins folder. In the example above, the files inside the ecotox plug-in are shown.
The XML files, which form the recipes that you can open and execute with
the Universal Simulator program, are found in the src/recipes folder. For example, you can find the XML files, used as examples in the previous chapter, in the
src/recipes/unisim_explained/writing_recipes folder:
46
If you previously installed the Universal Simulator program (Chapter 1), you will already
have these XML recipes present on your computer. They are in the Universal Simulator folder inside your standard documents folder. Possibly, you also wrote some additional XML
recipes yourself earlier and, most likely, you also saved them there. Take care not to confuse
47
the two different recipes folders: the one inside the Universal Simulator root folder (e.g.,
C:/dev/UniSim/src/recipes) and the one possibly inside your standard documents folder
(e.g., C:/Users/niels/Documents/UniSim-1-41/recipes).
3.3. Building from source code
This section is only for the reader who has previous experience with C++ programming, and who
wants to extend the existing set of models available for Universal Simulator. Before you start
writing your own code, you must build Universal Simulator from the downloaded source code.
The download procedure was described in section 3.1.
If you earlier on installed the end-user version of Universal Simulator (as described in
Chapter 1) then you automatically installed the Graphviz software as well. Graphviz is used by
Universal Simulator to draw diagrams. However, you may have gone directly to this chapter,
skipping the end-user installation, which is fine but then you have to install Graphviz yourself. Go
here to install Graphviz: www.graphviz.org. Follow the download and subsequent links. Pick
the version for your operating system and finally pick the current stable release version. First
time you run Universal Simulator, you will be asked in which folder you installed Graphviz.
To build Universal Simulator, you need to download the Boost library found at
www.boost.org. Click on the Get Boost link found there and follow the links to download the
latest version as a zip file. Unpack the zip file in a separate folder, together with the folder for the
Universal Simulator source code, for example in C:/dev/boost_1_48_0. To prevent confusion, avoid nested sub-folders, such as C:/dev/boost_1_48_0/boost_1_48_0.
Qt Creator is the IDE (Integrated Development Environment) used to build Universal Simulator. You can install Qt Creator from Qt Project. Notice that there are many diffent versions
depending on your computing platform. The interactive installation program will show you available options. To follow this tutorial, you should install Qt Creator on Windows with the MinGW
32-bits tool. After that crucial choice, simply accept all default suggestions during installation.
To prepare your computer for building Universal Simulator, you must set three environment
variables:
1.
2.
Create
QT_ROOT
environment
C:\Qt\5.1.0\mingw48_32\bin.
3.
Amend the Path environment variable. Typically with the same path as set for QT_ROOT.
the
variable.
Typically
as
Note: You typically will have later version numbers for both Boost and Qt.
Sometimes it may occur that you have no folder called C:\Qt\5.1.0\mingw48_32.
Maybe you picked the wrong installation file and installed a version of Qt Creator meant
to work together with MS Visual Studio. In that case, you will have a folder named
C:\Qt\5.1.0\msvc2010 or similar. However, in this manual we do not use that tool, so you
need to fix your Qt installation. Go to the Windows program menu, find the Qt folder and inside that click on the Qt Maintainance Tool application. In this application, choose Package
manager and proceed. In the options tree that appears, drill down this track (using the triangle
icon to move down one step): Qt - Qt 5.1.0. There, place a check mark to select the MinGW
48
component. Now proceed and let the installation complete. Afterwards check that the folder
C:\Qt\5.1.0\mingw48_32\bin is now present.
To access the environment variables: right-click Computer, click Properties, click
Advanced system settings, click Environment Variables, and you are brought to a view of you
environment variables.
Under User variables click New and create a variable called BOOST_ROOT with a value
referring to the folder where you put the Boost library, for instance, C:\dev\boost_1_48_0:
Repeat this procedure and create the QT_ROOT variable. Its value should refer to the folder
specifying your version of the Qt libraries. This folder is located inside the folder with the Qt
Creator installation, usually C:\Qt. The complete path, which you should put in the QT_ROOT
variable, should be something like C:\Qt\5.1.0\mingw48_32\bin:
49
You might have a higher version number of the Qt library than version 4.8.1 as in this example.
Check the folder structure on your computer and use the version number that you find.
Finally, find the Path variable under System variables. Double-click that and you will
see that its value is a long string of folder names, separated by semicolons. You may find it
convenient to copy and paste the whole string into a text editor, to get an overview of what
it contains.
The Path variable tells the Windows operating system in which folders to look for
executable files. Universal Simulator relies on a few libraries which reside in folders, that you
must include in the Path. Otherwise, the Universal Simulator version that you are about to build
will not work.
You need to append one additional folder to the Path. Luckily, it is the exact same folder as
you just set for QT_ROOT, i.e. C:\Qt\5.1.0\mingw48_32\bin, or similar. To add this folder
to the Path variable, type a semicolon at the end of the string that lists all the Path folders and
then add the path at the end:
50
To begin with you should go to the src/build/win folder and execute the batch file found
there called build_all.bat. This will cause a complete build of the Universal Simulator
program and all its plug-ins. You can follow the progress, both in the rolling text window that
appears and in the folders, where the build products are saved.
51
In the src/library folder, two library files will be produced. Their names begin with
base and engine and will be of DLL file type. In the src/plugins folder, one plug-in library
will be produced for each of the sub-folders in the src/plugins folder. They will be named
after their folder and will also be of DLL type. Together with a DLL file, you will always find a
file with the same name, except with lib in front.
Finally, in the src/applications folder, the Universal Simulator itself will appear. Its
name begins with UniSim. Another program, to run the suite of unit tests that follows Universal
Simulator, is built as well. Its name begins with test-unisim.
All the files built end with -n-nd, where n-n stands for the version number and the d stands
for developer. The d is put there to distinguish these files from those destined for the end-user.
The end-user files are those that are installed by the Universal Simulator installer, as described
in Chapter 1.
If you previously installed the Universal Simulator (Chapter 1), and if the building process
by build_all was successful, you now have two versions of Universal Simulator on your
computer. The first one is the end-user version, which you can execute through the Programs
menu. The second one is the developer version, which you can execute by double-clicking the
UniSim-n-nd.exe file found in src/applications. You can change the C++ code of the
developer version but not of the end-user version. However, both versions will accept the same
XML recipe files.
When you run Universal Simulator, you can tell easily whether it is the developer or
end-user version: The developer version has an x appended to its version number, wheres the
end-user version has not. For example, version 1.37.x vs. version 1.37. The version number is
displayed in the title line of the application and under Help|About.
If an error message appears when you try to run Universal Simulator, complaining about
a missing .dll file, it is because the Path variable on your computer was not set up correctly.
Check the steps explained previously in this section (3.3). The name of the missing .dll can
maybe guide you to find the correct folder to put in the Path.
You will find it a lot easier to navigate the source code, now that you have Qt Creator
installed. From its menu you can choose File|Open project and open any of the project files
(recognised by their type which is .pro). Notably, there is one inside each of the src/plugins
folders.
3.4. Universal Simulator algorithm
When you develop your own models, you define a new model class for each kind of model that
you need. A Model base class is supplied for this purpose. Its header file is in the folder of the
usbase library, and the Model class resides in the UniSim namespace. To set your models
apart from those of other developers, you pick you own namespace. In this case the modeller has
picked meadow for his namespace:
#include <usbase/model.h>
namespace meadow {
class Frog : public UniSim::Model
52
namespace The Model base class declares six virtual methods which are all defined empty in the
base class. You equip your model class with the desired behaviour by re-defining one or more
of these virtual methods. For the Frog class, methods reset and update were re-defined; the
constructor Frog(name, parent) will be called by Universal Simulator should a Frog model
be required by the recipe.
Here are the names and typical usage of the six virtual methods of the Model base class:
amend()
Called once just after the recipe has been opened by the user. The amend method allows you
to create model objects in addition to those already specified in the recipe. This can be used
to make quite sophisticated models. For instance, an EcologicalCommunity model could
take the number of species as a parameter.The amend method of EcologicalCommunity
could then create the appropriate number of Species models.
initialize()
The initialize method is called once, just after the user has started a simulation run. The
initialize method is commonly used for the model object to find other models that it
will collaborate with. Such connections are held in pointers, which will then usually be used
by the reset and update methods.
reset()
The reset method is called once before every iteration of the simulation. If the simulation
is only carried out once, then the reset method will likewise be called only once. The
reset method is defined for most models because its main purpose is to set all state
variables to their initial value. For the Frog class, totalDistance could be set to zero.
update()
The update method is usually the most important of the six methods, incarnating most
of the biological behaviour of the model. The update method is called once every time
step. Its main purpose is to update all state variables. In the Frog class, totalDistance
could be incremented with lengthOfJump. This would result in a linear increase in
totalDistance with time.
cleanup()
The cleanup method is called once after a simulation iteration has completed. It is not used
53
very often. Its typical use is to summarise the results of the simulation iteration.
debrief()
The debrief method is called once after the last simulation iteration has completed. It is
used even less than the cleanup method.
Since these methods will be called, once or repeatedly, for all model objects present in a simulation, it is important to know the order in which they are called. First of all, the logic explained
above is described equivalently and more succinctly, by this algorithm:
user opens recipe with File|Open menu;
amend all models;
show model diagram on screen;
user starts simulation with Simulation|Run menu;
initialize all models;
for each iteration {
reset all models;
for each time step
update all models;
clean-up all models;
}
debrief all models;
show output on screen and in files;
Whenever one of the six Model base class methods (amend, initialize, reset, update,
cleanup, debrief) is called in this algorithm, it is called for all models present in the simulation. Moreover, they are always called in the order in which the appear in the recipe. If some
models reside inside another model then the models inside will be handled first - in their order of
appearance in the recipe. These nested method invocations can go on to any depth, as defined by
the model hierarchy found in the recipe.
3.5. Communicating with models
The data members of your models should be private to the class, as exemplified by the Frog
class above. Yet, some data members must be made accessible, both for the recipe and for other
models, to enable your model to communicate. There are two ways to create access to a data
member: it can serve as an input, which gives others both read and write access to it, or as an
output, which only provides read access.
In the Universal Simulator framework, access is provided by the functions (actually, they are
C++ macros but you can disregard that detail) Input and Output. You use Input and Output
to set up the desired interface to the data members of your model. The correct place to add inputs
and outputs is in the model constructor:
#include <usbase/parameter.h>
#include <usbase/variable.h>
54
#include "frog.h"
#include "publish.h"
using namespace UniSim;
namespace Meadow {
PUBLISH(Frog)
The inputs and outputs must all be declared in the header file, in this case in frog.h. In the
example above, they have all been declared of type double. The type given here must match
how the parameter or variable was declared (in the header file), otherwise a compilation error
will ensue. The valid types are int, double, bool, QString, QDate and QTime.
To make the model available in the XML recipe, it must be published in the source file.
This is accomplished by the PUBLISH macro as shown. The PUBLISH macro is included from
publish.h.
Inputs have the benefit that their values can be set in the recipe. In this example, the user has
set initDensity to 800, while lengthOfJump is not mentioned and thus retains its default
value (12):
<model name="Rana" type="Pond::Frog">
<parameter name="initDensity" value="800"/>
</model>
Outputs cannot be changed from the recipe but you can refer to them, for instance, to be shown
in the output:
<output type="plot">
<parameter name="title" value="Total distance"/>
<trace name="time" ref="calendar[totalTime]"/>
<trace name="Total" ref="Rana[totalDistance]"/>
</output>
55
Lets say that we implement a Stork model, which needs frog density as an input to calculate
its food intake. Its constructor could look like this:
Stork::Stork(UniSim::Identifier name, QObject *parent)
: Model(name, parent)
{
}
This code sets preyDensity to a default of 50 but the user would likely prefer to link that value
to the actual population density of prey, e.g., the frogs. That could be achieved in the recipe:
<model name="stork" type="Pond::Stork">
<parameter name="preyDensity" ref="Rana[density]"/>
</model>
Would it be possible somehow to set that reference as the default value, so that the user in most
cases would not have to bother? Yes, we can do it, like this, in the Stork constructor:
Stork::Stork(UniSim::Identifier name, QObject *parent)
: Model(name, parent)
{
Input(double, initDensity, 500.);
// Initial density of storks
(per km2)
InputRef(double, preyDensity, "Rana[density]");
// Density of
prey (per km2)
Output(double, density);
// Density of storks (per km2)
}
However, if the user happens to have put no model named Rana in the recipe, this will cause
an error when the recipe is opened, because the reference cannot be found. The problem would
persist, even if the user added a Frog model but with another name than Rana, for example,
Rana_esculenta:
<model name="Rana_esculanta" type="Pond::Frog">
<parameter name="initDensity" value="800"/>
</model>
The question then arise if we could make the Stork model itself intelligent enough, that it would
look up any model in the recipe of the class Frog? Or, indeed, any number of models of classes
Frog, Fish or whatever would be allowed in the pond universe? Here, we will limit ourselves
to find just a single Frog model:
// In stork.h
#include <usbase/model.h>
namespace meadow {
class Stork : public UniSim::Model
56
{
public:
Stork(UniSim::Identifier name, QObject *parent);
void initialize();
void reset();
void update();
private:
// parameters
double initDensity;
// variables
double density;
// links
const double *preyDensity;
};
} // namespace
// In stork.cpp
#include "frog.h"
#include "publish.h"
#include "stork.h"
namespace meadow {
PUBLISH(Stork)
void Stork::initialize() {
Model *prey = seekOne<Frog*>("*");
preyDensity = prey->pullValuePtr<double>("density");
}
} // namespace
First of all, we do not need preyDensity as a parameter any more; the Stork model will
find that independently. In initialize(), the Stork model orientates itself to find the
Frog model. It finds the other model by the its class name Frog. By giving the model name
as a joker "*", any model of the class Frog will be found irrespective of its name, e.g., Rana,
Rana_esculanta or whatever.
The various seek and peek methods used to find model objects are explained below (3.6).
The prey pointer that we just obtained is asked, by way of the pullValuePtr method, for
a pointer to density. From now on Stork will have access to density through the pointer
variable preyDensity. The access will be read-only, as notified by the const modifier in the
declaration: const double *preyDensity.
It is not easy to judge whether a model should be imbibed with some intelligence to seek
out other models or not. As a general rule, you should only apply this technique when necessary.
In any case, it pays off first to establish all connections between models in the recipe only. Then,
as the model matures, inflexibilities may evolve which you can only solve by some built-in model
57
intelligence. The drawbacks of the technique are that your C++ code becomes more complicated,
the recipe less clear - and maybe even less flexible, thus opposing your original intent.
3.6. Navigating model structure
Model structure is defined by the user via the recipe. You must decide what makes a valid recipe.
Does a Stork model require that a Frog model is also present? Would it be allowed for more
than one Frog model to be present? To check such conditions and set up the necessary links
between models, your model may need to orientate itself at some point. The best place to do
that is in the initialize method. The method will only be invoked once during a simulation
run, and you are certain that all model objects belonging to the simulation have been created at
that time.
The Model base class provides a suite of peek and seek methods. All these methods look
for objects of a certain class and with a certain name. A joker ("*") can be used for the name to
find all objects of a certain class. Here are some introductory examples:
// Find any Model object called weather
Model *weather = seekOne<Model*>("weather");
// Find any Records object called weather
Records *weather = seekOne<Records*>("weather");
// Find all Fish children of ocean
QList<Fish*> fish = ocean->seekChildren<Fish*>("*");
// Find all my Model siblings
siblings = seekSiblings<Model*>("*">
In all the following diagrams, the object orientating itself is painted blue and the part of the
family tree that is searched is painted yellow. None of the methods will return the object itself as
a result (the object itself is excluded from the search).
These facilities may seem quite overwhelming. It is good to know, that you are unlikely to
need them in your first steps of model development.
58
Seeking any object
These methods search globally and are often used to find objects representing time and environment:
Model *calendar = seekOne<Model*>("calendar");
Model *weather = seekOne<Model*>("weather");
peekOne returns a pointer to object, or null if none was found, or throws an Exception
seekOne returns a pointer to object, or throws an Exception if none or more than one
was found
Seeking children
Models commonly need to establish contact with their children. The Insect model in the
following code builds a list of all its Stage children, finds its egg child in particular (which must
exist) and peeks for a Model named mould inside the egg. This mould object may exist or not.
In the latter case mould will become null:
59
void Insect::initialize() {
QList<Stage*> stages = seekChildren<Stage*>("*");
Model *egg = seekOneChild<Model*>("egg");
Model *eggMould = egg->peekOneChild<Model*>("mould");
}
The nearest object matching the given class and name is searched for in the order indicated by
numbers: first among the children, then among the ancestors children, step by step all the way
back to the root. The effect is close to the scope look-up rules for variable names in C++. This
offers great flexibility for the end-user. For example, it is used by UniSim::Stage to find the
nearest time object used for updating the development of the stage:
void Stage::initialize() {
Model *time = seekOneNearest<Model*>("time");
}
Thus the user can put a time model inside the Stage model to define a special chronology for
that Stage object. Or, the user can put it at a heigher level where it can be shared by many Stage
models, having this time model in common. Should a time model be placed both as a child and
further up search path (shown in the diagram above), then the result will be the first time object
one found (it being the nearest).
60
found
Seeking parent
There can be at most one parent of an object, so there is no seekParents. Sometime a parent
is needed to find shared relatives. Here an Animal objects finds all models of the Plant class,
which are nested inside the Animal objects parent:
void Animal::initialize() {
Model *parent = seekParent<Model*>("*");
QList<Plant*> plants = parent->seekDescendants<Plant*>("*");
}
Seeking siblings
A model my share an interest with its siblings. Perhaps they are predators and prey?
61
Seeking descendants
Whenever you seek for an objects child or children, consider whether this is too strict. Maybe
it is enough to demand that objects you look for are among the objects descendants? Maybe you
just want to look for all Organs inside, or for any model that has a child called mass:
QList<Organs*> organs = seekDescendants<Organ*>("*");
QList<Model*> masses = seekDescendants<Model*>("mass");
QSet<Model*> hasMass;
for (int i = 0;i < masses.size(); ++i)
hasMass << masses[i]->seekParent<Model*>("*");
Seeking ascendants
62
The ascendant search is short. Often you want to find some containing model without knowing
how deep you are in the model hierarchy yourself. Maybe you are a leaf on a tree, but do not
know how many model layers (twig, trunk) are in between you and the Tree. So, you search
for an ancestor of class Tree, or maybe just any type of Model called tree:
Tree *tree = seekOneAscendant<Tree*>("*");
Model *model = seekOneAscendant<Model*>("tree");
Neither method accepts that more than one ancestor, matching the search criteria, are found.
In addition, two methods work like peekOneAscendant and seekOneAscendant, except they refer to the nearest ascendant: peekNearestAscendant and seekNearestAscendant
even_odd.h and even_odd.cpp with source code for the EvenOdd model
The example plug-in is provided as a basis to create new plug-ins. You simple copy the folder
63
with contents and rename the copy. Software, such as Notepad++, provides search and replace
for all files in a folder and can help you renaming throughout the copied plug-in folder. These are
the necessary steps, for example to create a new plug-in called ocean. For the search-and-replace
operations, include files *.h;*.cpp;*.pro, unselect the option to match whole words only,
and select the option to match letter case:
1.
2.
3.
4.
5.
6.
7.
Write an XML recipe to test that the plug-in works. Recipes found in recipes/examples
can be used as a starting point.
8.
Start Universal Simulator from src/applications, open your test recipe and run a simulation
64
65
S_few_yrs
N_many_yrs
base_N_records, base_N_output
S_one_yr
S_many_yrs
base_S_records, base_S_output
So if you change the base_io recipe, all six scenario recipes will be affected, and if you
change the base_N_records recipe the three North Germany recipes will be affected. Recipes
beginning with base do not formulate a complete recipe on their own. They are only used as
building blocks for the scenario recipes.
4.3. Scenario outputs
If we start out with the northern scenario defined in the N_few_yrs recipe, we will be granted
five figures of output when the simulation is run. They all have curves overlaid, representing ten
iterations of the simulation, and all have x-axes showing time as the number of days since the
beginning of the year. The first figure shows the average temperature during the year:
Next, the pollen figure shows the daily rate of pollen deposition on nettle leaves (pollen per cm2
per day in red), the actual density pollen on nettle leaves (pollen per cm2 in blue) and the total
accumulation of pollen deposited on nettle leaves, not corrected for loss of pollen from the leaves
(pollen per cm2 in yellow):
66
Overwintering butterflies emerge in early spring according to the calendar. Hence, there is no
variation between years in their flight time. The development of subsequent stages, however, are
driven by day-degrees, which leads to variation between years:
To visualise the exposure of larvae to pollen, we combine the curves for pollen and larva density
in the same figure:
A log10-scale let us follow the predicted overlap also at low densities (values less than -2 not
shown). What we see is no overlap; the larvae finish their development before pollen deposition
begins
67
If larvae are exposed to pollen during their development, they will suffer an increased mortality, as determined by the dose-response curve included in the model. The net effect is illustrated in the last figure, which shows that, in this scenario, all larvae complete their development.
Consequently, the number of overwintering butterflies is the same at the end of the season as at
the beginning:
We can contrast these model predictions with those of the southern scenario defined in the
S_few_yrs recipe. Temperature is slightly higher, and the pollen season comes slightly earlier:
In this scenario, the butterfly has two generations. Both the emerging overwintering adults and
the newly produced first generation of adults are shown in the same figure:
68
For the second generation, the prediction is that the pupae will not alwaus have time to complete
their development:
This prediction of incomplete pupal development has no impact on the risk analysis, however,
because the end point is taken, not as the number of hibernating adults at the end of the year, but
as the number of larvae completing their development.
When we consider exposure, we realise that 1. generation larvae is present earlier than the
pollen season, while the 2. generation larvae seems fully exposed:
The response of the population is evident. In quite many years, only a fraction of the larvae
69
In years with cold autumns, even the successful larvae do not all reach adulthood but, as
noted above, this prediction does not affect the risk analysis. For further details consult
Holst et al. (2013).
It looks up the weather object and also checks how many sibling Plant objects it has. Since
only zero or one sibling is allowed, it faults otherwise. The throw statement will result in an
error showing up on the user screen. The other variable is a pointer to a Plant object (see its
declaration in plant.h), which is set in initialize, either to null or to point to the other
Plant object.
Once every day the update function of all Models objects is automatically invoked. The
update function of the Plant model consists of three steps which update, in sequence, the
crown zone area, light interception and weight:
void Plant::update() {
70
71
updateCrownZoneArea();
updateLightInterception();
updateWeight();
}
The crown zone area sz (sz in the code) is what makes the Conductance model special. It is the
area of the smallest circle that circumferences the whole canopy of one single plant. The plant is
considered to own this area. It is available only for the plant itself to fill up with leaf area. Thus
its dimension is
m2 ground area owned
[sz ] =
plant
The crown zone area is computed in one of three ways depending on which growth phase the
plant is currently in:
void Plant::updateCrownZoneArea() {
switch (phase) {
case Unlimited:
sz = A*pow(weight, phi);
break;
case UnderCompression:
sz = other ?
(1. - other->pullVariable("total_sz"))/n :
1./n;
break;
case WeightProportional:
Q_ASSERT(other);
sz = weight/(totalWeight +
other->pullVariable("totalWeight"));
}
total_sz = n*sz;
if (total_sz < 0)
sz = total_sz = 0.;
else if (total_sz > 1) {
total_sz = 1.;
sz = 1./n;
}
}
What is phase? It is a C++ enumeration. Enumerations are one of the simplest constructs in C++
and their explanation in any textbook is not frightening. The phase variable is declared in the
header plant.h, and the declaration of the Phase type is declared in phase.h.
In the Unlimited phase, the plant population simply grows as if each plant were growing
in isolation without competition. In that case, the crown zone area sz is computed according to
the allometric relation, given as a power function.
72
In the UnderCompression phase, the plants (one or two populations, represented by one
or two Plant objects) completely fill out the available area. To understand the logic, let us have
a look at the dimensions of the involved variables. Plant density is denoted by n. Hence
[n] =
m2
plants
ground area available
If there is only one plant population present (in which case other is null, which in C++ is
equivalent to false) then
sz = 1 n
To make the dimensions match we can infer the suiting units of the enumerator 1 in 1 n,
[ enumerator ] =
and thus
[1 n] =
m2 ground area owned
m2 ground area available
m2
plants
=
ground area available
Notice the use of the pullVariable method to require the current value of a variable from the
model pointer to by other. A complete list of the pull variables available for Plant models is
found in the documentation for the Plant class beginning on page 117.
In the WeightProportional phase, both plant populations are alloted a total crown
zone area in proportion to their total weight (eqs. 21 and 22 in Benjamin & Park (2007)). For
population 1, the proportion is
w1n1
w1n1 + w2 n2
73
The assertion Q_ASSERT(other) will cause a run time error if other is null. That is because
this calculation only makes sense if two populatios are present. To obtain the crown zone area of
plants in population 1, we have divided with the density of plants (n1) to obtain
sz1 =
w1
w1n1 + w2 n2
A dimensional analysis of the right hand side shows the its dimension matches that of the crown
zone area. Moreover, it follows that the total crown zone area of both populations together adds
up to 1,
n1sz1 + n2 sz2 = 1 m2 ground area owned per m2 ground area available
The code is valid for either plant, so in the coding w1 is represented as weight, w1n1 as totalWeight and w2 n2 as totalWeight pulled from the other plant.
After updating the total population crown zone area total_sz, checks are made to ensure
that it remains inside the valid [0..1] interval:
total_sz = n*sz;
if (total_sz < 0)
sz = total_sz = 0.;
else if (total_sz > 1) {
total_sz = 1.;
sz = 1./n;
}
This is necessary to guard against rounding off errors. The checks also evens out when the model
overshoots the crown zone area at the passage from the Unlimited to the UnderCompression
phase and from the UnderCompression phase to the WeightProportional phase.
Since the concept of crown zone area is particular to the Conductance model, it comes as
no surprise that its calculation is also the most complicated part of the model. The remaining
calculations are comparatively simple. Let us review how far we have come in our walk throught
the code.
void Plant::update() {
updateCrownZoneArea();
updateLightInterception();
updateWeight();
}
We have just covered the updateCrownZoneArea function, so we are now ready to calculate
light interception.
The fraction of light intercepted fz is calculated from the leaf area index within the crown
74
2
zone Lz (m leaf area per m2 ground area owned), which is calculated as the leaf area of a plant
divided by its crown zone area.
The plant leaf area LA_per_plant is estimated from plant weight assuming a simple
allometric relation. Thus we arrive at this implementation:
void Plant::updateLightInterception() {
LA_per_plant = F*pow(weight, theta);
Lz = LA_per_plant/sz;
fz = 1. - exp(-k*Lz);
}
First we pull the daily global irradiation I from the weather object. We multiply I with the
light-to-dry weight conversion efficiency eps, the crown zone area sz which is the effective
area that takes up light, and the fraction of light intercepted fz.
Only half of the global irradiation is photosynthetically active radiation (PAR = I / 2).
However, (eps, in code) was parameterized to operate on I rather than PAR. This choice is
arbitrary and inconsequential but one should always be aware whether should be applied to I
or PAR.
Next we add the increment dweight (g per plant) to the plant weight, and we update the
total population plant weight (g per m2 ground area available) by multiplying with plant density
n.
The update updates the state of the Plant object, in terms of its crown zone area, leaf area
and weight. But the code we have inspected so far, does not change its growth phase, whether
it be Unlimited, UnderCompression or WeightProportional. So, a Plant object does
not determine itself when to change phase; this instruction comes from the outside. The method
for that is naturally called changePhase:
void Plant::changePhase(Phase newPhase) {
phase = newPhase;
_phase = int(phase);
Q_ASSERT(phase == Unlimited || phase == UnderCompression
|| other);
}
The code is inconspicuous. Apart from actually changing the phase variable, it also updates the
75
related _phase which will take the value 0, 1or 2 depending on the phase. The _phase serves as
a pull variable so that the phase can be displayed as numeric figure, for example as a time trend.
The final assertion is put there to ensure consistency. It asserts that either we are in the Unlimited or UnderCompression phase, or there exist an other plant model. Thus it disallows being
in the WeightProportional phase, if there is only one Plant model present.
Now it is time to wonder what all this functionality is good for. The code is just sitting there.
Who is going to activate it? The UniSim framework will call the functions initialize once
and update daily. But who will be calling changePhase at the right time? We need some
powerful entity, another kind of object to oversee this business. This is what the Community
model is for.
But before continuing we need to add one more function to Plant, because Community
will need it: The function reUpdate undoes the weight increment of the last update and then
reinvokes update:
void Plant::reUpdate() {
weight -= dweight;
totalWeight = n*weight;
update();
}
Just as was the case for the Plant class, the update function of the Community class is doing
all the work with the help of a few other functions:
void Community::update() {
while (phaseChanged())
reUpdatePlants();
}
Before contemplating this code one should realise, that the automatic daily call of all update
functions proceeds in the order children-first. Thus the Plant objects are updated before the
Community object, because the plants are children of the community.
76
What we see is a while loop which potentially can re-update the plants one or more times.
This depends on the outcome of the phaseChanged function.
The community is in the same phase as the plant(s), except when there are two Plant
models present and one of them is in the UnderCompression phase. Then the other one is,
by necessity, still in the Unlimited phase, and the whole community is considered to be in the
UnderCompression phase.
The phaseChanged function is all about changing the phases of both the Community
model and the Plant model(s), as needed. It returns as a result (bool) whether phase was
actually changed:
bool Community::phaseChanged() {
updateTotalCrownZoneArea();
if (phase == Unlimited)
return phaseUnlimitedChanged();
else if (phase == UnderCompression && plants.size() == 2)
return phaseUnderCompressionChanged();
return false;
}
First one function is called to calculate the total crown zone area of the Plant model(s). The
remainder of the work is passed on to two other functions, called if the community is currently
in the Unlimited or UnderCompression phase, respectively. In the latter case, the phase
can only change further if two Plant models are present; if only one Plant model is present
it cannot proceed further than the UnderCompression phase. If the community has reached
the final phase WeightProportional, it cannot proceed either, which means that no action is
needed and the function simply returns false.
The summation of the total crown zone area could not be simpler:
void Community::updateTotalCrownZoneArea() {
sum_sz = 0.;
for (int i = 0; i < plants.size(); ++i)
sum_sz += plants[i]->pullVariable<double>("total_sz");
}
Next let us consider the case when we are in the Unlimited phase. If the total crown zone area
sum_sz has reached 1 thus exhausting the available ground area, then phase must change to
UnderCompression. This is what the phaseUnlimitedChanged does:
bool Community::phaseUnlimitedChanged() {
bool availableAreaExhausted = sum_sz >= 1.;
if (availableAreaExhausted) {
sortPlants();
smaller->changePhase(UnderCompression);
phase = UnderCompression;
return true;
}
return false;
77
The sortPlants function finds out which of the plants are smaller by weight and sets the two
Plant pointers, smaller and larger, accordingly. Only the smaller plant will change phase
to UnderCompression while the larger (if present) will continue to grow Unlimited.
The code for sortPlants is straightforward:
void Community::sortPlants() {
bool onlyOnePlant = plants.size() == 1;
if (onlyOnePlant) {
smaller = plants[0];
larger = 0;
return;
}
bool firstIsSmaller =
plants[0]->pullVariable<double>("weight") <
plants[1]->pullVariable<double>("weight");
if (firstIsSmaller) {
smaller = plants[0];
larger = plants[1];
}
else {
smaller = plants[1];
larger = plants[0];
}
}
In case only one plant is present, that one defaults to be the smaller and larger is set to null,
meaning it does not exist.
The final piece of the Community phase change puzzle is the phaseUnderCompressionChanged function. This function does nothing until it happens that the leaf area index
inside the crown zone of the smaller plant has reached that of the larger plant. Since the
smaller plant has been UnderCompression, this may happen given enough time:
bool Community::phaseUnderCompressionChanged() {
bool plantsAreEven =
smaller->pullVariable<double>("Lz") >=
larger->pullVariable<double>("Lz");
if (plantsAreEven)
{
smaller->changePhase(WeightProportional);
larger->changePhase(WeightProportional);
phase = WeightProportional;
return true;
}
return false;
78
}
The consequence is quite simple: both Plant models and the Community model goes into the
terminal WeightProportional phase.
Now it is time to revisit the while loop inside the update function:
void Community::update() {
while (phaseChanged())
reUpdatePlants();
}
All the code evoked by phaseChanged, that we just walked through, aimed to change phase
as needed and then returning false if phase remained unaltered and true, if it actually
were changed. We can see that in the latter case the plants will be re-updated. We need this
backtracking, because some conditions might otherwise remain broken; for example, the total
crown zone area might exceed 1.
This last function of Community contains no surprises:
void Community::reUpdatePlants() {
for (int i = 0; i < plants.size(); ++i)
plants[i]->reUpdate();
}
The model just contains one input irradiation which will be used as an output as well. Its
value remain constant throughout the simulation.
5.4. Running the model
The Conductance model is simple and demands only six parameters to be estimated: two for
each of the allometric relationships, one for the extinction coefficient and one for the conversion
efficiency. The table shows parameter values for two crops and five weed species.
79
Table. Parameter values for the Conductance model (from Park et al. 2007).
Leaf area
Species
F (m / g)
A (m / g)
(g / MJ)
Cabbage
0.0158
0.840
0.0314
0.529
0.71
1.40
Carrot
0.00975
0.801
0.0255
0.591
0.65
1.23
Tripleurospermum
inodurum
Solanum nigrum
0.0185
0.890
0.0245
0.623
0.59
1.63
0.0171
0.866
0.0265
0.747
0.70
1.20
Stellaria media
0.0173
0.849
0.0455
0.585
0.71
0.90
Trifolium repens
0.0158
0.916
0.0273
0.692
0.54
1.13
Veronica persica
0.0162
0.869
0.0242
0.696
0.53
1.33
To get a better sense of the Conductance model, let us look at a cabbage-nightshade system.
Nightshade has a more expansive growth form than cabbae. At a certain biomass, a nightshade
plant has a wider crown zone and a larger leaf area than a cabbage plant of the same weight
(see Fig.). The two species are equally good at absorbing light per leaf area since the extinction
coefficients k are about equal. But cabbage is more efficient at utilizing the absormed light as
expressed by its higher light use efficiency .
Leaf area (m )
0.4
0.3
0.2
0.1
0.0
10
20
30
0.4
0.3
nightshade
0.2
cabbage
0.1
0.0
0
10
20
30
Figure. Allometric relations for cabbage and nightshade (Solanum nigrum). Parameters
from table.
80
The question is what the net result of these differences in traits will be on the outcome of
competition. To address this problem we will do two experiments with the model: one simulation
with cabbage only and one with cabbage in competition with nightshade. The model XML files
to set up these simulations are found in the xml/models/conductance folder inside your
UniSim root folder.
Now is time to start the UniSim software and open the cabbage.xml file. You can see from
the model diagram, that shows up when you open the file, that the simulation has four models
inside it:
UniSim::TimeStepLimited
UniSim::Calendar
calendar
UniSim::Simulation
conductance::Weather
weather
conductance::Community
community
conductance::Plant
cabbage
The models include a Calendar to keep track of time. Calendar is part of the
UniSim package, as shown by the namespace qualification UniSim before its class name
UniSim::Calendar. In addition we find as expected, a Weather model and a Community
model to hold one or two Plant models. In this example only one Plant model, named cabbage, is presemt.
Try running (click the Simulation | Run menu) a simulation with cabbage alone (in file
cabbage.xml) and together with nightshade (in file cabbage-nightshade.xml). Verify that
the plots shown on screen makes sense. You can also study the output found in the output text
file, found in the folder you chose for output files.
To change the parameter values just open the XML file with a text editor such as
Notepad++. There is no need to close the UniSim program while you are editing the file. Save the
XML file in the editor when you are finished editing the parameters (let the editor remain open
too, for your convenience) and swap to UniSim where you click the File | Reopen menu to read
the XML file again and thus obtain the changed parameter settings. Run the simulation again and
study the output. You can swap between the editor and UniSim as you please keeping any XML
files open all the while.
5.5. Discussion
The Conductance model simulates only the growth of plants not their physiological development.
It would be quite simple though to add another model for plant development, say a day-degree
model for the period from emergence to flowering. At flowering growth would stop for species
5.5. Discussion
81
with determinate growth. For species with indeterminate growth, growth would continue maybe
until the first frost which could easily be pulled from a weather log file. A simple harvest model
would set harvest at a fixed date which would be the end of the story for many plants, even though
some weeds would re-grow from a stubble field.
In short, the Conductance model nicely encapsulates a period of plant growth in the field.
This makes it very easy to combine with other models.
500
40
400
Angots value
2
[MJ/m /d]
[W/m ]
30
300
20
200
10
100
0
0
100
200
Day of year
82
300
0
30 N
60 N
83
A weather station will usually register total daily irradiation per m2. But to calculate daily
photosynthesis we need more detailed information than that: How much of the irradition is
diffuse and how much is direct? How is irradiation distributed over the day?
The fraction of light that gets dissipated and thus turns diffuse depends on the atmosphere,
foremost the cloud cover. However, there exists an empirical relation between the fraction of
light that gets through the atmosphere (i.e. the irradiation measured by the weather station in
proportion to Angots value) and the fraction of light that is diffuse.
1.0
0.8
Fraction of
0.6
diffuse light
[0;1]
0.4
0.2
0.0
0
10
20
30
40
2
The figure show this relation at 55 N on Julian day 120. The fraction of diffuse light decreases
with increasing measured irradiation, from 100% at low light levels to a minimum of 23% when
the light is most intense.
The course of light intensity over the day goes from zero at sunrise to a maximum at midday,
when the sun is in zenith, and then down to zero again at sunset. The measured irradiation is the
average over the whole day, and it follows that the maximum intensity will be larger than the
measured daily average. Hours in this context are astronomically defined, irrespective of time
zones and daylight saving schedules. Only part of the sunlight is in the frequency spectrum
utilized by photosynthesis. This photosynthetically active radiation (PAR) comprises half of the
total sunlight energy.
300
PAR
total
200
direct
[W per m2 ground]
diffuse
100
0
0
12
Time of day [h]
18
24
84
The figure shows the course of indirect, direct and total PAR at 55 N on Julian day 120 with a
2
2
measured irradiation of 20 MJ/m /d (231 W/m , since 1W = 1J/s). A rough numerical integration
2
2
to calculate the average total PAR from this figure yields 115.7 W/m (9.996 MJ/m /d),
corresponding to half of the measured irradiation, as expected. INTERCOM measures PAR in
2
W/m units.
To calculate photosynthesis we must integrate over the whole day from sunrise to sunset.
To speed up this calculation INTERCOM applies Gaussian integration. For this, every day, the
rate of photosynthesis needs only to be calculated three times during the afternoon. The total
photosynthesis over the whole day is then calculated as a weighted average of these three point
values. The specific times will vary according to latiude and day of the year. At 55 N on Julian
day 120, for example, photosynthesis will be calculated on 12:50h, 15:43h and 18:58h. The
weights attributed to these are fixed (0.28, 0.44 and 0.28) and sum up to 1.
The density and structural characteristics of the plant canopy are important for the resulting
photosynthesis. First we will consider a canopy consisting only of the leaves of one species.
Later we will generalize this to any number of organs and any number of species. The vertical
distribution of leaf area can be summarized by an equation, such as a parabola, which will yield
a symmetric distribution of area on the vertical axis.
5
4
Leaf density
2
3
2
1
0
0.0
0.2
0.4
0.6
0.8
1.0
Described this way, the variable actually is a leaf density measured in m2 leaf per m3 space. In this
example, maximum plant height was set to 1 m and the total leaf area index (LAI) of the canopy
was set to 3. The leaf density at 0.5 m is larger than 3 m-1, so if the canopy was this dense all over,
LAI would be larger than 3. But at the bottom and the top of the canopy, this is compensated for
by a leaf density smaller than 3 m-1, so it all adds up to LAI equal to 3.
If we integrate leaf density vertically, accumulating the total leaf density from a certain
height above the ground and up to the top of the canopy, we arrive at the LAI above that height.
After factoring in the vertical integration in meters, we get the proper LAI units of m2 leaf per
m2 ground.
85
0
0.0
0.2
0.4
0.6
0.8
1.0
To model photosynthesis down through the canopy, we must integrate photosynthesis from
the top of the canopy downwards. To achieve this INTERCOM again uses Gaussion integration
but, in stead of calculation at 3 points as for PAR during the day, we need 5 points to obtain proper
precision. The 5 points are located at 5%, 23%, 50%, 77% and 95% of maximum plant height.
Their weights (0.12, 0.24, 0.28, 0.24 and 0.12) again add up to 1 for the weighted average, which
is a mathematical approximation of the integrated photosynthesis over the whole canopy.
We are now all set to begin the actual calculation of light absorption and CO2 assimilation:
We know the latitude, day of the year, time of the day, diffuse and direct PAR, and the LAI above
and the leaf density at a certain height in the canopy. We must repeat the calculation 15 times to
cover the 3 integration points during the day and 5 integration points down the canopy. In the end
we add all the calculated light absorption and assimilation rates, applaying the pertinent weights
of Gaussian integration and end up with the total light absorption and assimilation of the day.
First we make a further subdivision of the incoming direct light, which we now call total
direct light. The part of direct light that is directly absorbed as such by the leaf we call directdirect light. The remainder is dispersed and results in secondary diffuse light. The extinction
coefficient of the leaves can be measured empirically under 100% diffuse light and is then called
kdf . The extinction coefficients for total direct light (kdr,t) and for direct-direct light (kdr,bl) both
depend on sun height and thus on latitude, day of the year and time of the day.
8
Extinction
coefficient
[-]
Type of light:
diffuse
4
direct-direct
2
direct total
0
0
12
18
24
In this example, it can be seen that direct light is extinguished effectively when the sun is low.
86
So, when the sun is low, whatever little direct light there is, dies out quickly in the canopy.
The light penetrating to a certain level in the canopy decreases exponentially with the
effective LAI above that level. The effective LAI is the LAI times the extinction coefficient
(page 36 in Kropff & Laar 1993). For reasons explained further down we will instead call this
the effective extinction. Anyway, we can calculate the rate of light penetration for all three kinds
of light, applying the appropriate extinctions coefficient. However, a fraction of the light is
immediately reflected by the canopy and is thereby not available for absorption. Leaf reflectance
differs for the three kinds of light but, surprisingly, can be assumed equal for all plant species.
It has a fixed value for diffuse and direct-direct light whereas it depends on sun height for the
direct-total light.
0.2
Leaf
reflectance
[-]
Type of light:
0.15
diffuse
0.1
direct-direct
0.05
direct total
0.0
0
12
18
24
The light available at any height in the canopy can now be calculated from the total LAI
above that height and the pertinent extinction coefficients and reflectances. Here it is shown at
2
15:43h, the second integration point of the day, keeping the parameter settings so far (20 MJ/m /d
of sun light impinging at 55 N on day 120).
100
Type of light:
80
Available
diffuse
60
light
2
[W per m ground]
direct-direct
40
direct total
20
0
0.0
0.2
0.4
0.6
0.8
1.0
To obtain how much of the available light is actually absorbed at any height in the canopy,
we just need to multiply the available light with the pertinent extinction coefficients.
87
100
Type of light:
80
Light
diffuse
60
absorption rate
2
[W per m leaf]
direct-direct
40
direct total
20
0
0.0
0.2
0.4
0.6
0.8
1.0
The diligent reader will have noticed that the units changed from available W per m2 ground
to absorbed W per m2 leaf (eq. 4.12 in Kropff & Laar (1993)). How could this be accomplished
by multiplication with the extinction coefficient, which is after all unitless? Well, consider the
negative exponential law of light extinction: exp ( k LAI ). If we consider LAI unitless, k
becomes unitless by implication. But if we consider LAI in m2 leaf per m2 ground then k must
have the inverse dimension, m2 ground per m2 leaf. And, if we apply this dimension as we
multiply with k to go from light availability per ground area to light absorption per leaf area, the
units work out nicely.
To calculate the light absorption rate of shaded leaves (Ia,sh), i.e. leaf area not struck by
light directly, we take from above the absorption of diffuse light (red curve) and add to that
absorption of secondary diffuse light, which is simply the difference between the absorbed total
direct light (yellow curve) and direct-direct light (blue curve). This yields the red curve below.
100
50
80
40
absorption rate
60
30
40
20
20
10
per hour]
Light
[W per m leaf]
0.0
0.2
0.4
0.6
0.8
Assimilation rate
1.0
Photosynthesis turns assimilated CO2 into carbohydrates using the energy of the absorbed
light. In INTERCOM the assimilation rate is expressed in the (akward, you may think) units
of kg CO2 per ha leaf per hour. The light response curve, which converts absorbed light into
assimilated CO2, is defined by the conversion efficiency (kg CO2 per ha leaf per hour per (W
per m2 leaf)) and the maximum assimilation rate Amax (kg CO2 per ha leaf per hour); can also
2
6+3
4
be expressed in more intuitive units, such as g CO2 per MJ, by multiplication with 10 /10 /60
= 27.78.
88
50
40
Assimilation rate
30
[kg CO2 per ha leaf
per hour]
20
10
0
0
100
200
300
400
500
The curvature of light saturation causes assimilation (blue line above) to be less efficient towards
the top of the canopy where light is most intense. The parameters and Amax vary with plant
species, leaf quality and environmental conditions. Storkey (2005) determined the empirical
relationship between and Amax and temperature (T):
= 0.0095T + 0.635
Amax = 50(1 0.882T )
We used these relations here, applying the values at 20 C, = 0.445 kg CO2 per ha leaf per hour
per (W per m2 leaf) and Amax = 45.9 kg CO2 per ha leaf per hour. The upper limit on Amax was set
to 50 kg CO2 per ha leaf per hour, whereas in the original paper it was operating in other units.
The calculation of light absorption by sunlit leaves is more complicated because the absorption rate depends on the angle of the leaf surface with respect to the sun. The leaf distribution
is assumed to be spheric which means that all leaf angles are equally represented; one can think
of the green area in the canopy as a uniform, green sphere, the intensity of green corresponding
to the LAI. The light flux hitting this sphere perpendicularly, relatively to the light flux hitting
the ground (the measured direct PAR per ground m2), depends on the height of the sun. At the
equator at noon the two fluxes are equal but at lower heights of the sun, the relation shifts (in
proportion to the shadow that the sphere would cast) while at the same time the intensity of sunlight drops.
The net effect can be seen here at 55 N on Julian day 120. As both sun height and sun light
approaches zero, the perpendicular light intensity approaches zero divided by zero; hence, it is
shown only from early morning until late afternoon.
89
Incoming
perpendicular PAR
200
[W per m leaf]
100
Incoming
direct PAR
[W per m2 ground]
0
0
12
18
24
The calculated rate of light hitting perpendicularly can be used to calculate the absorption
rate of the whole canopy, which will be hit at all angles, according to the spheric leaf distribution
assumption. This integration over all leaf angles is carried out in INTERCOM using a 3-point
Gaussion integration. To get the total absorption rate of sunlit leaves, we must add to this, the
absorption rate of diffuse light, which will be the same as calculated above for shaded leaves.
Finally, this total light absorption rate of sunlit leaves is turned into an assimilation rate
by the same light saturation curve as for shaded leaves, exemplified here at 15:43h, the second
integration point of the day.
150
60
Light
absorption rate
for sunlit leaves
2
100
40
Assimilation rate
for sunlit leaves
[kg CO2 per ha leaf
50
20
[W per m leaf]
0
per hour]
0
0.0
0.2
0.4
0.6
0.8
1.0
Knowing the absorption and assimilation rate for both shaded and sunlit leaves, we only
need to divide the leaf area into these two proportions. Assuming a random distribution of leaf
area, the proportion of sunlit leaves is simply the negative exponential of the leaf area index
weighted by the extinction coefficient for direct-direct light (kdr,bl; bl is for black which makes
sense in this context, since we are calculating the area not obstructed by leaves).
Continuing our example from 55 N, Julian day 120, we get this profile of direct sunlight
filering down through the canopy at 15:43h.
90
1.0
0.8
Fraction sunlit
0.6
leaves [-]
0.4
0.2
0.0
0.0
0.2
0.4
0.6
0.8
1.0
Now, at any height we know both the fraction of shaded and sunlit leaves and their rates of
absorption and assimilation. We can obtain the net total light absorption and CO2 assimilation at
any height in the canopy, as the sum of the contributions from shaded and sunlit leaves, weighed
by their fraction of the the total. We get curves that go from the rates of sunlit leaves at the top
of the canopy to the most shaded leaves at the bottom.
150
60
Light
absorption rate
of leaves total
2
100
40
Assimilation rate
of leaves total
[kg CO2 per ha leaf
50
20
[W per m leaf]
0
per hour]
0
0.0
0.2
0.4
0.6
0.8
1.0
But these rates are still per leaf area. To proceed we have got to convert them to a per ground
2
area base. For that purpose we multiply the rates down the canopy with the leaf density (m leaf
per m3 space) at that height. To convert from leaf density to leaf area index, we also multiply
with plant height (set to 1 m, in this example). Thus the units per leaf area in the figure above
are multiplied with m2 leaf per m2 ground or, equally, ha leaf per ha ground, which yields the
units per ground area in the figure below. Since we chose a parabolic model of leaf density,
the resulting rates turn out quite small at the top of the canopy, because leaf density here is
quite small.
91
500
250
400
200
absorption rate
300
150
of leaves total
of leaves total
200
100
100
50
per hour]
Light
[W per m ground]
Assimilation rate
0
0.0
0.2
0.4
0.6
0.8
1.0
At this point you may have forgotten what the points are used for: They are used as a
shortcut to integrate the curves via Gaussion integration. If you leaf back through the figures,
curves with 5 points on them, really exist in 3 versions, one for each integration point during the
day. And curves with 3 points on them, really exist in 5 versions, one for each integration point
through the canopy. To arrive at the total amount of light absorption and CO2 assimilation for
the whole canopy and the whole day, we need to integrate these 15 curves, first over the canopy
and then over the day.
In our example, integration over canopy height yields this course of the whole-canopy rate
during the day.
300
150
200
100
100
50
Light
absorption rate
for leaves total
[W per m2 ground]
Assimilation rate
for leaves total
[kg CO2 per ha ground
per hour]
0
0
0
12
18
24
Taking the integration one step further, using the 3 Gaussion points to integrate these curves
over the day, we arrive at a light absorption rate of 156.74 W per m2 ground and an assimilation
rate of 42.23 kg CO2 per ha ground per h. To factor out time and arrive at the finite rates per day,
we must multiply by daylength (14.84 h, in this case). Thus we arrive, finally, at the end of the
calculations with 8.37 MJ absorbed per m2 ground and 641.42 kg CO2 assimilated per ha ground.
This should be held up against the total daily irradiation, set at 10 MJ PAR per m2 ground in
our example.
Lets congratulate ourselves with this achievement! But we are not quite finished yet. In
our canopy model we limited ourselves to consider only one population, namely that of a population of leaves with a parabolic vertical distribution. But in reality a canopy may consist of
any number of plant organ populations, leaves, stems, flowers, fruits, belonging to one or more
species. We must take a deep breath, retrace our steps and go through the logic right from the
92
beginning and see, which calculations would need to be changed to accomodate a multi-population canopy.
Our first discovery is the leaf density to height relation. There will, in general, be one such
relation, particular to each population present and possible of different shape, total LAI, and
maximum height. Consequently we must imagine the canopy as a multitude of such curves. Lets
consider three populations.
5
4
Leaf density
2
3
2
1
0
0.0
0.2
0.4
0.6
0.8
1.0
Each curve translates easily into the cumulative curve of that populations LAI above a certain
height .
3
0
0.0
0.2
0.4
0.6
0.8
1.0
The light available down through the canopy still decreases exponentially with the total
LAI above any particular. The only difference in the multi-population case is that the effective
extinction (k LAI) must be summed for all populations, applying their pertinent extinction coefficients.
The remaining calculations will remain, irrespective of the number of populations present.
The calculations just need to be repeated for each population to arrive at its daily finite rates of
light absorption and CO2 assimilation. It is a minor step then, in the end, to add up the finite daily
rates of light absorption and CO2 assimilation for each species, summing up the contributions
from the populations of plant organs belonging to that species.
93
To finish the story, we must subsequently turn the daily rate of CO2 assimilation into a
daily rate of biomass accumulation. This is achieved first by multipliction with 30/44 which is
the photosynthetic exchange rate from CO2 to CH 2O (carbohydrates, "sugars"). Part of these
carbohydrates is lost immediately to maintenance respiration while the rest is distributed among
the plant organs, according to the prevailing allocation scheme. But even the actual incorporation
of those carbohydrates comes at a cost, growth respiration, before the remainder is finally bound
as plant biomass. All this logic can be expressed straightforwardly in C++, as will be shown in
the following.
6.2. Light absorption refactored
We view a multispecies plant community as a composition of structural levels: community,
plant populations, plant organs and organ sub-components. This example shows the resulting
hierarchy in a community of just two populations, a crop and a weed:
community
wheat
height
leaves
area
mass
stem
area
mass
cheal
grains
area
root
mass
height
mass
stem
leaves
area
area
mass
root
mass
mass
Each of the boxes correspond to an object in the running model, and each arrow denote
a parent-child relationship. In this case the crop is composed of four organs and the weed of
three organs. The green organs each hold an object representing its area. All organs in addition
holds a mass. Both plants also hold an object to keep track of plant height. The areas have been
emphasized with a green background.
If we look at the classes these objects belong to, we can see that we need a total of six classes
to define this model (Community, Plant, Height, Organ, Area and Mass):
Community
Plant
Height
Organ
Area
Mass
Organ
Area
To be continued
Mass
Plant
Organ
Area
Mass
Organ
Mass
Height
Organ
Area
Mass
Organ
Area
Mass
Organ
Mass
95
Table 7.1. Variables necessary as input to perform calculations. An example of the input text
file is given in the UniSim weather folder (LakedataOBS2004-2005.txt).
Name
Unit
Variable name
Date
[dd/mm/yyyy]
date
LakeID
[-]
LakeID (ignored)
Oxygen concentration
[mg l ]
obsDO
Water temperature
[C]
tempw
[mol m-2 d ]
obsDLI
Wind speed
m-1
wind
-1
-1
T w:
Percentage of Saturation
Afterwards the percentage of saturation for a given observed dissolved oxygen concentration is
calculated according to the following simple equation:
DOsat,obs = 100
DOobs
DOsat
96
a function of day number of the year (Julian day) and the latitude. The user of the lake oxygen
plug-in needs to specify the latitude of location in the xml file. For further information about
calculation of the day length, see Kropff & Laar 1993.
Net Community Production Equation
Based on a statistical analysis we have compiled a multiple linear regression with satisfactory
2
significant explained variation (R =0.253, N=24,738, F=4190, P<0.001). The equation is
presented below:
NCP = 0.014DOsat, obs + 0.0022DLI 0.081DayLength 0.787
Where
-1
NCP:
DOsat,obs:
DLI:
DayLength:
[hours]
-1
This prediction equation is implemented into the UniSim lake plug-in and calculates the NCP
based on lake specific inputs.
7.1.3. Predicting NCP in Real Lakes
When extrapolating the NCP model from mesocosms to real lake data, changes in system proportions and factors controlling governing processes must be considered. One process is the system
exchange of oxygen between water column and overlaying atmosphere (Odum 1956). Lake oxygen reaeration is primarily controlled by wind speed (Banks & Herrera 1977, Gelda et al. 1996),
while the mesocosms reaeration are generated from constantly mixing by artificial steering
(Liboriussen et al. 2005). The UniSim lake oxygen plug-in is developed to calculate the NCP for
real lake and not mesocosms, thus we have implemented the opportunity for the user to adjust
the reaeration coefficient to fit a given lake.
Several empirical relations has been publish where reaeration coefficient
is estimated from wind speed as only important parameter (Liss 1973, Emerson 1975,
Banks & Herrera 1977, Deacon 1977, Mattingly 1977, OConnor 1983, Wanninkhof et al. 1985,
Boyd & Teichert-Coddington 1992, Livingstone & Imboden 1993, Portielje & Lijklema 1995,
Gelda et al. 1996, Gelda & Effler 2002, Crusius & Wanninkhof 2003). Thus, we have used the
empirical relation published by (Banks & Herrera 1977). Based on this relation the UniSim plugin calculates a lake specific reaeration coefficient from wind speed (see Table 7.1).
The system reaeration coefficient for the mesocosms in Lemming (K L,mes) is estimated to
-1
0.22 m d by Liboriussen et al. 2010. The Plug-in then use linear scaling, computed from the
ratio K L,lake / K L,mes between mesocosms system reaeration coefficient and the individual lake
specific reaeration coefficient (K L,lake) estimated from wind speed, to correct our NCP model to
97
individual lakes.
Furthermore the user can specify a range for the K L,lake parameter used as input to a
stochastic number generator generating the coefficient K L,lake,Random. This coefficient is also
used to calculate a NCP from linear scaling by the ratio K L,lake,Random /K L,mes. Thus the user can
view different estimations of the NCP where uncertainty on the reaeration coefficient implicit
is included.
If the user has limited knowledge about a lake specific system reaeration coefficient,
estimations from wind is the best approach. For that reason we derive the average reaeration
coefficient estimated from wind speed and present it in a plot (see section about plotting). Based
on this particular plot, the user can set the ranges for the stochastic number generator and thereby
quantify the NCP in a broader range and implicit account for uncertainty.
The reason why so much effort is put into this module is that the reaeration coefficient as
parameter is difficult to measure directly and thereby is uncertain to estimate as well.
7.1.4. Unit of output
Daily accumulated NCP is default calculated as mass oxygen production per square meter
-1
surface area per day [gO2 m-2 day ], however, the user can choose to change the unit to carbon
instead by taking into account the difference in atom mass between oxygen and carbon. This is
easily done by simply changing the parameter unit from 1 (oxygen) to 0 (carbon) in the model
XML file.
7.1.5. Setting the stochastic sampling number
In the model XML file the user can specify the number of iterations one batch model run
performs. Control of this parameter is of use if any post hoc statistical analysis is conducted.
By default the model performs 30 single runs in each batch where the reaeration coefficient is
changed each time within the user specified range (min and max for the stochastic sampling
range is also set in the XML file).
7.1.6. Plotting
WHen the simulation is run, output appears in several plots on the screen. Below their meaning
is explained.
Lake environment
Lake environment is an overview of the observed parameters: Daily Light Integral (DLI), wind
speed and Day length, variables classified as outer variables in respect to the lake as system. The
plot is simply graphs drawn from the input file where all variables are given on a daily time step,
but is presented to give the user overview.
Observations
-1
Observations is an overview of the in-lake observed parameters: oxygen [mg l ] and water
temperature [C] read from the input file and given on a daily time step.
Averaged estimated reaeration coefficient (from wind speed)
98
If the user has no knowledge about the reaeration coefficient for a specific lake, a value computed
from wind speed is the best estimate. Thus by looking at the average plot the user can then get
help to estimate the stochastic sampling range for the reaeration coefficient.
Net community production
Net community production presents two graphs (1) NCP (K L estimated from wind) and (2) NCP
(K L stochastic). (1) is the NCP where corrections in respect to reaeration coefficient is computed
from wind speed (see Table 7.1) whereas (2) is the NCP where corrections in respect to reaeration
coefficient is computed as and stochastic sampling process based on a user defined range.
Parameter
The stochastic sampling of parameter values for the reaeration coefficient based on a user
defined range is presented in the Parameter plot where each individually sampled value is plotted,
thus the user can view the actually sampled values.
Accumulated Net Community Production
The UniSim lake oxygen plug-in calculates NCP on a daily basis. However, for comparable
reasons the present calculations is summarize from daily values to an accumulated yearly net
community production. Following the curve, the accumulation is reset at the first of January each
year and thereby gives the yearly calendar net community production.
7.1.7. Output from the model
In the XML file output from the lake oxygen model is specified. The model automatically creates
an output file containing all parameters necessary for the calculations as well as calculated values
of dissolved oxygen concentration saturation percentage, net community production (both with
corrections where reaeration coefficients are estimated from stochastic sampling and from wind
speed, respectively). The UniSim model creates one file for each stochastic parameter estimate,
which can be used for post hoc statistical analysis.
99
100
When CarryingCapacity is set to a positive value, the Population model would behave
according to logistic growth; when its set to 0 or a negative value, exponential growth will be
presented instead. Note that Population model assumes infinite supply of resource during
growth (which means you will never see a decrease of density as long as g>m); to simulate
growth under limited resource, a Competition model should be introduced.
Demonstration
Model definition file Demo_PopulationGrowth.xml demonstrates exponential and logistic
population growth.
Model
Parameter
Value
Remarks
Population
InitialDensity
1000
Growthrate
0.03
MortalityRate
0.01
CarryingCapacity
CarryingCapacity
10000
Figure 7.1. Simulated population growth. Left: exponential growth; Right: logistic growth.
model to be used, but for now only one model (the Gutierrez-Baumgrtner functional response
model) is available. Each population is considered a consumer for the common resource in the
competition. For each consumer to sustain itself, a certain amount of resource is required, and this
101
is called "demand". Demand of the ith consumer (Di) in time t is dependent on the population
density (ni) and the demand rate (i), and is defined as:
Di = ni i t
However, in a limited environment, the demand of each consumer may not be realized due to the
consumers inability to acquire resource or the insufficiency of resource. So, in the case of no
interspecific competition, the actual resource consumed by the ith consumer (consumption,
noted as Ri), is dependent on the consumers ability to find the resource (determined by
search rate i), and the available resource in the environment (R). Ri can be modelled by the
Gutierrez-Baumgrtner functional response model (Gutierrez 1992):
Ri = Di
(1 e )
i R
Di
So, the actual growth of the ith consumer is now dependent on its demand and consumption,
which can be characterized by the supply/demand ratio:
R
i
Ri
i =
= 1 e Di
Di
And the observed growth rate for the ith consumer becomes:
ni
= ni gi i mi
t
Note that in the presence of a Competition model, the carrying capacity for a population is
implicitly determined by the available resource S which is determined by the Competition
model, so exponential instead of logistic growth would be used.
With the introduction of supply/demand ratio , the observed growth rate could now
become negative, indicating decrease of population density (Fig. 7.2). It should be noted that
when the calculated population density drops below 1, Population model will return 0 as the
output value. This ensures that population can "extinct" during competition since mathematically
the progressive decrease of density would only approximate zero indefinitly but never really
reach it. The total consumption of all consumers is:
Rtotal = Ri
i
102
And the remaining resource R is updated in each step as:
R R Rtotal
When R approaches zero, the calculated Rtotal could become greater than R. In that case we
assume that the consumers exhaust the resource completely, dividing the remaining resource
among them in proportion to Ri:
Ri
Ri
Rtotal R
Demand rate () and search rate (a) are defined in Population model as parameters DemandRate and SearchRate; Competition model will try to inquire their values as well as the
value of pull variable Density from Population model during simulation. Supply/demand
ratio () is calculated by Competition model and sent back to Population model, and can be
accessed through pull variable SupplyDemandRatio. Remaining resource (R) can be accessed
through pull variable AvailableResource from Competition model.
Demonstration
Model definition file Demo_PopulationGrowth.xml demonstrates exponential and logistic
population growth.
Model
Parameter
Value
Population
InitialResource
10000
Population_1
InitialDensity
500
Growthrate
0.04
MortalityRate
0.01
SearchRate
0.01
DemandRate
0.02
InitialDensity
1000
Growthrate
0.03
MortalityRate
0.01
SearchRate
0.015
DemandRate
0.03
Population_2
Remarks
103
Figure 7.2. Simulated competition of 2 populations. Left: the change of population (red and blue) and
community density (yellow); Right: the decrease of available resource
cases, these activities are reduced to simple enzymatic or chemical reactions, and they can be
simulated by reaction models.
There is a group of different reaction models to suit different senarios. All reaction models
take only one parameter InitialSubstrate. But during simulation, they will also try to
inquire parameter values describing metabolic dynamics from Population models. Each
reaction model would inquire parameter(s) from Population model during simulation, and this is
described in each section respectively.
Reaction models send current reaction rate and substrate concentration as output and they
can be accessed through pull variables Velocity and Substrate respectively.
NOTICE: A model of the type MicrobialCommunity::Reaction does exist, but it is
only meant as the base model for implementation. The model Reaction should never be used in
the simulation.
EnzymaticReaction Model
The metabolic activities of microorganisms are catalyzed by enzymes, so the EnzymaticReaction model is the fundament of all other Reaction models.
An enzyme catalyzed reaction could take several substrates, but in studies ususally only
one substrate is considered the limiting factor. For example, the monooxygenase in methane-oxidizing bacteria (MOB) oxidizes methane to formaldehyde through a reaction that also requires
oxygen. But in an aerobic environment where MOBs are most active, oxygen is ample and the
availability of methane limits the reaction. So, in situations like this, the dynamics of microbial
metabolic activity can be simplified to single-substrate enzymatic dynamics, and can be described
by Michaelis-Menten equation (Fig. 3, Up-left):
V S
V = S = max
Delatt K m + S
104
where V is the velocity of reaction, S is the substrate concentration, Vmax is the maximum velocity
and K m is the Michaelis-Menten constant.
The integrated form of Michaelis-Menten equation describes how substrate concentration
decreases over time (Fig. 3, Bottom-right, Red):
(S0 S) + K m ln
()
S0
= Vmax t
S
corresponding to K m.
ZeroOrderReaction Model
In certain cases, Michaelis-Menten equation can be approximated to simpler forms. If substrate
concentration S >> sK m, then V Vmax, and Michaelis-Menten equation can be approximated to
the rate equation of zero-order reaction (Fig. 3, Up-right):
S = k where k = V
max
0
0
t
In a zero-order reaction, the substrate concentration decreases linearly over time (Fig. 3,
Bottom-right, Blue):
S = S0 k 0 t
ZeroOrderReaction model would inquire parameter ZeroOrderRateConstant (k0) from
Population model.
FirstOrderReaction Model
Vmax
S, and Michaelis-Menten equation can be approxKm
imated to the rate equation of first-order reaction (Fig. 3, Bottom-left):
S = k S where k = Vmax
1
1
Km
t
In a first-order reaction, the substrate concentration decreases along an exponential decay curve
over time (Fig. 3, Bottom-right, Yellow):
105
S = S0 ek1t
FirstOrderReaction model would inquire parameter FirstOrderRateConstant (k1)
from Population model.
V(n =
kn0 S
Km + S
V(n =
knt S
Km + S
0)
t)
(Note: kn = Vmax)
From which we can define a density-activity coefficient :
V(n
t)
V(n
0)
nt
= 1 + n
n0
n0
It is easy to see that in an enzyme catalyzed reaction, change of population density will affect
Vmax but not K m; and in zero- and first-order reactions, the effect is on k0 and k1.
It should be noted that the change of population is dependent on population growth.
106
Logistic growth or growth under competition should be used instead of exponential growth,
which might generate unrealistic results.
In the case of changing population density, current reaction rate and substrate concentration
should be accessed through pull variables VelocityPDD and SubstratePDD respectively.
PDD stands for Population Density Dependent.
Demonstration
Model definition file Demo_Reaction.xml demonstrates the activity of methane oxidation
by a MOB population. Population density dependent reaction is demonstrated in a separate file
Demo_Reaction_PDD.xml, the result of which is not shown below.
Model
Parameter
Value
Population
InitialDensity
1000
ZeroOrderRateConstant
25
FirstOrderRateConstant
0.004
MichaelisMentenConstant
800
MaximumVelocity
30
EnzymaticReaction
InitialSubstrate
10000
ZeroOrderReaction
InitialSubstrate
10000
FirstOrderReaction
InitialSubstrate
10000
Remarks
Random:{Min, Max}: a random group from all populations with size ranging from Min
to Max are affected. Min must be equal to or greater than 1.
107
Random:{All} or Random:{*}: a random group from all populations are affected. This
is equivalent to Random:{1, Number_of_Populations}.
In each implementation of individual effect model, additional parameters are required in order
to perform respective simulation, and this is described in each section of the model.
NOTICE: A model of the type MicrobialCommunity::Effect does exist, but it is
only meant as the base model for implementation. The model Effect should never be used in
the simulation.
GeneralEffect Model
GeneralEffect is a simple implementation of Effect model which simulates the effect of an
environmental factor on the properties of populations. A simple usage of the GeneralEffect
108
Uniform:{Value}: the strength is uniform among all populations and takes the value
Range:{Min, Max}: the strength takes a random number between Min and Max.
appearance. You can even define a range for the value, but slightly different from the above,
it should be written in the form of min-max. E.g. Specified:{0.2, 0.3-0.5, 0.6}.
Effect ratio is defined as the ratio of the parameter value under effect to the value without effect.
So, effect ratio less than 1means the factor is inhibitory, while ratio greater than 1means the factor
is stimulative, and equal to 1 means theres no effect at all.
CompetitiveInhibition Model
CompetitiveInhibition implements the effect of a competitive inhibitor on enzyme-cat-
alyzed reactions. Competitive inhibitor competes with the substrate for the active site of an enzyme. In the presence of a competitive inhibitor, the Michaelis-Menten equation becomes:
V=
Vmax S
[I]
where = 1 +
KI
K m + S
[I] is the concentration of the competitive inhibitor, and K I is the inhibition constant. As a result,
CompetitiveInhibition model has two corresponding parameters: InhibitorConcentration and InhibitionConstant. It can be used, for example, to simulate the competitive
effect of ammonium on methane oxidation by MOBs.
7.2.7. Community Model
The Community model provides a realistic way to simulate real world situations. In most
cases, it is recommended to use Community model as a container to hold other models such
as Population, Competition, Reaction, and Effect. This not only simplifies the model
definition in the XML file, but also presents a more flexible way to run the simulation.
As already discussed above, Competition, Reaction and Effect models can interact
with Population models during the simulation, by either inquiring parameter values, or affect
the behavior of Population models. It should be noted by now that Competition, Reaction
and Effect models only interact with Population models that are on the same level as
themselves. For example, consider the following structure of models:
<Community_1>
<Competition_1 />
<Population_1 />
<Population_2 />
109
</Community_1>
<Community_2>
<Effect_1 />
<Population_3 />
<Population_4 />
</Community_2>
Competition_1 only affects Population_1 and Population_2, since they are all on
the same level (contained in Community_1); while Effect_1 only has an effect on Population_3 and Population_4. This behavior makes it possible to include several Community
models with different combination of submodels in one simulation and they can be insulated
from each other.
Stochastic Community
Another powerful feature of Community model is that it can stochastically select Population
models into the simulation. Coupled with UniSims RunIterator and random parameter
features, Community model provides an automated way to explore the effect of community
structure on community functions,
To generate stochastic communities, the parameter EnableStochasticCommunity
should be set to True. Then Community model takes three parameters to determine how the
stochastic communities are constructed:
1.
2.
generated in step 1, then those items will be selected randomly. To avoid this situation, set
MinPopulations to the number of items in AlwaysIncludedPopulations.
3.
If after step 2 therere still empty slots left, the rest of the Population models will be
selected randomly until all slots are filled.
Model Output
Community model can calculate a list of indices that describe the properties of the community,
110
sowingMonth
harvestDay
harvestMonth
weedExchangeRate
0.6
maxYield
800
maxYieldLossPct
60
slopeYieldLossPct
0.5
111
112
((0
0)(110
0)(210
0.3)(310
0.8)(410
1.6)(510
2.9)(610
5)(1000
5)(1200
5)(1650 2))
Calendar for leaf area index (LAI) running on temperature sum since sowing (day-degrees above C).
Defined as a list of (temperature-sum LAI) pairs.
lai
double
Tsum
double
laiCalendar
VARIABLES
2
A.1.2. awe::InstantMortality
Once per year, at the given month and day, an InstantMortality object effectuates given
mortalities on one or more PlantGrowhtStage models. This can be used to simulate discrete
mortaly events caused by field operations, for example, spraying or soil cultivation.
It is natural to create InstantMortality objects as descendants (or, inside) of a Crop
model. The mortalities will then only be in effect when that crop is current in the Rotation.
PARAMETERS
day
month
mortalities
empty string
A.1.3. awe::PlantGrowthStage
A PlantGrowthStage holds two UniSim::Stage models inside, represing plant density
both as plants per m2 and density equivalents per m2. One density eqivalent corresponds to the
density of one plant that emerged simultaneouly with the crop. Later emerging plant counts as
less than one density equivalent per plant. Thus equivalence is meant as equivalent in terms of
competitiveness towards the crop
PARAMETERS
113
inflowAsDensity
inflowAsDensityEqs
instantMortality
VARIABLES
outflowAsDensity
double
outflowAsDensityEqs
double
A.1.4. awe::Rotation
The Rotation model holds as children the Crop models that are part of the rotation. It keeps
check of the current crop according to cropping sequence and the harvest and sowing events
pertaining to Crop models.
PARAMETERS
crops
empty string
double
VARIABLES
lai
A.1.5. awe::SeedBank
2
The SeedBank model holds the density of seeds in the soil (per ). Seeds are divide into two
groups: dormant and non-dormant. Newly produced seeds enter the seed bank as dormant. Dormancy is lost on 1 January every year, and all dormant seeds are then movedinto the non-dormant group.
PARAMETERS
initialDensity
1000
114
emergenceCalendar
(0 0 5 10 20
40 10 5 0 0
0 0)
yearlyEmergenceRate
0.2
yearlyMortalityRate
0.1
cropLaiExp
0.04282
instantMortality
VARIABLES
number
double
dormant
double
nonDormant
double
dailyEmergenceRatio
double
totalEmergenceRatio
double
dailyEmergenceDensity
double
totalEmergenceDensity
double
cropEffectOnEmergence
double
115
double
A.1.6. awe::Weather
The Weather model produces data for daily average temperature, assuming a sine curverelation
over the year, y = a + b( x + c )2, where x is the day of the year [0..365].
365
PARAMETERS
a
-0.75
17.2
VARIABLES
T
double
Tavg
double
Tsum
double
A.1.7. awe::Weed
The Weed model holds the SeedBank model, PlantGrowthStage models for seedling,
juvenile and mature stages, and a UniSim::Stage model to represent seeds on the plant.
The Weed model orchestrates the progressive flow of weed individuals through these
models. For the PlantGrowthStage models there are parallel flows of density equivalents.
PARAMETERS
c1
6.904
c2
0.7491
See c1.
seedProdSlope
seedProdExp
VARIABLES
116
projectedDeqs
double
projectedYieldLossPct
double
projectedMass
double
seedsDropping
double
double
117
double
A.2.2. conductance::Plant
A Plant object grows, in terms of biomass, leaf area and crown zone area, according to its
current competition phase
PARAMETERS
initWeight
initDay
initMonth
0.03
phi
0.67
0.01
118
theta
0.9
0.6
eps
20
weight
double
totalWeight
double
sz
double
total_sz
double
Lz
double
fz
double
LA_per_plant
double
dweight
double
phase
int
LAI
double
VARIABLES
2
A.2.3. conductance::Weather
This Weather object holds fixed values for global irradiation and daily average temperature.
PARAMETERS
irradiation
10
119
alpha
0.007
S0
0.27
0.017
0.007
gSini
250
PARmin
tm
30
ts
45
useTemperature
no
A0
12
theta
0.0035
double
Seq
double
S60
double
Ar
double
VARIABLES
120
14
onsetFileName
empty string
VARIABLES
value
double
total
double
A.4.2. ecotox::DepositionMonotonicSampled
Seasonal deposition curve sampled from an empirical distribution, beginning at value zero and
ending at value one at the end of the season. The distribution data must be supplied as a column
in the records of the weather model.
VARIABLES
value
double
total
double
A.4.3. ecotox::DepositionMonotonicWeibull
Seasonal deposition curve described by a Weibull curve
PARAMETERS
alpha
21.54
beta
1.868
121
dateMax
31/7/2011
dateShift
VARIABLES
value
double
total
double
A.4.4. ecotox::LogLogistic
The log-logistic dose-response curve described by
y = ymin
(ymax ymin)
x slope
1 + ED50
The value of the dose x is given by the parameter dose below. As for any other parameter,
you can either set this to a fixed or a variable value. For dose you most often want a variable value supplied from another model. If you set dose to pollen[pollenDensity]
then the response will reflect current pollen density. Other possible measures include
pollen[stdPollenDensity] and pollen[toxinDensity], see Pollen on page 121.
PARAMETERS
dose
lower
upper
ED50
10
slope
VARIABLES
value
double
A.4.5. ecotox::Pollen
This model must be composed of two models, depositionRate and lossRate, and possibly
a third model, depositionFlush. Its parameters determine the total deposition and the
122
distance from the source.
The LogLogistic dose-response model can pull the current dose from Pollen as pollenDensity, toxinDensity or stdPollenDensity.The exchange rate between these different
units of density is determined by the parameters pollenMass and toxinConc, which set the
mass and toxin concentration for the crop at hand, and stdPollenMass and stdToxinConc,
which set the corresponding values for a standard reference crop. The transformations are
toxinDensity = pollenDensity*pollenMass*toxinConc
and
stdPollenDensity =
pollenDensity*pollenMass/stdPollenMass*toxinConc/stdToxinConc
PARAMETERS
distance
distanceExp
-0.548
distanceMin
0.3
Npeak
1750
VARIABLES
pollenDepositionRate
pollenDepositionTotal
pollenDensity
double
double
double
A.4.6. ecotox::PollenLossConstant
With a constant rate of pollen loss, pollen disappears following a negetive exponential curve.
PARAMETERS
rate
0.01
double
VARIABLES
value
123
A.4.7. ecotox::PollenLossSampled
With sampled loss rate, the daily loss rate is determind by picking a value at random from the
supplied list of loss rates.
PARAMETERS
rates
(0 0.5 0.9)
double
VARIABLES
value
124
An Area object keeps track of the area (cm per plant) which carries out photosynthesis
according to its parameters and sub-models. It must hold three sub-models as children, named
density, amax and lightUseEfficiency. The latter two specify the shape of the light
response curve and the first the shape of the canopy.
PARAMETERS
scatteringCoeff
0.2
kDiffuse
0.7
writeTestOutput
no
allocation
VARIABLES
value
double
LAI
double
lightAbsorption
double
CO2Assimilation
double
grossProduction
double
A.5.2. intercom::AreaDensityEven
This model can serve as a density sub-model for an Area object. The density is the same at all
heights from zero to canopy height.
125
A.5.3. intercom::AreaDensitySymmetric
This model can serve as a density sub-model for an Area object. The density is parabolic from
zero to canopy height.
A.5.4. intercom::AreaDensityTapering
This model can serve as a density sub-model for an Area object. The density increases linearly
from zero at canopy height to its maximum at zero height.
A.5.5. intercom::AreaDensityTopheavy
This model can serve as a density sub-model for an Area object. The density increases
non-linearly from zero to canopy height, resulting in a topheavy shape typical of flowers
A.5.6. intercom::AssimilationMaxGivenTemp
This model can serve as the amax sub-model of an Area object. Based on the Tday variable of
Tday)
weather model, it calculates the maximum assimilation rate as maxAmax(1 radix
PARAMETERS
radix
0.882
maxAmax
50
VARIABLES
value
double
A.5.7. intercom::Community
A Community model holds one or more Plant child models. It resolves the competition for
light in daily time steps, calculating total light absorption and CO2 assimilation of the whole
canopy (i.e. of all its Plant objects) and dividing the resulting total among its Plant objects.
If more than one Community object is present they will work in parallel without any interference (e.g. competition for light). Thus different scenarios can be compared in one simulation run.
PARAMETERS
earlyGrowthThreshold
126
testMode
no
In test mode, the plants stop growing after earlyGrowthThreshold has been reached. Daily photosynthesis is calculated but not allocated.
VARIABLES
isInEarlyGrowth
bool
LAI
double
lightAbsorption
double
CO2Assimilation
double
grossProduction
double
A.5.8. intercom::EarlyGrowth
The EarlyGrowth model is a simple expontial curve based on photothermal time. A photothermal time model must be available as a sibling.
PARAMETERS
initialArea
0.05
growthRate
double
VARIABLES
area
A.5.9. intercom::Height
A Plant model must have one child model named height with a height pull variable
returning the height. The Height class provides the standard height model of INTERCOM
which is a logistic growth curve working on photothermal time.
hmax h0
height(t) = h0 +
1 + exp( slope(t tm))
The height model looks for the nearest model named time to provide the daily time increment.
A UniSim::PhotoThermalTime model can be used for this purpose (see page 152).
PARAMETERS
h0
0.05
hmax
slope
0.0085
tm
624
127
VARIABLES
height
double
A.5.10. intercom::InstantMortality
List of instant mortalities [0;1] applied on a certain day and month to the listed plant organs, for
example, ((leaves 0)(stem 0.05)(flowers 0)). Plant organs not mentioned will not be
afflicted. Those mentioned must exist inside Plant.
PARAMETERS
day
month
survival
empty string
A.5.11. intercom::LightUseEfficiencyGivenTemp
This model can serve as the lightUseEfficiency child model of an Area object. It calculates
light use (or light conversion) effiency as a linear relation on Tday of the weather model
PARAMETERS
slope
-0.0095
intercept
0.635
Slope of the line (kg CO2 per ha leaf per hour per
(W per m2 leaf) per C).
Intercept of the line (kg CO2 per ha leaf per hour
per (W per m2 leaf)).
VARIABLES
value
double
A.5.12. intercom::Mass
This model can serve as a mass child model of an Organ model. It holds iself a mass child
model to hold the actual mass (g/plant) which is usually of the UniSim::Stage class to simulate
an ageing mass
PARAMETERS
allocation
double
VARIABLES
value
128
allocationRate
double
currentPartition
double
A.5.13. intercom::Organ
An Organ model is a child of a Plant model. It contains one child model called mass and
optionally an additional model of the Area class
PARAMETERS
maintenanceCoeff
0.03
CH2ORequirement
1.5
VARIABLES
Absorbed light (W per m2 ground per day).
Assimilated kg CO2 per ha ground per day.
lightAbsorption
double
CO2Assimilation
double
grossProduction
double
maintenanceResp
double
growthResp
double
netAllocation
double
allocatedPerPlant
double
propAllocatedPerPlant
double
A.5.14. intercom::PartitioningFixed
This model supplies a partitioning coefficient with a fixed value
PARAMETERS
value
129
A.5.15. intercom::PartitioningFixedByStage
Pending
PARAMETERS
value
values
empty string
A.5.16. intercom::Phenology
The model of plant phenology must be a child of a Plant model. It may consist of any number
of UniSim::Stage models
VARIABLES
alive
double
A.5.17. intercom::Plant
A Plant model is a child of the Community model. It holds one or more Organ child models
and additional child models called time, height and earlyGrowth.
PARAMETERS
100
mass
double
LAI
double
lightAbsorption
double
allocatedPerPlant
double
CO2Assimilation
double
grossProduction
double
maintenanceResp
double
density
VARIABLES
2
130
growthResp
double
availableProduction
double
netAllocation
double
A.5.18. intercom::SpecificLeafArea
This can serve as the specificLeafArea model of an Area model. It models specific leaf area
2
(m /g) as a linear relation on photothermal time, supplied by the nearest model called time, for
example a UniSim::PhotoThermalTime model.
PARAMETERS
initial
240
slope
-0.075
double
VARIABLES
value
A.5.19. intercom::Weather
The model named weather of this class must be present, as several other models rely on daily
weather recordings. The weather model holds a UniSim::Records inside which manages
the daily readings from a weather file. This weather file must hold at least four columns labelled:
Date, Tmin, Tmax and irradiationMJ. In addition to these four, Weather itself adds additional
pull variables.
Values of irradiation rates pertain to the current time of the day, as set by the clock
object
VARIABLES
Tavg
double
Tday
double
irradiation
double
Daily average temperature calculated as the average of Tmin and Tmax (C).
Daily day temperature calculated as Tmax minus
one quarter of the span between Tmax and Tmin
(C).
Daily total irradiation. Same as irradiationMJ
read from weather records but with adjusted units
2
(W/m ).
131
parTotal
double
parDiffuse
double
parDirect
double
132
no
MinPopulations
MaxPopulations
AlwaysIncludedPopulations
empty string
VARIABLES
Density
double
Richness
int
SimpsonIndex
double
ShannonIndex
Evenness
double
double
GiniCoefficient
double
A.6.2. MicrobialCommunity::Competition
Description pending
PARAMETERS
EnableCompetition
yes
InitialResource
CompetitionModel
default
VARIABLES
double
133
Description.
A.6.3. MicrobialCommunity::CompetitiveInhibition
Description pending
PARAMETERS
EnableEffect
yes
TargetPopulations
empty string
InhibitionConstant
InhibitorConcentration
Concentration of inhibitor.
A.6.4. MicrobialCommunity::Effect
Description pending
PARAMETERS
EnableEffect
yes
TargetPopulations
empty string
A.6.5. MicrobialCommunity::EnzymaticReaction
Description pending
PARAMETERS
100
Substrate
double
SubstratePDD
double
Velocity
double
VelocityPDD
double
Concentration of substrate.
Concentration of substrate, population density dependent.
Reaction velocity.
Reaction velocity, population density dependent.
InitialSubstrate
VARIABLES
134
A.6.6. MicrobialCommunity::FirstOrderReaction
Description pending
PARAMETERS
100
Substrate
double
SubstratePDD
double
Velocity
double
VelocityPDD
double
Concentration of substrate.
Concentration of substrate, population density dependent.
Reaction velocity.
Reaction velocity, population density dependent.
InitialSubstrate
VARIABLES
A.6.7. MicrobialCommunity::GeneralEffect
Description pending
PARAMETERS
EnableEffect
yes
TargetPopulations
TargetParameter
empty string
EffectRatio
empty string
empty string
A.6.8. MicrobialCommunity::Population
Description pending
PARAMETERS
SpeciesName
Bacterium
IsActive
yes
InitialDensity
CarryingCapacity
LagPhase
GrowthRate
MortalityRate
SearchRate
135
DemandRate
ZeroOrderRateConstant
FirstOrderRateConstant
MichaelisMentenConstant
MaximumVelocity
Demand rate.
Zero-order rate constant.
SupplyDemandRatio
VARIABLES
Density
double
DensityActivityCoefficient
double
Population density.
Bacterial density-activity coefficient.
A.6.9. MicrobialCommunity::Reaction
Description pending
PARAMETERS
100
Substrate
double
SubstratePDD
double
Velocity
double
VelocityPDD
double
Concentration of substrate.
Concentration of substrate, population density dependent.
Reaction velocity.
Reaction velocity, population density dependent.
InitialSubstrate
VARIABLES
A.6.10. MicrobialCommunity::ZeroOrderReaction
Description pending
PARAMETERS
100
Substrate
double
SubstratePDD
double
Velocity
double
Concentration of substrate.
Concentration of substrate, population density dependent.
Reaction velocity.
InitialSubstrate
VARIABLES
136
VelocityPDD
double
137
desc.
double
desc.
VARIABLES
value
A.7.2. mussel_bed::Mussel
Mussel population model
PARAMETERS
initialDensity
initialN
1000
LossB
LossN
growthRate
0.3
VARIABLES
N
double
density
double
A.7.3. mussel_bed::MusselGrowthRate
Mussel population growth rate model
PARAMETERS
intrinsicRate
0.019
carryingCapacity
15
138
density
double
total growth rate for the current density, temperature and salinity (kg/m2).
VARIABLES
value
A.7.4. mussel_bed::SalinityScale
Scaling of growth rate by Salinity. Yields a number [0;1]
PARAMETERS
Smax
30
Smin
24
double
VARIABLES
value
A.7.5. mussel_bed::SalinitySRScale
Scaling searching rate of starfish by average salinity. Yields a number [0;1]
PARAMETERS
Smax
31
Smin
10
desc.
desc.
double
desc.
VARIABLES
value
A.7.6. mussel_bed::searchrate
estimating appearance for fResp
PARAMETERS
maxSR
double
VARIABLES
value
A.7.7. mussel_bed::Starfish
starfish population model
PARAMETERS
139
inDensity
0.3
mortality
stgrowthRate
0.12
VARIABLES
stdensity
double
A.7.8. mussel_bed::StarfishFeedingRate
Scaled Feeding rate of starfish
PARAMETERS
stdensity
0.3
double
VARIABLES
value
A.7.9. mussel_bed::StarfishGrowthRate
transform feeding rate into new starfish biomass
PARAMETERS
supply
0.007
stDensity
0.3
temperature
13
double
VARIABLES
value
A.7.10. mussel_bed::StarfishSalMortality
Starfish mortality produced by salinity changes
PARAMETERS
Smax
28
Smin
12
double
desc.
VARIABLES
value
140
A.7.11. mussel_bed::TemperatureScale
Scaling of growth rate by temperature. Yields a number [0;1]
PARAMETERS
temperature
12
avgs
0.005
double
VARIABLES
value
A.7.12. mussel_bed::TemperatureStScale
Scaling of feeding rate of starfish by Temperature. Yields a number [0;1]
PARAMETERS
temperature
15
double
VARIABLES
value
A.7.13. mussel_bed::thinning
stimate loss rate considering also self thinning rule
PARAMETERS
Density
supply
VARIABLES
thin
double
LossN
double
LossB
double
avgs
double
maxN
double
141
0.5
density
fecundity
20
proportionEggsInWater
20
Proportion of females.
Density of adults.
Eggs laid per female per day.
desc.
VARIABLES
eggsLaidInWater
double
eggsLaidOnGround
double
A.8.2. rvf::Egg
Mosquitoes eggs in water
VARIABLES
totalEggsInflow
double
desc.
A.8.3. rvf::InactiveEgg
Inactive eggs laid on the ground.
PARAMETERS
initialDensity
lossRate
20
activationRate
20
inflow
desc.
desc.
desc.
desc.
VARIABLES
density
eggsLost
double
eggsActivated
double
double
desc.
desc.
desc.
142
A.8.4. rvf::MosquitoFecundity
0
20
desc.
desc.
20
desc.
double
desc.
VARIABLES
value
A.8.5. rvf::WaterLevel
Water level in the environment.
PARAMETERS
initialValue
100
dailyRainfall
dailyLoss
10
desc.
desc.
desc.
double
desc.
VARIABLES
value
143
10
0.008
double
VARIABLES
accumulated
A.9.2. seed_emergence::Weather
Converts units of soil water potential from kPa to MPa.
VARIABLES
Tavg
double
SWP
double
144
infectionRate
sourceModel
empty string
empty string
desc.
desc.
desc.
desc.
double
targetModel
VARIABLES
leavesInfected
A.10.2. strawberry::LeafProduction
Computes daily production of new leaves
PARAMETERS
productionRate
0.1
double
desc.
VARIABLES
value
145
A.11.2. UniSim::AsymptoticDecreasing
Asymptotic curve which begins at a value of max at x=0and decreases to min as a lower
asymtote ar large x. The slope parameter determines the curvature
PARAMETERS
x
min
max
slope
0.5
double
VARIABLES
value
A.11.3. UniSim::AsymptoticIncreasing
Asymptotic curve which begins at a value of min at x=0and increases to max as an upper
asymtote ar large x. The slope parameter determines the curvature
PARAMETERS
x
min
max
slope
0.5
double
VARIABLES
value
A.11.4. UniSim::Calendar
The Calendar model keeps track of the date. Since latitude is one of its parameters, it also
knows of the current day length. Solar elevation is calculated every time the hour of the day is
set by a tick of the global clock object. For example,
146
#include <usbase/clock.h>
double hour = 12.5; // Half-past noon
clock()->doTick(hour);
PARAMETERS
latitude
52
initialDate
1/1/2000
initialTimeOfDay
0:0:0
timeStep
timeUnit
timeStepOffset
-1
VARIABLES
date
date
timeOfDay
time
dateTime
datetime
timeStepSecs
double
totalTimeSteps
int
totalTime
int
totalDays
double
dayOfYear
int
day
int
month
int
year
int
hour
int
Current date.
Current time of day.
Current date and time.
Duration of timeStep in seconds.
Total number of time steps performed since beginning of simulation.
Total time, in units determined by timeUnit.
passed since beginning of simulation.
Total days passed since beginning of simulation.
Day number in year, also known as Julian day.
Current day in month (1..31).
Current month (1..12).
Current year.
Current hour of the day (0..23).
147
minute
int
second
int
dateAsReal
double
dayLength
double
sinb
double
sinLD
double
cosLD
double
A.11.5. UniSim::CrossTab
Output class. Description pending
PARAMETERS
fileName
output.txt
A.11.6. UniSim::DayDegrees
This is a standard day-degree model. It obtains the daily average temperature from the weather
object, which must exist as Model named weather having a pull variable named Tavg. The
daily increment in day-degrees increases linerly above T0 until Topt. Above Tops it decreases
linearly until Tmax.
The DayDegree model is derived from the PhysiologicalTime base class, like the
alternatives: Days, HydroThermalTime, LactinTime and PhotoThermalTime. They
all start updating right from the beginning, or when triggered by a child model, for example a
TriggerByDate model.
PARAMETERS
T0
Topt
100
Tmax
100
VARIABLES
step
double
148
total
double
A.11.7. UniSim::Days
This model has the same pull variables as the DayDegrees model but it works in simple
chronological time counting every day as just that, one day.
VARIABLES
step
double
total
double
A.11.8. UniSim::Exponential
Simple exponential growth model, y = exp(rt ), where t is taken from the nearest model called
time.
PARAMETERS
initialValue
0.05
growthRate
VARIABLES
value
double
increment
double
A.11.9. UniSim::Fixed
Often used for test purposes, or an initial version of a model, a Fixed model sets up fixed
values for chosen parameters, and push and pull variables. The only type of values currently
supported is double. Note that these artifical parameters and variables are not created until
initialize() of Fixed is called. This is unlike their real counterparts which are always
created in the models constructor
PARAMETERS
parameters
()
149
A.11.10. UniSim::FunctionalResponseGB
The Gutierrez-Baumgaertner functional response model, including the energy budget for
egestion and respiration
PARAMETERS
apparancy
resourceDensity
100
demand
egestionRatio
respiration
The apparancy of the resource, also known as attack rate or search rate.
The density of the resource (prey, host).
The finite demand rate of the consumer (predator,
parasitoid) population.
Egestion fraction of consumption.
Demand to cover respiration costs.
VARIABLES
supply
double
sdRatio
double
totalDemand
double
totalSupply
double
egestion
double
attacksPerHost
double
numHostsAttacked
double
propHostsAttacked
double
The net supply obtained (net resource consumption, parasitoids infected [0; demand].
The supply/demand ratio [0;1].
Total demand obtained to cover net supply, egestion
and respiration.
Total supply obtained to cover net supply, egestion
and respiration.
Amount of totalSupply lost to egestion.
Amount of totalSupply lost to egestion.
Amount of totalSupply lost to egestion.
Amount of totalSupply lost to egestion.
A.11.11. UniSim::HydroThermalTime
Hydrothermal time accounts for temperature and soil water potential at the same time. In this
implementation the daily increment, as calculated by the DayDegrees model, is set to zero if
soil water potential is less than the threshold, otherwise the daily increment is unaltered. A Model
named weather with a pull variable named SWP must exist to supply HydroThermalTime
with soil water potential.
PARAMETERS
T0
Topt
100
Tmax
100
150
T
SWP0
SWPTopt
100
Kt
weather[Tavg].
Soil water potential threshold (MPa).
Temperature optimum (C). Above this value, the
soil water potential threshold increases linearly by
Kt.
Rate of increase (MPa/C) in soil water potential
threshold above SWPTOpt.
VARIABLES
step
double
total
double
swpThreshold
double
A.11.12. UniSim::Inachis
A stage-structured model of the Nymphalid butterfly Inachis io.
PARAMETERS
sexRatio
0.5
eggProduction
100
Proportion females.
Lifetime egg production of one female.
A.11.13. UniSim::Infection
Multi-way infection based upon Predation model.
PARAMETERS
apparencyMatrix
empty string
File with references to predator demands and apparency value for each predator x prey combination.
A.11.14. UniSim::InsectLifeCycle
A stage-structured insect model. Under development
VARIABLES
eclosedReproductiveAdults
double
151
adultsToHibernation
double
deadAdults
double
A.11.15. UniSim::LactinTime
This is the physiological time scale of Lactin et al. (reference to be added). It pulls the daily
average temperature from the weather object just like the DayDegrees model. The equation
used to calculate the daily increment in physiological time is exp(ax) exp(ab (b x) c) + d,
where x is daily average temperature.
PARAMETERS
a
0.13
42
-0.1
Equation parameter.
Equation parameter.
Equation parameter.
Equation parameter.
VARIABLES
step
double
total
double
A.11.16. UniSim::Map
Creates output as an animated map. The output element must hold exactly one Trace element.
PARAMETERS
fileName
output.txt
range
(0 100)
steps
log10
no
152
A.11.17. UniSim::PhotoThermalTime
Photothermal time accounts for temperature and day length at the same time. In this implementation the daily increment, as calculated by the DayDegrees model, is multiplied by day length
in hours (acquired from the calendar object) divided by 24 hours.
PARAMETERS
T0
Topt
100
Tmax
100
VARIABLES
step
double
total
double
A.11.18. UniSim::Plot
Output class. Description pending
PARAMETERS
title
empty string
logy
no
ymin
NA
ymax
NA
penWidth
symbolSize
A.11.19. UniSim::Predation
Multi-way predation based upon FunctionalResponseGB model.
PARAMETERS
153
empty string
File with references to predator demands and apparency value for each predator x prey combination.
A.11.20. UniSim::RandomLognormal
The model maintains a random variable with a log-normal distribution.
PARAMETERS
minValue
NA
maxValue
NA
maxTries
100
mean
10
sd
double
Random value.
VARIABLES
value
A.11.21. UniSim::RandomNormal
The model maintains a random variable with a normal distribution.
PARAMETERS
minValue
NA
maxValue
NA
maxTries
100
mean
10
sd
double
Random value.
VARIABLES
value
A.11.22. UniSim::RandomPoisson
The model maintains a random variable with a Poisson distribution.
PARAMETERS
minValue
NA
maxValue
NA
154
maxTries
100
mean
10
double
Random value.
VARIABLES
value
A.11.23. UniSim::RandomUniform
The model maintains a random variable with uniform (i.e. flat) distribution.
PARAMETERS
minValue
NA
maxValue
NA
maxTries
100
double
Random value.
VARIABLES
value
A.11.24. UniSim::Range
The model produces equally spaced numbers inside a [min,max] range.
PARAMETERS
progress
min
max
100
scale
linear
steps[progress].
Minimum value in range.
Maximum value in range.
Scale is either linear or log10. With a log10
scale, min=-2 and max=3, values in the range
[0.01,1000] will result.
VARIABLES
value
double
A.11.25. UniSim::Records
A Records model reads input from a text file formatted in columns with labels in the first line.
Columns can be separated by spaces or tab characters. Labels may not contain spaces. A pull
variable will be created for every column in the input file, named after the column label. There
can be more than one Records model present in a simulation.
Columns named date and time have special meanings, as they are used to synchronize
155
the readings from the input file with the calendar model. If you have either a date or a time
column, or both, then the calendar model will be reset to the time indicated in the first line of
records, before the simulation begins. While this is the behaviour usually wanted, you can also
change this by setting imposeInitialDateTime to no.
The pull variables for date and time are mostly used for test purposes. If you need to know
about the current date and time of day, you should pull this information from the calender
model. See page 145.
PARAMETERS
fileName
records.txt
fileLocation
input
imposeInitialDateTime
yes
randomizeInitialYear
no
VARIABLES
currentDateTime
datetime
nextDateTime
datetime
firstDateTime
datetime
lastDateTime
datetime
currentDate
date
nextDate
date
currentTime
time
nextTime
time
A.11.26. UniSim::RunIteratorFixed
The model increments its iteration counter for every update. Its value remains true as long
as iteration numIterations.
PARAMETERS
numIterations
10
156
VARIABLES
value
bool
iteration
int
A.11.27. UniSim::Scenarios
The Scenarios model is used to iterate through several parameter settings. Description pending
PARAMETERS
scenarios.txt
iteration
int
numIterations
int
value
bool
fileName
VARIABLES
A.11.28. UniSim::Scheduled
A Scheduled model produces canned data which are derived from a list of time value pairs,
e.g., ((10.2 14.6) (45.1 32.3) (57.1 24.43)). Values are interpolated from the
current time which is taken from the nearest model called time. At times outside the range
covered by the list (outside [10.2;57.1], in this case) values are extrapolated (to 14.6 or 24.43, in
this case).
PARAMETERS
empty string
value
double
increment
double
Current value.
Increment in value during the latest time step.
schedule
VARIABLES
A.11.29. UniSim::SensitivityAnalysis
Integrator class. Description pending
PARAMETERS
maxSteps
100
factor
-1
description.
description.
157
relative
-1
absolute
-1
days
10
seconds
60
description.
description.
description.
description.
VARIABLES
stepNumber
int
progress
double
runNumber
int
A.11.30. UniSim::Stage
The Stage model implements a distributed delay (Manetsch 1976, Vansickle 1977). The implementation follows the original FORTRAN code of Abkin & Wolf (1976). The two parameters
duration and k determine the average and variance of stage duration with variance equal to
duration2 / k2. The time scale used by the Stage model is determined by the nearest model
called time.
PARAMETERS
k
30
duration
100
growthRate
sdRatio
instantMortality
instantLossRate
phaseInflow
inflow
initialInflow
158
0
value
double
number
double
inflowTotal
double
outflowTotal
double
phaseInflowTotal
double
phaseOutflowTotal
double
growthIncrement
double
phaseOutflow
latestInflow
QVector<double>
double
outflow
double
timeStep
double
phaseOutflowProportion
VARIABLES
A.11.31. UniSim::StageAndPhase
The StageAndPhase model simulates a population undergoing two processes at the same, for
instancephysiological development (ageing) and incubation (after being infected). The discern
the two, the first is called a stage and the second, a phase. Phase change is characterisedby the
parameters phaseL and phaseK with the same meaning as L and k in the Stage class.
PARAMETERS
k
30
duration
100
growthRate
sdRatio
159
instantMortality
instantLossRate
phaseInflow
phaseK
30
phaseDuration
100
inflow
timeStep
phaseTimeStep
VARIABLES
value
double
number
double
inflowTotal
double
outflowTotal
double
phaseInflowTotal
double
phaseOutflowTotal
double
growthIncrement
double
phaseOutflow
QVector<double>
QVector<double>
QVector<double>
latestInflow
outflow
A.11.32. UniSim::StageDemand
This model calculates the growth demand of the stage, identified by stage, which must be of
type UniSim::Stage.The stages growthDemand method is used for the calculation.
PARAMETERS
stage
empty string
160
VARIABLES
value
double
A.11.33. UniSim::Steps
Integrator class. Description pending
PARAMETERS
maxSteps
100
description.
stepNumber
int
progress
double
runNumber
int
VARIABLES
A.11.34. UniSim::Sum
Calculates sum of variables supplied as a list of references. The variables must all be of
type double.
PARAMETERS
toAdd
empty string
double
VARIABLES
value
A.11.35. UniSim::Table
Output class. Description pending
PARAMETERS
fileName
output.txt
A.11.36. UniSim::TimeLimited
Integrator class. Description pending
PARAMETERS
maxTime
30
description.
int
VARIABLES
stepNumber
161
progress
double
runNumber
int
A.11.37. UniSim::TriggerByDate
The TriggerByDate model can be used by other models to trigger changes in their
behaviour.
PARAMETERS
fromDate
1/1/1900
dateShift
toDate
1/1/1900
frequency
Yearly
triggerAtReset
yes
VARIABLES
value
bool
A.11.38. UniSim::Weather
This Weather model simply supplies a daily reading from a Records child model. If the
records file contains a column named Tavg then that colum is used. Otherwise, if columns named
Tmin and Tmax are present then Tavg is calculated as the average of those
VARIABLES
Tavg
double
162
A.12. vg plugin
Virtual greenhouse.
Authors: Oliver Krner, AgroTech, Denmark.
Niels Holst, Aarhus University, Flakkebjerg, Denmark.
A.12.1. vg::AirInfiltration
Desc
PARAMETERS
timeStepSecs
height
roofRatio
sideRatio
windspeed
screensAirTransmission
leakage
calendar[timeStepSecs].
construction[height].
construction[roofRatio].
construction[sideRatio].
environment[windspeed].
screens[airTransmission].
0.5
double
VARIABLES
value
A.12.2. vg::BlackoutScreenController
Desc
PARAMETERS
fromTime
0:0:0
toTime
0:0:0
maxSignalHighHumidity
0.95
radiationThreshold
followEnergyScreen
yes
time
NA
radiation
A.12. vg plugin
isHumidityHigh
163
no
climate/humidity[isHigh].
double
VARIABLES
signal
A.12.3. vg::BoundaryLayerResistance
Desc
PARAMETERS
windSpeed
ventilation
environment[windspeed].
greenhouse/ventilation[value].
VARIABLES
value
double
A.12.4. vg::ControlElement
Desc
PARAMETERS
signal
timeStepSecs
initState
rate
0
0.1
..[signal].
calendar[timeStepSecs].
Initial value of state.
Rate at which state approaches signal (per
minute).
VARIABLES
state
course
double
int
A.12.5. vg::ControlElementAsym
Desc
PARAMETERS
signal
timeStepSecs
initState
..[signal].
calendar[timeStepSecs].
Initial value of state.
164
rateUp
0.1
rateDown
0.01
VARIABLES
state
course
double
int
A.12.6. vg::CoverDew
Desc
PARAMETERS
timeStepSecs
numTimeSteps
coverArea
groundArea
Tcover
mcIndoors
dewScreen
calendar[timeStepSecs].
calendar[totalTimeSteps].
greenhouse/construction[coverArea].
greenhouse/construction[groundArea].
../temperature[value].
climate/humidity[mc].
regulation/screens[dew].
double
VARIABLES
value
A.12.7. vg::CoverTemperature
Desc
PARAMETERS
Tindoors
Toutdoors
Tsky
windspeed
latcov
climate/temperature[value].
environment[temperature].
environment[skyTemperature].
environment[windspeed].
greenhouse/construction[latcov].
double
VARIABLES
value
A.12. vg plugin
165
A.12.8. vg::CoverVapourFlux
Desc
PARAMETERS
Tindoors
mcIndoors
diffuseRadiation
rbH2O
climate/temperature[value].
climate/humidity[mc].
climate/radiation[diffuse].
crop/rbH2O[value].
VARIABLES
double
kdiff
0.8
coverage
0.1
absorbedRadiation
temperature
double
double
surfaceMoistureContent
double
transpirationConductance
latentHeatFlux
double
dew
double
value
A.12.9. vg::Crop
Desc
PARAMETERS
VARIABLES
double
A.12.10. vg::CropLayer
Desc
PARAMETERS
Tindoors
mcIndoors
vpIndoors
vpdIndoors
climate/temperature[value].
climate/humidity[mc].
climate/humidity[vp].
climate/humidity[vpd].
166
diffuseRadiation
cropLai
lowerPipeHeatFlux
kDiff
riH2O
rbH2O
longWaveAbsorption
crop[kDiff].
crop/riH2O[value].
crop/rbH2O[value].
crop/radiationAbsorption[longWave].
absorbedRadiation
temperature
double
double
surfaceMoistureContent
transpirationConductance
latentHeatFlux
double
double
double
dew
double
climate/radiation[diffuse].
crop/growth[lai].
pipes/lower[heatFlux].
VARIABLES
A.12.11. vg::CropRadiationAbsorption
Desc
PARAMETERS
Tindoors
diffuseRadiation
screenTransmission
lampLongWaveEmission
lampShortWaveEmission
climate/temperature[value].
climate/radiation[diffuse].
regulation/screens[lightTransmission].
regulation/light/attributes[longWaveEmission].
regulation/light/attributes[shortWaveEmission].
longWave
double
shortWave
double
VARIABLES
A.12. vg plugin
167
A.12.12. vg::EnergyScreenBalance
Desc
PARAMETERS
indoorsDirectRadiation
indoorsTemperature
outdoorsTemperature
KCover
climate/radiation[direct].
climate/temperature[value].
environment[temperature].
construction[KCover].
double
VARIABLES
value
A.12.13. vg::EnergyScreenController
Desc
PARAMETERS
maxSignalHighHumidity
0.95
radiationThreshold
10
radiation
isHumidityHigh
no
double
VARIABLES
signal
A.12.14. vg::Environment
Desc
PARAMETERS
co2
350
windDirection
temperature
rh
radiation
diffuseRadiation
windSpeed
CO2 concentration(ppm).
Wind direction [0;360].
./records[Tair].
./records[RHair].
./records[GlobRad].
./records[DifRad].
./records[WindSpeed].
168
0
./records[Tsky].
directRadiation
double
vp
double
mc
double
skyTemperature
VARIABLES
A.12.15. vg::GreenhouseConstruction
Desc
PARAMETERS
width
50
length
50
height
roofRatio
sideRatio
windowLength
windowHeight
0.825
fractionWindows
0.078
alphaVentilationMax
latcov
44
Kcover
7.9
floorHec
glassType
single
lampType
HPSL
35
Width (m).
Length (m).
Height (m).
Roof/Side wall ratio (-).
Side ratio ? (-).
Window length (m).
Window height (m).
Fraction windows [0;1].
Max. ventilation opening (degrees).
Lat cover (degrees).
K value of greenhouse cover (W/m2/K).
Heat capacity of the floor (?).
Possible values: double, hortiplus, single.
Possible values: hpsl, led.
VARIABLES
iGlassType
int
iLampType
int
volume
double
groundArea
double
coverArea
double
averageHeight
double
A.12. vg plugin
169
A.12.16. vg::GreenhouseEnergetics
Desc
PARAMETERS
coverDew
screenDew
cropDew
ventilation
energyScreenState
longWaveLight
shortWaveLight
lampHeat
Toutdoors
Tfloor
cropLatentHeatFlux
KScreenEnergy
KCover
7.9
floorHec
5.2
greenhouse/cover/dew[value].
regulation/screens[dew].
crop[dew].
greenhouse/ventilation[value].
screens/energy/control[state].
light/attributes[longWaveEmission].
light/attributes[shortWaveEmission].
light/attributes[heatEmission].
environment[temperature].
floor/temperature[state].
crop[latentHeatFlux].
K-value for energy screen (W/m2/K).
K-value for greenhouse cover (W/m2/K).
Heat capacity of the floor (W/m2/K).
VARIABLES
energyBalance
double
heatCapacity
double
Tunheated
double
dewHeat
double
outdoorsHeat
double
floorHeat
double
A.12.17. vg::GreenhouseVentilation
Desc
VARIABLES
value
double
170
A.12.18. vg::HeatingDemand
Desc
PARAMETERS
Tminimum
energyBalance
heatCapacity
setpoints/temperature[minimum].
greenhouse/energetics[energyBalance].
greenhouse/energetics[heatCapacity].
VARIABLES
total
double
perPipe
double
A.12.19. vg::HumiditySetpoints
Desc
PARAMETERS
radiation
daylightThreshold
maxRHDay
10
maxRHNight
90
minDeltaXBasis
80
environment[radiation].
Global radiation threshold for daylight (W/m2).
Setpoint for relative humidity during the day (%).
Setpoint for relative humidity during the night
(%).
Setpoint for delta x (g/m3).
VARIABLES
maxRH
double
minDeltaX
double
A.12.20. vg::IndoorsRadiation
Desc
PARAMETERS
glassType
sinb
outdoorsDirectRadiation
outdoorsDiffuseRadiation
construction[iGlassType].
calendar[sinb].
environment[directRadiation].
environment[diffuseRadiation].
A.12. vg plugin
171
0.79
direct
double
diffuse
double
diffuseTransmission
VARIABLES
A.12.21. vg::LampAttributes
Desc
PARAMETERS
lampType
capacity
40
construction[iLampType].
Capacity of installed lamps (W/m2).
ballastCorrection
heatEmission
double
longWaveEmission
double
shortWaveEmission
parEmission
double
energyUse
double
VARIABLES
double
A.12.22. vg::LightController
Desc
PARAMETERS
onDay
300
offDay
60
onTime
offTime
0:0:0
NA
onRadiation
offRadiation
20
day
time
NA
172
0
environment[radiation].
signal
double
signalDay
bool
signalTime
bool
signalRadiation
bool
radiation
VARIABLES
A.12.23. vg::MicroclimateHumidity
Desc
PARAMETERS
timeStepSecs
mcOutdoors
height
ventilation
temperature
mcCropSurface
cropTranspirationConductance
screenState
Tscreen
Tcover
maxRH
minDeltaX
calendar[timeStepSecs].
environment[mc].
greenhouse/construction[averageHeight].
greenhouse/ventilation[value].
../temperature[value].
crop[surfaceMoistureContent].
crop[transpirationConductance].
screens/energy/control[state].
screens/energy/temperature[value].
greenhouse/cover/temperature[value].
setpoints/humidity[maxRH].
setpoints/humidity[minDeltaX].
VARIABLES
rh
double
prevRh
double
vp
double
vpd
double
mc
double
moistureDeficit
double
isHigh
bool
A.12.24. vg::MicroclimateTemperature
Desc
A.12. vg plugin
173
PARAMETERS
energyBalance
heatCapacity
pipesHeatFlux
VARIABLES
value
double
A.12.25. vg::PidControl
Desc
PARAMETERS
direction
ceiling
timeStepSecs
actualValue
20
targetValue
20
initSignal
Kp
Ti
1000000
Td
double
pipeType
s51
heatingDemand
Tunheated
energyScreenCourse
Tminimum
Tindoors
actualTpipe
pipeLength
1.822
VARIABLES
signal
A.12.26. vg::Pipe
Desc
PARAMETERS
setpoints/temperature[minimum].
climate/temperature[value].
./control[state].
Pipe length (m/m2).
174
70
signal
double
heatFlux
double
calendar[timeStepSecs].
heatFlux
double
energyUsed
double
TmaxPipe
VARIABLES
A.12.27. vg::Pipes
Desc
PARAMETERS
timeStepsSecs
VARIABLES
A.12.28. vg::ProportionalControl
Desc
PARAMETERS
direction
ceiling
actualValue
20
targetValue
20
gapMultiplier
pBand
maxSignal
100
yes
signalNotNegative
VARIABLES
signal
double
Response between zero and maxSignal, increasing with increasing difference between actualValue and targetValue, positive or negative according to direction of change and setting of signalNotNegative flag.
A.12. vg plugin
175
A.12.29. vg::ScreenDew
Desc
PARAMETERS
timeStepSecs
numTimeSteps
state
Tscreen
mcIndoors
calendar[timeStepSecs].
calendar[totalTimeSteps].
../control[state].
../temperature[value].
climate/humidity[mc].
double
temperature
double
airTransmission
double
lightTransmission
dew
double
double
VARIABLES
value
A.12.30. vg::Screens
Desc
VARIABLES
A.12.31. vg::ScreenTemperature
Desc
PARAMETERS
Tindoors
Tcover
climate/temperature[value].
greenhouse/cover/temperature[value].
double
VARIABLES
value
A.12.32. vg::ScreenTransmission
Desc
PARAMETERS
screenState
../control[state].
176
ratio
0.3
double
VARIABLES
value
A.12.33. vg::ShadeScreenController
Desc
PARAMETERS
maxSignalHighHumidity
0.95
radiationThreshold
10
temperatureThreshold
28
tolerance
2000
followEnergyScreen
yes
radiation
temperature
isHumidityHigh
no
double
VARIABLES
signal
A.12.34. vg::StomatalResistance
Desc
PARAMETERS
rh
co2
PgcMol
rbH2O
climate/humidity[rh].
climate/co2/[value].
crop/photosynthesis[PgcMol].
crop/rbH2O[value].
double
VARIABLES
value
A.12. vg plugin
177
A.12.35. vg::TemperatureSetpoints
Desc
PARAMETERS
humidityIncrement
humidityDecrement
setMinimum
./humidityIncrement[signal].
./humidityDecrement[signal].
20
setMaximum
27
VARIABLES
minimum
double
maximum
double
A.12.36. vg::VentilationByTemperatureDiff
Desc
PARAMETERS
indoorsTemperature
outdoorsTemperature
ventilationMax
climate/temperature[value].
environment[temperature].
../maximum[signal].
double
VARIABLES
signal
A.12.37. vg::VentilationController
Desc
PARAMETERS
windSideProportion
0.75
indoorsTemperature
178
outdoorsTemperature
maxTemperature
environment[temperature].
windSpeed
byTemperature
byTemperatureDiff
byHumidity
setpoints/temperature[maximum].
environment[windspeed].
./byTemperature[signal].
./byTemperatureDiff[signal].
maxSignal
./byHumidity[signal].
./maximum[signal].
VARIABLES
signal
double
leeSideSignal
double
windSideSignal
double
A.12.38. vg::VentilationLatentEnergyBalance
Desc
PARAMETERS
timeStepSecs
groundArea
height
ventilation
mcIndoors
mcOutdoors
calendar[timeStepSecs].
greenhouse/construction[groundArea].
greenhouse/construction[averageHeight].
greenhouse/ventilation[value].
climate/humidity[mc].
environment[mc].
VARIABLES
value
double
totalLoss
double
A.12.39. vg::VentilationMax
Desc
PARAMETERS
radiation
thresholdRadiation
dayMax
10
environment[radiation].
Threshold radiation day vs. night (W/m2).
100
A.12. vg plugin
nightMax
179
5
double
VARIABLES
signal
A.12.40. vg::WindowsVentilation
Desc
PARAMETERS
Tindoors
Toutdoors
windspeed
windowLength
alphaVentilationMax
fractionWindows
ventilationLeeSide
ventilationWindSide
construction[fractionWindows].
regulation/ventilation/leeSideControl[state].
regulation/ventilation/windSideControl[state].
double
climate/temperature[value].
environment[temperature].
environment[windspeed].
construction[windowLength].
construction[alphaVentilationMax].
VARIABLES
value
180
References
Abkin MH & Wolf C. Computer library for agricultural systems simulation. Distributed delay
routines: DEL, DELS, DELF, DELLF, DELVF, DELLVF, pages 1-88. Tech. Rep. CLASS-8
(1976), Department of Agricultural Economics, Michigan State University.
Alados I & Alados-Arboledas L. Validation of an empirical model for photosynthetically active
radiation. International Journal of Climatology 19, 1145-1152 (1999).
Banks RB & Herrera FF. Effect of wind and rain on surface reaeration. Journal of the
Hydraulics Division 103, 489-504 (1977).
Benjamin LR & Park SE. The Conductance model of plant growth and competition in
monoculture and species mixtures: a review. Weed Research 47, 284-298 (2007).
Boyd CE & Teichert-Coddington D. Relationship between wind speed and reaeration in small
aquaculture ponds. Aquacultural Engineering 11, 121-131 (1992).
Crusius J & Wanninkhof R. Gas transfer velocities measured at low wind speed over a lake.
Limnology and Oceanography 48, 1010-1017 (2003).
Deacon 1977. Gas transfer to and across an air-water interface. Tellus 29, 363-374 (1977).
Emerson S. Gas exchange rates in small Canadian shield lakes. Limnology and Oceanography
20, 754-761 (1975).
Gelda RK, Auer MT, Effler SW, Chapra SC & Storey ML. Determination of reaeration coefficients: whole-lake approach. Journal of Environmental Engineering 122, 269-275 (1996).
Gelda RK & Effler SW. Estimating oxygen exchange across the airwater interface of a
hypereutrophic lake. Hydrobiologia 487, 243-254 (2002).
Holst N, Lang A, Gabor LOtto M. Increased mortality is predicted of Inachis io larvae caused
by Bt-maize pollen in European farmland. Ecological Modelling, 250, 126-133 (2013).
Jellison R & Melack JM. Meromixis in hypersaline Mono Lake, California. 1. Stratification
and vertical mixing during the onset, persistence, and breakdown of meromixis. Limnology and
Oceanography 38, 1008-1019 (1993).
Kropff MJ & van Laar HH. Modelling Crop-Weed Interactions, pages 1-274. CAB International, Wallingford, UK and International Rice Research Institute, Manila, The Philippinnes, 1993.
Liboriussen L, Landkildehus F et al.. Global warming: Design of a flow-through shallow lake
mesocosm climate experiment. Limnol. Oceanogr.: Methods 3, 1-9 (2005).
Liboriussen L, Lauridsen TL F et al.. Effects of warming and nutrients on sediment community
respiration in shallow lakes: an outdoor mesocosm experiment. Freshwater Biology ?, ?-?
181
182
References
(2010).
Liss PS. Processes of gas exchange across an air-water interface. Deep Sea Research and
Oceanographic Abstracts 20, 221-238. (1973).
Livingstone DM & Imboden DM. The non-linear influence of wind-speed variability on gas
transfer in lakes. Tellus B 45, 275-295 (1993).
Manetsch TJ. Time-varying distributed delays and their use in aggregate models of large
systems. IEEE Transactions on Systems, Man and Cybernetics 6, 547-553 (1976).
Mattingly GE. Experimental study of wind effects on reaeration. Journal of the Hydraulics
Division 103, 311-323 (1977).
OConnor DJ. Wind effects on gas-liquid transfer coefficients. Journal of Environmental
Engineering 109, 731-752 (1983).
Odum HT. Primary production in flowing waters. Limnology and Oceanography 1, 102-117
(1956).
Park SE, Benjamin LR, Aikman DP & Watkinson AR. Predicting the growth interactions
between plants in mixed species stands using a simple mechanistic model. Annals of Botany 87,
523-536 (2001).
Portielje R & Lijklema L. The effect of reaeration and benthic algae on the oxygen balance of
an artificial ditch. Ecological Modelling 79, 35-48 (1995).
Serret P, Robinson C, Fernndez E, Teira E, Tilstone G & Prez V. Predicting plankton net
community production in the Atlantic Ocean. Deep Sea Research Part II: Topical Studies in
Oceanography 56, 941-953. (2009).
Storkey J. Modelling assimilation rates of 14 temperate arable weed species as a function of the
environment and leaf traits. Weed Research 45, 361-370 (2005).
Udo SO & Aro TO. Global PAR related to global solar radiation for central Nigeria. Agricultural and Forest Meteorology 97, 21-31 (1999).
Vansickle J. Attrition in distributed delay models. IEEE Transactions on Systems, Man and
Cybernetics 7, 635-638 (1977).
Wanninkhof RIK, Ledwell JR & Broecker WS. Gas exchange-wind speed relation measured
with sulfur hexafluoride on a lake. Science 227, 1224-1226 (1985).
Wetzel RG. Limnology. Lake and River Ecosystems. Academic Press, San Diego, 2001.
Index
BoundaryLayerResistance, 163
byHumidity, 178
byTemperature, 178
byTemperatureDiff, 178
c, 119, 121, 151
c1, 115
c2, 115
Calendar, 145
capacity, 171
CarryingCapacity carryingCapacity, 134,
137
CH2ORequirement, 128
co2, 167, 176
CO2Assimilation, 124, 126, 128, 129
Community, 117, 125, 132
Competition, 132
CompetitionModel, 132
CompetitiveInhibition, 133
conductance, 117
ControlElement, 163
ControlElementAsym, 163
cosLD, 147
course, 163, 164
coverage, 165
coverArea, 164, 168
CoverDew coverDew, 164, 169
CoverTemperature, 164
CoverVapourFlux, 165
Crop, 111, 165
cropDew, 169
cropEffectOnEmergence, 114
cropLai, 166
cropLaiExp, 114
cropLatentHeatFlux, 169
CropLayer, 165
CropRadiationAbsorption, 166
crops, 113
cropTranspirationConductance, 172
CrossTab, 147
CumulativeEmergence, 143
currentDate, 155
183
Index
184
currentDateTime, 155
currentPartition, 128
currentTime, 155
d, 151
dailyEmergenceDensity, 114
dailyEmergenceRatio, 114
dailyEmergenceRatioPotential, 115
dailyFecundity, 142
dailyLoss, 142
dailyRainfall, 142
date, 146
dateAsReal, 147
dateMax, 121
dateShift, 121, 161
dateTime, 146
day, 112, 127, 146, 171
DayDegrees, 147
dayLength, 147
daylightThreshold, 170
dayMax, 178
dayOfYear, 146
Days days, 148, 157
deadAdults, 151
demand, 149
DemandRate, 135
density Density density, 129, 132, 135, 137,
138, 140, 141
DensityActivityCoefficient, 135
DepositionFlush, 120
DepositionMonotonicSampled, 120
DepositionMonotonicWeibull, 120
dew, 165, 166, 175
dewHeat, 169
dewScreen, 164
diffuse, 171
diffuseRadiation, 165, 166, 167
diffuseTransmission, 171
direct, 171
direction, 173, 174
directRadiation, 168
distance, 122
distanceExp, 122
distanceMin, 122
dormant, 114
dormantInflow, 114
dose, 121
Index
fractionWindows, 168, 179
frequency, 161
fromDate, 161
fromTime, 162
FunctionalResponseGB, 149
fz, 118
g, 116
gapMultiplier, 174
GeneralEffect, 134
GiniCoefficient, 132
glassType, 168, 170
GreenhouseConstruction, 168
GreenhouseEnergetics, 169
GreenhouseVentilation, 169
grossProduction, 124, 126, 128, 129
groundArea, 164, 168, 178
growthIncrement, 158, 159
GrowthRate growthRate, 126, 134, 137, 148,
157, 158
growthResp, 128, 130
gSini, 119
0, 126
harvestDay, 111
harvestMonth, 111
heatCapacity, 169, 170, 173
heatEmission, 171
heatFlux, 174
HeatingDemand heatingDemand, 170, 173
Height height, 126, 127, 162, 168, 172, 178
hmax, 126
hour, 146
humidityDecrement, 177
humidityIncrement, 177
HumiditySetpoints, 170
HydrodynamicSRScale, 137
HydroThermalTime, 149
iGlassType, 168
iLampType, 168
imposeInitialDateTime, 155
Inachis, 150
InactiveEgg, 141
increment, 148, 156
inDensity, 139
indoorsDirectRadiation, 167
IndoorsRadiation, 170
indoorsTemperature, 167, 177
185
Infection, 144, 150
infectionRate, 144
inflow, 141, 157, 159
inflowAsDensity, 113
inflowAsDensityEqs, 113
inflowTotal, 158, 159
InhibitionConstant, 133
InhibitorConcentration, 133
initDay, 117
initial, 130
initialArea, 126
initialDate, 146
initialDensity InitialDensity, 113, 134, 137,
141
initialInflow, 157
initialN, 137
InitialResource, 132
InitialSubstrate, 133, 134, 135
initialTimeOfDay, 146
initialValue, 142, 148
initMonth, 117
initSignal, 173
initState, 163
initWeight, 117
inoculumDensity, 144
InsectLifeCycle, 150
instantLossRate, 157, 159
InstantMortality instantMortality, 112, 113,
114, 127, 157, 159
intercept, 127
intercom, 124
intrinsicRate, 137
irradiation, 118, 130
IsActive, 134
isHigh, 172
isHumidityHigh, 163, 167, 176
isInEarlyGrowth, 126
iteration, 156
k, 118, 157, 158
Kcover KCover, 167, 168, 169
kdiff kDiff, 165, 166
kDiffuse, 124
Kp, 173
KScreenEnergy, 169
Kt, 150
LA_per_plant, 118
186
LactinTime, 151
LagPhase, 134
lai LAI, 112, 113, 118, 124, 126, 129
laiCalendar, 112
LampAttributes, 171
lampHeat, 169
lampLongWaveEmission, 166
lampShortWaveEmission, 166
lampType, 168, 171
lastDateTime, 155
latcov, 164, 168
latentHeatFlux, 165, 166
latestInflow, 158, 159
latitude, 146
Leaf, 119
LeafProduction, 144
leakage, 162
leavesInfected, 144
leeSideSignal, 178
length, 168
lightAbsorption, 124, 126, 128, 129
LightController, 171
lightTransmission, 175
LightUseEfficiencyGivenTemp, 127
log10, 151
LogLogistic, 121
logy, 152
longWave, 166
longWaveAbsorption, 166
longWaveEmission, 171
longWaveLight, 169
LossB, 137, 140
LossN, 137, 140
lossRate, 141
lower, 121
lowerPipeHeatFlux, 166
Lz, 118
maintenanceCoeff, 128
maintenanceResp, 128, 129
Map, 151
Mass mass, 127, 129
max, 145, 154
maxAmax, 125
maxflow, 137
maximum, 177
MaximumVelocity, 135
Index
maxN, 140
MaxPopulations, 132
maxRH, 170, 172
maxRHDay, 170
maxRHNight, 170
maxSignal, 174, 178
maxSignalHighHumidity, 162, 167, 176
maxSR, 138
maxSteps, 156, 160
maxTemperature, 178
maxTime, 160
maxTries, 153, 154
maxValue, 153, 154
maxYield, 111
maxYieldLossPct, 111
mc, 168, 172
mcCropSurface, 172
mcIndoors, 164, 165, 175, 178
mcOutdoors, 172, 178
mean, 153, 154
MichaelisMentenConstant, 135
MicrobialCommunity, 132
MicroclimateHumidity, 172
MicroclimateTemperature, 172
min, 145, 154
minDeltaX, 170, 172
minDeltaXBasis, 170
minimum, 177
MinPopulations, 132
minute, 147
minValue, 153, 154
moistureDeficit, 172
month, 112, 127, 146
mortalities, 112
mortality, 139
MortalityRate, 134
MosquitoFecundity, 142
Mussel, 137
mussel_bed, 137
MusselGrowthRate, 137
n N, 118, 137, 140
netAllocation, 128, 130
nextDate, 155
nextDateTime, 155
nextTime, 155
nightMax, 179
Index
nonDormant, 114
Npeak, 122
number, 114, 158, 159
numHostsAttacked, 149
numIterations, 155, 156
numTimeSteps, 164, 175
offDay, 171
offRadiation, 171
offTime, 171
onDay, 171
onRadiation, 171
onsetFileName, 120
onTime, 171
Organ, 128
outdoorsDiffuseRadiation, 170
outdoorsDirectRadiation, 170
outdoorsHeat, 169
outdoorsTemperature, 167, 177, 178
outflow, 158, 159
outflowAsDensity, 113
outflowAsDensityEqs, 113
outflowTotal, 158, 159
parameters, 148
parDiffuse, 131
parDirect, 131
parEmission, 171
PARmin, 119
PartitioningFixed, 128
PartitioningFixedByStage, 129
parTotal, 131
pBand, 174
penWidth, 152
perPipe, 170
PgcMol, 176
phase, 118
phaseDuration, 159
phaseInflow, 157, 159
phaseInflowTotal, 158, 159
phaseK, 159
phaseOutflow, 158, 159
phaseOutflowProportion, 158
phaseOutflowTotal, 158, 159
phaseTimeStep, 159
Phenology, 129
phi, 117
PhotoThermalTime, 152
187
PidControl, 173
Pipe, 173
pipeLength, 173
Pipes, 174
pipesHeatFlux, 173
pipeType, 173
Plant, 117, 129
PlantGrowthStage, 112
Plot, 152
Pollen, 121
pollenDensity, 122
pollenDepositionRate, 122
pollenDepositionTotal, 122
PollenLossConstant, 122
PollenLossSampled, 123
Population, 134
Predation, 152
prevRh, 172
productionRate, 144
progress, 154, 157, 160, 161
projectedDeqs, 116
projectedMass, 116
projectedYieldLossPct, 116
propAllocatedPerPlant, 128
propHostsAttacked, 149
ProportionalControl, 174
proportionEggsInWater, 141
radiation, 162, 167, 170, 172, 176, 178
radiationThreshold, 162, 167, 176
radix, 125
randomizeInitialYear, 155
RandomLognormal, 153
RandomNormal, 153
RandomPoisson, 153
RandomUniform, 154
range Range, 151, 154
rate, 122, 163
rateDown, 164
rates, 123
rateUp, 164
ratio, 176
rbH2O, 165, 166, 176
Reaction, 135
Records, 154
relative, 157
resourceDensity, 149
188
respiration, 149
rh, 167, 172, 176
Richness, 132
riH2O, 166
roofRatio, 162, 168
Rotation, 113
RunIteratorFixed, 155
runNumber, 157, 160, 161
rvf, 141
S, 119
S0, 119
S60, 119
SalinityScale, 138
SalinitySRScale, 138
scale, 154
scatteringCoeff, 124
Scenarios, 156
schedule, 156
Scheduled, 156
screenDew ScreenDew, 169, 175
Screens, 175
screensAirTransmission, 162
screenState, 172, 175
ScreenTemperature, 175
screenTransmission ScreenTransmission,
166, 175
sd, 153
sdRatio, 149, 157, 158
SearchRate searchrate, 134, 138
second, 147
seconds, 157
seed_emergence, 143
SeedBank, 113
seedProdExp, 115
seedProdSlope, 115
seedsDropping, 116
SensitivityAnalysis, 156
Seq, 119
setMaximum, 177
setMinimum, 177
sexRatio, 141, 150
ShadeScreenController, 176
ShannonIndex, 132
shortWave, 166
shortWaveEmission, 171
shortWaveLight, 169
Index
sideRatio, 162, 168
signal, 163, 167, 172, 173, 174, 176, 177, 178,
179
signalDay, 172
signalNotNegative, 174
signalRadiation, 172
signalTime, 172
SimpsonIndex, 132
sinb, 147, 170
Sini, 119
sinLD, 147
skyTemperature, 168
slope, 121, 126, 127, 130, 145
slopeYieldLossPct, 111
Smax, 138, 139
Smin, 138, 139
sourceModel, 144
sowingDay, 111
sowingMonth, 111
SpeciesName, 134
SpecificLeafArea, 130
Stage stage, 157, 159
StageAndPhase, 158
StageDemand, 159
Starfish, 138
StarfishFeedingRate, 139
StarfishGrowthRate, 139
StarfishSalMortality, 139
state, 163, 164, 175
stdensity stDensity, 139, 139
step, 147, 148, 150, 151, 152
stepNumber, 157, 160
steps Steps, 151, 160
stgrowthRate, 139
StomatalResistance, 176
strawberry, 144
Substrate, 133, 134, 135
SubstratePDD, 133, 134, 135
Sum, 160
sum_sz, 117
supply, 139, 140, 149
SupplyDemandRatio, 135
surfaceMoistureContent, 165, 166
survival, 127
SWP, 143
SWP0, 150
Index
swpThreshold, 150
SWPTopt, 150
symbolSize, 152
sz, 118
T, 115, 147, 150, 152
T0, 147, 149, 152
Table, 160
targetModel, 144
TargetParameter, 134
TargetPopulations, 133, 134
targetValue, 173, 174
Tavg, 115, 130, 143, 161
Tcover, 164, 172, 175
Td, 173
Tday, 130
temperature, 139, 140, 165, 166, 167, 172,
175, 176
TemperatureScale, 140
TemperatureSetpoints, 177
TemperatureStScale, 140
temperatureThreshold, 176
testMode, 126
Tfloor, 169
theta, 118, 119
thin, 140
thinning, 140
thresholdRadiation, 178
Ti, 173
time, 162, 171
TimeLimited, 160
timeOfDay, 146
timeStep, 146, 158, 159
timeStepOffset, 146
timeStepSecs, 146, 162, 163, 164, 172, 173,
175, 178
timeStepsSecs, 174
timeUnit, 146
Tindoors, 164, 165, 166, 173, 175, 179
title, 152
tm, 119, 126
Tmax, 147, 149, 152
TmaxPipe, 174
Tminimum, 170, 173
toAdd, 160
toDate, 161
tolerance, 176
189
Topt, 147, 149, 152
total, 120, 121, 148, 150, 151, 152, 170
total_sz, 118
totalDays, 146
totalDemand, 149
totalEggsInflow, 141
totalEmergenceDensity, 114
totalEmergenceRatio, 114
totalLoss, 178
totalSupply, 149
totalTime, 146
totalTimeSteps, 146
totalWeight, 118
toTime, 162
Toutdoors, 164, 169, 179
transpirationConductance, 165, 166
triggerAtReset, 161
TriggerByDate, 161
ts, 119
Tscreen, 172, 175
Tsky, 164
Tsum, 112, 115
Tunheated, 169, 173
UniSim, 145
upper, 121
useTemperature, 119
value, 120, 121, 122, 123, 124, 125, 127, 128,
129, 130, 137, 138, 139, 140, 142, 144,
145, 148, 153, 154, 156, 158, 159, 160,
161, 162, 163, 164, 165, 167, 169, 173,
175, 176, 178, 179
values, 129
Velocity, 133, 134, 135
VelocityPDD, 133, 134, 135, 136
ventilation, 163, 169, 172, 178
VentilationByTemperatureDiff, 177
VentilationController, 177
VentilationLatentEnergyBalance, 178
ventilationLeeSide, 179
ventilationMax VentilationMax, 177, 178
ventilationWindSide, 179
vg, 162
volume, 168
vp, 168, 172
vpd, 172
vpdIndoors, 165
190
vpIndoors, 165
waterLevel WaterLevel, 142, 142
waterLevelThreshold, 142
Weather, 115, 118, 130, 143, 161
Weed, 115
weedExchangeRate, 111
weight, 118
width, 168
windDirection, 167
windowHeight, 168
windowLength, 168, 179
WindowsVentilation, 179
windSideProportion, 177
windSideSignal, 178
windSpeed windspeed, 162, 163, 164, 167,
178, 179
writeTestOutput, 124
x, 145
year, 146
yearlyEmergenceRate, 114
yearlyMortalityRate, 114
ymax, 152
ymin, 152
ZeroOrderRateConstant, 135
ZeroOrderReaction, 135
Index