Severn_04: Simulation of a regulated withdrawal (closed-loop control)

David Dorchies

library(airGRiwrm)

Presentation of the case study

Starting from the network and the calibration set in the vignette “V03_Open-loop_influenced_flow,” we add 2 intake points for irrigation.

The following code chunk resumes the procedure of the vignette “V03_Open-loop_influenced_flow”:

data(Severn)
nodes <- Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
nodes$distance_downstream <- nodes$distance_downstream
nodes$model <- "RunModel_GR4J"
griwrm <- CreateGRiwrm(nodes, list(id = "gauge_id", down = "downstream_id", length = "distance_downstream"))
griwrmV03 <- griwrm
griwrmV03$model[griwrm$id == "54002"] <- NA
griwrmV03$model[griwrm$id == "54095"] <- NA
griwrmV03
#>      id  down length         model    area
#> 1 54057  <NA>     NA RunModel_GR4J 9885.46
#> 2 54032 54057     15 RunModel_GR4J 6864.88
#> 3 54001 54032     45 RunModel_GR4J 4329.90
#> 4 54095 54001     42          <NA> 3722.68
#> 5 54002 54057     43          <NA> 2207.95
#> 6 54029 54032     32 RunModel_GR4J 1483.65

Network configuration

The intake points are located:

We have to add this 2 nodes in the GRiwrm object that describes the network:

griwrmV04 <- rbind(
  griwrmV03,
  data.frame(
    id = c("Irrigation1", "Irrigation2"),
    down = c("54001", "54032"),
    length = c(35, 10),
    model = NA,
    area = NA
  )
)
plot(griwrmV04)

Blue-grey nodes figure upstream basins (rainfall-runoff modeling only) and green nodes figure intermediate basins, coupling rainfall-runoff and hydraulic routing modeling. Nodes in red color are direct injection points (positive or negative flow) in the model.

It’s important to notice that even if the points “Irrigation1” and “Irrigation2” are physically located on a single branch of the Severn river as well as gauging stations “54095,” “54001” and “54032,” nodes “Irrigation1” and “Irrigation2” are not represented on the same branch in this conceptual model. Consequently, with this network configuration, it is not possible to know the value of the flow in the Severn river at the “Irrigation1” or “Irrigation2” nodes. These values are only available in nodes “54095,” “54001” and “54032” where rainfall-runoff and hydraulic routing are actually modeled.

Irrigation objectives and flow demand at intakes

Irrigation1 covers an area of 15 km² and Irrigation2 covers an area of 30 km².

The objective of these irrigation systems is to cover the rainfall deficit (Burt et al. 1997) with 80% of success. Below is the calculation of the 8th decile of monthly water needed given meteorological data of catchments “54001” and “54032” (unit mm/day) :

# Formatting climatic data for CreateInputsModel (See vignette V01_Structure_SD_model for details)
BasinsObs <- Severn$BasinsObs
DatesR <- BasinsObs[[1]]$DatesR
PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
Qobs <- cbind(sapply(BasinsObs, function(x) {x$discharge_spec}))
Precip <- ConvertMeteoSD(griwrm, PrecipTot)
PotEvap <- ConvertMeteoSD(griwrm, PotEvapTot)

# Calculation of the water need at the sub-basin scale
dailyWaterNeed <- PotEvap - Precip
dailyWaterNeed <- cbind(as.data.frame(DatesR), dailyWaterNeed[,c("54001", "54032")])
monthlyWaterNeed <- SeriesAggreg(dailyWaterNeed, "%Y%m", rep("mean",2))
monthlyWaterNeed <- SeriesAggreg(dailyWaterNeed, "%m", rep("q80",2))
monthlyWaterNeed[monthlyWaterNeed < 0] <- 0
monthlyWaterNeed$DatesR <- as.numeric(format(monthlyWaterNeed$DatesR,"%m"))
names(monthlyWaterNeed)[1] <- "month"
monthlyWaterNeed <- monthlyWaterNeed[order(monthlyWaterNeed$month),]
monthlyWaterNeed
#>       month     54001     54032
#> 25        1 0.2400000 0.2365627
#> 1721      2 0.5918416 0.6188486
#> 2804      3 1.2376475 1.2384480
#> 3745      4 2.1809664 2.2036046
#> 4721      5 3.0230456 3.0555408
#> 5716      6 3.4775922 3.5096402
#> 6722      7 3.5305228 3.5769480
#> 7644      8 2.6925228 2.7331421
#> 8637      9 1.8323644 1.8489218
#> 9588     10 0.8626301 0.8867260
#> 10554    11 0.2707842 0.2497664
#> 11491    12 0.1488753 0.1665834

We restrict the irrigation season between March and September As a consequence, the crop requirement can be expressed in m3/s as follows:

irrigationObjective <- monthlyWaterNeed
# Conversion in m3/day
irrigationObjective$"54001" <- monthlyWaterNeed$"54001" * 15 * 1E3
irrigationObjective$"54032" <- monthlyWaterNeed$"54032" * 30 * 1E3
# Irrigation period between March and September
irrigationObjective[-seq(3,9),-1] <- 0
# Conversion in m3/s
irrigationObjective[,c(2,3)] <- round(irrigationObjective[,c(2,3)] / 86400, 1)
irrigationObjective$total <- rowSums(irrigationObjective[,c(2,3)])
irrigationObjective
#>       month 54001 54032 total
#> 25        1   0.0   0.0   0.0
#> 1721      2   0.0   0.0   0.0
#> 2804      3   0.2   0.4   0.6
#> 3745      4   0.4   0.8   1.2
#> 4721      5   0.5   1.1   1.6
#> 5716      6   0.6   1.2   1.8
#> 6722      7   0.6   1.2   1.8
#> 7644      8   0.5   0.9   1.4
#> 8637      9   0.3   0.6   0.9
#> 9588     10   0.0   0.0   0.0
#> 10554    11   0.0   0.0   0.0
#> 11491    12   0.0   0.0   0.0

We assume that the efficiency of the irrigation systems is equal to 50% as proposed by Seckler, Molden, and Sakthivadivel (2003). as a consequence, the flow demand at intake for each irrigation system is as follows (unit: m3/s):

# Application of the 50% irrigation system efficiency on the water demand
irrigationObjective[,seq(2,4)] <- irrigationObjective[,seq(2,4)] / 0.5
# Display result in m3/s
irrigationObjective
#>       month 54001 54032 total
#> 25        1   0.0   0.0   0.0
#> 1721      2   0.0   0.0   0.0
#> 2804      3   0.4   0.8   1.2
#> 3745      4   0.8   1.6   2.4
#> 4721      5   1.0   2.2   3.2
#> 5716      6   1.2   2.4   3.6
#> 6722      7   1.2   2.4   3.6
#> 7644      8   1.0   1.8   2.8
#> 8637      9   0.6   1.2   1.8
#> 9588     10   0.0   0.0   0.0
#> 10554    11   0.0   0.0   0.0
#> 11491    12   0.0   0.0   0.0

Restriction of irrigation in case of water scarcity

Minimal environmental flow at the intakes

In the UK, abstraction restrictions are driven by Environmental Flow Indicator (EFI) supporting Good Ecological Status (GES) (Klaar et al. 2014). Abstraction restriction consists in limiting the proportion of available flow for abstraction in function of the current flow regime (Reference taken for a river that is highly sensitive to abstraction classified “ASB3”).

restriction_rule <- data.frame(quantile_natural_flow = c(.05, .3, 0.5, 0.7),
                               abstraction_rate = c(0.1, 0.15, 0.20, 0.24))

The control of the abstraction will be done at the gauging station downstream all the abstraction locations (node “54032”). So we need the flow corresponding to the quantiles of natural flow and flow available for abstraction in each case.

quant_m3s32 <- quantile(
  Qobs[,"54032"] * griwrmV04[griwrmV04$id == "54032", "area"] / 86.4,
  restriction_rule$quantile_natural_flow,
  na.rm = TRUE
)
restriction_rule_m3s <- data.frame(
  threshold_natural_flow = quant_m3s32,
  abstraction_rate = restriction_rule$abstraction_rate
)

matplot(restriction_rule$quantile_natural_flow,
        cbind(restriction_rule_m3s$threshold_natural_flow,
              restriction_rule$abstraction_rate * restriction_rule_m3s$threshold_natural_flow,
              max(irrigationObjective$total)),
        log = "x", type = "l",
        main = "Quantiles of flow on the Severn at Saxons Lode (54032)",
        xlab = "quantiles", ylab = "Flow (m3/s)",
        lty = 1, col = rainbow(3, rev = TRUE)
        )
legend("topleft", legend = c("Natural flow", "Abstraction limit", "Irrigation max. objective"),
       col = rainbow(3, rev = TRUE), lty = 1)