From 10f48a097acc184d3781483e27058527fcf05a29 Mon Sep 17 00:00:00 2001 From: David <david.dorchies@inrae.fr> Date: Thu, 5 Dec 2024 03:18:48 +0100 Subject: [PATCH] fix(RunModel.GRiwrmOutputsModel): test and debug final state Refs #174 --- R/RunModel.Supervisor.R | 12 +- .../test-RunModel.GRiwrmOutputsModel.R | 135 ++++++++++++------ 2 files changed, 99 insertions(+), 48 deletions(-) diff --git a/R/RunModel.Supervisor.R b/R/RunModel.Supervisor.R index 5dd28fa..57a59f2 100644 --- a/R/RunModel.Supervisor.R +++ b/R/RunModel.Supervisor.R @@ -159,20 +159,24 @@ RunModel.Supervisor <- function(x, RunOptions, Param, ...) { message(" 100%") for (id in SD_Ids) { - StateEnd <- x$OutputsModel[[id]]$StateEnd if (inherits(x$InputsModel[[id]], "GR")) { + # Copy OutputsModel from original run of GR contribution for the whole time series + # Except for StateEnd which has been modified + StateEnd <- x$OutputsModel[[id]]$StateEnd x$OutputsModel[[id]] <- OutputsModelGR[[id]] + class_StateEnd <- class(x$OutputsModel[[id]]$StateEnd) + x$OutputsModel[[id]]$StateEnd <- c(x$OutputsModel[[id]]$StateEnd, StateEnd) + class(x$OutputsModel[[id]]$StateEnd) <- class_StateEnd } else { + # Add missing DatesR for non GR models x$OutputsModel[[id]]$DatesR <- x$InputsModel[[1]]$DatesR[IndPeriod_Run] } + # Copy stored outputs for the whole time series for (outputVar in outputVars[[id]]) { x$OutputsModel[[id]][[outputVar]] <- x$storedOutputs[[outputVar]][, id] } x$OutputsModel[[id]]$Qsim <- x$storedOutputs$Qsim_m3[, id] / sum(x$InputsModel[[id]]$BasinAreas, na.rm = TRUE) / 1e3 - class_StateEnd <- class(x$OutputsModel[[id]]$StateEnd) - x$OutputsModel[[id]]$StateEnd <- c(x$OutputsModel[[id]]$StateEnd, StateEnd) - class(x$OutputsModel[[id]]$StateEnd) <- class_StateEnd x$OutputsModel[[id]]$RunOptions$WarmUpQsim_m3 <- OM_WarmUp[[id]]$Qsim_m3 x$OutputsModel[[id]]$RunOptions$WarmUpQsim <- OM_WarmUp[[id]]$Qsim_m3 / sum(x$InputsModel[[id]]$BasinAreas, na.rm = TRUE) / 1e3 diff --git a/tests/testthat/test-RunModel.GRiwrmOutputsModel.R b/tests/testthat/test-RunModel.GRiwrmOutputsModel.R index ee05413..d0dc612 100644 --- a/tests/testthat/test-RunModel.GRiwrmOutputsModel.R +++ b/tests/testthat/test-RunModel.GRiwrmOutputsModel.R @@ -1,49 +1,52 @@ 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 + +# Setup model +griwrm <- CreateGRiwrm(rbind( + n_derived_rsrvr, + data.frame( + id = "WD", + down = "Dam", + length = 0, + area = NA, + model = NA ) - for (x in ls(e)) assign(x, get(x, e)) +)) +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) +# 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") - ) +# Loop over periods months periods +dfTS <- data.frame( + DatesR = DatesR, + yearmonth = format(DatesR, "%Y-%m") +) +dfTS <- dfTS[1:(which(dfTS$yearmonth == "1987-01")[1]), ] + +test_that("RunModel.GRiwrmOutputsModel works with InputsModel", { for(ym in unique(dfTS$yearmonth[dfTS$DatesR > OM[[1]]$DatesR])) { @@ -64,6 +67,50 @@ test_that("RunModel.GRiwrmOutputsModel works", { Qinf = ym_Qinf) } - expect_equal(nrow(attr(OM, "Qm3s")), length(DatesR) - 364) - expect_equal(length(OM[[1]]$DatesR), length(DatesR) - 364) + expect_equal(nrow(attr(OM, "Qm3s")), nrow(dfTS) - 364) + expect_equal(length(OM[[1]]$DatesR), nrow(dfTS) - 364) +}) + +test_that("RunModel.GRiwrmOutputsModel works with Supervisor", { + + sv <- CreateSupervisor(InputsModel) + + curve <- approx(x = c(31*11 - 365, 30 * 6, 31 * 11, 366 + 30 * 6), + y = c(20E6, 90E6, 20E6, 90E6), + xout = 1:366)$y + + fn_guide_curve_factory <- function(sv, curve) { + function(y) { + # How much to release for reaching the filling curve ? + deltaV <- sv$OutputsModel$Dam$Vsim - curve[lubridate::yday(sv$ts.date)] + # Minimum 500L/s and max 1E6 m3 + return(max(86400 / 2, min(1E6, deltaV))) + } + } + fn_guide_curve <- fn_guide_curve_factory(sv, curve) + + CreateController(sv, "dam_filling_curve", + Y = NULL, + U = "Dam", + fn_guide_curve) + + for(ym in unique(dfTS$yearmonth[dfTS$DatesR > OM[[1]]$DatesR])) { + message("Processing period ", ym) + # 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 = sv, + RunOptions = RunOptions, + IndPeriod_Run = ym_IndPeriod_Run, + Qinf = ym_Qinf) + } + expect_gte(sum(attr(OM, "Qm3s")$WD), sum(Qinf$WD[1:(nrow(dfTS) - 364)])) }) -- GitLab