Apart from tools for assessment of an individual reservoir, the wateres package can be used to calculate variables for a system of reservoirs. In such a system, time series of inflows to a reservoir consist of sum of outflows (i.e. yields) from relevant upstream reservoirs and runoff generated by the corresponding intercatchment. The intercatchment runoff is calculated as a difference between original time series of inflow to the reservoir and sum of inflows to the upstream reservoirs.

Moreover, a water redistribution within the system can be applied in order to investigate potential decrease of deficit volumes.

Let’s assume the case of the Rivendell reservoir satisfying water demand in the Bruinen catchment and the Tharbad reservoir for the Greyflood catchment downwards; their data are available within the package tests. Deficit volumes for the individual catchments can be calculated and the corresponding wateres reservoirs can be set together with their input variables as described in the Reservoir Characteristics vignette. The only differences, related to the system settings, are the arguments id and down_id of the as.wateres function. These arguments define the system structure:

library(wateres)
# Bruinen and Rivendell
bru_data = read.table(
    "../tests/testthat/bruinen.txt", header = TRUE, colClasses = c("Date", "numeric", "numeric"))
bru = as.wateres(data.frame(DTM = bru_data$DTM, Q = bru_data$Q), storage = 0, area = 0)
bru_mrf = 1.514
bru_resul = calc_series(bru, yield = bru_mrf - bru_data$USE, throw = TRUE)

eas = data.frame(
    elevation = c(496, 499, 502, 505, 508, 511, 514, 517, 520, 523, 526, 529),
    area = 1e3 * c(0, 5, 58, 90, 133, 180, 253, 347, 424, 483, 538, 754),
    storage = 1e6 * c(0, 0.003, 0.161, 0.53, 1.085, 1.864, 2.943, 4.439, 6.362, 8.626, 11.175, 14.4))
riv = as.wateres("../tests/testthat/rivendell.txt", 14.4e6, 754e3, eas = eas, id = "riv", down_id = "thar")
idcs = which(riv$DTM %in% bru$DTM)
riv = resize_input(riv, idcs[1], idcs[length(idcs)])
riv = set_evaporation(riv, altitude = 529)
riv = set_precipitation(riv, c(55, 40, 44, 43, 81, 72, 85, 84, 52, 54, 48, 58))
riv = set_wateruse(riv, -bru_resul$deficit)

# Greyflood and Tharbad
grey_data = read.table(
    "../tests/testthat/greyflood.txt", header = TRUE, colClasses = c("Date", "numeric", "numeric"))
grey = as.wateres(data.frame(DTM = grey_data$DTM, Q = grey_data$Q), storage = 0, area = 0)
grey_mrf = 3.711
grey_resul = calc_series(grey, yield = grey_mrf - grey_data$USE, throw = TRUE)

eas = data.frame(
    elevation = c(245, 248, 251, 254, 257, 260, 263, 266, 269, 272, 275, 278, 281, 284, 287, 290, 293, 296),
    area = 1e3 * c(0, 2, 30, 90, 223, 315, 447, 636, 823, 975, 1154, 1348, 1545, 1758, 1996, 2218, 2440, 2672),
    storage = 1e6 * c(0, 0.002, 0.041, 0.202, 0.61, 1.279, 2.2, 3.525, 5.301, 7.449, 9.994, 12.99,
        16.423, 20.333, 24.792, 29.774, 35.273, 41.3))
thar = as.wateres("../tests/testthat/tharbad.txt", 41.3e6, 2672e3, eas = eas, id = "thar")
thar = set_evaporation(thar, altitude = 296)
thar = set_precipitation(thar, c(55, 40, 44, 43, 81, 72, 85, 84, 52, 54, 48, 58))
thar = set_wateruse(thar, -grey_resul$deficit)

The system is created by the as.system function: individual wateres objects passed as its arguments are joined into a list which is of the wateres_system class:

sys = as.system(riv, thar)

When creating a system, the check.wateres_system function is automatically invoked. It ensures that the system has a correct structure, inappropriate reservoirs are removed eventually.

The time series of reservoir variables calculated within the system are obtained by the calc_system function with a vector of reservoir yields given. The types argument defines types of calculation1 and names of list items with corresponding results:

sys_resul = calc_system(
    sys, yields = c(riv = 0.033, thar = 2.718), types = c("system_plain", "system_transfer"))

For this value of type, the resulting list consists of two items (each of them contains wateres_series for all reservoirs): system_plain with results for individual reservoirs and system_transfer for which water redistribution was considered.

The water redistribution (in this case it means that water from the Rivendell reservoir can be passed downwards to the Tharbad reservoir) is solved for each time step with any deficit volume independently and simple principles are applied2.

The redistribution is stored in the transfer column of the results:

sys_resul$system_transfer$riv$transfer[22:25]
## [1] -9667191.1 -3599207.1  -314250.4        0.0
sys_resul$system_transfer$thar$transfer[22:25]
## [1] 9667191.1 3599207.1  314250.4       0.0

The results show that the original total deficit volume for the Greyflood catchment (sum(grey_resul$deficit) = 3.92 × 10⁹ m³) is decreased by the Tharbad reservoir by 59 % (to sum(sys_resul$system_plain$thar$deficit) = 1.6 × 10⁹ m³). Assuming water transfer from the Rivendell reservoir, this Tharbad reservoir deficit is decreased by 6 % to sum(sys_resul$system_transfer$thar$deficit) = 1.51 × 10⁹ m³.

Transfer to the Tharbad reservoir caused additional deficits in the Rivendell reservoir3 (increase from sum(sys_resul$system_plain$riv$deficit) = 0.16 × 10⁹ m³ to sum(sys_resul$system_transfer$riv$deficit) = 0.18 × 10⁹ m³), however they are significantly lesser than the gained decrease.


  1. Apart from the types presented later, single_plain for independent calculation of the reservoirs and a fictional scenario single_transfer with water transfer added are available.

  2. After satisfying whole deficit volume – if it is possible – all available water is moved downwards. Finally, exceeding volume for the bottom reservoir is moved back to their source reservoirs proportionally.

  3. At time steps different from time steps of original deficits.