Mathematical expressions: expressing mathematical equations in Simile

This section focuses on how to express mathematical expressions in Simile as diagram symbols and an expression in Simile.

Conditional expressions

Sometimes, the usual mathematical expressions aren’t enough. For example, although it’s easy to say that one variable is proportional to another, by multiplying it by a constant, it’s much harder to say that the value of a variable depends on whether another variable is above or below a threshold value. Simile’s equation language provides if...then statements as a way of handling these either / or situations. Using these conditional statements, alternative expressions are used depending on the result of evaluating a condition. For example, the overflow of water from a tank will be high if the tank is full, and zero otherwise.

Conditional statements are made up of several parts, some of which (the middle elseif parts) are optional. The general form is:

if C1 then E1 elseif C2 then E2 ..... else En

where:

  • C1, C2,... are some conditions
  • E1 is the expression used if the first condition is true
  • E2 is the expression used if the second condition is true and the first is not
  • En is the expression used if all the conditions are false

For example, if the maximum volume of the tank is stored in a variable called “Maximum”, and the amount of water in the tank is stored in a variable called “Amount” then the following expression could be used to calculate the overflow rate: “if Amount>=Maximum then 100 else 0”. In this case “Amount>=Maximum” is the condition, and 100 is the expression when the condition is true (the tank is full) and 0 is the expression when the condition is false (the tank is less than full).

Notes:

  • The elseif part is optional, and you can have as many of them as you like.
  • You must have the final else part.
  • Each condition has three parts: any expression, a comparison operator (<, >, =), and any expression.

Differential equations

At heart, many Systems Dynamics models consist of differential equations, each one represented by a compartment / flow structure, though you don’t need to know this to set up the model. On the other hand, if you’re given the differential equations, it is very straightforward to enter these into the model.

For example, given the differential equation:

dx/dt = x/20 - x2/2000

you know two things:

  1. there is a state variable, x, whose value changes through time; and
  2. the rate of change of the value of x depends only on the value of x itself.

With this information, you can deduce that it is necessary to have one compartment, labelled “x”, one flow, labelled, say “dx by dt”, and an influence arrow from the compartment to the flow.

Differential equation model diagram

The equation can then be entered, exactly as given, into the equation dialgoue box for the flow. In Simile’s equation language, this is written “x/20-x^2/2000”. To run the model, and solve the differential equation, it is also necessary to know the initial value of x, i.e. the value at time zero. This is not given by the equation itself, but is usually reported, often described as the initial conditions. Enter this value in the equation bar (or equation dialogue box) for the compartment — in this example, “1” works well.

To complete this simulation, run the model for 200 time units, and display (plot) the values of the compartment and of the flow on separate graphs. Note that the value you enter for “dt” in the run control, by default “0.1”, is used as the time step for performing numerical integration by the Euler method. This particular equation is not very sensitive to the time step used, but if very rapid rates of change are encountered, it can be necessary to experiment with reducing the time step to find the optimum balance between speed of execution and numerical stability.

Differential equation model results

Note that in some mathematical notations, dx/dt is written as x with a dot above it, but the two mean exactly the same. Note also that the differential equation in this case can be broken into two parts, one positive contribution to the rate of change (an increase), x/20, and one negative contribution to the rate of change (a decrease), x2/2000. If this has a physical significance, two flows can be used, one flowing into the compartment and representing the positive contribution, and the other flowing out of the compartment and representing the negative contribution. Simile will automatically net the outflows off against the inflows in determining the overall rate of change.

Multipliers

Many ecological processes are influenced by several factors together. For example, plant growth may be influenced by temperature, radiation, and soil water content. It is often difficult to know how to combine the effect of these factors.

One method is to envisage each factor as having some optimum value: when all the influencing factors are at this optimum, then the process (e.g. growth) proceeds at some maximum rate. When a factor is not at its optimum value, then the rate of the process is reduced. Thus, a general solution is to use an expression of the form:

flow = flowmax*m1*m2*m3

where:

  • flow is the calculated flow rate
  • flowmax is the max flow rate if all influencing factors have their optimum values
  • m1, m2 etc are multipliers for each influencing factor (e.g. m1 could be the temperature multiplier)

To calculate the multipliers, you might use the abs function to find out the difference between a factor and its optimum value. You then need to scale the multiplier so that it lies between zero and one. Alternatively, suppose that plants do not grow at all below Tmin nor above Tmax. Then the following expression would work:

q=(Topt-Tmin)/(Tmax-Topt),
if ((T>Tmin)&&(T<Tmax)) then
(((T-Tmin)^q) * (Tmax-T)) / (((Topt-Tmin)^q) * (Tmax-Topt))
else
0

You may notice that the above expression involves an intermediate variable q. It is a valuable feature of Simile’s equation language that expressions can often be simplified by calculating a sub-expression that is used more than once and assigning it to an intermediate variable.

The expression is also formatted to make it easier to read. The equation dialogue box preserves the formatting you enter. It doesn’t affect the parsing of the equation, but it does make it easier for the user.

Using functions of time

It is often useful to be able to use current simulation time in your model: for example, you may want to incorporate a gradual increase in some external variable such as temperature. For this purpose, a special function called time is provided in Simile.

The time function has a value equal to the number of time units that has elapsed since the start of the simulation (which is assigned a time of zero). To help avoid any confusion, please note that it has nothing to do with the real-world time that elapses as the model runs. How long a simulation takes to run depends on how complex it is and how fast your computer is, amongst other factors, but none of these influences the time function. If you run a simulation for 100 time units, then the time function will increase from zero to 100 during the simulation. This may take 20 seconds of your time or it may take 20 minutes, depending as I say, on the model’s complexity and the speed of your computer.

You can use the time function in constructing expressions in Simile’s equation language. This gives enormous flexibility in constructing expressions. Perhaps the two most common uses are in drawing sketch graphs to illustrate how some external influence changes through time, and in constructing cycles, such as the repetition of the seasons year after year.

Cycles

Many environmental factors vary on a daily or an annual basis: e.g. temperature, radiation, evapotranspiration. It is desirable to be able to capture this if you want to capture the effect of the factor on the behaviour of your modelled system, and if the time-scale is appropriate.

Let’s assume that your time unit is the month (i.e. all your rates are expressed per month, and that simulation time is shown in month).

The function fmod is used to calculate remainders when doing division. For example, dividing 28 by 12, gives two with a remainder of four. This gives us a mathematical means to create a cycle. Dividing the time function by 12 and looking only at the remainder will give a series of numbers from zero to 11 in sequence again and again. We can use these as the month number (0=January, 1=February, 2=March and so on).

To return to the example used in illustrating the sketch graph, rainfall patterns repeat year after year. So we can modify the expression used in the equation for the sketch graph to use the fmod function as well as the time function. This looks like this: “graph(fmod(time(),12))”

In fact there are now easier ways to get data into a Simile model and have it repeat after a certain period of time. The sketch graph dialogue includes a pulldown menu with the caption "Out of range:" which gives a series of options for how to pick a value when the input value is outside the range covered by the graph. The options are:

  • Truncate, which means return the value at the nearest side of the graph,
  • Extrapolate, which means extend the last (or first) section of the sketch graph in a straight line to the required datapoint, or
  • Wraparound, which means that the range of values given by the graph repeats after the given input range to cover any input value.

Using the Wraparound option has the same effect as placing an "fmod()" function around the expression supplied to the graph function.

Sketch graphs

We can combine the use of the time function with the sketched graph. This is very useful when you have a historical record for some external factor, e.g. rainfall or temperature: the graph you sketch is a copy of the historical record.

For example, to use a sketch of how rainfall varies throughout the year in your model, you first create a variable called “rainfall”. Double-click on this variable to set its properties, and click on the “Graph” button. This opens the sketch pad window.

Enter the range on the X-axis, from a minimum of zero to a maximum of 12 which corresponds to one year, if the time unit is one month.(in general, the maximum value on the X-axis will correspond to the length of time you want the simulation to run for) Enter the range of the Y-axis from, for example, zero to 30, depending on how rainy your locality is.

Sketch a curve with perhaps two well-defined peaks, to enable you to see the response clearly when you run the model. Use the on-line help if you're unsure of how to draw the curve.

Click “OK” and return to the equation dialogue box. You’ll notice that the function name graph( ) has been entered in the equation. To complete the expression, use the time( ) function as its argument. The expression should read “graph(time())”.