diff --git a/.Rbuildignore b/.Rbuildignore index 6f4318f..a038a86 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -8,3 +8,4 @@ ^codecov\.yml$ ^index\.md$ ^README\.md$ +^data-raw$ diff --git a/DESCRIPTION b/DESCRIPTION index 698a0b0..fdb3c84 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -24,15 +24,28 @@ Description: R Package for Simulating the Impact of Different License: MIT + file LICENSE URL: https://github.com/KWB-R/keys.lid BugReports: https://github.com/KWB-R/keys.lid/issues +Depends: + R (>= 2.10) Imports: dplyr, + ggplot2, + lubridate, kwb.event, kwb.swmm, + kwb.utils, + plotly, + scales, + stringr, swmmr, + readr, readxl, + rlang, + tibble, tidyr, + tidyselect, xts, - zoo + zoo, + magrittr Suggests: car, covr, @@ -44,8 +57,10 @@ VignetteBuilder: knitr Remotes: github::kwb-r/kwb.event, - github::kwb-r/kwb.swmm + github::kwb-r/kwb.swmm, + github::kwb-r/kwb.utils Encoding: UTF-8 LazyData: true +LazyDataCompression: xz Roxygen: list(markdown = TRUE) RoxygenNote: 7.1.1 diff --git a/NAMESPACE b/NAMESPACE index 19e62a7..98529d9 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,22 +1,64 @@ # Generated by roxygen2: do not edit by hand +export("%>%") +export(boxplot_runoff_max) +export(boxplot_runoff_volume) +export(boxplot_vrr) export(computeVol) export(extdata_file) +export(lidconfig_to_swmm) export(makeRainfallRunoffEvents) export(monthlyPattern) +export(plot_vrr_median) export(readObservations) export(readPredictions) export(read_scenarios) +export(simulate_performance) +export(simulate_performances) +import(ggplot2) +importFrom(dplyr,any_vars) +importFrom(dplyr,arrange) importFrom(dplyr,bind_rows) +importFrom(dplyr,desc) +importFrom(dplyr,filter_at) +importFrom(dplyr,group_by) importFrom(dplyr,left_join) +importFrom(dplyr,mutate) +importFrom(dplyr,select) +importFrom(dplyr,summarise) +importFrom(dplyr,vars) importFrom(kwb.event,getEvents) +importFrom(kwb.swmm,calculate_rainevent_stats) +importFrom(kwb.swmm,extdata_file) +importFrom(kwb.swmm,get_results) +importFrom(kwb.utils,catAndRun) +importFrom(kwb.utils,resolve) +importFrom(lubridate,year) +importFrom(magrittr,"%>%") +importFrom(plotly,ggplotly) +importFrom(plotly,layout) +importFrom(plotly,plot_ly) +importFrom(readr,cols) +importFrom(readr,read_csv) importFrom(readxl,excel_sheets) importFrom(readxl,read_xlsx) +importFrom(rlang,.data) importFrom(stats,aggregate) importFrom(stats,approx) +importFrom(stats,median) importFrom(stats,setNames) +importFrom(stringr,str_replace) +importFrom(stringr,str_to_upper) +importFrom(swmmr,read_inp) importFrom(swmmr,read_out) +importFrom(swmmr,run_swmm) +importFrom(swmmr,write_inp) +importFrom(tibble,tibble) importFrom(tidyr,pivot_longer) +importFrom(tidyr,pivot_wider) +importFrom(tidyr,unnest) +importFrom(tidyselect,all_of) +importFrom(tidyselect,starts_with) importFrom(utils,read.table) importFrom(xts,tzone) importFrom(zoo,coredata) diff --git a/R/lidconfig_to_swmm.R b/R/lidconfig_to_swmm.R new file mode 100644 index 0000000..7d049ae --- /dev/null +++ b/R/lidconfig_to_swmm.R @@ -0,0 +1,56 @@ +#' Convert LID config to SWMM LID controls +#' @param df data frame for a single scenario of a LID (as returned by +#' \code{\link{read_scenarios}}) +#' @return data frame with SWMM LID controls +#' @export +#' @importFrom readr cols read_csv +#' @importFrom kwb.swmm extdata_file +#' @importFrom dplyr any_vars bind_rows filter_at left_join mutate select vars +#' @importFrom tidyr pivot_wider +#' @importFrom rlang .data +#' @importFrom tidyselect all_of starts_with +#' @importFrom stringr str_to_upper +#' @examples +#' scenarios <- keys.lid::read_scenarios() +#' unique(scenarios$lid_name_tidy) +#' lid <- "permeable_pavement" +#' lid_selected <- scenarios %>% dplyr::filter(.data$lid_name_tidy == lid) +#' scenario_names <- unique(lid_selected$scenario_name) +#' scenario_name <- scenario_names[1] +#' scenario_name +#' lid_selected_scenario <- lid_selected[lid_selected$scenario_name == scenario_name,] +#' lid_controls <- lidconfig_to_swmm(lid_selected_scenario) +#' str(lid_controls) +lidconfig_to_swmm <- function(df) { + + lid_para <- readr::read_csv(kwb.swmm::extdata_file("lid/required_parameteristion.csv"), + col_types = readr::cols(.default = "c")) + + lid_parametersation <- df %>% + dplyr::filter(!is.na(.data$value)) %>% + dplyr::filter(!is.na(.data$id_type_parameter)) %>% + dplyr::select(tidyselect::all_of(c("lid_name_tidy", "type", "id_type_parameter", "scenario_name", "value"))) %>% + dplyr::left_join(lid_para %>% + dplyr::select(.data$lid_id, .data$lid_name_tidy), by = "lid_name_tidy") %>% + dplyr::mutate("Name" = sprintf("%s.%s", .data$lid_name_tidy, .data$scenario_name), + "Type/Layer" = stringr::str_to_upper(.data$type), + ) %>% + dplyr::filter(!is.na(.data$value)) %>% + dplyr::select(tidyselect::all_of(c("Name", "Type/Layer", "id_type_parameter", "value"))) %>% + tidyr::pivot_wider(names_from = "id_type_parameter", + names_prefix = "Par", + values_from = "value") %>% + dplyr::filter_at(dplyr::vars(tidyselect::starts_with("Par")), dplyr::any_vars(!is.na(.data))) + + ## dont know why 5 is needed by SWMM (but generated in SWMM GUI) + lid_parametersation[lid_parametersation$`Type/Layer` == "SURFACE", "Par5"] <- 5 + + lid_id <- lid_para$lid_id[lid_para$lid_name_tidy == unique(df$lid_name_tidy)] + + lid_header <- lid_parametersation[1,] + lid_header[1,3:ncol(lid_header)] <- NA_real_ + lid_header$`Type/Layer` <- lid_id + + dplyr::bind_rows(lid_header, lid_parametersation) + +} diff --git a/R/performances.R b/R/performances.R new file mode 100644 index 0000000..8def19a --- /dev/null +++ b/R/performances.R @@ -0,0 +1,25 @@ +#' Performance results for LIDs +#' +#' A dataset containing the performance of LIDs for different climate conditions +#' created with R script in /data-raw/performances.R +#' +#' @format A nested tibble with 290 rows and 16 variables: +#' \describe{ +#' \item{zone_id}{climate zone id} +#' \item{lid_name_tidy}{tidy LID name} +#' \item{scenario_name}{name of LID scenario} +#' \item{catchment_area_m2}{catchment area in squaremeters} +#' \item{lid_area_fraction}{fraction of LID compared to total catchment} +#' \item{lid_area_m2}{total LID area} +#' \item{lid_usage}{tibble with LID usage parameterisation} +#' \item{lid_controls}{tibble with LID controls parameterisation} +#' \item{subcatchment}{tibble with subcatchment parameterisation} +#' \item{annual}{tibble with two columns "year" and "vrr" (volume rainfall retended for each year} +#' \item{events_max}{tibble with maximum values for each rainfall event} +#' \item{events_sum}{tibble with sum values for each rainfall event} +#' \item{col_eventsep}{name of SWMM results used for event separation} +#' \item{model_inp}{path to SWMM model input file} +#' \item{model_rpt}{path to SWMM model report file} +#' \item{model_out}{path to SWMM model output file} +#' } +"performances" diff --git a/R/plot.R b/R/plot.R new file mode 100644 index 0000000..c0b6d8a --- /dev/null +++ b/R/plot.R @@ -0,0 +1,212 @@ +#' Plot Median VRR +#' +#' @param lid tidy name of LID +#' @param performances nested tibble (default: \code{\link{performances}}) +#' @return interactive plot of performance results +#' @export +#' @importFrom tidyr unnest +#' @importFrom dplyr group_by summarise +#' @importFrom plotly ggplotly layout +#' @import ggplot2 +#' @importFrom stats median +#' @examples +#' \dontrun{ +#' lids <- unique(keys.lid::performances$lid_name_tidy) +#' sapply(lids, function(lid) print(keys.lid::plot_vrr_median(lid))) +#' } +plot_vrr_median <- function(lid = "bioretention_cell", + performances = keys.lid::performances) { + + perf_selected <- performances %>% + dplyr::filter(.data$lid_name_tidy == lid) + + catchment_area_m2 <- unique(perf_selected$catchment_area_m2) + + g <- perf_selected %>% + dplyr::mutate(label = sprintf("%s (%d m2)", .data$scenario_name, .data$lid_area_m2)) %>% + tidyr::unnest(.data$annual) %>% + # dplyr::filter(.data$vrr > 0) %>% + dplyr::group_by(.data$zone_id, + .data$lid_name_tidy, + .data$scenario_name, + .data$lid_area_fraction) %>% + dplyr::summarise(vrr_median = stats::median(.data$vrr)) %>% + dplyr::ungroup() %>% + ggplot2::ggplot(ggplot2::aes_string(x = "lid_area_fraction", + y = "vrr_median", + color = "scenario_name")) + + ggplot2::facet_wrap(~ zone_id, ncol = 1) + + ggplot2::geom_line() + + ggplot2::geom_point() + + ggplot2::labs(title = sprintf("%s (catchment area: %d m2)", + lid, + catchment_area_m2), + y = "Median Volume Rainfall Retended per Year (%)") + + ggplot2::coord_cartesian(ylim = c(0,1)) + + ggplot2::scale_y_continuous(labels = scales::percent_format(accuracy = 1)) + + ggplot2::theme_bw() + + ggplot2::theme(legend.position = "bottom") + + plotly::ggplotly(g) %>% + plotly::layout(legend = list(orientation = "h", x = 0, y = -0.1 ), + ylab = list(orientation = "v", x = 0, y = -0.4 )) +} + +#' Boxplot Volume Rainfall Retended per Year +#' +#' @param lid tidy name of LID (default: "bioretention_cell") +#' @param zone_id climate zone id to plot (default: 1) +#' @param performances nested tibble (default: \code{\link{performances}}) +#' @return interactive plot of performance results +#' @export +#' @importFrom tidyr unnest +#' @importFrom dplyr group_by summarise +#' @importFrom plotly plot_ly layout +#' @examples +#' \dontrun{ +#' boxplot_vrr(lid = "bioretention_cell", zone_id = 1) +#' } +boxplot_vrr <- function(lid = "bioretention_cell", + zone_id = 1, + performances = keys.lid::performances) { + + sel_zone <- as.integer(zone_id) + + perf_selected <- performances %>% + dplyr::mutate(zone_id = as.integer(.data$zone_id)) %>% + dplyr::filter(.data$lid_name_tidy == lid, + .data$zone_id == sel_zone) + + catchment_area_m2 <- unique(perf_selected$catchment_area_m2) + + perf_selected %>% + dplyr::mutate(lid_area_fraction = as.factor(.data$lid_area_fraction), + scenario_name = as.factor(.data$scenario_name), + label = sprintf("%s (%d m2)", .data$scenario_name, .data$lid_area_m2)) %>% + tidyr::unnest(.data$annual) %>% + dplyr::group_by(.data$zone_id, + .data$lid_name_tidy, + .data$scenario_name, + .data$lid_area_fraction) %>% + plotly::plot_ly(x = ~lid_area_fraction, + y = ~vrr*100, + color = ~scenario_name, + type = "box") %>% + plotly::layout(boxmode = "group", + title = sprintf("zone %d: %s (catchment area: %s m2)", + zone_id, + lid, + catchment_area_m2), + xaxis = list(title='LID area fraction'), + yaxis = list(title='Volume Rainfall Retended (%)', + range = c(0, 100)), + legend = list(orientation = "h", x = 0, y = -0.1 )) + + +} + + +#' Boxplot Runoff Maximum per Event +#' +#' @param lid tidy name of LID (default: "bioretention_cell") +#' @param zone_id climate zone id to plot (default: 1) +#' @param performances nested tibble (default: \code{\link{performances}}) +#' @return interactive plot of performance results +#' @export +#' @importFrom tidyr unnest +#' @importFrom dplyr group_by summarise +#' @importFrom plotly plot_ly layout +#' @examples +#' \dontrun{ +#' boxplot_runoff_max(lid = "bioretention_cell", zone_id = 1) +#' } +boxplot_runoff_max <- function(lid = "bioretention_cell", + zone_id = 1, + performances = keys.lid::performances) { + + sel_zone <- as.integer(zone_id) + + perf_selected <- performances %>% + dplyr::mutate(zone_id = as.integer(.data$zone_id)) %>% + dplyr::filter(.data$lid_name_tidy == lid, + .data$zone_id == sel_zone) + + catchment_area_m2 <- unique(perf_selected$catchment_area_m2) + + perf_selected %>% + dplyr::mutate(lid_area_fraction = as.factor(lid_area_fraction), + scenario_name = as.factor(.data$scenario_name), + label = sprintf("%s (%d m2)", .data$scenario_name, .data$lid_area_m2)) %>% + tidyr::unnest(.data$events_max) %>% + dplyr::group_by(.data$zone_id, + .data$lid_name_tidy, + .data$scenario_name, + .data$lid_area_fraction) %>% + plotly::plot_ly(x = ~lid_area_fraction, + y = ~max_total_runoff_mmPerHour, + color = ~scenario_name, + type = "box") %>% + plotly::layout(boxmode = "group", + title = sprintf("zone %d: %s (catchment area: %s m2)", + zone_id, + lid, + catchment_area_m2), + xaxis = list(title='LID area fraction'), + yaxis = list(title='Maximum total runoff (mm/h per event)'), + legend = list(orientation = "h", x = 0, y = -0.1 )) + + +} + +#' Boxplot Runoff Volume per Event +#' +#' @param lid tidy name of LID (default: "bioretention_cell") +#' @param zone_id climate zone id to plot (default: 1) +#' @param performances nested tibble (default: \code{\link{performances}}) +#' @return interactive plot of performance results +#' @export +#' @importFrom tidyr unnest +#' @importFrom dplyr group_by summarise +#' @importFrom plotly plot_ly layout +#' @examples +#' \dontrun{ +#' boxplot_runoff_volume(lid = "bioretention_cell", zone_id = 1) +#' } +boxplot_runoff_volume <- function(lid = "bioretention_cell", + zone_id = 1, + performances = keys.lid::performances) { + + sel_zone <- as.integer(zone_id) + + perf_selected <- performances %>% + dplyr::mutate(zone_id = as.integer(.data$zone_id)) %>% + dplyr::filter(.data$lid_name_tidy == lid, + .data$zone_id == sel_zone) + + catchment_area_m2 <- unique(perf_selected$catchment_area_m2) + + perf_selected %>% + dplyr::mutate(lid_area_fraction = as.factor(lid_area_fraction), + scenario_name = as.factor(.data$scenario_name), + label = sprintf("%s (%d m2)", .data$scenario_name, .data$lid_area_m2)) %>% + tidyr::unnest(.data$events_sum) %>% + dplyr::group_by(.data$zone_id, + .data$lid_name_tidy, + .data$scenario_name, + .data$lid_area_fraction) %>% + dplyr::mutate(sum_total_runoff_cbm = .data$dur * .data$sum_total_runoff / 1000 / catchment_area_m2) %>% + plotly::plot_ly(x = ~lid_area_fraction, + y = ~sum_total_runoff_cbm, + color = ~scenario_name, + type = "box") %>% + plotly::layout(boxmode = "group", + title = sprintf("zone %d: %s (catchment area: %s m2)", + zone_id, + lid, + catchment_area_m2), + xaxis = list(title='LID area fraction'), + yaxis = list(title='Total Runoff Volume (m3 per m2 per event)'), + legend = list(orientation = "h", x = 0, y = -0.1 )) + + +} diff --git a/R/read_scenarios.R b/R/read_scenarios.R index a43699f..d604120 100644 --- a/R/read_scenarios.R +++ b/R/read_scenarios.R @@ -9,25 +9,28 @@ #' @importFrom readxl excel_sheets read_xlsx #' @importFrom stats setNames #' @importFrom tidyr pivot_longer +#' @importFrom tidyselect all_of #' read_scenarios <- function( scenarios_xlsx = extdata_file("scenarios/swmm_lid-parameterisation.xlsx") ) { -sheets <- readxl::excel_sheets(scenarios_xlsx) +lids <- readxl::excel_sheets(scenarios_xlsx) scenarios <- dplyr::bind_rows(stats::setNames( - lapply(sheets, function(sheet) { - readxl::read_xlsx(scenarios_xlsx, sheet = sheet) -}), nm = sheets), + lapply(lids, function(lid) { + lid <- readxl::read_xlsx(scenarios_xlsx, sheet = lid) + cols <- names(lid)[!names(lid) %in% c("lid_name_tidy", + "type", + "id_type_parameter", + "parameter_unit", + "comment", + "reference")] + tidyr::pivot_longer(lid, + cols = tidyselect::all_of(cols), + names_to = "scenario_name", + values_to = "value") +}), nm = lids), .id = "lid_name_tidy") -cols <- names(scenarios)[!names(scenarios) %in% c("lid_name_tidy", - "type", - "parameter_unit", - "comment", - "reference")] -tidyr::pivot_longer(scenarios, - cols = cols, - names_to = "scenario_name", - values_to = "value") + } diff --git a/R/simulate_performance.R b/R/simulate_performance.R new file mode 100644 index 0000000..76f9701 --- /dev/null +++ b/R/simulate_performance.R @@ -0,0 +1,189 @@ +#' Simulate Performance of LID +#' +#' @param lid_selected tibble with a selected LID as retrieved by \code{\link{read_scenarios}} +#' @param lid_area_fraction fraction of LID in subcatchment (default: 0) +#' @param catchment_area_m2 catchment area (default: 1000 m2) +#' @param col_eventsep SWMM output column used for event separation (default: +#' "total_rainfall") +#' @param swmm_base_inp path to SWMM model to be used as template for modification +#' (default: keys.lid::extdata_file("scenarios/models/model_template.inp")) +#' @param swmm_climate_dir directory with climate data +#' (default: keys.lid::extdata_file("rawdata/weather_sponge_regions") +#' @param swmm_exe Name and path to swmm5 executable. If not manually set, +#' the following paths are looked up: linux: "/usr/bin/swmm5" darwin: +#' "/Applications/swmm5" windows: "C:/Program Files (x86)/EPA SWMM 5.1/swmm5.exe", +#' (default: NULL) +#' @param model_dir default: keys.lid::extdata_file("scenarios/models") +#' @param zone_ids climate zone ids to be used for simulation (default: 1L:5L) + +#' @return tibble with nested lists containing all scenario performance +#' @importFrom dplyr arrange desc +#' @importFrom rlang .data +#' @importFrom lubridate year +#' @importFrom tibble tibble +#' @importFrom stringr str_replace +#' @importFrom swmmr read_inp run_swmm write_inp +#' @importFrom kwb.swmm calculate_rainevent_stats get_results +#' @importFrom kwb.utils resolve catAndRun +#' @export +#' @examples +#' \dontrun{ +#' scenarios <- keys.lid::read_scenarios() +#' unique(scenarios$lid_name_tidy) +#' lid <- "permeable_pavement" +#' lid_selected <- scenarios %>% dplyr::filter(.data$lid_name_tidy == lid) +#' pp_0.00 <- keys.lid::simulate_performance(lid_selected, +#' lid_area_fraction = 0.00) +#' pp_1.0 <- keys.lid::simulate_performance(lid_selected, +#' lid_area_fraction = 1.0) +#' pp <- dplyr::bind_rows(pp_0.00, pp_1.0) +#' } +simulate_performance <- function( + lid_selected, + lid_area_fraction = 0, + catchment_area_m2 = 1000, + col_eventsep = "total_rainfall", + swmm_base_inp = keys.lid::extdata_file("scenarios/models/model_template.inp"), + swmm_climate_dir = keys.lid::extdata_file("rawdata/weather_sponge_regions"), + swmm_exe = NULL, + model_dir = keys.lid::extdata_file("scenarios/models"), + zone_ids = 1L:5L +) { + + swmm_inp <- swmmr::read_inp(swmm_base_inp) + + flow_unit <- swmm_inp$options$Value[swmm_inp$options$Option == "FLOW_UNITS"] + stopifnot(flow_unit == "LPS") + + lid_area_m2 <- lid_area_fraction * catchment_area_m2 + + lapply(zone_ids, function(zone_id) { + scenario_names <- unique(lid_selected$scenario_name) + msg_txt <- sprintf("Simulating LID '%s' with %s scenarios for climate zone %d (remaining zones: %d)", + unique(lid_selected$lid_name_tidy), + length(scenario_names), + zone_id, length(zone_ids)-zone_id) + kwb.utils::catAndRun(messageText = msg_txt, expr = { + lapply(scenario_names, function(selected_scenario) { + lid_selected_scenario <- lid_selected %>% + dplyr::filter(.data$scenario_name == selected_scenario) + + lid_controls <- lidconfig_to_swmm(lid_selected_scenario) + + + subcatchment <- tibble::tibble(Name = "S1", + `Rain Gage` = "RainGage", + Outlet = "Out1", + Area = kwb.swmm::squaremeter_to_hectar(catchment_area_m2), + Perc_Imperv = 100, + Width = 6, + Perc_Slope = 0.5, + Curb_Len = 0, + Snowpack = "snowPack1" + ) + + swmm_inp$subcatchments <- subcatchment + + + lid_usage <- tibble::tibble("Subcatchment" = "S1", + "LID Process" = lid_controls$Name[1], + "Number" = 1, + "Area" = lid_area_m2, + "Width" = 6, + "InitSat" = 0, + "FromImp" = 0, + "ToPerv" = 0, + "RptFile" = "*", + "DrainTo" = "* 0" + ) + + + path_inp_file <- paste0(sprintf("%s/zone-%d_%s_lidshare-%1.2f", + model_dir, + zone_id, + lid_controls$Name[1], + lid_area_fraction), + ".inp") + path_rpt_file <- stringr::str_replace(path_inp_file, "\\.inp", "\\.rpt") + path_out_file <- stringr::str_replace(path_inp_file, "\\.inp", "\\.out") + + + swmm_inp$lid_controls <- lid_controls + swmm_inp$lid_usage <- lid_usage # lid_controls$Name[1] + + + paths_list <- list(temp = "/swmm_climeng_zone_temp.txt", + rain = "/swmm_bwsti_zone_rain_hourly.txt" + ) + + paths <- kwb.utils::resolve(paths_list, + climate_dir = swmm_climate_dir, + zone_id = zone_id) + + stopifnot(all(file.exists(unlist(paths) + ) + ) + ) + + + swmm_inp$raingages$Source <- sprintf('FILE \"%s\" BWSTI MM', + normalizePath(paths$rain)) + swmm_inp$temperature[swmm_inp$temperature$`Data Element`=="FILE", "Values"] <- sprintf('\"%s\"', + normalizePath(paths$temp)) + + swmmr::write_inp(swmm_inp, file = path_inp_file) + swmmr::run_swmm(inp = path_inp_file, + rpt = path_rpt_file, + out = path_out_file, + exec = swmm_exe + ) + + + lps_to_mmPerHour <- function(values) { + values * 3.6 + } + + results_system <- kwb.swmm::get_results(path_out = path_out_file, + vIndex = c(1,4)) %>% + dplyr::mutate(total_runoff_mmPerHour = lps_to_mmPerHour(.data$total_runoff)) + + results_vrr <- results_system %>% + dplyr::mutate(year = lubridate::year(.data$datetime)) %>% + dplyr::group_by(.data$year) %>% + dplyr::summarise(vrr = 1 - (sum(.data$total_runoff_mmPerHour) / sum(.data$total_rainfall))) + + + rainevent_stats_sum <- kwb.swmm::calculate_rainevent_stats(results_system, + col_eventsep = col_eventsep, + aggregation_function = "sum") %>% + dplyr::arrange(dplyr::desc(.data$sum_total_rainfall)) + + rainevent_stats_max <- kwb.swmm::calculate_rainevent_stats(results_system, + col_eventsep = col_eventsep, + aggregation_function = "max") %>% + dplyr::arrange(dplyr::desc(.data$max_total_rainfall)) + + + tibble::tibble(lid_name_tidy = unique(lid_selected$lid_name_tidy), + scenario_name = selected_scenario, + catchment_area_m2 = catchment_area_m2, + lid_area_fraction = lid_area_fraction, + lid_area_m2 = lid_area_m2, + lid_usage = list(lid_usage), + lid_controls = list(lid_controls), + subcatchment = list(subcatchment), + annual = list(results_vrr), + events_sum = list(rainevent_stats_sum), + events_max = list(rainevent_stats_max), + col_eventsep = col_eventsep, + model_inp = path_inp_file, + model_rpt = path_rpt_file, + model_out = path_out_file) + + }) %>% + dplyr::bind_rows() + +})}) %>% dplyr::bind_rows(.id = "zone_id") + + +} diff --git a/R/simulate_performances.R b/R/simulate_performances.R new file mode 100644 index 0000000..ff77249 --- /dev/null +++ b/R/simulate_performances.R @@ -0,0 +1,54 @@ +#' Simulate Performances of LID +#' +#' @param lid_area_fractions fractions of LID in subcatchment (default: c(0,1) +#' @inheritParams simulate_performance +#' @return tibble with nested lists containing all scenario performances for +#' varying lid_area_fractions +#' @export +#' @importFrom dplyr arrange desc +#' @importFrom rlang .data +#' @importFrom lubridate year +#' @importFrom tibble tibble +#' @importFrom stringr str_replace +#' @importFrom swmmr read_inp run_swmm write_inp +#' @importFrom kwb.swmm calculate_rainevent_stats get_results +#' @importFrom stats setNames +#' @examples +#' \dontrun{ +#' scenarios <- keys.lid::read_scenarios() +#' unique(scenarios$lid_name_tidy) +#' lid <- "permeable_pavement" +#' lid_selected <- scenarios %>% dplyr::filter(.data$lid_name_tidy == lid) +#' pp <- keys.lid::simulate_performances(lid_selected, +#' lid_area_fractions = c(0,1) +#' ) +#' } +simulate_performances <- function( + lid_selected, + lid_area_fractions = c(0,1), + catchment_area_m2 = 1000, + col_eventsep = "total_rainfall", + swmm_base_inp = keys.lid::extdata_file("scenarios/models/model_template.inp"), + swmm_climate_dir = keys.lid::extdata_file("rawdata/weather_sponge_regions"), + swmm_exe = NULL, + model_dir = keys.lid::extdata_file("scenarios/models"), + zone_ids = 1L:5L +) { + lid <- unique(lid_selected$lid_name_tidy) + label <- sprintf("%s_%0.2f", lid, lid_area_fractions) + stats::setNames( + lapply(lid_area_fractions, function(lid_area_fraction) { + simulate_performance(lid_selected, + lid_area_fraction, + catchment_area_m2, + col_eventsep, + swmm_base_inp, + swmm_climate_dir, + swmm_exe, + model_dir, + zone_ids) + }), nm = label) %>% + dplyr::bind_rows() +} + + diff --git a/R/utils-pipe.R b/R/utils-pipe.R new file mode 100644 index 0000000..fd0b1d1 --- /dev/null +++ b/R/utils-pipe.R @@ -0,0 +1,14 @@ +#' Pipe operator +#' +#' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. +#' +#' @name %>% +#' @rdname pipe +#' @keywords internal +#' @export +#' @importFrom magrittr %>% +#' @usage lhs \%>\% rhs +#' @param lhs A value or the magrittr placeholder. +#' @param rhs A function call using the magrittr semantics. +#' @return The result of calling `rhs(lhs)`. +NULL diff --git a/data-raw/performances.R b/data-raw/performances.R new file mode 100644 index 0000000..cc14722 --- /dev/null +++ b/data-raw/performances.R @@ -0,0 +1,60 @@ +## code to prepare `DATASET` dataset goes here +library(keys.lid) + +scenarios <- keys.lid::read_scenarios() + +paths_list <- list( + swmm_exe = "C:/Program Files (x86)/EPA SWMM 5.1.015/swmm5.exe" + ) + +paths <- kwb.utils::resolve(paths_list) + +### takes about 2.5h for all four LIDs to simulate + +### Bioretention Cell +br <- keys.lid::simulate_performances( + lid_selected = scenarios[scenarios$lid_name_tidy == "bioretention_cell",], + lid_area_fractions = c(0, 0.05, 0.1, 0.2), + catchment_area_m2 = 1000, + swmm_exe = paths$swmm_exe +) + +### Green Roof +gr <- keys.lid::simulate_performances( + lid_selected = scenarios[scenarios$lid_name_tidy == "green_roof",], + lid_area_fractions = c(0,1), + catchment_area_m2 = 1000, + swmm_exe = paths$swmm_exe +) + +### Permeable Pavement +pp <- keys.lid::simulate_performances( + lid_selected = scenarios[scenarios$lid_name_tidy == "permeable_pavement",], + lid_area_fractions = c(0, 1), + catchment_area_m2 = 1000, + swmm_exe = paths$swmm_exe +) + +### Rain Barrel +rb <- keys.lid::simulate_performances( + lid_selected = scenarios[scenarios$lid_name_tidy == "rain_barrel",], + lid_area_fractions = c(0, 0.1, 0.2, 0.4), + catchment_area_m2 = 1000, + swmm_exe = paths$swmm_exe +) + + +performances <- br %>% + dplyr::bind_rows(gr) %>% + dplyr::bind_rows(pp) %>% + dplyr::bind_rows(rb) + +#saveRDS(object = performances, file = "performances.rds") +#readRDS(file = "performances.rds") + +### Check different compression formats (as recommended by Rcmdcheck): +### https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Data-in-packages + +#usethis::use_data(performances, compress = "gzip", overwrite = TRUE) #44.6MB +#usethis::use_data(performances, compress = "bzip2", overwrite = TRUE) #18.9MB +usethis::use_data(performances, compress = "xz", overwrite = TRUE) #0.6MB diff --git a/data/performances.rda b/data/performances.rda new file mode 100644 index 0000000..8cb75b2 Binary files /dev/null and b/data/performances.rda differ diff --git a/inst/extdata/scenarios/models/.gitignore b/inst/extdata/scenarios/models/.gitignore new file mode 100644 index 0000000..abb553b --- /dev/null +++ b/inst/extdata/scenarios/models/.gitignore @@ -0,0 +1,3 @@ +tmp.ini +tmp.out +tmp.rpt diff --git a/inst/extdata/scenarios/models/model_template.inp b/inst/extdata/scenarios/models/model_template.inp new file mode 100644 index 0000000..fc12562 --- /dev/null +++ b/inst/extdata/scenarios/models/model_template.inp @@ -0,0 +1,142 @@ +[TITLE] +;;Project Title/Notes + +[OPTIONS] +;;Option Value +FLOW_UNITS LPS +INFILTRATION HORTON +FLOW_ROUTING KINWAVE +LINK_OFFSETS DEPTH +MIN_SLOPE 0 +ALLOW_PONDING NO +SKIP_STEADY_STATE NO + +IGNORE_SNOWMELT YES +START_DATE 04/30/2008 +START_TIME 00:00:00 +REPORT_START_DATE 04/30/2008 +REPORT_START_TIME 00:00:00 +END_DATE 10/15/2019 +END_TIME 23:00:00 +SWEEP_START 01/01 +SWEEP_END 12/31 +DRY_DAYS 0 +REPORT_STEP 01:00:00 +WET_STEP 01:00:00 +DRY_STEP 01:00:00 +ROUTING_STEP 01:00:00 +RULE_STEP 00:00:00 + +INERTIAL_DAMPING PARTIAL +NORMAL_FLOW_LIMITED BOTH +FORCE_MAIN_EQUATION H-W +VARIABLE_STEP 0.75 +LENGTHENING_STEP 0 +MIN_SURFAREA 1.14 +MAX_TRIALS 8 +HEAD_TOLERANCE 0.0015 +SYS_FLOW_TOL 5 +LAT_FLOW_TOL 5 +MINIMUM_STEP 0.5 +THREADS 1 + +[EVAPORATION] +;;Data Source Parameters +;;-------------- ---------------- +TEMPERATURE +DRY_ONLY NO + +[TEMPERATURE] +;;Data Element Values +FILE "swmm_climeng_zone1_temp.txt" +WINDSPEED FILE +SNOWMELT 0 0.5 0.6 18 39 0 +ADC IMPERVIOUS 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +ADC PERVIOUS 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 + +[RAINGAGES] +;;Name Format Interval SCF Source +;;-------------- --------- ------ ------ ---------- +RainGage VOLUME 1:00 1 FILE "swmm_bwsti_zone1_rain_hourly.txt" BWSTI MM + +[SUBCATCHMENTS] +;;Name Rain Gage Outlet Area %Imperv Width %Slope CurbLen SnowPack +;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- ---------------- +S1 RainGage Out1 0.0065 100 6 0.5 0 snowPack1 + +[SUBAREAS] +;;Subcatchment N-Imperv N-Perv S-Imperv S-Perv PctZero RouteTo PctRouted +;;-------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- +S1 0.01 0.1 1 25 0 OUTLET + +[INFILTRATION] +;;Subcatchment MaxRate MinRate Decay DryTime MaxInfil +;;-------------- ---------- ---------- ---------- ---------- ---------- +S1 700 350 80 5 90 + +[LID_CONTROLS] +;;Name Type/Layer Parameters +;;-------------- ---------- ---------- +Gr2 GR +Gr2 SURFACE 0 0.313411733086687 0.0845782298611011 6.94508363259956 5 +Gr2 SOIL 108.799609355628 0.599323754012585 0.378954279981554 0.211478835605085 170.699292724021 58.6889489809982 78.9419485256076 +Gr2 DRAINMAT 65.0779889663681 0.252694211550988 0.400062839913182 + +[LID_USAGE] +;;Subcatchment LID Process Number Area Width InitSat FromImp ToPerv RptFile DrainTo FromPerv +;;-------------- ---------------- ------- ---------- ---------- ---------- ---------- ---------- ------------------------ ---------------- ---------- +S1 Gr2 1 65 6 0 0 0 * * 0 + +[SNOWPACKS] +;;Name Surface Parameters +;;-------------- ---------- ---------- +snowPack1 PLOWABLE 0.0001 0.0002 4 0.5 0.00 0.00 0.0 +snowPack1 IMPERVIOUS 0.0001 0.0002 4 0.5 0.00 0.00 50 +snowPack1 PERVIOUS 0.0001 0.0002 4 0.5 0.00 0.00 50 +snowPack1 REMOVAL 1.0 0.0 0.0 0.0 0.0 0.0 + +[OUTFALLS] +;;Name Elevation Type Stage Data Gated Route To +;;-------------- ---------- ---------- ---------------- -------- ---------------- +Out1 0 FREE NO + +[PATTERNS] +;;Name Type Multipliers +;;-------------- ---------- ----------- +Recovery MONTHLY 1.5 1.5 1.5 1.5 1.5 1.5 +Recovery 1.5 1.5 1.5 1.5 1.5 1.5 + +[REPORT] +;;Reporting Options +SUBCATCHMENTS ALL +NODES ALL +LINKS ALL + +[TAGS] + +[MAP] +DIMENSIONS 0.000 0.000 10000.000 10000.000 +Units None + +[COORDINATES] +;;Node X-Coord Y-Coord +;;-------------- ------------------ ------------------ +Out1 3384.528 6666.667 + +[VERTICES] +;;Link X-Coord Y-Coord +;;-------------- ------------------ ------------------ + +[Polygons] +;;Subcatchment X-Coord Y-Coord +;;-------------- ------------------ ------------------ +S1 4613.197 6416.382 +S1 4670.080 4232.082 +S1 1985.210 4288.965 +S1 1962.457 6439.135 + +[SYMBOLS] +;;Gage X-Coord Y-Coord +;;-------------- ------------------ ------------------ +RainGage 1598.407 5426.621 + diff --git a/inst/extdata/scenarios/swmm_lid-parameterisation.xlsx b/inst/extdata/scenarios/swmm_lid-parameterisation.xlsx index 48a2a65..34745ae 100644 Binary files a/inst/extdata/scenarios/swmm_lid-parameterisation.xlsx and b/inst/extdata/scenarios/swmm_lid-parameterisation.xlsx differ diff --git a/man/boxplot_runoff_max.Rd b/man/boxplot_runoff_max.Rd new file mode 100644 index 0000000..521afa3 --- /dev/null +++ b/man/boxplot_runoff_max.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/plot.R +\name{boxplot_runoff_max} +\alias{boxplot_runoff_max} +\title{Boxplot Runoff Maximum per Event} +\usage{ +boxplot_runoff_max( + lid = "bioretention_cell", + zone_id = 1, + performances = keys.lid::performances +) +} +\arguments{ +\item{lid}{tidy name of LID (default: "bioretention_cell")} + +\item{zone_id}{climate zone id to plot (default: 1)} + +\item{performances}{nested tibble (default: \code{\link{performances}})} +} +\value{ +interactive plot of performance results +} +\description{ +Boxplot Runoff Maximum per Event +} +\examples{ +\dontrun{ +boxplot_runoff_max(lid = "bioretention_cell", zone_id = 1) +} +} diff --git a/man/boxplot_runoff_volume.Rd b/man/boxplot_runoff_volume.Rd new file mode 100644 index 0000000..f334742 --- /dev/null +++ b/man/boxplot_runoff_volume.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/plot.R +\name{boxplot_runoff_volume} +\alias{boxplot_runoff_volume} +\title{Boxplot Runoff Volume per Event} +\usage{ +boxplot_runoff_volume( + lid = "bioretention_cell", + zone_id = 1, + performances = keys.lid::performances +) +} +\arguments{ +\item{lid}{tidy name of LID (default: "bioretention_cell")} + +\item{zone_id}{climate zone id to plot (default: 1)} + +\item{performances}{nested tibble (default: \code{\link{performances}})} +} +\value{ +interactive plot of performance results +} +\description{ +Boxplot Runoff Volume per Event +} +\examples{ +\dontrun{ +boxplot_runoff_volume(lid = "bioretention_cell", zone_id = 1) +} +} diff --git a/man/boxplot_vrr.Rd b/man/boxplot_vrr.Rd new file mode 100644 index 0000000..1a7b035 --- /dev/null +++ b/man/boxplot_vrr.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/plot.R +\name{boxplot_vrr} +\alias{boxplot_vrr} +\title{Boxplot Volume Rainfall Retended per Year} +\usage{ +boxplot_vrr( + lid = "bioretention_cell", + zone_id = 1, + performances = keys.lid::performances +) +} +\arguments{ +\item{lid}{tidy name of LID (default: "bioretention_cell")} + +\item{zone_id}{climate zone id to plot (default: 1)} + +\item{performances}{nested tibble (default: \code{\link{performances}})} +} +\value{ +interactive plot of performance results +} +\description{ +Boxplot Volume Rainfall Retended per Year +} +\examples{ +\dontrun{ +boxplot_vrr(lid = "bioretention_cell", zone_id = 1) +} +} diff --git a/man/lidconfig_to_swmm.Rd b/man/lidconfig_to_swmm.Rd new file mode 100644 index 0000000..d00285e --- /dev/null +++ b/man/lidconfig_to_swmm.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lidconfig_to_swmm.R +\name{lidconfig_to_swmm} +\alias{lidconfig_to_swmm} +\title{Convert LID config to SWMM LID controls} +\usage{ +lidconfig_to_swmm(df) +} +\arguments{ +\item{df}{data frame for a single scenario of a LID (as returned by +\code{\link{read_scenarios}})} +} +\value{ +data frame with SWMM LID controls +} +\description{ +Convert LID config to SWMM LID controls +} +\examples{ +scenarios <- keys.lid::read_scenarios() +unique(scenarios$lid_name_tidy) +lid <- "permeable_pavement" +lid_selected <- scenarios \%>\% dplyr::filter(.data$lid_name_tidy == lid) +scenario_names <- unique(lid_selected$scenario_name) +scenario_name <- scenario_names[1] +scenario_name +lid_selected_scenario <- lid_selected[lid_selected$scenario_name == scenario_name,] +lid_controls <- lidconfig_to_swmm(lid_selected_scenario) +str(lid_controls) +} diff --git a/man/performances.Rd b/man/performances.Rd new file mode 100644 index 0000000..67ba23a --- /dev/null +++ b/man/performances.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/performances.R +\docType{data} +\name{performances} +\alias{performances} +\title{Performance results for LIDs} +\format{ +A nested tibble with 290 rows and 16 variables: +\describe{ +\item{zone_id}{climate zone id} +\item{lid_name_tidy}{tidy LID name} +\item{scenario_name}{name of LID scenario} +\item{catchment_area_m2}{catchment area in squaremeters} +\item{lid_area_fraction}{fraction of LID compared to total catchment} +\item{lid_area_m2}{total LID area} +\item{lid_usage}{tibble with LID usage parameterisation} +\item{lid_controls}{tibble with LID controls parameterisation} +\item{subcatchment}{tibble with subcatchment parameterisation} +\item{annual}{tibble with two columns "year" and "vrr" (volume rainfall retended for each year} +\item{events_max}{tibble with maximum values for each rainfall event} +\item{events_sum}{tibble with sum values for each rainfall event} +\item{col_eventsep}{name of SWMM results used for event separation} +\item{model_inp}{path to SWMM model input file} +\item{model_rpt}{path to SWMM model report file} +\item{model_out}{path to SWMM model output file} +} +} +\usage{ +performances +} +\description{ +A dataset containing the performance of LIDs for different climate conditions +created with R script in /data-raw/performances.R +} +\keyword{datasets} diff --git a/man/pipe.Rd b/man/pipe.Rd new file mode 100644 index 0000000..a648c29 --- /dev/null +++ b/man/pipe.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils-pipe.R +\name{\%>\%} +\alias{\%>\%} +\title{Pipe operator} +\usage{ +lhs \%>\% rhs +} +\arguments{ +\item{lhs}{A value or the magrittr placeholder.} + +\item{rhs}{A function call using the magrittr semantics.} +} +\value{ +The result of calling \code{rhs(lhs)}. +} +\description{ +See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. +} +\keyword{internal} diff --git a/man/plot_vrr_median.Rd b/man/plot_vrr_median.Rd new file mode 100644 index 0000000..b0184ed --- /dev/null +++ b/man/plot_vrr_median.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/plot.R +\name{plot_vrr_median} +\alias{plot_vrr_median} +\title{Plot Median VRR} +\usage{ +plot_vrr_median( + lid = "bioretention_cell", + performances = keys.lid::performances +) +} +\arguments{ +\item{lid}{tidy name of LID} + +\item{performances}{nested tibble (default: \code{\link{performances}})} +} +\value{ +interactive plot of performance results +} +\description{ +Plot Median VRR +} +\examples{ +\dontrun{ +lids <- unique(keys.lid::performances$lid_name_tidy) +sapply(lids, function(lid) print(keys.lid::plot_vrr_median(lid))) +} +} diff --git a/man/simulate_performance.Rd b/man/simulate_performance.Rd new file mode 100644 index 0000000..3711729 --- /dev/null +++ b/man/simulate_performance.Rd @@ -0,0 +1,62 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/simulate_performance.R +\name{simulate_performance} +\alias{simulate_performance} +\title{Simulate Performance of LID} +\usage{ +simulate_performance( + lid_selected, + lid_area_fraction = 0, + catchment_area_m2 = 1000, + col_eventsep = "total_rainfall", + swmm_base_inp = keys.lid::extdata_file("scenarios/models/model_template.inp"), + swmm_climate_dir = keys.lid::extdata_file("rawdata/weather_sponge_regions"), + swmm_exe = NULL, + model_dir = keys.lid::extdata_file("scenarios/models"), + zone_ids = 1L:5L +) +} +\arguments{ +\item{lid_selected}{tibble with a selected LID as retrieved by \code{\link{read_scenarios}}} + +\item{lid_area_fraction}{fraction of LID in subcatchment (default: 0)} + +\item{catchment_area_m2}{catchment area (default: 1000 m2)} + +\item{col_eventsep}{SWMM output column used for event separation (default: +"total_rainfall")} + +\item{swmm_base_inp}{path to SWMM model to be used as template for modification +(default: keys.lid::extdata_file("scenarios/models/model_template.inp"))} + +\item{swmm_climate_dir}{directory with climate data +(default: keys.lid::extdata_file("rawdata/weather_sponge_regions")} + +\item{swmm_exe}{Name and path to swmm5 executable. If not manually set, +the following paths are looked up: linux: "/usr/bin/swmm5" darwin: +"/Applications/swmm5" windows: "C:/Program Files (x86)/EPA SWMM 5.1/swmm5.exe", +(default: NULL)} + +\item{model_dir}{default: keys.lid::extdata_file("scenarios/models")} + +\item{zone_ids}{climate zone ids to be used for simulation (default: 1L:5L)} +} +\value{ +tibble with nested lists containing all scenario performance +} +\description{ +Simulate Performance of LID +} +\examples{ +\dontrun{ +scenarios <- keys.lid::read_scenarios() +unique(scenarios$lid_name_tidy) +lid <- "permeable_pavement" +lid_selected <- scenarios \%>\% dplyr::filter(.data$lid_name_tidy == lid) +pp_0.00 <- keys.lid::simulate_performance(lid_selected, + lid_area_fraction = 0.00) +pp_1.0 <- keys.lid::simulate_performance(lid_selected, + lid_area_fraction = 1.0) +pp <- dplyr::bind_rows(pp_0.00, pp_1.0) +} +} diff --git a/man/simulate_performances.Rd b/man/simulate_performances.Rd new file mode 100644 index 0000000..d84ee66 --- /dev/null +++ b/man/simulate_performances.Rd @@ -0,0 +1,61 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/simulate_performances.R +\name{simulate_performances} +\alias{simulate_performances} +\title{Simulate Performances of LID} +\usage{ +simulate_performances( + lid_selected, + lid_area_fractions = c(0, 1), + catchment_area_m2 = 1000, + col_eventsep = "total_rainfall", + swmm_base_inp = keys.lid::extdata_file("scenarios/models/model_template.inp"), + swmm_climate_dir = keys.lid::extdata_file("rawdata/weather_sponge_regions"), + swmm_exe = NULL, + model_dir = keys.lid::extdata_file("scenarios/models"), + zone_ids = 1L:5L +) +} +\arguments{ +\item{lid_selected}{tibble with a selected LID as retrieved by \code{\link{read_scenarios}}} + +\item{lid_area_fractions}{fractions of LID in subcatchment (default: c(0,1)} + +\item{catchment_area_m2}{catchment area (default: 1000 m2)} + +\item{col_eventsep}{SWMM output column used for event separation (default: +"total_rainfall")} + +\item{swmm_base_inp}{path to SWMM model to be used as template for modification +(default: keys.lid::extdata_file("scenarios/models/model_template.inp"))} + +\item{swmm_climate_dir}{directory with climate data +(default: keys.lid::extdata_file("rawdata/weather_sponge_regions")} + +\item{swmm_exe}{Name and path to swmm5 executable. If not manually set, +the following paths are looked up: linux: "/usr/bin/swmm5" darwin: +"/Applications/swmm5" windows: "C:/Program Files (x86)/EPA SWMM 5.1/swmm5.exe", +(default: NULL)} + +\item{model_dir}{default: keys.lid::extdata_file("scenarios/models")} + +\item{zone_ids}{climate zone ids to be used for simulation (default: 1L:5L)} +} +\value{ +tibble with nested lists containing all scenario performances for +varying lid_area_fractions +} +\description{ +Simulate Performances of LID +} +\examples{ +\dontrun{ +scenarios <- keys.lid::read_scenarios() +unique(scenarios$lid_name_tidy) +lid <- "permeable_pavement" +lid_selected <- scenarios \%>\% dplyr::filter(.data$lid_name_tidy == lid) +pp <- keys.lid::simulate_performances(lid_selected, + lid_area_fractions = c(0,1) + ) +} +} diff --git a/vignettes/scenarios.Rmd b/vignettes/scenarios.Rmd index 33e3657..0529cc4 100644 --- a/vignettes/scenarios.Rmd +++ b/vignettes/scenarios.Rmd @@ -12,12 +12,189 @@ knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) + +#keys.lid::performances ``` +## Scenarios + ```{r setup} library(keys.lid) -lid_scenarios <- keys.lid::read_scenarios() -DT::datatable(lid_scenarios) +paths_list <- list( + swmm_exe = "C:/Program Files (x86)/EPA SWMM 5.1.015/swmm5.exe" + ) + +paths <- kwb.utils::resolve(paths_list) + + +scenarios <- keys.lid::read_scenarios() + +DT::datatable(scenarios) + + +``` +## Simulate Performance + +The SWMM simulations (years: 2008 - 2019) and calculation of +performance metrics (volume rainfall retended, rainfall event sums/max) for four +LIDs with different parameterisations and for five different climate zones +in China (in total: 290 model runs) takes about 2h 20min (~ 30 seconds per model +run) on my laptop. + +```{r simulate_performances, eval = FALSE} + +### Bioretention Cell +br <- keys.lid::simulate_performances( + lid_selected = scenarios[scenarios$lid_name_tidy == "bioretention_cell",], + lid_area_fractions = c(0, 0.05, 0.1, 0.2), + catchment_area_m2 = 1000, + swmm_exe = paths$swmm_exe +) + +### Green Roof +gr <- keys.lid::simulate_performances( + lid_selected = scenarios[scenarios$lid_name_tidy == "green_roof",], + lid_area_fractions = c(0,1), + catchment_area_m2 = 1000, + swmm_exe = paths$swmm_exe +) + +### Permeable Pavement +pp <- keys.lid::simulate_performances( + lid_selected = scenarios[scenarios$lid_name_tidy == "permeable_pavement",], + lid_area_fractions = c(0, 1), + catchment_area_m2 = 1000, + swmm_exe = paths$swmm_exe +) + +### Rain Barrel +rb <- keys.lid::simulate_performances( + lid_selected = scenarios[scenarios$lid_name_tidy == "rain_barrel",], + lid_area_fractions = c(0, 0.1, 0.2, 0.4), + catchment_area_m2 = 1000, + swmm_exe = paths$swmm_exe +) + + +performances <- br %>% + dplyr::bind_rows(gr) %>% + dplyr::bind_rows(pp) %>% + dplyr::bind_rows(rb) +``` + +## Evaluate Performance + +### Median Volume Rainfall Retended per Year + +#### Bioretention Cell + +```{r evaluate_performance_vrr_br, fig.height=7, fig.width=7} + +keys.lid::plot_vrr_median("bioretention_cell") + +``` + +#### Green Roof + +```{r evaluate_performance_vrr_gr, fig.height=7, fig.width=7} + +keys.lid::plot_vrr_median("green_roof") + +``` + +#### Permeable Pavements + +```{r evaluate_performance_vrr_pp, fig.height=7, fig.width=7} + +keys.lid::plot_vrr_median("permeable_pavement") + +``` + +#### Rain Barrel + +```{r evaluate_performance_vrr_rr, fig.height=7, fig.width=7} + +keys.lid::plot_vrr_median("rain_barrel") + +``` + +### Boxplots + +Example for LID **green roof** in **climate zones 1 and 5** + +#### Volume Rainfall Retended + +**Zone 1** + +```{r evaluate_performance_boxplot_vrr_gr_zone1, fig.height=7, fig.width=7} + +keys.lid::boxplot_vrr(lid = "green_roof", zone_id = 1) + +``` + +**Zone 2** + +```{r evaluate_performance_boxplot_vrr_gr_zone2, fig.height=7, fig.width=7} + +keys.lid::boxplot_vrr(lid = "green_roof", zone_id = 2) + +``` + +**Zone 3** + +```{r evaluate_performance_boxplot_vrr_gr_zone3, fig.height=7, fig.width=7} + +keys.lid::boxplot_vrr(lid = "green_roof", zone_id = 3) + +``` + +**Zone 4** + +```{r evaluate_performance_boxplot_vrr_gr_zone4, fig.height=7, fig.width=7} + +keys.lid::boxplot_vrr(lid = "green_roof", zone_id = 4) + +``` + +**Zone 5** + +```{r evaluate_performance_boxplot_vrr_gr_zone5, fig.height=7, fig.width=7} + +keys.lid::boxplot_vrr(lid = "green_roof", zone_id = 5) + +``` + +#### Runoff Maximum per Event + +**Zone 1** + +```{r evaluate_performance_boxplot_runoff_max_gr_zone1, fig.height=7, fig.width=7} + +keys.lid::boxplot_runoff_max(lid = "green_roof", zone_id = 1) + +``` +**Zone 5** + +```{r evaluate_performance_boxplot_runoff_max_gr_zone5, fig.height=7, fig.width=7} + +keys.lid::boxplot_runoff_max(lid = "green_roof", zone_id = 5) + +``` + +#### Runoff Volume per Event + +**Zone 1** + +```{r evaluate_performance_boxplot_runoff_volume_gr_zone1, fig.height=7, fig.width=7} + +keys.lid::boxplot_runoff_volume(lid = "green_roof", zone_id = 1) + +``` +**Zone 5** + +```{r evaluate_performance_boxplot_runoff_volume_gr_zone5, fig.height=7, fig.width=7} + +keys.lid::boxplot_runoff_volume(lid = "green_roof", zone_id = 5) ``` diff --git a/vignettes/sensitivity.Rmd b/vignettes/sensitivity.Rmd index 1b02c44..ece1707 100644 --- a/vignettes/sensitivity.Rmd +++ b/vignettes/sensitivity.Rmd @@ -188,7 +188,7 @@ for(i in seq_len(l)){ Qcolumn = 'runoff') rainfall_volume <- sum(yearj$rainfall_depth, na.rm = TRUE) - vrr[j] <- runoff_volume/rainfall_volume + vrr[j] <- 1 - runoff_volume/rainfall_volume } sensitivity_results[i,