Commit 0ed4b876 authored by Dorchies David's avatar Dorchies David
Browse files

feat: Overriding airGR CreateInputsModel, RunOptions and RunModel

Fix #4
Showing with 368 additions and 139 deletions
+368 -139
# Generated by roxygen2: do not edit by hand # Generated by roxygen2: do not edit by hand
S3method(Calibration,default)
S3method(Calibration,griwrm)
S3method(CreateInputsModel,Griwrm)
S3method(CreateInputsModel,default)
S3method(CreateRunOptions,GriwrmInputsModel)
S3method(CreateRunOptions,InputsModel)
S3method(RunModel,GriwrmInputsModel)
S3method(RunModel,InputsModel)
S3method(merge,Gits) S3method(merge,Gits)
export(Calibration)
export(CreateInputsModel)
export(CreateRunOptions)
export(Ginet) export(Ginet)
export(Girop) export(Girop)
export(Gits) export(Gits)
export(RunModelGriwrm) export(RunModel)
export(SetAirGrInputsAndOptions)
export(getNodeRanking) export(getNodeRanking)
import(airGR) import(airGR)
#' Title #' Create InputsModel object for a GRIWRM network
#' #'
#' @param ginet #' @param ginet
#' @param girop #' @param girop
#' @param gits #' @param gits
#' @param IndPeriod_Run
#' @param IndPeriod_WarmUp
#' #'
#' @return #' @return
#' @import airGR
#' @export #' @export
#' #'
#' @examples #' @examples
RunModelGriwrm <- function(ginet, girop, gits, IndPeriod_Run, IndPeriod_WarmUp = NULL, verbose = TRUE) { CreateInputsModel.Griwrm <- function(ginet, girop, gits, verbose = TRUE) {
OutputsModels <- list() InputsModel <- CreateEmptyGriwrmInputsModel()
for(id in getNodeRanking(ginet)) { for(id in getNodeRanking(ginet)) {
if(verbose) cat("*** Treating sub-basin", id, "... ***\n") if(verbose) cat("CreateInputsModel.griwrm: Treating sub-basin", id, "...\n")
InputsModel[[id]] <- CreateOneGriwrmInputsModel(id, ginet, girop, gits)
# Set InputsModel and RunOptions }
lIO <- SetAirGrInputsAndOptions( return(InputsModel)
id, ginet, girop, gits, OutputsModels, }
IndPeriod_Run, IndPeriod_WarmUp
)
# Prepare param for upstream sub-basin or basin with hydraulic routing
Param <- unlist(girop$params[girop$id == id])
# Run the model for the sub-basin
OutputsModels[[id]] <- RunModel(
FUN_MOD = girop$model[girop$id == id],
InputsModel = lIO$InputsModel,
RunOptions = lIO$RunOptions,
Param = Param
)
} #' Create an empty InputsModel object for GRIWRM nodes
OutputsModels #'
#' @return
#'
#' @examples
CreateEmptyGriwrmInputsModel <- function() {
InputsModel <- list()
class(InputsModel) <- append(class(InputsModel), "GriwrmInputsModel")
return(InputsModel)
} }
#' Title
#' Create one InputsModel for a GRIWRM node
#' #'
#' @param id
#' @param ginet #' @param ginet
#' @param girop #' @param girop
#' @param gits #' @param gits
#' @param IndPeriod_Run #' @param id
#' @param IndPeriod_WarmUp
#' #'
#' @return #' @return
#' @import airGR
#' @export
#' #'
#' @examples #' @examples
SetAirGrInputsAndOptions <- function(id, ginet, girop, gits, OutputsModels, IndPeriod_Run, IndPeriod_WarmUp = NULL) { CreateOneGriwrmInputsModel <- function(id, ginet, girop, gits) {
node <- ginet[ginet$id == id,] node <- ginet[ginet$id == id,]
FUN_MOD <- girop$model[girop$id == id] FUN_MOD <- girop$model[girop$id == id]
# Set hydraulic parameters # Set hydraulic parameters
UpstrNodes <- ginet$id[ginet$down == id & !is.na(ginet$down)] UpstreamNodes <- ginet$id[ginet$down == id & !is.na(ginet$down)]
if(length(UpstrNodes) == 0) { QobsUpstr <- NULL
# Upstream sub-basin LengthHydro <- NULL
QobsUpstr <- NULL BasinAreas <- NULL
LengthHydro <- NULL
BasinAreas <- NULL if(length(UpstreamNodes) > 0) {
} else {
# Sub-basin with hydraulic routing # Sub-basin with hydraulic routing
for(i in 1:length(UpstrNodes)) { for(idUpstrNode in UpstreamNodes) {
QobsUpstr1 <- matrix( QobsUpstr1 <- matrix(gits[[idUpstrNode]]$Qobs, ncol = 1)
c( if(is.null(QobsUpstr)) {
rep(0, length(IndPeriod_WarmUp)),
OutputsModels[[UpstrNodes[i]]]$Qsim
), ncol = 1
)
if(i == 1) {
QobsUpstr <- QobsUpstr1 QobsUpstr <- QobsUpstr1
} else { } else {
QobsUpstr <- cbind(QobsUpstr, QobsUpstr1) QobsUpstr <- cbind(QobsUpstr, QobsUpstr1)
} }
} }
LengthHydro <- matrix(ginet$length[girop$id %in% UpstrNodes] , nrow = 1) LengthHydro <- matrix(ginet$length[girop$id %in% UpstreamNodes] , nrow = 1)
BasinAreas <- matrix( BasinAreas <- matrix(
c( c(
girop$area[girop$id %in% UpstrNodes], girop$area[girop$id %in% UpstreamNodes],
girop$area[girop$id == id] - sum(girop$area[girop$id %in% UpstrNodes]) girop$area[girop$id == id] - sum(girop$area[girop$id %in% UpstreamNodes])
), ),
nrow = 1 nrow = 1
) )
} }
# Set model inputs
# Set model inputs with the airGR function
InputsModel <- CreateInputsModel( InputsModel <- CreateInputsModel(
FUN_MOD = FUN_MOD, FUN_MOD,
DatesR = gits$date, DatesR = gits$date,
Precip = gits[[id]]$Precip, Precip = gits[[id]]$Precip,
PotEvap = gits[[id]]$PotEvap, PotEvap = gits[[id]]$PotEvap,
...@@ -97,11 +82,14 @@ SetAirGrInputsAndOptions <- function(id, ginet, girop, gits, OutputsModels, IndP ...@@ -97,11 +82,14 @@ SetAirGrInputsAndOptions <- function(id, ginet, girop, gits, OutputsModels, IndP
LengthHydro = LengthHydro, LengthHydro = LengthHydro,
BasinAreas = BasinAreas BasinAreas = BasinAreas
) )
# Set model options
RunOptions <- CreateRunOptions( # Add Identifiers of connected nodes in order to be able to update them with simulated flows
FUN_MOD = FUN_MOD, InputsModel$id <- id
InputsModel = InputsModel, IndPeriod_Run = IndPeriod_Run, if(length(UpstreamNodes) > 0) {
IniStates = NULL, IniResLevels = NULL, IndPeriod_WarmUp = IndPeriod_WarmUp InputsModel$UpstreamNodes <- UpstreamNodes
) }
list(InputsModel = InputsModel, RunOptions = RunOptions) # Add the model function
InputsModel$FUN_MOD <- FUN_MOD
return(InputsModel)
} }
...@@ -10,126 +10,3 @@ ...@@ -10,126 +10,3 @@
CreateInputsModel <- function(x, ...) { CreateInputsModel <- function(x, ...) {
UseMethod("CreateInputsModel", x) UseMethod("CreateInputsModel", x)
} }
#' Wrapper for the airGR::CreateInputsModel function
#'
#' @param FUN_MOD
#' @param DatesR
#' @param Precip
#' @param PrecipScale
#' @param PotEvap
#' @param TempMean
#' @param TempMin
#' @param TempMax
#' @param ZInputs
#' @param HypsoData
#' @param NLayers
#' @param QobsUpstr
#' @param LengthHydro
#' @param BasinAreas
#' @param verbose
#'
#' @return
#' @export
#'
#' @examples
CreateInputsModel.default <- function(FUN_MOD,
DatesR,
Precip, PrecipScale = TRUE,
PotEvap = NULL,
TempMean = NULL, TempMin = NULL, TempMax = NULL,
ZInputs = NULL, HypsoData = NULL, NLayers = 5,
QobsUpstr = NULL, LengthHydro = NULL, BasinAreas = NULL,
verbose = TRUE) {
airGR::CreateInputsModel(FUN_MOD, DatesR, Precip, PrecipScale, PotEvap,
TempMean, TempMin, TempMax, ZInputs, HypsoData, NLayers,
QobsUpstr, LengthHydro, BasinAreas, verbose)
}
#' Create InputsModel object for a GRIWRM network
#'
#' @param ginet
#' @param girop
#' @param gits
#'
#' @return
#' @export
#'
#' @examples
CreateInputsModel.Griwrm <- function(ginet, girop, gits, verbose = TRUE) {
InputsModel <- CreateEmptyGriwrmInputsModel()
for(id in getNodeRanking(ginet)) {
if(verbose) cat("CreateInputsModel.griwrm: Treating sub-basin", id, "...\n")
InputsModel[[id]] <- CreateOneGriwrmInputsModel(id, ginet, girop, gits)
}
}
#' Create an empty InputsModel object for GRIWRM
#'
#' @return
#' @export
#'
#' @examples
CreateEmptyGriwrmInputsModel <- function() {
InputsModel <- list()
class(InputsModel) <- append(class(InputsModel), "GriwrmInputsModel")
return(InputsModel)
}
#' Create one InputsModel for a GRIWRM node
#'
#' @param ginet
#' @param girop
#' @param gits
#' @param id
#'
#' @return
#' @export
#'
#' @examples
CreateOneGriwrmInputsModel <- function(id, ginet, girop, gits) {
node <- ginet[ginet$id == id,]
FUN_MOD <- girop$model[girop$id == id]
# Set hydraulic parameters
UpstrNodes <- ginet$id[ginet$down == id & !is.na(ginet$down)]
QobsUpstr <- NULL
LengthHydro <- NULL
BasinAreas <- NULL
if(length(UpstrNodes) > 0) {
# Sub-basin with hydraulic routing
for(idUpstrNode in UpstrNodes) {
QobsUpstr1 <- matrix(gits[[idUpstrNode]]$Qobs, ncol = 1)
if(is.null(QobsUpstr)) {
QobsUpstr <- QobsUpstr1
} else {
QobsUpstr <- cbind(QobsUpstr, QobsUpstr1)
}
}
LengthHydro <- matrix(ginet$length[girop$id %in% UpstrNodes] , nrow = 1)
BasinAreas <- matrix(
c(
girop$area[girop$id %in% UpstrNodes],
girop$area[girop$id == id] - sum(girop$area[girop$id %in% UpstrNodes])
),
nrow = 1
)
}
# Set model inputs
CreateInputsModel(
FUN_MOD,
DatesR = gits$date,
Precip = gits[[id]]$Precip,
PotEvap = gits[[id]]$PotEvap,
QobsUpstr = QobsUpstr,
LengthHydro = LengthHydro,
BasinAreas = BasinAreas
)
}
#' Wrapper for the airGR::CreateInputsModel function
#'
#' @param FUN_MOD
#' @param DatesR
#' @param Precip
#' @param PrecipScale
#' @param PotEvap
#' @param TempMean
#' @param TempMin
#' @param TempMax
#' @param ZInputs
#' @param HypsoData
#' @param NLayers
#' @param QobsUpstr
#' @param LengthHydro
#' @param BasinAreas
#' @param verbose
#'
#' @return
#' @import airGR
#' @export
#'
#' @examples
CreateInputsModel.default <- function(FUN_MOD,
DatesR,
Precip, PrecipScale = TRUE,
PotEvap = NULL,
TempMean = NULL, TempMin = NULL, TempMax = NULL,
ZInputs = NULL, HypsoData = NULL, NLayers = 5,
QobsUpstr = NULL, LengthHydro = NULL, BasinAreas = NULL,
verbose = TRUE) {
airGR::CreateInputsModel(FUN_MOD, DatesR, Precip, PrecipScale, PotEvap,
TempMean, TempMin, TempMax, ZInputs, HypsoData, NLayers,
QobsUpstr, LengthHydro, BasinAreas, verbose)
}
#' Title
#'
#' @param InputsModel
#' @param IndPeriod_WarmUp
#' @param IndPeriod_Run
#' @param IniStates
#' @param IniResLevels
#' @param Imax
#' @param Outputs_Cal
#' @param Outputs_Sim
#' @param MeanAnSolidPrecip
#' @param IsHyst
#' @param warnings
#' @param verbose
#'
#' @return
#' @export
#'
#' @examples
CreateRunOptions.GriwrmInputsModel <- function(InputsModel, IndPeriod_WarmUp = NULL, IndPeriod_Run,
IniStates = NULL, IniResLevels = NULL, Imax = NULL,
Outputs_Cal = NULL, Outputs_Sim = "all",
MeanAnSolidPrecip = NULL, IsHyst = FALSE,
warnings = TRUE, verbose = TRUE) {
RunOptions <- list()
class(RunOptions) <- append(class(RunOptions), "GriwrmRunOptions")
for(InputsModelBasin in InputsModel) {
RunOptions[[InputsModelBasin$id]] <- CreateRunOptions(
InputsModel = InputsModelBasin,
IndPeriod_WarmUp = IndPeriod_WarmUp,
IndPeriod_Run = IndPeriod_Run,
IniStates = IniStates,
IniResLevels = IniResLevels,
Imax = Imax,
Outputs_Cal = Outputs_Cal,
Outputs_Sim = Outputs_Sim,
MeanAnSolidPrecip = MeanAnSolidPrecip,
IsHyst = IsHyst,
warnings = warnings,
verbose = verbose
)
}
return(RunOptions)
}
#' Title
#'
#' @param FUN_MOD
#' @param InputsModel
#' @param IndPeriod_WarmUp
#' @param IndPeriod_Run
#' @param IniStates
#' @param IniResLevels
#' @param Imax
#' @param Outputs_Cal
#' @param Outputs_Sim
#' @param MeanAnSolidPrecip
#' @param IsHyst
#' @param warnings
#' @param verbose
#'
#' @return
#' @export
#'
#' @examples
CreateRunOptions.InputsModel <- function(InputsModel,
IndPeriod_WarmUp = NULL, IndPeriod_Run,
IniStates = NULL, IniResLevels = NULL, Imax = NULL,
Outputs_Cal = NULL, Outputs_Sim = "all",
MeanAnSolidPrecip = NULL, IsHyst = FALSE,
warnings = TRUE, verbose = TRUE) {
airGR::CreateRunOptions(FUN_MOD = InputsModel$FUN_MOD,
InputsModel = InputsModel,
IndPeriod_WarmUp = IndPeriod_WarmUp,
IndPeriod_Run = IndPeriod_Run,
IniStates = IniStates,
IniResLevels = IniResLevels,
Imax = Imax,
Outputs_Cal = Outputs_Cal,
Outputs_Sim = Outputs_Sim,
MeanAnSolidPrecip = MeanAnSolidPrecip,
IsHyst = IsHyst,
warnings = warnings,
verbose = verbose)
}
#' Title
#'
#' @param ...
#' @param InputsModel
#'
#' @return
#' @export
#'
#' @examples
CreateRunOptions <- function(InputsModel, ...) {
UseMethod("CreateRunOptions", InputsModel)
}
#' Title
#'
#' @param ginet
#' @param girop
#' @param gits
#' @param IndPeriod_Run
#' @param IndPeriod_WarmUp
#'
#' @return
#' @export
#'
#' @examples
RunModel.GriwrmInputsModel <- function(InputsModel, RunOptions, girop, verbose = TRUE) {
OutputsModels <- list()
for(IM in InputsModel) {
if(verbose) cat("RunModel.GriwrmInputsModel: Treating sub-basin", IM$id, "...\n")
# Update InputsModel$QobsUpstr with simulated upstream flows
if(length(IM$UpstreamNodes) > 0) {
for(i in 1:length(IM$UpstreamNodes)) {
QobsUpstr1 <- matrix(
c(
rep(0, length(RunOptions[[IM$id]]$IndPeriod_WarmUp)),
OutputsModels[[IM$UpstreamNodes[i]]]$Qsim
), ncol = 1
)
if(i == 1) {
IM$QobsUpstr <- QobsUpstr1
} else {
IM$QobsUpstr <- cbind(IM$QobsUpstr, QobsUpstr1)
}
}
}
# Run the model for the sub-basin
OutputsModels[[IM$id]] <- RunModel(
InputsModel = IM,
RunOptions = RunOptions[[IM$id]],
Param = unlist(girop$params[girop$id == IM$id])
)
}
return(OutputsModels)
}
#' Wrapper for \code{\link[airGR]{RunModel}} which performs a single model run with the provided function over the selected period.
#'
#' @param InputsModel object of class \emph{InputsModel}, see \code{\link[airGR]{CreateInputsModel}} for details.
#' @param RunOptions object of class \emph{RunOptions}, see \code{\link[airGR]{CreateRunOptions}} for details.
#' @param Param numeric vector of model parameters.
#' @param FUN_MOD hydrological model function (e.g. \code{\link[airGR]{RunModel_GR4J}}, \code{\link[airGR]{RunModel_CemaNeigeGR4J}}).
#'
#' @return
#' @export
#'
#' @examples
RunModel.InputsModel <- function(InputsModel, RunOptions, Param, FUN_MOD = NULL) {
if(is.null(FUN_MOD)) {
FUN_MOD <- InputsModel$FUN_MOD
}
airGR::RunModel(InputsModel, RunOptions, Param, FUN_MOD)
}
R/RunModel.R 0 → 100644
#' RunModel function for both airGR and GriwrmInputsModel object
#'
#' @param InputsModel
#' @param ...
#'
#' @return
#' @export
#'
#' @examples
RunModel <- function(InputsModel, ...) {
UseMethod("RunModel", InputsModel)
}
...@@ -80,10 +80,9 @@ load_ts <- function(x) { ...@@ -80,10 +80,9 @@ load_ts <- function(x) {
delim = ";", skip = 16, trim_ws = TRUE) delim = ";", skip = 16, trim_ws = TRUE)
ts$Date <- as.POSIXlt(lubridate::ymd(ts$Date)) ts$Date <- as.POSIXlt(lubridate::ymd(ts$Date))
# Interpolation of data gap in the discharge time serie # Interpolation of data gap in the discharge time serie
browser
ts[ts$Qnat < 0, "Qnat"] <- NA ts[ts$Qnat < 0, "Qnat"] <- NA
if(is.na(ts$Qnat[nrow(ts)])) { if(is.na(ts$Qnat[nrow(ts)])) {
ts$Qnat[nrow(ts)] <- 0 # End of time series converge to zero ts$Qnat[nrow(ts)] <- 0 # No value at the end: time serie converge to zero
} }
ts$Qnat <- zoo::na.approx(ts$Qnat) ts$Qnat <- zoo::na.approx(ts$Qnat)
ts ts
...@@ -120,7 +119,7 @@ The airGR CreateInputsModel function is extended in order to handle the ginet ob ...@@ -120,7 +119,7 @@ The airGR CreateInputsModel function is extended in order to handle the ginet ob
```{r} ```{r}
InputsModel <- CreateInputsModel(ginet, girop, gits) InputsModel <- CreateInputsModel(ginet, girop, gits)
``` ```
...@@ -129,6 +128,6 @@ The airGR CreateInputsModel function is extended in order to handle the ginet ob ...@@ -129,6 +128,6 @@ The airGR CreateInputsModel function is extended in order to handle the ginet ob
```{r} ```{r}
dir.create("_cache", showWarnings = FALSE) dir.create("_cache", showWarnings = FALSE)
save(ginet, girop, gits, file = "_cache/seine.RData") save(ginet, girop, gits, InputsModel, file = "_cache/seine.RData")
``` ```
...@@ -9,13 +9,25 @@ output: html_document ...@@ -9,13 +9,25 @@ output: html_document
knitr::opts_chunk$set(echo = TRUE) knitr::opts_chunk$set(echo = TRUE)
``` ```
## Load parameters of GR4 run-off model ## Load libraries
```{r} ```{r}
library(griwrm) library(griwrm)
```
## Load parameters of GR4 run-off model
### Loading network and time series data
Run `vignette("01_First_network", package = "griwrm")` before this one in order to create the Rdata file loaded below:
```{r}
load("_cache/seine.RData") load("_cache/seine.RData")
``` ```
### Loading
Data comes from calibration of ClimAware project with naturalised flows. Data comes from calibration of ClimAware project with naturalised flows.
```{r} ```{r}
...@@ -27,7 +39,7 @@ ClimAwareParams ...@@ -27,7 +39,7 @@ ClimAwareParams
``` ```
The lag $\tau_0$ and route $K_0$ parameters of TGR are expressed as time delay in hours corresponding to the delay time between the farest upstream inlet and the outlet of the sub-basin. The lag $\tau_0$ and route $K_0$ parameters of TGR are expressed as time delay in hours corresponding to the delay time between the farest upstream inlet and the outlet of the sub-basin.
Almost all sub basin has only a lag parameter. The only exception is for La Marne à Noisiel (NOISI_17) that has a routing parameter which can be approximated to a single lag parameter equals to $\tau_0 + K_0$. Almost all sub basin has only a lag parameter. The only exception is for La Marne à Noisiel (NOISI_17) that has a routing parameter which can be approximated to a single lag parameter equals to $\tau_0 + K_0$.
This lag parameter has to be converted in a speed in m/s used in the airGR lag model: This lag parameter has to be converted in a speed in m/s used in the airGR lag model:
...@@ -48,22 +60,52 @@ for(id in girop$id) { ...@@ -48,22 +60,52 @@ for(id in girop$id) {
girop$params[girop$id == id] <- list(params[params$id == id, c("S", "IGF", "KR", "T", sLag)]) girop$params[girop$id == id] <- list(params[params$id == id, c("S", "IGF", "KR", "T", sLag)])
} }
dplyr::select(params, id, S, IGF, KR, T, LAG)
``` ```
## Run the SD model for the whole basin ## GriwmRunOptions object
The `CreateRunOptions()` function allows to prepare the options required to the `RunModel()` function.
The user must at least define the following arguments:
* InputsModel: the associated input data
* IndPeriod_Run: the period on which the model is run
```{r} ```{r}
# Time settings
library(lubridate) library(lubridate)
IndPeriod_Run <- seq( IndPeriod_Run <- seq(
which(gits$date == (gits$date[1] + months(12))), # Set aside warm-up period which(InputsModel[[1]]$DatesR == (InputsModel[[1]]$DatesR[1] + months(12))), # Set aside warm-up period
length(gits$date)) # Until the end of the time series length(InputsModel[[1]]$DatesR) # Until the end of the time series
)
```
The warmup period could also be defined as is:
```{r}
IndPeriod_WarmUp = seq(1,IndPeriod_Run[1]-1) IndPeriod_WarmUp = seq(1,IndPeriod_Run[1]-1)
```
OutputsModels <- RunModelGriwrm(
ginet, girop, gits,
IndPeriod_Run = IndPeriod_Run, ```{r}
IndPeriod_WarmUp = IndPeriod_WarmUp RunOptions <- CreateRunOptions(
InputsModel = InputsModel,
IndPeriod_WarmUp = IndPeriod_WarmUp,
IndPeriod_Run = IndPeriod_Run
)
```
## Run the SD model for the whole basin
```{r}
OutputsModels <- RunModel(
InputsModel = InputsModel,
RunOptions = RunOptions,
girop
) )
``` ```
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment