R Interface for US EPA's SWMM

Functions to connect the widely used Storm Water Management Model (SWMM) of the United States Environmental Protection Agency (US EPA) < https://www.epa.gov/water-research/storm-water-management-model-swmm> to R with currently two main goals: (1) Run a SWMM simulation from R and (2) provide fast access to simulation results, i.e. SWMM's binary '.out'-files. High performance is achieved with help of Rcpp. Additionally, reading SWMM's '.inp' and '.rpt' files is supported to glance model structures and to get direct access to simulation summaries.


CRAN_Status_Badge BuildStatus

Functions to connect the widely used Storm Water Management Model (SWMM) of the United States Environmental Protection Agency (US EPA) to R with currently two main goals: (1) Run a SWMM simulation from R and (2) provide fast access to simulation results, i.e. SWMM’s binary ‘.out’-files. High performance is achieved with help of Rcpp. Additionally, reading SWMM’s ‘.inp’ and ‘.rpt’ files is supported to glance model structures and to get direct access to simulation summaries.

Installation is easy thanks to CRAN:

install.packages("swmmr")

You can install the dev version from github with:

# install.packages("remotes")
remotes::install_github("dleutnant/[email protected]")

Example

This is a basic example which shows you how to work with the package. We use the example shipped with the SWMM5 executable.

Initiate a SWMM run and retrieve simulation results

library(swmmr)
library(purrr) # to conveniently work with list objects
 
# set path to inp
# If your operating system is Windows, the Example model files are usually 
# located at "C:\Users\your user name\Documents\EPA SWMM Projects\Examples".
# For convenience the Example1.inp model is also included in the swmmr package.
inp_path <- system.file("extdata", "Example1.inp", package = "swmmr", mustWork = TRUE)
 
# glance model structure, the result is a list of data.frames with SWMM sections
inp <- read_inp(x = inp_path)
#> Warning: Expected 6 pieces. Additional pieces discarded in 13 rows [1, 2,
#> 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13].
#> Warning: Expected 9 pieces. Additional pieces discarded in 13 rows [1, 2,
#> 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13].
 
# available SWMM sections
summary(inp)
#>               Length Class  Mode
#> title          1     tbl_df list
#> options        2     tbl_df list
#> evaporation    2     tbl_df list
#> raingages      5     tbl_df list
#> subcatchments  9     tbl_df list
#> subareas       8     tbl_df list
#> infiltration   6     tbl_df list
#> junctions      6     tbl_df list
#> outfalls       6     tbl_df list
#> conduits       9     tbl_df list
#> xsections      8     tbl_df list
#> pollutants    11     tbl_df list
#> landuses       4     tbl_df list
#> coverages      3     tbl_df list
#> buildup        7     tbl_df list
#> washoff        7     tbl_df list
#> timeseries     4     tbl_df list
#> report         2     tbl_df list
#> map            2     tbl_df list
#> coordinates    3     tbl_df list
#> vertices       3     tbl_df list
#> polygons       3     tbl_df list
#> symbols        3     tbl_df list
 
# for example, inspect section subcatchments
inp$subcatchments
#> # A tibble: 8 x 9
#>   Name  `Rain Gage` Outlet  Area Perc_Imperv Width Perc_Slope CurbLen
#>   <chr> <chr>       <chr>  <int>       <int> <int>      <dbl>   <int>
#> 1 1     RG1         9         10          50   500     0.0100       0
#> 2 2     RG1         10        10          50   500     0.0100       0
#> 3 3     RG1         13         5          50   500     0.0100       0
#> 4 4     RG1         22         5          50   500     0.0100       0
#> 5 5     RG1         15        15          50   500     0.0100       0
#> 6 6     RG1         23        12          10   500     0.0100       0
#> 7 7     RG1         19         4          10   500     0.0100       0
#> 8 8     RG1         18        10          10   500     0.0100       0
#> # ... with 1 more variable: Snowpack <lgl>
 
# run a simulation
# the result is a named list of paths, directing
# to the inp, rpt and out-file, respectively.
files <- run_swmm(inp = inp_path)
#> arguments 'minimized' and 'invisible' are for Windows only
 
# we can now read model results from the binary output:
# here, we focus on the system variable (iType = 3) from which we pull
# total rainfall (in/hr or mm/hr) and total runoff (flow units) (vIndex = c(1,4)).
results <- read_out(files$out, iType = 3, vIndex = c(1, 4))
 
# results is a list object containing two time series 
str(results, max.level = 2)
#> List of 1
#>  $ system_variable:List of 2
#>   ..$ total_rainfall:An 'xts' object on 1998-01-01 01:00:00/1998-01-02 12:00:00 containing:
#>   Data: num [1:36, 1] 0.25 0.5 0.8 0.4 0.1 ...
#>   Indexed by objects of class: [POSIXct,POSIXt] TZ: GMT
#>   xts Attributes:  
#>  NULL
#>   ..$ total_runoff  :An 'xts' object on 1998-01-01 01:00:00/1998-01-02 12:00:00 containing:
#>   Data: num [1:36, 1] 0 6.22 13.03 24.25 14.17 ...
#>   Indexed by objects of class: [POSIXct,POSIXt] TZ: GMT
#>   xts Attributes:  
#>  NULL
 
# basic summary
results[[1]] %>% invoke(merge, .) %>% summary
#>      Index                     total_rainfall     total_runoff    
#>  Min.   :1998-01-01 01:00:00   Min.   :0.00000   Min.   : 0.0000  
#>  1st Qu.:1998-01-01 09:45:00   1st Qu.:0.00000   1st Qu.: 0.0000  
#>  Median :1998-01-01 18:30:00   Median :0.00000   Median : 0.0000  
#>  Mean   :1998-01-01 18:30:00   Mean   :0.07361   Mean   : 2.1592  
#>  3rd Qu.:1998-01-02 03:15:00   3rd Qu.:0.00000   3rd Qu.: 0.1033  
#>  Max.   :1998-01-02 12:00:00   Max.   :0.80000   Max.   :24.2530
 
# basic plotting
results[[1]] %>% imap( ~ plot(.x, main = .y))
#> $total_rainfall

#> 
#> $total_runoff

 
# We also might be interested in the report file:
# use read_rpt to get is a list of data.frames with SWMM summary sections
report <- read_rpt(files$rpt)
 
# glance available summaries
summary(report)
#>                                  Length Class  Mode
#> analysis_options                 2      tbl_df list
#> runoff_quantity_continuity       3      tbl_df list
#> runoff_quality_continuity        3      tbl_df list
#> flow_routing_continuity          3      tbl_df list
#> quality_routing_continuity       3      tbl_df list
#> highest_flow_instability_indexes 2      tbl_df list
#> routing_time_step_summary        2      tbl_df list
#> subcatchment_runoff_summary      9      tbl_df list
#> subcatchment_washoff_summary     3      tbl_df list
#> node_depth_summary               8      tbl_df list
#> node_inflow_summary              9      tbl_df list
#> node_flooding_summary            7      tbl_df list
#> outfall_loading_summary          7      tbl_df list
#> link_flow_summary                8      tbl_df list
#> conduit_surcharge_summary        6      tbl_df list
#> link_pollutant_load_summary      3      tbl_df list
 
# convenient access to summaries through list structure
report$subcatchment_runoff_summary
#> # A tibble: 8 x 9
#>   Subcatchment Total_Precip Total_Runon Total_Evap Total_Infil
#>   <chr>               <dbl>       <dbl>      <dbl>       <dbl>
#> 1 1                    2.65          0.         0.        1.16
#> 2 2                    2.65          0.         0.        1.21
#> 3 3                    2.65          0.         0.        1.16
#> 4 4                    2.65          0.         0.        1.16
#> 5 5                    2.65          0.         0.        1.24
#> 6 6                    2.65          0.         0.        2.27
#> 7 7                    2.65          0.         0.        2.14
#> 8 8                    2.65          0.         0.        2.25
#> # ... with 4 more variables: Total_Runoff_Depth <dbl>,
#> #   Total_Runoff_Volume <dbl>, Total_Peak_Runoff <dbl>,
#> #   Total_Runoff_Coeff <dbl>

Visualisation of model structure

With help of packages ‘ggplot2’ and ‘sf’ we can easily plot entire swmm models. Note that ggplot2 (>= 2.2.1.9000) is required, which provides the geometric object geom_sf().

library(ggplot2)
 
# initially, we convert the objects to be plotted as sf objects:
# here: subcatchments, links, junctions, raingages
sub_sf <- subcatchments_to_sf(inp)
lin_sf <- links_to_sf(inp)
jun_sf <- junctions_to_sf(inp)
rg_sf <- raingages_to_sf(inp)
 
# calculate coordinates (centroid of subcatchment) for label position
lab_coord <- sub_sf %>% 
  sf::st_centroid() %>%
  sf::st_coordinates() %>% 
  tibble::as_tibble()
 
# raingage label
lab_rg_coord <- rg_sf %>% 
  {sf::st_coordinates(.) + 500} %>% # add offset
  tibble::as_tibble()
  
# add coordinates to sf tbl
sub_sf <- dplyr::bind_cols(sub_sf, lab_coord)
rg_sf <- dplyr::bind_cols(rg_sf, lab_rg_coord)
 
# create the plot
ggplot() + 
  # first plot the subcatchment and colour continously by Area
  geom_sf(data = sub_sf, aes(fill = Area)) + 
  # label by subcatchments by name
  geom_label(data = sub_sf, aes(X, Y, label = Name), alpha = 0.5, size = 3) +
  # add links and highlight Geom1
  geom_sf(data = lin_sf, aes(colour = Geom1), size = 2) +
  # add junctions
  geom_sf(data = jun_sf, aes(size = Elevation), colour = "darkgrey") + 
  # finally show location of raingage
  geom_sf(data = rg_sf, shape = 10) + 
  # label raingage
  geom_label(data = rg_sf, aes(X, Y, label = Name), alpha = 0.5, size = 3) +
  # change scales
  scale_fill_viridis_c() +
  scale_colour_viridis_c(direction = -1) +
  # change theme
  theme_linedraw() +
  theme(panel.grid.major = element_line(colour = "white")) +
  # add labels
  labs(title = "SWMM model Example1", 
       subtitle = "customized visualization")

Contributions

This Git repository uses the Git Flow branching model (the git flow extension is useful for this). The dev branch contains the latest contributions and other code that will appear in the next release, and the master branch contains the code of the latest release, which is exactly what is currently on CRAN.

Contributing to this package is easy. Just send a pull request. When you send your PR, make sure dev is the destination branch on the swmmr repository. Your PR should pass R CMD check --as-cran, which will also be checked by Travis CI when the PR is submitted.

Code of condcut

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

Acknowledgments

This package has been mainly developed in the course of the project STBMOD, carried out at the Institute for Infrastructure, Water, Resources, Environment (IWARU) of the Muenster University of Applied Sciences. The project was funded by the German Federal Ministry of Education and Research (BMBF, FKZ 03FH033PX2).

The development of the R package was inspired by the work of Peter Steinberg. Also, it benefits from the Interface Guide of SWMM.

Citation

To cite package ‘swmmr’ in publications use:

Dominik Leutnant and Anneke Doering (2018). swmmr: R Interface for US EPA’s SWMM. R package version 0.8.0. https://github.com/dleutnant/swmmr

A BibTeX entry for LaTeX users is

@Manual{, title = {swmmr: R Interface for US EPA’s SWMM}, author = {Dominik Leutnant and Anneke Doering}, year = {2018}, note = {R package version 0.8.0}, url = {https://github.com/dleutnant/swmmr}, }

News

swmmr 0.9.0

Breaking changes

  • Mac OS and Linux users only: The default path for swmm exec is expected to be "/usr/local/bin" or "/usr/bin"

New features

  • autoplot and summarygenerics added

  • swmmr detects and assigns the latest swmm5 version if multiple swmm versions are installed (Windows only) (#18)

  • inp_to_sf gets new paramter remove_invalid to increase conversion performance in case all geometries have already been checked beforehand.

  • read_rpt result contains a tibble containing analysis info (also for errors) (#26)

Bug fixes

  • read_rpt now respects all report sections (#21)

  • subcatchments_to_sf returned an error if a geometry was insufficient defined (3 points are now at least required)

  • LID performance summary from *.rpt file is now correctly read (@maltehenrichs)

  • write_inp and read_inp are more robust.

Internal

  • The path to swmm5 exec is now stored as package option swmmr.exec when the package gets loaded

  • Substantially cleaned code basis (@hsonne)

  • inp_to_sf to convert swmm sections to sf geometries is significantly faster

swmmr 0.8.1

Bug fixes

  • read_out correctly reads and assigns multiple objects instead of shuffling (thanks to Benjamin and Christian for spotting this bug)

swmmr 0.8.0

Breaking changes

  • read_inp sections are now all in lower letters.

New features

  • vignettes added

  • LID report file reader read_lid_rpt

  • *.inp and *.rpt files can be read with different locales (e.g. encodings).

  • Read *.rpt files with read_rpt and get direct access to simulation summaries.

  • Convert swmm objects to simple features (sf) with *_to_sf.

  • read_inp returns now an object of class inp.

Bug fixes

swmmr 0.7.0

  • Added a NEWS.md file to track changes to the package.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("swmmr")

0.9.0 by Dominik Leutnant, 9 months ago


https://github.com/dleutnant/swmmr


Report a bug at https://github.com/dleutnant/swmmr/issues


Browse source code at https://github.com/cran/swmmr


Authors: Dominik Leutnant [aut, cre] , Anneke Doering [aut] , Malte Henrichs [ctb] , Hauke Sonnenberg [ctb]


Documentation:   PDF Manual  


Task views: Hydrological Data and Modeling


GPL-3 license


Imports dplyr, purrr, readr, Rcpp, tibble, tidyr, utils, xts, zoo

Suggests DEoptim, ggplot2, sf, knitr, rmarkdown, testthat

Linking to Rcpp

System requirements: SWMM (>=5.1.012)


See at CRAN