2.2. The dynamic modelling framework

2.2.1. The dynamic modelling class

For dynamic (temporal) modelling, PCRaster comes with a predefined class. It will make it relatively simple to do time iterations, and to define inputs and outputs of a model. Open the file dynMod.py in your editor, on Microsoft Windows we recommend for instance the standard Python editor (IDLE) that comes with Python (available at Start, Programs, Python, IDLE). The script is the most basic script for dynamic modelling, it does only contain the statements that are needed for the control flow of the program. When you start a project, you can take this template and add statements to construct a model. But first run this ‘empty’ model.


Question: What does it print?

  1. It prints dots; each dot represents a second run time.

  2. Idem, each dot represents a time step.

Correct answers: b.

Feedback: None


When constructing the model, you will only add statements to the initial and dynamic methods. For more advanced models you may want to add also calculations outside these methods, but for now, you will see that the initial and dynamic methods provide most of what you need.

Now let’s see how it executes things that you add to the initial and dynamic. Replace the pass statement in the initial with

print('running the initial')

Replace the pass statement in the dynamic with

timeStep = self.currentTimeStep()
print('running the dynamic for time step: ', timeStep)

Save and run the modified model.


Question: What is the order in which the initial and dynamic are executed?

  1. The initial and dynamic are executed at the same time.

  2. First the initial is executed once. Next, the dynamic is executed 10 times.

  3. The initial is not executed, it only runs the dynamic.

Correct answers: b.

Feedback: None


2.2.2. Modelling with feedback

Now, let’s do forward modelling with feedback. We have a reservoir that is defined by the differential equation:

dx/dt = -cx

In hydrology, this is known as a linear reservoir. The variable x is the amount of water in the reservoir, and c is a rate constant. The script feedback.py solves the linear reservoir equation using an explicit solution. Open the script and run it.

The initial sets the initial content of the reservoir. Here it merely uses an initial value that is converted to another unit, using conversionValue. For the variable x in the differential equation, the script uses the variable name reservoir. The dynamic solves the differential equation by subtracting each timestep the outflow from the reservoir. Note that the variable reservoir is preceded by self.. This is needed because all other variables, e.g. conversionValue are local variables, i.e. they exist only in the method (initial or dynamic) were they have been defined. Preceding a variable with self. makes it a member variable of the class. This means it exists (can be used) in all other methods.

Add to the dynamic the line

print(conversionValue)

and run the model.


Question: What is printed? How can you solve this error if you really want to print it in the dynamic?

  1. An error message is printed, indicating there is a typo in the script.

  2. An error message is printed, which indicates that conversionValue is defined as a local variable. The solution is to use self.conversionValue throughout the script.

  3. An error message is printed, which indicates that conversionValue is defined as a global variable. The solution is to use self.conversionValue throughout the script.

Correct answers: b.

Feedback: None


An extension to the reservoir equation would be to add constant inflow of 0.5:

dx/dt = -cx + 0.5

Modify the script to simulate this inflow.


Question: What did you add to the script? Where did you type it?

  1. I added + 0.5 to self.reservoir in the initial.

  2. I added inflow = 0.5 to the initial and changed the line in the dynamic to: self.reservoir = self.reservoir - outflow + inflow

  3. I added self.inflow = 0.5 to the initial and changed the line in the dynamic to: self.reservoir = self.reservoir - outflow + self.inflow

Correct answers: c.

Feedback:

from pcraster import *
from pcraster.framework import *

class MyFirstModel(DynamicModel):
  def __init__(self):
    DynamicModel.__init__(self)
    setclone('dem.map')

  def initial(self):
    conversionValue = 3.0
    self.reservoir = 30.0 / conversionValue
    print('initial reservoir is: ', self.reservoir)
    self.inflow = 0.5

  def dynamic(self):
    outflow = 0.1 * self.reservoir 
    self.reservoir = self.reservoir - outflow + self.inflow
    print(self.reservoir)

nrOfTimeSteps=100
myModel = MyFirstModel()
dynamicModel = DynamicFramework(myModel,nrOfTimeSteps)
dynamicModel.run()

Question: If you run the model for a long time, what happens to the reservoir?

  1. The reservoir decreases until it reaches 5.

  2. The reservoir increases until it reaches 5.

  3. The reservoir decreases until it reaches 3.

  4. The reservoir increases until it reaches 3.

Correct answers: a.

Feedback: None