knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = nzchar(Sys.getenv("riversCentralAsia_vignette_eval")) ) knitr::opts_knit$set( rmarkdown.html_vignette.check_title = FALSE )
RS Minerve{target="_blank"} is a free to use hydrologic-hydraulic modelling software. It's accessibility makes is especially suitable for typical Hydromet tasks like flow forecasting. The package riversCentralAsia includes a number of functions to read and write files which interact with RS MINERVE. These tools are interesting for automated writing of forcing files and for reading post-processing and visualization of simulation results or model parameters.
Using the package RSMinerveR
, the software can be run from inside R.
For details on model components and on file formates used in RS MINERVE please refer to the RS MINERVE manuals{target="_blank"}.
The following RSMinerve objects are currently supported in the riversCentralAsia
package:\
- Station\
- Source\
- SOCONT\
- Kinematic\
- Junction\
- GSM\
- HBV92\
- Comparator
The parameters for these objects are described in the RS MINERVE User Manual{target="_blank"}.
The example below requires you to download the package repository as well as the riversCentralAsia_ExampleData repository (see README{target="_blank"}).
library(tidyverse) library(lubridate) library(riversCentralAsia) # Adapt the path below if necessary parameters_orig <- readRSMParameters( "../../riversCentralAsia_ExampleData/Atbaschy_PAR_postCal.txt") |> dplyr::filter(Parameters == "Ku [1/d]") ggplot(parameters_orig) + geom_col(aes(Zone, Values), position = "dodge") + ylab(parameters_orig$Parameters[1]) + theme_bw()
The following shows an example how the model parameters can be changed and written to a RS MINERVE-readable format.
# Doubble all Ku-values in zone A: parameters <- readRSMParameters( "../../riversCentralAsia_ExampleData/Atbaschy_PAR_postCal.txt") |> mutate(Values = ifelse(Parameters == "Ku [1/d]" & Zone == "A", Values * 2, Values)) comparison <- parameters_orig |> mutate(Set = "Original") |> add_row(parameters |> dplyr::filter(Parameters == "Ku [1/d]") |> mutate(Set = "Modified")) ggplot(comparison) + geom_col(aes(Zone, Values, fill = Set), position = "dodge") + scale_fill_viridis_d() + ylab(parameters_orig$Parameters[1]) + theme_bw() # Uncomment to write and adapt the output file path (second argument). # writeRSMParameters(parameters, "Parameters_modified_Ku.txt")
Another useful application for the RS MINERVE I/O functions is the reading of simulation results and the analysis of the partitioning of the total basin discharge into the individual fluxes. The code below illustrates how this may be done:
Writing a selection node file that can be imported to RS MINERVE where the selection can be used to export the selected simulation results. This is useful for large models with many model objects where it is cumbersome to manually toggle the desired results in RS MINERVE.
A check node file is written in the xml format (see RS MINERVE documentation{target="_blank"}). You can have a look at an example of a check node file in the demo data folder{target="_blank"}.
When I need to write a specific check node file, I typically ask RS MINERVE to write an example file for me (by selecting a few examples of variables I want to export) and then write the check node file in R by adapting the example below.
# In this example, we want to export all fluxes and some states from all # hydrological response units (HRU) in our hydrological model from RS MINERVE. # # Make sure you have the example shape file with the hydrological response units # used for hydrological modelling in RS MINERVE (16076_HRU.shp) downloaded from # the example data set. # Adapt the path below # This reads in the names of the HRUs Object_IDs <- sf::st_read("../../riversCentralAsia_ExampleData/16076_HRU.shp") |> sf::st_drop_geometry() # Adapt the path to the demo data folder on your computer if necessary data_path <- "../../riversCentralAsia_ExampleData/" # Write check node file hbv_var_list <- c("Qr (m3/s)", "Qu (m3/s)", "Ql (m3/s)", "SWE (m)", "HUM (m)", "SU (m)", "SL (m)", "Peq (m/s)") station_var_list <- c("P (m/s)") data <- tibble( Model = rep("Model Atbaschy", length(Object_IDs$name)*length(hbv_var_list) + length(Object_IDs$name)*length(station_var_list)), Object = c(rep("HBV92", (length(Object_IDs$name)*length(hbv_var_list))), rep("Station", (length(Object_IDs$name)*length(station_var_list)))), ID = c(rep(Object_IDs$name, each = length(hbv_var_list)), paste("Station", rep(Object_IDs$name, each = length(station_var_list)), sep = " ")), Variable = c(rep(hbv_var_list, length(Object_IDs$name)), rep(station_var_list, length(Object_IDs$name))) ) writeSelectionCHK(filepath = paste0(data_path, "FluxesAndStates.chk"), data = data, name = "Fluxes and states")
We then read the simulation results.
To reproduce the example below, please download the example files as described in README{target="_blank"} and adapt the paths below.
# Adapt the path to the demo data folder on your computer if necessary data_path <- "../../riversCentralAsia_ExampleData/" # Fluxes and model states per elevation bands fs <- readResultCSV(paste0(data_path, "Atbaschy_Results_Fluxes_and_States.csv")) |> mutate(model = gsub("Station ", "", model)) Tth <- 1 # HBV model parameter for partitioning of solid and liquid precipitation forcing <- readForcingCSV(paste0(data_path, "hist_obs_rsm.csv")) |> dplyr::select(-c(X, Y, Z, Category)) |> pivot_wider(names_from = c(Sensor, Unit), names_sep = "_", values_from = Value) |> mutate(Month = month(Date), P_mmd = `P_mm/d`, Rain_mmd = ifelse(T_C >= Tth, `P_mm/d`, 0), Snow_mmd = ifelse(T_C < Tth, `P_mm/d`, 0)) |> # Long-term mean per HRU group_by(Month, Station) |> summarise(P_mmd = mean(P_mmd, na.rm = TRUE), Rain_mmd = mean(Rain_mmd, na.rm = TRUE), Snow_mmd = mean(Snow_mmd, na.rm = TRUE)) |> # Sum per Basin group_by(Month) |> summarise(P_mmd = sum(P_mmd, na.rm = TRUE), Rain_mmd = sum(Rain_mmd, na.rm = TRUE), Snow_mmd = sum(Snow_mmd, na.rm = TRUE)) |> ungroup() |> dplyr::select(-P_mmd) |> pivot_longer(-Month, names_to = "Precipitation", values_to = "Values") |> mutate(Precipitation = ifelse(Precipitation == "Rain_mmd", "Liquid", "Solid")) |> rename(Component = Precipitation) forcing_plot <- ggplot(forcing) + geom_col(aes(Month, Values, fill = Component), position = "stack") + ylab("Precipitation [mm/d]") + scale_x_continuous(breaks = c(1:12), labels = c("J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D")) + theme_bw() # Glacier discharge is already aggregated to sub-basin level gl <- readResultCSV(paste0(data_path, "Atbaschy_Results_Glacier_Sources.csv")) |> mutate(variable = "Qgl", model = gsub("glaciers_", "", model), model = paste(toupper(substr(model, 1, 1)), substr(model, 2, nchar(model)), sep=""), Month = month(date)) |> # Calculate mean flux per HRU group_by(Month, variable, model) |> summarise(value = mean(value), na.rm = TRUE) |> # Sum over basin group_by(Month, variable) |> summarise(value = sum(value, na.rm = TRUE)) |> ungroup() |> mutate(variable = factor(variable, levels = c("Qgl", "Qr", "Qu", "Ql"))) mean_monthly_fluxes <- fs |> dplyr::filter(unit == "m3/s", date > as_date("1990-01-01")) |> mutate(Month = month(date)) |> group_by(Month, variable, model) |> summarise(value = mean(value), na.rm = TRUE) |> group_by(Month, variable) |> summarise(value = sum(value, na.rm = TRUE)) |> ungroup() |> mutate(variable = factor(variable, levels = c("Qgl", "Qr", "Qu", "Ql"))) |> add_row(gl) discharge_plot <- ggplot(mean_monthly_fluxes) + geom_area(aes(Month, value, fill = variable), position = "stack") + scale_fill_viridis_d(name = "Component", direction = -1) + ylab("Discharge [m3/s]") + scale_x_continuous(breaks = c(1:12), labels = c("J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D")) + theme_bw() gridExtra::grid.arrange(forcing_plot, discharge_plot, ncol = 1)
And last but not least a modeler might wish to produce flow duration curves based on simulation results. Flow duration curves are used, for example, for the design of hydraulic infrastructure.
# Note: This example requires downloading of the example data and running of the code chunk above (section Reading & plotting results). # Calculate the flow duration curve Qtot <- fs |> dplyr::filter(unit == "m3/s", date > as_date("1990-01-01")) |> group_by(date) |> summarise(Qtot_m3s = sum(value)) |> ungroup() fdc <- computeAnnualFlowDurationCurve(data = Qtot, column = "Qtot_m3s", date = "date") |> dplyr::filter(Ma <= 12) |> mutate(Ma = as.numeric(Ma), Year = factor(Year)) fdc_mean <- fdc |> group_by(Ma) |> summarise(Qtot_m3s = mean(Qtot_m3s)) |> ungroup() ggplot(fdc) + geom_line(aes(Ma, Qtot_m3s, colour = Year), linewidth = 0.6, alpha = 0.6, show.legend = FALSE) + geom_line(data = fdc_mean, aes(Ma, Qtot_m3s)) + ylab("Discharge [m3/s]") + xlab("Duration [months]") + scale_colour_manual(values = rep("gray", length(unique(fdc$Year)))) + scale_x_continuous(breaks = c(1:12), labels = c(1:12)) + theme_bw()
In gray we see the flow duration curves of the individual years and in black the mean flow duration curve.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.