diff --git a/NAMESPACE b/NAMESPACE index b6a9c8a12d3e777bb54c5efb230f1b6eb8539ca6..21c69ae9dfc53d4ad97be185aa57cf5099c5d1cb 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -21,12 +21,17 @@ S3method(CreateRunOptions,InputsModel) S3method(CreateRunOptions,character) S3method(RunModel,GR) S3method(RunModel,GRiwrmInputsModel) +S3method(RunModel,GRiwrmOutputsModel) S3method(RunModel,InputsModel) S3method(RunModel,Supervisor) +S3method(extractParam,GRiwrmOutputsCalib) +S3method(extractParam,GRiwrmOutputsModel) S3method(isNodeDownstream,GRiwrm) S3method(isNodeDownstream,GRiwrmInputsModel) S3method(isNodeUpstream,GRiwrm) S3method(isNodeUpstream,GRiwrmInputsModel) +S3method(merge,GRiwrmOutputsModel) +S3method(merge,OutputsModel) S3method(plot,GRiwrm) S3method(plot,GRiwrmOutputsModel) S3method(plot,OutputsModelReservoir) @@ -47,6 +52,7 @@ export(RunModel_Reservoir) export(as.Qm3s) export(extractParam) export(getAllNodesProperties) +export(getNextTimeSteps) export(getNoSD_Ids) export(getNodeProperties) export(getNodeRanking) diff --git a/R/CreateInputsModel.GRiwrm.R b/R/CreateInputsModel.GRiwrm.R index 8d10cac60d97a60a75c139c17941fb926e6750ab..60f11d7f6e57d729bb51808b59150bac6f66a503 100644 --- a/R/CreateInputsModel.GRiwrm.R +++ b/R/CreateInputsModel.GRiwrm.R @@ -116,57 +116,21 @@ CreateInputsModel.GRiwrm <- function(x, DatesR, warning("The usage of 'Qobs' is deprecated, use 'Qinf' instead") Qinf <- Qobs } - varNames <- c("Precip", "PotEvap", "TempMean", "Qinf", "Qmin", - "TempMin", "TempMax", "ZInputs", "HypsoData", "NLayers") - names(varNames) <- varNames - lapply(varNames, function(varName) { - v <- get(varName) - if (!is.null(v)) { - if (is.matrix(v) || is.data.frame(v)) { - if (is.null(colnames(v))) { - stop(sprintf( - "'%s' must have column names", - varName - )) - } else if (!all(colnames(v) %in% x$id)) { - stop(sprintf( - "'%s' column names must be included in 'id's of the GRiwrm object", - varName - ), "\n", - sprintf("These columns are not known: %s", - paste(colnames(v)[!colnames(v) %in% x$id], collapse = ", "))) - } else if (any(duplicated(colnames(v)))) { - stop(sprintf( - "'%s' has duplicated column names: '%s'", - varName, - paste(colnames(v)[duplicated(colnames(v))], collapse = "', '") - )) - } - if (!varName %in% c("ZInputs", "NLayers", "HypsoData") && nrow(v) != length(DatesR)) { - stop(sprintf( - "'%s' number of rows and the length of 'DatesR' must be equal", - varName - )) - } - if (varName %in% c("Precip", "PotEvap", "Qmin")) { - if (any(is.na(v))) { - stop(sprintf( - "`NA` values detected in '%s'. Missing values are not allowed in InputsModel", - varName - )) - } - if (any(v < 0)) { - stop(sprintf( - "'%s' values must be positive or nul. Missing values are not allowed in InputsModel", - varName - )) - } - } - } else if (!varName %in% c("ZInputs", "NLayers")) { - stop(sprintf("'%s' must be a matrix or a data.frame", varName)) - } - } - }) + + checkInputsModelArguments( + x, + DatesR, + Precip = Precip, + PotEvap = PotEvap, + TempMean = TempMean, + Qinf = Qinf, + Qmin = Qmin, + TempMin = TempMin, + TempMax = TempMax, + ZInputs = ZInputs, + HypsoData = HypsoData, + NLayers = NLayers + ) if (is.null(Qinf)) Qinf <- matrix(0, ncol = 0, nrow = length(DatesR)) if (is.null(Qrelease)) Qrelease <- matrix(0, ncol = 0, nrow = length(DatesR)) diff --git a/R/CreateSupervisor.R b/R/CreateSupervisor.R index dfd0880d8a8392cb3368072a55f4eb33641ad719..2b6eccc0224d6a7dc61fbab7bfb44026a22ee1c9 100644 --- a/R/CreateSupervisor.R +++ b/R/CreateSupervisor.R @@ -4,7 +4,7 @@ #' See [RunModel.Supervisor] and vignettes for examples of use. #' #' @param InputsModel \[object of type `GRiwrmInputsModel`\] inputs of the model -#' @param TimeStep [numeric] number of time steps between each supervision +#' @param TimeStep [integer] number of time steps between each supervision #' #' @return A `Supervisor` object which is an [environment] containing all the necessary variables to run a supervised simulation, such as: #' - `DatesR` [POSIXct]: vector of date from `InputsModel` diff --git a/R/RunModel.GRiwrmOutputsModel.R b/R/RunModel.GRiwrmOutputsModel.R new file mode 100644 index 0000000000000000000000000000000000000000..382d66c408f0a9bec27d2e6523c217a593f82432 --- /dev/null +++ b/R/RunModel.GRiwrmOutputsModel.R @@ -0,0 +1,131 @@ +#' RunModel for hot restart after a previous simulation period +#' +#' This function allows to restart a simulation at the end of a previous +#' simulation period. Parameters `Qinf`, `Qrelease`, and `Qmin` can be +#' redefined for this new simulation period. +#' +#' @details +#' `IndPeriod_Run` or `DatesR` must must be continuous periods starting the +#' time step after the last simulation time step of the `GRiwrmOutputsModel` +#' object provided through the argument `x`. +#' +#' `Qinf`, `Qmin`, and `Qrelease` are used for overwriting the corresponding +#' arguments provided to [CreateInputsModel.GRiwrm] for the period to be simulated. +#' Therefore, the number of rows of these arguments must correspond to +#' `IndPeriod_Run` or `DatesR` lengths. +#' +#' @inheritParams getNextTimeSteps +#' @inheritParams RunModel.GRiwrmInputsModel +#' @inheritParams airGR::CreateRunOptions +#' @param DatesR (optional) [POSIXt] vector of dates of period to be used for +#' the model run. See details +#' @param Qinf (optional) [matrix] or [data.frame] of [numeric] containing +#' observed flows. It must be provided only for nodes of type "Direct +#' injection" and "Diversion" \[m3 per time step\]. +#' Column names correspond to node IDs. Negative flows are abstracted from +#' the model and positive flows are injected to the model. See details +#' @param Qmin (optional) [matrix] or [data.frame] of [numeric] containing +#' minimum flows to let downstream of a node with a Diversion \[m3 per +#' time step\]. Default is zero. Column names correspond to node IDs. +#' See details +#' @param Qrelease (optional) [matrix] or [data.frame] of [numeric] containing +#' release flows by nodes using the model `RunModel_Reservoir` \[m3 per +#' time step\]. See details +#' @param merge_outputs [logical] Merge simulation outputs with the one provided +#' in argument `x` +#' @param ... Further arguments for compatibility with S3 methods +#' +#' @inherit RunModel.GRiwrmInputsModel return +#' @export +#' +RunModel.GRiwrmOutputsModel <- function(x, + InputsModel, + RunOptions, + IndPeriod_Run = which(InputsModel[[1]]$DatesR %in% DatesR), + DatesR = getNextTimeSteps(x), + Qinf = NULL, + Qrelease = NULL, + Qmin = NULL, + merge_outputs = TRUE, + ...) { + stopifnot(inherits(x, "GRiwrmOutputsModel"), + inherits(InputsModel, "GRiwrmInputsModel"), + inherits(RunOptions, "GRiwrmRunOptions")) + # Check Run Period + next_time_step <- getNextTimeSteps(x) + next_index <- which(InputsModel[[1]]$DatesR == next_time_step) + if (IndPeriod_Run[1] != next_index) { + stop("`IndPeriod_Run` should have its first element equal to ", next_index) + } + + # State Initiation + for (id in names(RunOptions)) { + # Run model for the sub-basin and one time step + RunOptions[[id]]$IniResLevels <- NULL + RunOptions[[id]]$IniStates <- serializeIniStates(x[[id]]$StateEnd) + RunOptions[[id]]$IndPeriod_WarmUp <- 0L + RunOptions[[id]]$IndPeriod_Run <- IndPeriod_Run + } + + # Inputs change + checkInputsModelArguments( + attr(InputsModel, "GRiwrm"), + InputsModel[[1]]$DatesR[IndPeriod_Run], + Qinf = Qinf, + Qrelease = Qrelease, + Qmin = Qmin + ) + inputs <- list(Qinf = Qinf, Qrelease = Qrelease, Qmin = Qmin) + inputs[sapply(inputs, is.null)] <- NULL + for (inputArg in names(inputs)) { + input <- inputs[[inputArg]] + if (length(IndPeriod_Run) != nrow(input)) { + stop("The Argument ", inputArg, + " must have a number of rows identical to the lenght of `IndPeriod_Run`") + } + for (id in colnames(input)) { + v <- input[, id, drop = TRUE] + if (inputArg %in% c("Qrelease", "Qmin")) { + if (inputArg == "Qrelease" && !InputsModel[[id]]$isReservoir) { + stop("The column ", id, " of the argument `Qrelease` does not refer to a Reservoir node") + } + if (inputArg == "Qmin" && !InputsModel[[id]]$hasDiversion) { + stop("The column ", id, " of the argument `Qmin` does not refer to a Diversion node") + } + if (is.null(InputsModel[[id]][[inputArg]])) { + stop("InputsModel[['", id, "']] should contain a `", inputArg, "` item") + } + InputsModel[[id]][[inputArg]][IndPeriod_Run] <- v + } + if (inputArg == "Qinf") { + g <- attr(InputsModel, "GRiwrm") + if (is.null(InputsModel[[id]])) { + # Direct Injection + id_down <- g$down[g$id == id] + InputsModel[[id_down]]$Qupstream[IndPeriod_Run, id] <- v + } else { + if (!InputsModel[[id]]$hasDiversion) { + stop("The column ", id, " of the argument `Qinf` does not refer to a DirectInjection or a Diversion node") + } + # Update withdrawal due to Diversion + InputsModel[[id]]$Qdiv[IndPeriod_Run] <- -v + } + } + } + } + + # Run the model + OM <- suppressMessages( + RunModel( + InputsModel, + RunOptions = RunOptions, + Param = extractParam(x) + ) + ) + + if (merge_outputs) { + OM <- merge(x, OM) + } + + return(OM) +} diff --git a/R/RunModel.InputsModel.R b/R/RunModel.InputsModel.R index 424f73ab65b93cc5dabdc31fea0c66e881cba22e..0693e4427078cbcfe79c654cfd8602ba8385d698 100644 --- a/R/RunModel.InputsModel.R +++ b/R/RunModel.InputsModel.R @@ -43,6 +43,9 @@ RunModel.InputsModel <- function(x = NULL, } } + # Avoiding Error in `FUN_MOD(x, RunOptions, Param)`: NA/NaN/Inf in foreign function call (arg 7) + RunOptions$IniStates[is.na(RunOptions$IniStates)] <- 0 + FUN_MOD <- match.fun(FUN_MOD) if (identical(FUN_MOD, RunModel_Lag)) { OutputsModel <- RunModel_Routing(x, RunOptions, Param) diff --git a/R/RunModel_Reservoir.R b/R/RunModel_Reservoir.R index e0db27aff4e1ef05484b51d9919c409c612c467d..c290116fdf4bed521bfb7dcef846cd942011ed72 100644 --- a/R/RunModel_Reservoir.R +++ b/R/RunModel_Reservoir.R @@ -146,6 +146,7 @@ RunModel_Reservoir <- function(InputsModel, RunOptions, Param) { OutputsModel$RunOptions$WarmUpQdiv_m3 <- Qdiv_m3[iWarmUp] } } + OutputsModel$RunOptions$Param <- Param iRun <- length(IndPerWarmUp) + seq(length(RunOptions$IndPeriod_Run)) OutputsModel$Qsim_m3 <- Qsim_m3[iRun] OutputsModel$Vsim <- Vsim[iRun] diff --git a/R/utils.Calibration.R b/R/utils.Calibration.R index 2d7157230e9af87d68edcd5fa8a65658cbad8561..96b05f7dba7b049be054a6ca5266c6a1a68a218a 100644 --- a/R/utils.Calibration.R +++ b/R/utils.Calibration.R @@ -278,6 +278,18 @@ transferGRparams <- function(InputsModel, Param, donor, receiver, default_param #' @export #' extractParam <- function(x) { - stopifnot(inherits(x, "GRiwrmOutputsCalib")) + UseMethod("extractParam") +} + +#' @export +#' @rdname extractParam +extractParam.GRiwrmOutputsCalib <- function(x) { lapply(x, "[[", "ParamFinalR") } + +#' @export +#' @rdname extractParam +extractParam.GRiwrmOutputsModel <- function(x) { + lapply(x, function(o) o$RunOptions$Param) +} + diff --git a/R/utils.CreateInputsModel.R b/R/utils.CreateInputsModel.R index c0bd112d45971bf608e94b159bd265befe565bf4..6683fec0501dcb48f3682a25fabe8cbd2ee990e7 100644 --- a/R/utils.CreateInputsModel.R +++ b/R/utils.CreateInputsModel.R @@ -57,3 +57,65 @@ checkQinfQrelease <- function(g, varname, Q) { } return(Q) } + +#' Check the parameters provided to CreateInputsModel.GRiwrm +#' +#' @param x GRiwrm +#' @param DatesR DatesR +#' @param ... Parameters to check +#' +#' @return Nothing +#' @noRd +#' +checkInputsModelArguments <- function(x, DatesR, ...) { + dots <- list(...) + + lapply(names(dots), function(varName) { + v <- dots[[varName]] + if (!is.null(v)) { + if (is.matrix(v) || is.data.frame(v)) { + if (is.null(colnames(v))) { + stop(sprintf( + "'%s' must have column names", + varName + )) + } else if (!all(colnames(v) %in% x$id)) { + stop(sprintf( + "'%s' column names must be included in 'id's of the GRiwrm object", + varName + ), "\n", + sprintf("These columns are not known: %s", + paste(colnames(v)[!colnames(v) %in% x$id], collapse = ", "))) + } else if (any(duplicated(colnames(v)))) { + stop(sprintf( + "'%s' has duplicated column names: '%s'", + varName, + paste(colnames(v)[duplicated(colnames(v))], collapse = "', '") + )) + } + if (!varName %in% c("ZInputs", "NLayers", "HypsoData") && nrow(v) != length(DatesR)) { + stop(sprintf( + "'%s' number of rows and the length of 'DatesR' must be equal", + varName + )) + } + if (varName %in% c("Precip", "PotEvap", "Qmin")) { + if (any(is.na(v))) { + stop(sprintf( + "`NA` values detected in '%s'. Missing values are not allowed in InputsModel", + varName + )) + } + if (any(v < 0)) { + stop(sprintf( + "'%s' values must be positive or nul. Missing values are not allowed in InputsModel", + varName + )) + } + } + } else if (!varName %in% c("ZInputs", "NLayers")) { + stop(sprintf("'%s' must be a matrix or a data.frame", varName)) + } + } + }) +} diff --git a/R/utils.RunModel.R b/R/utils.RunModel.R index f1aef1ed8bbbbf33309b69756c936eb1e7719069..7846a97678d5521ada988e61803b55552ffb1340 100644 --- a/R/utils.RunModel.R +++ b/R/utils.RunModel.R @@ -61,7 +61,8 @@ OutputsModelQsim <- function(InputsModel, OutputsModel, IndPeriod_Run) { #' @noRd #' serializeIniStates <- function(IniStates) { - unlist(IniStates) + IniStates <- unlist(IniStates) + return(IniStates) } @@ -88,3 +89,56 @@ calcOverAbstraction <- function(O, WarmUp) { } return(O) } + + +#' Get the next time steps date/time of a simulation +#' +#' @param x Object returned by [RunModel.GRiwrmInputsModel], +#' [RunModel.Supervisor], or [RunModel.GRiwrmOutputsModel] +#' @param TimeStep [integer] number of time steps to get after the end of the +#' simulation +#' +#' @return A [POSIXct] containing the date/time of the time steps following +#' the end of the simulation. +#' @export +#' +getNextTimeSteps <- function(x, TimeStep = 1L) { + stopifnot(inherits(x, "GRiwrmOutputsModel"), + is.integer(TimeStep)) + last_date <- dplyr::last(x[[1]]$DatesR) + first_date <- last_date + attr(x, "TimeStep") + return(seq(first_date, length.out = TimeStep, by = attr(x, "TimeStep"))) +} + + +#' Merge Two outputs of airGR simulations +#' +#' @param x,y **OutputsModel** objects from [airGR::RunModel], +#' [RunModel.GRiwrmInputsModel], [RunModel.GRiwrmOutputsModel], [RunModel.Supervisor] +#' @param ... Not used +#' +#' @return An object **OutputsModel** with merged times series of simulation +#' results. +#' @rdname merge.OutputsModel +#' @export +#' +merge.OutputsModel <- function(x, y, ...) { + items <- names(x) + items <- items[!grepl("RunOptions|StateEnd", items)] + for (item in items) { + y[[item]] <- c(x[[item]], y[[item]]) + } + return(y) +} + +#' @rdname merge.OutputsModel +#' @export +merge.GRiwrmOutputsModel <- function(x, y, ...) { + y_attributes <- attributes(y) + y <- lapply(setNames(nm = names(y)), function(id) { + merge(x[[id]], y[[id]]) + }) + attributes(y) <- y_attributes + attr(y, "Qm3s") <- rbind(attr(x, "Qm3s"), attr(y, "Qm3s")) + return(y) +} diff --git a/man/CreateSupervisor.Rd b/man/CreateSupervisor.Rd index fed5a90124c95e9b4dbad2926efb889ca3a89970..c3083814275d78410cb23ac68af0da4673fd5bc8 100644 --- a/man/CreateSupervisor.Rd +++ b/man/CreateSupervisor.Rd @@ -9,7 +9,7 @@ CreateSupervisor(InputsModel, TimeStep = 1L) \arguments{ \item{InputsModel}{[object of type \code{GRiwrmInputsModel}] inputs of the model} -\item{TimeStep}{\link{numeric} number of time steps between each supervision} +\item{TimeStep}{\link{integer} number of time steps between each supervision} } \value{ A \code{Supervisor} object which is an \link{environment} containing all the necessary variables to run a supervised simulation, such as: diff --git a/man/RunModel.GRiwrmOutputsModel.Rd b/man/RunModel.GRiwrmOutputsModel.Rd new file mode 100644 index 0000000000000000000000000000000000000000..5dd80327f1370caa39943e2d8b154f0af88c6d6f --- /dev/null +++ b/man/RunModel.GRiwrmOutputsModel.Rd @@ -0,0 +1,80 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/RunModel.GRiwrmOutputsModel.R +\name{RunModel.GRiwrmOutputsModel} +\alias{RunModel.GRiwrmOutputsModel} +\title{RunModel for hot restart after a previous simulation period} +\usage{ +\method{RunModel}{GRiwrmOutputsModel}( + x, + InputsModel, + RunOptions, + IndPeriod_Run = which(InputsModel[[1]]$DatesR \%in\% DatesR), + DatesR = getNextTimeSteps(x), + Qinf = NULL, + Qrelease = NULL, + Qmin = NULL, + merge_outputs = TRUE, + ... +) +} +\arguments{ +\item{x}{Object returned by \link{RunModel.GRiwrmInputsModel}, +\link{RunModel.Supervisor}, or \link{RunModel.GRiwrmOutputsModel}} + +\item{InputsModel}{[object of class \emph{InputsModel}] see \code{\link[airGR]{CreateInputsModel}} for details} + +\item{RunOptions}{[object of class \emph{GRiwrmRunOptions}] see \link{CreateRunOptions.GRiwrmInputsModel} for details} + +\item{IndPeriod_Run}{[numeric] index of period to be used for the model run [-]. See details} + +\item{DatesR}{(optional) \link{POSIXt} vector of dates of period to be used for +the model run. See details} + +\item{Qinf}{(optional) \link{matrix} or \link{data.frame} of \link{numeric} containing +observed flows. It must be provided only for nodes of type "Direct +injection" and "Diversion" [m3 per time step]. +Column names correspond to node IDs. Negative flows are abstracted from +the model and positive flows are injected to the model. See details} + +\item{Qrelease}{(optional) \link{matrix} or \link{data.frame} of \link{numeric} containing +release flows by nodes using the model \code{RunModel_Reservoir} [m3 per +time step]. See details} + +\item{Qmin}{(optional) \link{matrix} or \link{data.frame} of \link{numeric} containing +minimum flows to let downstream of a node with a Diversion [m3 per +time step]. Default is zero. Column names correspond to node IDs. +See details} + +\item{merge_outputs}{\link{logical} Merge simulation outputs with the one provided +in argument \code{x}} + +\item{...}{Further arguments for compatibility with S3 methods} +} +\value{ +An object of class \emph{GRiwrmOutputsModel}. +This object is a \link{list} of \emph{OutputsModel} objects produced by \link{RunModel.InputsModel} +for each node of the semi-distributed model. + +It also contains the following attributes (see \link{attr}): +\itemize{ +\item "Qm3s": a \link{data.frame} containing the dates of simulation and one column by node +with the simulated flows in cubic meters per seconds (See \link{plot.Qm3s}) +\item "GRiwrm": a copy of the \emph{GRiwrm} object produced by \link{CreateGRiwrm} and used for the simulation +\item "TimeStep": time step of the simulation in seconds +} +} +\description{ +This function allows to restart a simulation at the end of a previous +simulation period. Parameters \code{Qinf}, \code{Qrelease}, and \code{Qmin} can be +redefined for this new simulation period. +} +\details{ +\code{IndPeriod_Run} or \code{DatesR} must must be continuous periods starting the +time step after the last simulation time step of the \code{GRiwrmOutputsModel} +object provided through the argument \code{x}. + +\code{Qinf}, \code{Qmin}, and \code{Qrelease} are used for overwriting the corresponding +arguments provided to \link{CreateInputsModel.GRiwrm} for the period to be simulated. +Therefore, the number of rows of these arguments must correspond to +\code{IndPeriod_Run} or \code{DatesR} lengths. +} diff --git a/man/extractParam.Rd b/man/extractParam.Rd index 702831cc13de6f4fc189db5911f15700f62dda3f..4f410a4f592b1bfd43302ca70466f3263304c509 100644 --- a/man/extractParam.Rd +++ b/man/extractParam.Rd @@ -2,9 +2,15 @@ % Please edit documentation in R/utils.Calibration.R \name{extractParam} \alias{extractParam} +\alias{extractParam.GRiwrmOutputsCalib} +\alias{extractParam.GRiwrmOutputsModel} \title{Extract calibrated parameters} \usage{ extractParam(x) + +\method{extractParam}{GRiwrmOutputsCalib}(x) + +\method{extractParam}{GRiwrmOutputsModel}(x) } \arguments{ \item{x}{A \emph{GRiwrmOutputsModel} object returned by \link{Calibration.GRiwrmInputsModel}} diff --git a/man/getNextTimeSteps.Rd b/man/getNextTimeSteps.Rd new file mode 100644 index 0000000000000000000000000000000000000000..d3984e0822b2f990d14566a6a30921b992a6d982 --- /dev/null +++ b/man/getNextTimeSteps.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.RunModel.R +\name{getNextTimeSteps} +\alias{getNextTimeSteps} +\title{Get the next time steps date/time of a simulation} +\usage{ +getNextTimeSteps(x, TimeStep = 1L) +} +\arguments{ +\item{x}{Object returned by \link{RunModel.GRiwrmInputsModel}, +\link{RunModel.Supervisor}, or \link{RunModel.GRiwrmOutputsModel}} + +\item{TimeStep}{\link{integer} number of time steps to get after the end of the +simulation} +} +\value{ +A \link{POSIXct} containing the date/time of the time steps following +the end of the simulation. +} +\description{ +Get the next time steps date/time of a simulation +} diff --git a/man/merge.OutputsModel.Rd b/man/merge.OutputsModel.Rd new file mode 100644 index 0000000000000000000000000000000000000000..373d4f31ae6727373c7f5672e15f8721a788814b --- /dev/null +++ b/man/merge.OutputsModel.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.RunModel.R +\name{merge.OutputsModel} +\alias{merge.OutputsModel} +\alias{merge.GRiwrmOutputsModel} +\title{Merge Two outputs of airGR simulations} +\usage{ +\method{merge}{OutputsModel}(x, y, ...) + +\method{merge}{GRiwrmOutputsModel}(x, y, ...) +} +\arguments{ +\item{x, y}{\strong{OutputsModel} objects from \link[airGR:RunModel]{airGR::RunModel}, +\link{RunModel.GRiwrmInputsModel}, \link{RunModel.GRiwrmOutputsModel}, \link{RunModel.Supervisor}} + +\item{...}{Not used} +} +\value{ +An object \strong{OutputsModel} with merged times series of simulation +results. +} +\description{ +Merge Two outputs of airGR simulations +} diff --git a/tests/testthat/helper_1_RunModel.R b/tests/testthat/helper_1_RunModel.R index c8d7fedbc0bf33119c0820ffdc591a7fa8973cb3..57110eb77e2d6273cdcd813668b05a6d64bb3681 100644 --- a/tests/testthat/helper_1_RunModel.R +++ b/tests/testthat/helper_1_RunModel.R @@ -17,6 +17,7 @@ setupRunModel <- griwrm = NULL, Qinf = NULL, Qrelease = NULL, + Qmin = NULL, IsHyst = FALSE) { data(Severn) @@ -100,8 +101,9 @@ setupRunModel <- InputsModel <- suppressWarnings(CreateInputsModel(griwrm, DatesR, Precip, PotEvap, TempMean = TempMean, - Qobs = Qinf, + Qinf = Qinf, Qrelease = Qrelease, + Qmin = Qmin, IsHyst = IsHyst)) # RunOptions diff --git a/tests/testthat/test-RunModel.GRiwrmOutputsModel.R b/tests/testthat/test-RunModel.GRiwrmOutputsModel.R new file mode 100644 index 0000000000000000000000000000000000000000..ee054134b557c234ce66c6147cc53245c89f9038 --- /dev/null +++ b/tests/testthat/test-RunModel.GRiwrmOutputsModel.R @@ -0,0 +1,69 @@ +skip_on_cran() +test_that("RunModel.GRiwrmOutputsModel works", { + # Setup model + griwrm <- CreateGRiwrm(rbind( + n_derived_rsrvr, + data.frame( + id = "WD", + down = "Dam", + length = 0, + area = NA, + model = NA + ) + )) + data(Severn) + DatesR <- Severn$BasinsObs[[1]]$DatesR + Qinf <- data.frame( + # Diversion to the dam + `54095` = rep(-1E6, length(DatesR)), + # Withdrawal in the dam + WD = rep(-250000, length(DatesR)) + ) + names(Qinf)[1] <- "54095" + # Release of the dam back to the river + Qrelease <- data.frame(Dam = rep(100E3, length(DatesR))) + # Diversion limited by fixed minimum flow to let in the river + Qmin <- data.frame("54095" = rep(3E6, length(DatesR))) + names(Qmin) <- "54095" + e <- setupRunModel( + griwrm = griwrm, + Qinf = Qinf, + Qrelease = Qrelease, + Qmin = Qmin, + runRunOptions = FALSE + ) + for (x in ls(e)) assign(x, get(x, e)) + + # Set up initial conditions + RunOptions <- CreateRunOptions(InputsModel, IndPeriod_WarmUp = 1:364, IndPeriod_Run = 365L) + Param <- c(ParamMichel[names(ParamMichel) %in% griwrm$id], list(Dam = c(100E6, 1))) + OM <- RunModel(InputsModel, RunOptions, Param) + + # Loop over periods months periods + dfTS <- data.frame( + DatesR = DatesR, + yearmonth = format(DatesR, "%Y-%m") + ) + + for(ym in unique(dfTS$yearmonth[dfTS$DatesR > OM[[1]]$DatesR])) { + + # Preparing extract of Qinf for the current run + ym_IndPeriod_Run <- which(dfTS$yearmonth == ym) + ym_Qinf <- Qinf[ym_IndPeriod_Run, , drop = FALSE] + ym_Qrelease <- Qrelease[ym_IndPeriod_Run, , drop = FALSE] + + # 50% Restriction on reservoir withdrawals if remaining less than 90 days of water + nb_remain_days <- OM$Dam$StateEnd$Reservoir$V / (-ym_Qinf$`WD`[1] + ym_Qrelease$Dam[1]) + if (nb_remain_days < 180) { + ym_Qinf$`WD` <- -(max(0, OM$Dam$StateEnd$Reservoir$V - sum(ym_Qrelease$Dam))) / 365 + } + OM <- RunModel(OM, + InputsModel = InputsModel, + RunOptions = RunOptions, + IndPeriod_Run = ym_IndPeriod_Run, + Qinf = ym_Qinf) + } + + expect_equal(nrow(attr(OM, "Qm3s")), length(DatesR) - 364) + expect_equal(length(OM[[1]]$DatesR), length(DatesR) - 364) +}) diff --git a/vignettes/V06_Modelling_regulated_diversion.Rmd b/vignettes/V06_Modelling_regulated_diversion.Rmd index 1c37c46f31bce11504b77ad639da09ea04d82bf8..c08819b685323faaf0d97a78f13a82de793b49b2 100644 --- a/vignettes/V06_Modelling_regulated_diversion.Rmd +++ b/vignettes/V06_Modelling_regulated_diversion.Rmd @@ -195,7 +195,7 @@ with and without low-flow support at station 54001: dfQdiv <- data.frame(DatesR = OM_div[[1]]$DatesR, Diverted_flow = OM_div$`54001`$Qdiv_m3 / 86400) -oldpar <- par(mfrow=c(3,1), mar = c(2.5,4,1,1)) +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"