Skip to contents

This vignette shows how to couple a hydrological model with a hydrological model without a snow model. While snow, TUW and the airGR models come with an own snow module (the latter just with renaming the model from GR6J to CemaNeigeGR6J), this needs a bit more coding within this package (and can be done more integrated similar to the airGR package in the future). Important new parts are in italic.

Preparations

Load packages

Create a minimum input

minimum_input <- input_data %>% 
  filter(HSU_ID == "2303") %>% 
  select(DatesR, P, T, E)

# convert Date to POSIXct
minimum_input$DatesR <- as.POSIXct(minimum_input$DatesR)
attr(minimum_input$DatesR, "tzone") <- "UTC"

New parts are in italic:

Choose a snow module and a hydrological model (without an own snow module)

cal_par <- default_cal_par # todo: this needs to be changed
snow_module <- "CemaNeige"
# todo: topmodel is not running right now as the required BasinInfo is not provided in example data
model <- "sacramento"

Set model parameters

param <- (default_cal_par[[model]]$upper + default_cal_par[[model]]$lower) / 2
print(param)
#>       uztwm       uzfwm         uzk       pctim       adimp       zperc 
#>  75.5000000  75.5000000   0.3000000   0.0500005   0.2000000 125.5000000 
#>        rexp       lztwm       lzfsm       lzfpm        lzsk        lzpk 
#>   2.5000000 250.5000000 500.5000000 500.5000000   0.1300000   0.1250500 
#>       pfree 
#>   0.3000000

Set snow module parameters

snow_param <- (default_cal_par[[snow_module]]$upper + default_cal_par[[snow_module]]$lower) / 2
print(snow_param)
#> [1]  0.50000 54.51825

Create input

# todo: check on basin_info
input <- create_input(model, minimum_input, list()) %>% 
  suppressWarnings() %>% suppressMessages()

Create snow input

snow_input <- create_input(snow_module, minimum_input, list()) %>% 
  suppressWarnings() %>% suppressMessages()

Run the model without the snow module

sim <- simulate_model(model, param, input)

Run the model with the snow module

Simulate snow module

# simulate snow module
snow_module_results <- simulate_snow(snow_module, snow_param, snow_input) %>% 
  suppressWarnings() %>% suppressMessages()

Update precipitation with snow module surface water runoff

input$P <- snow_module_results$surface_water_runoff

Run the model with updated input*

sim_update <- simulate_model(model, param, input)

Combine snow and runoff results (not required, just nice)

sim_update <- merge_snow_runoff_sim(sim_update, snow_module_results)

The output contains now also the snow module results SWE, psolid, pliquid and melt, and more_info contains a list of 2, i.e both the complete hydrological model and the snow module results with all details directly from the original package output.

str(sim_update)
#> List of 9
#>  $ date                : Date[1:14853], format: "1981-01-01" "1981-01-02" ...
#>  $ Qsim                : num [1:14853] 48.9 42.7 38.6 32.5 28.4 ...
#>  $ Qobs                : NULL
#>  $ SWE                 : num [1:14853] 6.05 13.87 15.07 37.63 46.31 ...
#>  $ psolid              : num [1:14853] 6.05 7.82 3.9 22.56 8.68 ...
#>  $ pliquid             : num [1:14853] 1.03 0 23.47 0 0 ...
#>  $ melt                : num [1:14853] 0 0 2.7 0 0 ...
#>  $ more_info           :List of 2
#>   ..$ output_model:List of 2
#>   .. ..$ init_model  :List of 7
#>   .. .. ..$ call        : language hydromad::hydromad(DATA = NULL, sma = sma, routing = routing, uztwm = c(1,  150), uzfwm = c(1, 150), uzk = c(0.1,| __truncated__ ...
#>   .. .. ..$ parlist     :List of 13
#>   .. .. .. ..$ uztwm: num [1:2] 1 150
#>   .. .. .. ..$ uzfwm: num [1:2] 1 150
#>   .. .. .. ..$ uzk  : num [1:2] 0.1 0.5
#>   .. .. .. ..$ pctim: num [1:2] 1e-06 1e-01
#>   .. .. .. ..$ adimp: num [1:2] 0 0.4
#>   .. .. .. ..$ zperc: num [1:2] 1 250
#>   .. .. .. ..$ rexp : num [1:2] 0 5
#>   .. .. .. ..$ lztwm: num [1:2] 1 500
#>   .. .. .. ..$ lzfsm: num [1:2] 1 1000
#>   .. .. .. ..$ lzfpm: num [1:2] 1 1000
#>   .. .. .. ..$ lzsk : num [1:2] 0.01 0.25
#>   .. .. .. ..$ lzpk : num [1:2] 0.0001 0.25
#>   .. .. .. ..$ pfree: num [1:2] 0 0.6
#>   .. .. ..$ last.updated: POSIXct[1:1], format: "2025-08-25 14:02:55"
#>   .. .. ..$ sma         : chr "sacramento"
#>   .. .. ..$ sma.fun     : chr "sacramento.sim"
#>   .. .. ..$ sma.formals :Dotted pair list of 24
#>   .. .. .. ..$ DATA        : symbol 
#>   .. .. .. ..$ uztwm       : symbol 
#>   .. .. .. ..$ uzfwm       : symbol 
#>   .. .. .. ..$ uzk         : symbol 
#>   .. .. .. ..$ pctim       : symbol 
#>   .. .. .. ..$ adimp       : symbol 
#>   .. .. .. ..$ zperc       : symbol 
#>   .. .. .. ..$ rexp        : symbol 
#>   .. .. .. ..$ lztwm       : symbol 
#>   .. .. .. ..$ lzfsm       : symbol 
#>   .. .. .. ..$ lzfpm       : symbol 
#>   .. .. .. ..$ lzsk        : symbol 
#>   .. .. .. ..$ lzpk        : symbol 
#>   .. .. .. ..$ pfree       : symbol 
#>   .. .. .. ..$ etmult      : num 1
#>   .. .. .. ..$ dt          : num 1
#>   .. .. .. ..$ uztwc_0     : num 0.5
#>   .. .. .. ..$ uzfwc_0     : num 0.5
#>   .. .. .. ..$ lztwc_0     : num 0.5
#>   .. .. .. ..$ lzfsc_0     : num 0.5
#>   .. .. .. ..$ lzfpc_0     : num 0.5
#>   .. .. .. ..$ adimc_0     : num 0.5
#>   .. .. .. ..$ min_ninc    : num 20
#>   .. .. .. ..$ return_state: logi FALSE
#>   .. .. ..$ warmup      : num 100
#>   .. .. ..- attr(*, "class")= chr [1:2] "hydromad.sacramento" "hydromad"
#>   .. ..$ fitted_model:List of 9
#>   .. .. ..$ call        : language hydromad::hydromad(DATA = (zoo::read.zoo(input[ind, ]))(), sma = sma, routing = routing,      uztwm = 75.5, uzfwm| __truncated__ ...
#>   .. .. ..$ parlist     :List of 13
#>   .. .. .. ..$ uztwm: num 75.5
#>   .. .. .. ..$ uzfwm: num 75.5
#>   .. .. .. ..$ uzk  : num 0.3
#>   .. .. .. ..$ pctim: num 0.05
#>   .. .. .. ..$ adimp: num 0.2
#>   .. .. .. ..$ zperc: num 126
#>   .. .. .. ..$ rexp : num 2.5
#>   .. .. .. ..$ lztwm: num 250
#>   .. .. .. ..$ lzfsm: num 500
#>   .. .. .. ..$ lzfpm: num 500
#>   .. .. .. ..$ lzsk : num 0.13
#>   .. .. .. ..$ lzpk : num 0.125
#>   .. .. .. ..$ pfree: num 0.3
#>   .. .. ..$ last.updated: POSIXct[1:1], format: "2025-08-25 14:02:55"
#>   .. .. ..$ sma         : chr "sacramento"
#>   .. .. ..$ sma.fun     : chr "sacramento.sim"
#>   .. .. ..$ sma.formals :Dotted pair list of 24
#>   .. .. .. ..$ DATA        : symbol 
#>   .. .. .. ..$ uztwm       : symbol 
#>   .. .. .. ..$ uzfwm       : symbol 
#>   .. .. .. ..$ uzk         : symbol 
#>   .. .. .. ..$ pctim       : symbol 
#>   .. .. .. ..$ adimp       : symbol 
#>   .. .. .. ..$ zperc       : symbol 
#>   .. .. .. ..$ rexp        : symbol 
#>   .. .. .. ..$ lztwm       : symbol 
#>   .. .. .. ..$ lzfsm       : symbol 
#>   .. .. .. ..$ lzfpm       : symbol 
#>   .. .. .. ..$ lzsk        : symbol 
#>   .. .. .. ..$ lzpk        : symbol 
#>   .. .. .. ..$ pfree       : symbol 
#>   .. .. .. ..$ etmult      : num 1
#>   .. .. .. ..$ dt          : num 1
#>   .. .. .. ..$ uztwc_0     : num 0.5
#>   .. .. .. ..$ uzfwc_0     : num 0.5
#>   .. .. .. ..$ lztwc_0     : num 0.5
#>   .. .. .. ..$ lzfsc_0     : num 0.5
#>   .. .. .. ..$ lzfpc_0     : num 0.5
#>   .. .. .. ..$ adimc_0     : num 0.5
#>   .. .. .. ..$ min_ninc    : num 20
#>   .. .. .. ..$ return_state: logi FALSE
#>   .. .. ..$ warmup      : num 0
#>   .. .. ..$ data        :'zooreg' series from 1981-01-01 to 2021-08-31
#>   Data: num [1:14853, 1:3] 1.03 0 26.17 0 0 ...
#>   .. .. .. ..- attr(*, "dimnames")=List of 2
#>   .. .. .. .. ..$ : NULL
#>   .. .. .. .. ..$ : chr [1:3] "P" "E" "T"
#>   Index:  POSIXct[1:14853], format: "1981-01-01" ...
#>   Frequency: 1.15740740740741e-05 
#>   .. .. ..$ U           :'zooreg' series from 1981-01-01 to 2021-08-31
#>   Data: num [1:14853] 48.9 42.7 38.6 32.5 28.4 ...
#>   Index:  POSIXct[1:14853], format: "1981-01-01" ...
#>   Frequency: 1.15740740740741e-05 
#>   .. .. ..- attr(*, "class")= chr [1:2] "hydromad.sacramento" "hydromad"
#>   ..$ snow_module :List of 3
#>   .. ..$ DatesR         : POSIXlt[1:14853], format: "1981-01-01" "1981-01-02" ...
#>   .. ..$ CemaNeigeLayers:List of 1
#>   .. .. ..$ Layer01:List of 11
#>   .. .. .. ..$ Pliq        : num [1:14853] 1.03 0 23.47 0 0 ...
#>   .. .. .. ..$ Psol        : num [1:14853] 6.05 7.82 3.9 22.56 8.68 ...
#>   .. .. .. ..$ SnowPack    : num [1:14853] 6.05 13.87 15.07 37.63 46.31 ...
#>   .. .. .. ..$ ThermalState: num [1:14853] -0.21 -1.38 0 -0.58 -2.72 ...
#>   .. .. .. ..$ Gratio      : num [1:14853] 0.0196 0.045 0.0489 0.1221 0.1502 ...
#>   .. .. .. ..$ PotMelt     : num [1:14853] 0 0 17.8 0 0 ...
#>   .. .. .. ..$ Melt        : num [1:14853] 0 0 2.7 0 0 ...
#>   .. .. .. ..$ PliqAndMelt : num [1:14853] 1.03 0 26.17 0 0 ...
#>   .. .. .. ..$ Temp        : num [1:14853] -0.42 -2.55 2.43 -1.16 -4.86 ...
#>   .. .. .. ..$ Gthreshold  : num [1:14853] 308 308 308 308 308 ...
#>   .. .. .. ..$ Glocalmax   : num [1:14853] -1000 -1000 -1000 -1000 -1000 ...
#>   .. ..$ StateEnd       :List of 3
#>   .. .. ..$ Store          :List of 4
#>   .. .. .. ..$ Prod: num NA
#>   .. .. .. ..$ Rout: num NA
#>   .. .. .. ..$ Exp : num NA
#>   .. .. .. ..$ Int : num NA
#>   .. .. ..$ UH             :List of 2
#>   .. .. .. ..$ UH1: num [1:20] NA NA NA NA NA NA NA NA NA NA ...
#>   .. .. .. ..$ UH2: num [1:40] NA NA NA NA NA NA NA NA NA NA ...
#>   .. .. ..$ CemaNeigeLayers:List of 4
#>   .. .. .. ..$ G      : num 1.13e-05
#>   .. .. .. ..$ eTG    : num 0
#>   .. .. .. ..$ Gthr   : num NA
#>   .. .. .. ..$ Glocmax: num NA
#>   .. .. ..- attr(*, "class")= chr [1:3] "IniStates" "CemaNeige" "daily"
#>   .. ..- attr(*, "class")= chr [1:3] "OutputsModel" "daily" "CemaNeige"
#>  $ surface_water_runoff: num [1:14853] 1.03 0 26.17 0 0 ...

Plot results

Here is a simple plot for simulated discharge with (red) and without (black) the snow module, skipping the first ~3 years (warm-up):

plot(sim$date[3*365:length(sim$date)], sim$Qsim[3*365:length(sim$date)], type = "l", main = "Simulated Discharge", ylab = "Q [mm/d]", xlab = "Date")
lines(sim_update$date[3*365:length(sim$date)], sim_update$Qsim[3*365:length(sim$date)], col="red")

Next steps

Now you do this again with a different hydrological model or snow module (see table in vignette("model_overview")), or proceed with vignette("calibrate_validate").