diff --git a/R/CreateGRiwrm.R b/R/CreateGRiwrm.R index 81c9c59a6981659622c32c54288f0c07bee6a897..2c46b0ef1f5a829609038ca96cdb78198c106022 100644 --- a/R/CreateGRiwrm.R +++ b/R/CreateGRiwrm.R @@ -256,15 +256,15 @@ getNodeProperties <- function(id, griwrm) { upstreamIds <- griwrm$id[!griwrm$id %in% griwrm$down] gaugedIds <- griwrm$id[!is.na(griwrm$model) & griwrm$model != "Ungauged"] divertedIds <- griwrm$id[!is.na(griwrm$model) & griwrm$model == "Diversion"] - p <- c( + p <- list( position = ifelse(id %in% upstreamIds, "Upstream", "Intermediate"), hydrology = ifelse(id %in% gaugedIds, "Gauged", ifelse(is.na(griwrm$model[griwrm$id == id]), "DirectInjection", "Ungauged")) ) - if (length(divertedIds) > 0) { - if (id %in% divertedIds) p["diverted"] <- "Diversion" - } + p$Upstream <- p$position == "Upstream" + p$DirectInjection = p$hydrology == "DirectInjection" + p$Diversion = id %in% divertedIds return(p) } diff --git a/R/CreateInputsModel.GRiwrm.R b/R/CreateInputsModel.GRiwrm.R index ec38978debc2e9e1b31f88f0f3875a20380d9dc6..6eb5dfbeda12ef3f73817b732d5782bcc268f6b7 100644 --- a/R/CreateInputsModel.GRiwrm.R +++ b/R/CreateInputsModel.GRiwrm.R @@ -245,10 +245,9 @@ CreateEmptyGRiwrmInputsModel <- function(griwrm) { #' @return \emph{InputsModel} object for one. #' @noRd CreateOneGRiwrmInputsModel <- function(id, griwrm, ..., Qobs, Qmin) { - hasDiversion <- "Diversion" %in% getNodeProperties(id, griwrm) + hasDiversion <- getNodeProperties(id, griwrm)$Diversion if (hasDiversion) { rowDiv <- which(griwrm$id == id & griwrm$model == "Diversion") - hasDiversion <- TRUE diversionOutlet <- griwrm$down[rowDiv] griwrm <- griwrm[-rowDiv, ] } diff --git a/R/RunModel.InputsModel.R b/R/RunModel.InputsModel.R index fd38a4a92ad7529d6a5cc3b8da57cf9592c1c2d1..12727eb4adc6c6aa5dd404e4b654ca97368c970c 100644 --- a/R/RunModel.InputsModel.R +++ b/R/RunModel.InputsModel.R @@ -37,21 +37,30 @@ RunModel.InputsModel <- function(x, RunOptions, Param, FUN_MOD = NULL, ...) { #' On a Diversion node, this function is called after `airGR::RunModel` to #' divert a part of the flow to another node than the original downstream one. #' -#' @param InputsModel \[object of class \emph{InputsModel}\] see [airGR::CreateInputsModel] for details +#' @param InputsModel \[object of class \emph{InputsModel}\] see +#' [airGR::CreateInputsModel] for details +#' @param RunOptions Same parameter as in [RunModel.GRiwrmInputsModel] #' @param OutputsModel Output of [airGR::RunModel] +#' @param updateQsim [logical] for updating Qsim after diversion in the output #' -#' @return Updated OutputsModel object with diversion: -#' Qsim +#' @return Updated `OutputsModel` object after diversion #' @noRd #' -RunModel_Diversion <- function(InputsModel, RunOptions, OutputsModel) { +RunModel_Diversion <- function(InputsModel, + RunOptions, + OutputsModel, + updateQsim = TRUE) { OutputsModel$Qnat <- OutputsModel$Qsim lQ <- calc_Qdiv(OutputsModel$Qsim_m3, InputsModel$Qdiv[RunOptions$IndPeriod_Run], InputsModel$Qmin[RunOptions$IndPeriod_Run]) + #message(paste(InputsModel$Qdiv[RunOptions$IndPeriod_Run], lQ$Qdiv, lQ$Qsim, InputsModel$Qmin[RunOptions$IndPeriod_Run], sep = ", ")) OutputsModel$Qdiv_m3 <- lQ$Qdiv OutputsModel$Qsim_m3 <- lQ$Qsim - OutputsModel$Qsim <- OutputsModel$Qsim_m3 / sum(InputsModel$BasinAreas, na.rm = TRUE) / 1e3 + if (updateQsim) { + OutputsModel$Qsim <- + OutputsModel$Qsim_m3 / sum(InputsModel$BasinAreas, na.rm = TRUE) / 1e3 + } if ("WarmUpQsim" %in% RunOptions$Outputs_Sim) { lQ <- calc_Qdiv(OutputsModel$RunOptions$WarmUpQsim_m3, InputsModel$Qdiv[RunOptions$IndPeriod_WarmUp], diff --git a/R/RunModel.SD.R b/R/RunModel.SD.R index 6d141d421caee7ba321f18cae3d28fca2e9f8c41..5498bcfa30a510832ac21f4f79d7d56673931668 100644 --- a/R/RunModel.SD.R +++ b/R/RunModel.SD.R @@ -8,5 +8,9 @@ #' @export #' RunModel.SD <- function(x, RunOptions, Param, QcontribDown, ...) { - airGR::RunModel_Lag(x, RunOptions = RunOptions, Param = Param[1], QcontribDown = QcontribDown) + OutputsModel <- airGR::RunModel_Lag(x, + RunOptions = RunOptions, + Param = Param[1], + QcontribDown = QcontribDown) + return(OutputsModel) } diff --git a/R/RunModel.Supervisor.R b/R/RunModel.Supervisor.R index ed7a588c6d4dd32b275d88cc337f310b3cfe6660..78f6f2bf90b65c28173228aba8bd67e6c44fa75f 100644 --- a/R/RunModel.Supervisor.R +++ b/R/RunModel.Supervisor.R @@ -33,32 +33,35 @@ RunModel.Supervisor <- function(x, RunOptions, Param, ...) { # Run runoff model for each sub-basin x$OutputsModel <- lapply(X = x$InputsModel, FUN = function(IM) { - RunModel.GR(IM, - RunOptions = RunOptions[[IM$id]], - Param = Param[[IM$id]]) + OM_GR <- RunModel.GR(IM, + RunOptions = RunOptions[[IM$id]], + Param = Param[[IM$id]]) + if (IM$hasDiversion) OM_GR$Qnat <- OM_GR$Qsim + return(OM_GR) }) - class(x$OutputsModel) <- append(class(x$OutputsModel), "GRiwrmOutputsModel") - # Copy simulated pure runoff flows (no SD nodes) to Qupstream in downstream SD nodes - for(id in getNoSD_Ids(x$InputsModel)) { - downId <- x$InputsModel[[id]]$down - if(!is.null(x$InputsModel[[downId]])) { - x$InputsModel[[downId]]$Qupstream[RunOptions[[downId]]$IndPeriod_Run, id] <- - x$OutputsModel[[id]]$Qsim_m3 - } + class(x$OutputsModel) <- c("GRiwrmOutputsModel", class(x$OutputsModel)) + + # Copy simulated pure runoff flows (no SD nor Diversion nodes) to Qupstream + for(id in getNoSD_Ids(x$InputsModel, include_diversion = FALSE)) { + updateQupstream.Supervisor(x, id, IndPeriod_Run) } - # Save Qsim for step by step simulation + # Save OutputsModel for step by step simulation QcontribDown <- do.call( cbind, lapply(x$OutputsModel, "[[", "Qsim") ) - Qsim_m3 <- do.call( cbind, lapply(x$OutputsModel, "[[", "Qsim_m3") ) + if (length(getDiversionRows(x$griwrm)) > 0) { + # Outputs of Diversion nodes + Qdiv_m3 <- Qsim_m3[, sv$griwrm$id[getDiversionRows(x$griwrm)], drop = FALSE] * NA + Qnat <- Qdiv_m3 + } - # Initialisation of model states by running the model with no supervision on warm-up period + # Initialization of model states by running the model with no supervision on warm-up period RunOptionsWarmUp <- RunOptions for(id in names(x$InputsModel)) { RunOptionsWarmUp[[id]]$IndPeriod_Run <- RunOptionsWarmUp[[id]]$IndPeriod_WarmUp @@ -96,23 +99,35 @@ RunModel.Supervisor <- function(x, RunOptions, Param, ...) { doSupervision(x) } # Loop over sub-basin using SD model - for(id in getSD_Ids(x$InputsModel)) { - # Run the SD model for the sub-basin and one time step - RunOptions[[id]]$IndPeriod_Run <- iTS + for(id in getSD_Ids(x$InputsModel, add_diversion = TRUE)) { + # Run model for the sub-basin and one time step RunOptions[[id]]$IniStates <- serializeIniStates(x$OutputsModel[[id]]$StateEnd) - x$OutputsModel[[id]] <- RunModel.SD( - x$InputsModel[[id]], - RunOptions = RunOptions[[id]], - Param = Param[[id]], - QcontribDown = QcontribDown[x$ts.index, id] - ) - # Storing Qsim in the data.frame Qsim + RunOptions[[id]]$IndPeriod_Run <- iTS + if (RunOptions[[id]]$FeatFUN_MOD$IsSD) { + # Route upstream flows for SD nodes + x$OutputsModel[[id]] <- RunModel.SD( + x$InputsModel[[id]], + RunOptions = RunOptions[[id]], + Param = Param[[id]], + QcontribDown = QcontribDown[x$ts.index, id] + ) + } else { + x$OutputsModel[[id]]$Qsim_m3 <- Qsim_m3[x$ts.index, id] + } + if (x$InputsModel[[id]]$hasDiversion) { + # Compute diverted and simulated flows on Diversion nodes + x$OutputsModel[[id]] <- + RunModel_Diversion(x$InputsModel[[id]], + RunOptions = RunOptions[[id]], + OutputsModel = x$OutputsModel[[id]]) + } + # Storing Qsim_m3 and Qdiv_m3 data.frames Qsim_m3[x$ts.index, id] <- x$OutputsModel[[id]]$Qsim_m3 - # Routing Qsim to Qupstream of downstream nodes - if(!is.na(x$InputsModel[[id]]$down)) { - x$InputsModel[[x$InputsModel[[id]]$down]]$Qupstream[iTS, id] <- - x$OutputsModel[[id]]$Qsim_m3 + if (x$InputsModel[[id]]$hasDiversion) { + Qdiv_m3[x$ts.index, id] <- x$OutputsModel[[id]]$Qdiv_m3 } + # Routing Qsim_m3 and Qdiv_m3 to Qupstream of downstream nodes + updateQupstream.Supervisor(x, id, iTS) } x$ts.previous <- x$ts.index } @@ -123,6 +138,9 @@ RunModel.Supervisor <- function(x, RunOptions, Param, ...) { x$OutputsModel[[id]]$Qsim_m3 <- Qsim_m3[, id] x$OutputsModel[[id]]$Qsim <- Qsim_m3[, id] / sum(x$InputsModel[[id]]$BasinAreas, na.rm = TRUE) / 1e3 + if (x$InputsModel[[id]]$hasDiversion) { + x$OutputsModel[[id]]$Qdiv_m3 <- Qdiv_m3[, id] + } } attr(x$OutputsModel, "Qm3s") <- OutputsModelQsim(x$InputsModel, x$OutputsModel, IndPeriod_Run) @@ -131,3 +149,18 @@ RunModel.Supervisor <- function(x, RunOptions, Param, ...) { return(x$OutputsModel) } + +updateQupstream.Supervisor <- function(x, id, iTS) { + downId <- x$InputsModel[[id]]$down + if(!is.null(x$InputsModel[[downId]])) { + x$InputsModel[[downId]]$Qupstream[iTS, id] <- + x$OutputsModel[[id]]$Qsim_m3 + } + if (x$InputsModel[[id]]$hasDiversion) { + divOutId <- x$InputsModel[[id]]$diversionOutlet + if (!is.na(divOutId)) { + x$InputsModel[[divOutId]]$Qupstream[iTS, id] <- + x$OutputsModel[[id]]$Qdiv_m3 + } + } +} diff --git a/R/plot.GRiwrm.R b/R/plot.GRiwrm.R index 88b49c94c7cfcee2aedb7a8f3117b215071695bc..aa2ee083e7ff226b9230768e7e37cd4172d7b554 100644 --- a/R/plot.GRiwrm.R +++ b/R/plot.GRiwrm.R @@ -82,11 +82,11 @@ plot.GRiwrm <- function(x, getNodeClass <- function(id, griwrm) { props <- getNodeProperties(id, griwrm) - if (props["hydrology"] == "DirectInjection") { - nc <- props["hydrology"] + if (props$DirectInjection) { + nc <- "DirectInjection" } else { nc <- paste0(props["position"], props["hydrology"]) } - if("diverted" %in% names(props)) nc <- paste0(nc, "Diversion") + if (props$Diversion) nc <- paste0(nc, "Diversion") return(nc) } diff --git a/R/utils.R b/R/utils.R index 286ee698a01bb4ffa1ba770ea6eb41875a040d61..4e961f9144a77095700d7d9b9dd508b459ae8122 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,15 +1,16 @@ #' Function to obtain the ID of sub-basins using SD model #' #' @param InputsModel \[`GRiwrmInputsModel` object\] +#' @param add_diversion [logical] for adding upstream nodes with diversion #' #' @return [character] IDs of the sub-basins using SD model #' @export -getSD_Ids <- function(InputsModel) { +getSD_Ids <- function(InputsModel, add_diversion = FALSE) { if (!inherits(InputsModel, "GRiwrmInputsModel")) { stop("Argument `InputsModel` should be of class GRiwrmInputsModel") } bSDs <- sapply(InputsModel, function (IM) { - inherits(IM, "SD") + inherits(IM, "SD") | IM$hasDiversion }) names(InputsModel)[bSDs] } @@ -17,15 +18,16 @@ getSD_Ids <- function(InputsModel) { #' Function to obtain the ID of sub-basins not using SD model #' #' @param InputsModel \[`GRiwrmInputsModel` object\] +#' @param include_diversion [logical] for including diversion nodes #' #' @return [character] IDs of the sub-basins not using the SD model #' @export -getNoSD_Ids <- function(InputsModel) { +getNoSD_Ids <- function(InputsModel, include_diversion = TRUE) { if (!inherits(InputsModel, "GRiwrmInputsModel")) { stop("Argument `InputsModel` should be of class GRiwrmInputsModel") } bSDs <- sapply(InputsModel, function (IM) { - !inherits(IM, "SD") + !inherits(IM, "SD") & (include_diversion | !IM$hasDiversion) }) names(InputsModel)[bSDs] } @@ -45,7 +47,7 @@ getDataFromLocation <- function(loc, sv) { stop("Reaching output of other controller is not implemented yet") } else { if(sv$nodeProperties[[loc]]["hydrology"] != "DirectInjection") { - if (sv$nodeProperties[[loc]]["position"] == "Upstream") { + if (sv$nodeProperties[[loc]]$Upstream) { sv$OutputsModel[[loc]]$Qsim_m3[sv$ts.previous] } else { sv$OutputsModel[[loc]]$Qsim_m3 @@ -67,13 +69,22 @@ getDataFromLocation <- function(loc, sv) { #' @noRd setDataToLocation <- function(ctrlr, sv) { l <- lapply(seq(length(ctrlr$Unames)), function(i) { - node <- sv$griwrm4U$down[sv$griwrm4U$id == ctrlr$Unames[i]] # limit U size to the number of simulation time steps of the current supervision time step U <- ctrlr$U[seq.int(length(sv$ts.index)),i] - # ! Qupstream contains warm up period and run period => the index is shifted - if(!is.null(sv$InputsModel[[node]])) { - sv$InputsModel[[node]]$Qupstream[sv$ts.index0 + sv$ts.index, - ctrlr$Unames[i]] <- U + + locU <- ctrlr$Unames[i] + if (sv$nodeProperties[[locU]]$DirectInjection) { + # Direct injection node => update Qusptream of downstream node + node <- sv$griwrm4U$down[sv$griwrm4U$id == locU] + # ! Qupstream contains warm up period and run period => the index is shifted + if(!is.null(sv$InputsModel[[node]])) { + sv$InputsModel[[node]]$Qupstream[sv$ts.index0 + sv$ts.index, locU] <- U + } + } else if (sv$nodeProperties[[locU]]$Diversion){ + # Diversion node => update Qdiv with -U + sv$InputsModel[[locU]]$Qdiv[sv$ts.index0 + sv$ts.index] <- -U + } else { + stop("Node ", locU, " must be a Direct Injection or a Diversion node") } }) } diff --git a/man/getNoSD_Ids.Rd b/man/getNoSD_Ids.Rd index 50750697f100619ec9e4813a74cc898fa21400aa..644d49eaf4ad79b18c723423d51f58d8ecf10e4d 100644 --- a/man/getNoSD_Ids.Rd +++ b/man/getNoSD_Ids.Rd @@ -4,10 +4,12 @@ \alias{getNoSD_Ids} \title{Function to obtain the ID of sub-basins not using SD model} \usage{ -getNoSD_Ids(InputsModel) +getNoSD_Ids(InputsModel, include_diversion = TRUE) } \arguments{ \item{InputsModel}{[\code{GRiwrmInputsModel} object]} + +\item{include_diversion}{\link{logical} for including diversion nodes} } \value{ \link{character} IDs of the sub-basins not using the SD model diff --git a/man/getSD_Ids.Rd b/man/getSD_Ids.Rd index 1a863101f37fddc766c1d33d37152fd54350cf5a..a1987eca097fe7e47c1da1a9408e39dadae1ede8 100644 --- a/man/getSD_Ids.Rd +++ b/man/getSD_Ids.Rd @@ -4,10 +4,12 @@ \alias{getSD_Ids} \title{Function to obtain the ID of sub-basins using SD model} \usage{ -getSD_Ids(InputsModel) +getSD_Ids(InputsModel, add_diversion = FALSE) } \arguments{ \item{InputsModel}{[\code{GRiwrmInputsModel} object]} + +\item{add_diversion}{\link{logical} for adding upstream nodes with diversion} } \value{ \link{character} IDs of the sub-basins using SD model diff --git a/vignettes/V06_Modelling_regulated_diversion.Rmd b/vignettes/V06_Modelling_regulated_diversion.Rmd new file mode 100644 index 0000000000000000000000000000000000000000..f8f4c3646711f44bfb79712f5423c3930abf62ef --- /dev/null +++ b/vignettes/V06_Modelling_regulated_diversion.Rmd @@ -0,0 +1,205 @@ +--- +title: "Severn_06: Modelling of a regulated diversion" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Severn_06: Modelling of a regulated diversion} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + fig.width = 6, + fig.asp = 0.68, + out.width = "70%", + fig.align = "center" +) +``` + +```{r setup} +library(airGRiwrm) +data(Severn) +``` + +## The study case + +In this vignette, we are still using the study case of the vignette #1 and #2, and +we are going to simulate a diversion at the node "54029" to provide flow to the node +"54001" in order to support low flows in the Severn river. + +This objective is to maintain a minimum flow equals to the 3th decile of the flow +at station "54001" without remaining less than the first decile of the flow downstream +the station "54029". + +Let's compute the flow quantiles at each station in m3/s: + +```{r} +Qobs <- cbind(sapply(Severn$BasinsObs, function(x) {x$discharge_spec})) +Qobs <- Qobs[, Severn$BasinsInfo$gauge_id] +Qobs_m3s <- t(apply(Qobs, 1, function(r) r * Severn$BasinsInfo$area * 1E3 / 86400)) +apply(Qobs_m3s[, c("54029", "54001")], 2, quantile, probs = seq(0,1,0.1), na.rm = TRUE) +``` + +The rule to apply is expressed as follow: + +> The diversion from "54029" is computed to maintain a minimum flow of 20 m3/s at +the gauging station "54001". The diversion is allowed as far as the flow at the +gauging station "54029" is above 2.6 m3/s. + +## Network + +```{r} + +nodes_div <- Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")] +nodes_div$model <- "RunModel_GR4J" +nodes_div <- rbind(nodes_div, data.frame(gauge_id = "54029", + downstream_id = "54001", + distance_downstream = 25, + model = "Diversion", + area = NA)) +renameCols <- list(id = "gauge_id", down = "downstream_id", length = "distance_downstream") +griwrmV06 <- CreateGRiwrm(nodes_div, renameCols) +plot(griwrmV06) +``` + +## GRiwrmInputsModel object + +We produce below the same operations as in the vignette "V02_Calibration_SD_model" to prepare the input data: + +```{r} +data(Severn) +nodes <- Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")] +nodes$model <- "RunModel_GR4J" +griwrm <- CreateGRiwrm(nodes, list(id = "gauge_id", down = "downstream_id", length = "distance_downstream")) +BasinsObs <- Severn$BasinsObs +DatesR <- BasinsObs[[1]]$DatesR +PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation})) +PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti})) +Precip <- ConvertMeteoSD(griwrm, PrecipTot) +PotEvap <- ConvertMeteoSD(griwrm, PotEvapTot) +``` + +The main difference here is that we need to provide a diverted flow and a minimum +remaining flow at station "54029". As, the diverted flow will be calculated during +simulation, we provide a initial diverted flow equals to zero for all the time steps. + +```{r} +Qdiv <- matrix(rep(0, length(DatesR)), ncol = 1) +colnames(Qdiv) <- "54029" +Qmin <- matrix(rep(2.6 * 86400, length(DatesR)), ncol = 1) +colnames(Qmin) <- "54029" +IM_div <- CreateInputsModel(griwrmV06, DatesR, Precip, PotEvap, Qobs = Qdiv, Qmin = Qmin) +``` + +## Implementation of the regulation controller + +### The supervisor + +The simulation is piloted through a `Supervisor` that can contain one or more +`Controller`. The supervision time step will be here the same as the simulation +time step: 1 day. Each day, the decision is taken for the current day from the +measurement simulated the previous time step. + +```{r} +sv <- CreateSupervisor(IM_div, TimeStep = 1L) +``` + +### The control logic function + +On a Diversion node, the minimum remaining flow is provided with the inputs and +is automatically taken into account by the model. So the control logic function +has only to take care about how much water to divert to the gauging station +"54002". + +We need to enclose the logic function in a function factory providing the +Supervisor in the environment of the function: + +```{r} +#' @param sv the Supervisor environment +logicFunFactory <- function(sv) { + #' @param Y Flow measured at "54002" the previous time step + function(Y) { + Qnat <- Y + # We need to remove the diverted flow to compute the natural flow at "54002" + lastU <- sv$controllers[[sv$controller.id]]$U + if (length(lastU) > 0) { + Qnat <- Y - lastU + } + return(-max(15 * 86400 - Qnat, 0)) + } +} +``` + +### The controller + +We declare the controller which defines where is the measurement `Y` , where to +apply the decision `U` with which logic function: + +```{r} +CreateController(sv, + ctrl.id = "Low flow support", + Y = "54001", + U = "54029", + FUN = logicFunFactory(sv)) +``` + + +## Running the simulation + +First we need to create a `GRiwrmRunOptions` object and load the parameters calibrated in the vignette "V02_Calibration_SD_model": + +```{r} +# Running simulation between 2002 and 2005 +IndPeriod_Run <- seq( + which(DatesR == as.POSIXct("2002-01-01")), + which(DatesR == as.POSIXct("2005-01-01")) +) +IndPeriod_WarmUp = seq(IndPeriod_Run[1] - 366,IndPeriod_Run[1] - 1) +RunOptions <- CreateRunOptions(IM_div, + IndPeriod_WarmUp = IndPeriod_WarmUp, + IndPeriod_Run = IndPeriod_Run) +ParamV02 <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm")) +``` + +And we run the supervised model: + +```{r} +OM_div <- RunModel(sv, RunOptions = RunOptions, Param = ParamV02) +``` + +To compare results with diversion and without diversion, we run the model without +the supervision (remember that we have set the diverted flow at zero in the inputs): + +```{r} +OM_nat <- RunModel(IM_div, RunOptions = RunOptions, Param = ParamV02) +``` + + +## Exploring results + +Let's plot the diverted flow, and compare the flow at stations 54029 and 54001, +with and without low-flow support at station 54001: + +```{r, fig.asp=1} +dfQdiv <- data.frame(DatesR = OM_div[[1]]$DatesR, + Diverted_flow = OM_div$`54029`$Qdiv_m3 / 86400) + +oldpar <- par(mfrow=c(3,1), mar = c(2.5,4,1,1)) +plot.Qm3s(dfQdiv) + +# Plot natural and influenced flow at station "54001" and "54029" +thresholds <- c("54029" = 2.6, "54001" = 15) +lapply(c("54029", "54001"), function(id) { + df <- cbind(attr(OM_div, "Qm3s")[, c("DatesR", id)], + attr(OM_nat, "Qm3s")[, id]) + names(df) <- c("DatesR", + paste(id, "with irrigation"), + paste(id, "natural flow")) + plot.Qm3s(df, ylim = c(0,50)) + abline(h = thresholds[id], col = "green") +}) +par(oldpar) +``` +