Basic Single Reservoir
This example shows how to build a simple single reservoir model.
File Structure
The file structure looks as follows:
<base_dir>
│ <model_file>.py
├───input
│ ├───(plot_table.csv)
│ └───rtcDataConfig.xml
│ └───rtcParameterConfig.xml
│ └───timeseries_import.xml
├───lookup_tables
│ ├───lookup_tables.csv
│ ├───(<data1>.csv)
│ ├───(<data2>.csv)
│ └───(<data3>.csv)
└───output
The <base_dir> is the base directory that contains all files to run the model. It consists of the following files and folders.
<model_file>.py: main model file that describes all the schemes for controlling the reservoir flow.
input: directory containing all parameters and external input data.
plot_table.csv (optional): file that describes how the output should be visualised.
rtcParameterConfig.xml: file that contains the model parameters.
timeseries_import.xml: file with all input timeseries and initial conditions.
rtcDataConfig.xml: file that contains the mappings for input/output timeseries (from FEWS) and internal model variables.
lookup_tables: directory that contains all data for lookup tables.
lookup_tables.csv: file that describes all lookup tables.
***.csv: data files that contain data for generating lookup tables.
Each of these files will be described in more detail in the following sections.
Creating Template Files
Using the command rtc-tools-reservoir-template -d <base_dir> -n <reservoir_name>
from the command line will create a directory <base_dir> with template files
for a reservoir model called <reservoir_name>.
The directory <base_dir> will be created in the current working directory
and will contain a file structure as described above.
The generated source file and data files are all template files
that need to be completed by the user.
Main Model File
An example of the main model file <model_file>.py is given below.
1"""Example that illustrates how to create a basic model."""
2
3from pathlib import Path
4
5from rtctools.util import run_simulation_problem
6
7from rtctools_simulation.reservoir.model import InputVar, ModelConfig, ReservoirModel
8
9CONFIG = ModelConfig(base_dir=Path(__file__).parent)
10
11
12class SingleReservoir(ReservoirModel):
13 """Example single reservoir model."""
14
15 def apply_schemes(self):
16 """Apply schemes for controlling the reservoir."""
17
18 # Get current time.
19 datetime = self.get_current_datetime()
20 # Apply schemes.
21 h = self.get_var("H")
22 h_crest = self.get_var("H_crest")
23 self.include_rainevap()
24 if h > h_crest:
25 april = 4
26 september = 9
27 if april <= datetime.month <= september:
28 self.set_q(
29 target_variable=InputVar.Q_OUT,
30 input_type="parameter",
31 input_data=0.4,
32 )
33 else:
34 self.apply_spillway()
35 else:
36 self.set_q(
37 target_variable=InputVar.Q_OUT,
38 input_type="parameter",
39 input_data=0.2,
40 )
41
42 def calculate_output_variables(self):
43 """Calculate additional output variables."""
44 self.calculate_rule_curve_deviation(periods=3, h_var="H")
45
46
47# Create and run the model.
48if __name__ == "__main__":
49 run_simulation_problem(SingleReservoir, config=CONFIG)
The template file mentioned in the previous section will look very similar to this file,
except that the apply_schemes() method still needs to be filled out, and the optional def,
calculate_output_variables(), is not added..
The line
CONFIG = ModelConfig(base_dir=Path(__file__).parent)
sets the model configuration.
This model configuration is defined by the base directory base_dir.
In most cases, the base directory is Path(__file__).parent,
which is the directory of the current file.
The line
class SingleReservoir(ReservoirModel):
defines a class SingleReservoir
that inherits all properties and functionalities
of the predefined class ReservoirModel.
An overview of this class can be found in Reservoir API
and details of the underlying model it uses can be found in Single Reservoir Model.
The method apply_schemes() is called every timestep and contains the logic
for which schemes are applied.
The first argument self is the SingleReservoir object itself.
Since SingleReservoir inherits from ReservoirModel,
self can call any of the ReservoirModel methods, such as
get_current_datetime(),
get_var(),
set_q(),
apply_spillway().
An overview of all available ReservoirModel methods
can be found in Reservoir API.
In this example, the apply_schemes() method starts
by including rain and rain evaporation by calling self.include_rainevap().
Since apply_schemes() is applied at each time step,
this means rain and evaporation is included at each time step.
The method then checks if the elevation H is higher than the crest elevation H_crest.
If this is the case, and the current month is in between April and September,
the outflow is set by set_q().
Otherwise, the spillway scheme is applied.
If the elevation is below the crest elevation, the outflow is set by set_q().
The last line
# Create and run the model.
if __name__ == "__main__":
run_simulation_problem(SingleReservoir, config=CONFIG)
runs a SingleReservoir model.
To run the model, we can run python <model_file>.py from the command line.
Lookup tables
Lookup tables are used to define relations between volume, elevation, surface area, and outflow. They are defined in the <base_dir>/lookup_tables folder. A description of all lookup tables is given in the lookup_tables.csv file. In this example, this file looks as follows.
name |
data |
var_in |
var_out |
|---|---|---|---|
h_from_v |
v_h.csv |
volume_m3 |
height_m |
v_from_h |
v_h.csv |
height_m |
volume_m3 |
area_from_v |
v_area.csv |
volume_m3 |
area_m2 |
qspill_from_h |
h_qspill.csv |
height_m |
qspill_m3_per_s |
It consists of the following columns.
name: name of the lookup_table. The default reservoir model uses the lookup tables h_from_v, area_from_v, and qspill_from_h.
data: data file used to create the lookup table. This should a csv file where all fields are seperated by a
,.var_in: input variable for creating the lookup table. This should be one of the columns in the data file.
var_out: output variable for creating the lookup table. This should be one of the columns in the data file.
A data file, such as v_h.csv, looks as follows.
volume_m3 |
height_m |
|---|---|
0 |
1542.306754 |
13439700 |
1562.118995 |
16152300 |
1563.643014 |
21700800 |
1566.691051 |
… |
… |
When setting up the model, the model object will look for the following lookup tables:
h_from_v
area_from_v
qout_from_v
qspill_from_h
It is therefore important to use these same names in the lookup_tables.csv file.
Input Data Files
The input folder contains a configuration file rtcDataConfig.xml a parameter file rtcParameterConfig.xml, and an input data file timeseries_import.xml.
The rtcDataConfig.xml file contains a mapping between external data and internal model variables. In this example, rtcParameterConfig.xml looks as follows.
<?xml version="1.0" encoding="UTF-8"?>
<rtcDataConfig xmlns="http://www.wldelft.nl/fews" xmlns:rtc="http://www.wldelft.nl/fews" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.wldelft.nl/fews ../xsd/rtcDataConfig.xsd">
<timeSeries id="V">
<PITimeSeries>
<locationId>reservoir</locationId>
<parameterId>V</parameterId>
</PITimeSeries>
</timeSeries>
...
</rtcDataConfig>
The line <timeSeries id=V> indicates that the model variable is called V
and the lines <locationId>reservoir</locationId> and <parameterId>V</parameterId>
indicate that V has locationId resrvoir and parameterId V.
The locationId and parameterId are used to label data in data files
such as the input file timeseries_import.xml or the output file timeseries_export.xml.
The input file timeseries_import.xml is usually not created by the user, but generated by a FEWS application. In this example, the input file contains the following lines.
<series>
<header>
<type>instantaneous</type>
<moduleInstanceId>reservoir</moduleInstanceId>
<locationId>reservoir</locationId>
<parameterId>V</parameterId>
<timeStep unit="second" multiplier="3600"/>
<startDate date="2022-06-07" time="06:00:00"/>
<endDate date="2022-06-27" time="06:00:00"/>
<forecastDate date="2022-06-07" time="06:00:00"/>
<missVal>-999.0</missVal>
<stationName>Reservoir1</stationName>
<units>m3</units>
</header>
<event date="2022-06-07" time="06:00:00" value="136500000" flag="8"/>
</series>
The line <event date="2022-06-07" time="06:00:00" value="136500000" flag="8"/>
sets the value of V at the initial time (2022-06-07, 06:00:00).
We only provide the reservoir volume V with an initial value
and therefore there is only one event block.
If we want to set a variable at each time step, like the inflow Q_in,
we have an event block for each time step.
Output Data
The results of the simulation will appear in the output folder in a file called timeseries_export.xml. The data is linked to model variables via the rtcDataConfig.xml in the same way as with timeseries_import.xml.
Automatic Plotting
You can optionally include a plot_table.csv in the input folder. This is used by the rtc-tools-interfaces module (automatically installed with this package) to plot the model output. For more details on how to use this file and visualize results, see RTC-Tools-Interface.
The results of the simulation run can be seen in the plot below.