R/read_out.R

Defines functions read_out get_out_version get_out_content

Documented in get_out_content get_out_version read_out

#' @useDynLib swmmr
#' @importFrom Rcpp sourceCpp
NULL

#' @title Read time series data from SWMM's .out file
#' @description Reads the binary output ('.out') generated by the stormwater 
#' management model 'SWMM' and creates a list of xts-objects.
#' @param file The file to be read.
#' @param iType Sets the result type: 0 for Subcatchments,
#' 1 for nodes, 2 for links, 3 for system variables. 
#' Leave empty for retrieving elements available.
#' @param object_name Sets the objects of which time series data is returned.
#' Leave empty for retrieving elements available.
#' @param vIndex Sets the variables to be read (s. Details).
#' Leave empty for retrieving elements available.
#' @return A list of xts-objects.
#' 
#' @examples  
#' \dontrun{
#' xts_list_of_results <- read_out("model.out")
#' } 
#' 
#' @seealso \code{\link[xts]{xts}}.
#' @details 
#' 
#' vIndex depends on the result type. Choices are...
#' 
#' for each \strong{subcatchment} variable:
#' \itemize{
#'  \item 0 for rainfall rate (in/hr or mm/hr),
#'  \item 1 for snow depth (inches or millimeters),
#'  \item 2 for evaporation loss (in/day or mm/day),
#'  \item 3 for infiltration loss (in/hr or mm/hr),
#'  \item 4 for runoff flow (flow units),
#'  \item 5 for groundwater flow into the drainage network (flow units),
#'  \item 6 for groundwater elevation (ft or m),
#'  \item 7 for soil moisture in the unsaturated groundwater zone (volume fraction),
#'  \item 7 + N for washoff concentration of each pollutant (mass/liter).
#' }
#' 
#' for each \strong{node} variable:
#' \itemize{
#'  \item 0 for water depth (ft or m above the node invert elevation),
#'  \item 1 for hydraulic head (ft or m, absolute elevation per vertical datum),
#'  \item 2 for stored water volume (including ponded water, ft3 or m3),
#'  \item 3 for lateral inflow (runoff + all other external inflows, in flow units),
#'  \item 4 for total inflow (lateral inflow + upstream inflows, in flow units),
#'  \item 5 for surface flooding (excess overflow when the node is at full depth, in flow units),
#'  \item 5 + N for concentration of each pollutant after any treatment (mass/liter),
#' }
#' 
#' for each \strong{link} variable:
#' \itemize{
#'  \item 0 for flow rate (flow units),
#'  \item 1 for average water depth (ft or m),
#'  \item 2 for flow velocity (ft/s or m/s),
#'  \item 3 for volume of water (ft3 or m3),
#'  \item 4 for capacity (fraction of full area filled by flow for conduits; control setting for pumps and regulators),
#'  \item 4 + N for concentration of each pollutant (mass/liter),
#' }
#' 
#' for each \strong{system-wide} variable:
#' \itemize{
#'  \item 0 for air temperature (deg. F or deg. C),
#'  \item 1 for total rainfall (in/hr or mm/hr),
#'  \item 2 for total snow depth (inches or millimeters),
#'  \item 3 for average losses (in/hr or mm/hr),
#'  \item 4 for total runoff (flow units),
#'  \item 5 for total dry weather inflow (flow units),
#'  \item 6 for total groundwater inflow (flow units),
#'  \item 7 for total RDII inflow (flow units),
#'  \item 8 for total external inflow (flow units),
#'  \item 9 for total direct inflow (flow units),
#'  \item 10 for total external flooding (flow units),
#'  \item 11 for total outflow from outfalls (flow units),
#'  \item 12 for total nodal storage volume ( ft3 or m3),
#'  \item 13 for potential evaporation (in/day or mm/day),
#'  \item 14 for actual evaporation (in/day or mm/day).
#' }
#' 
#' @rdname read_out
#' @export
read_out <- function(file="",
                     iType = NULL,
                     object_name = NULL,
                     vIndex = NULL) {
  
  # open swmm out file
  list_of_results <- OpenSwmmOutFile(outFile = file)
  
  # close swmm out file
  on.exit(CloseSwmmOutFile())
  
  if (exists("error", list_of_results)) {
    warning("error reading out file")
    return(list_of_results)
  }
  
  # check version and raise warning
  if (list_of_results$meta$version < 51000) {
    warning("This package was developed and tested with '.out-files' of SWMM >= 5.1.010.
             Caution is advised when importing time series from older versions.")
  }

  # check if water pollutants are available
  if (identical(character(0), list_of_results$pollutants$names)) {
    PollNames <- NULL  
  } else {
    PollNames <- list_of_results$pollutants$names
  } 
                      
  # make selection of results more convenient
  iType <- .get_iType(iType = iType)$iType
  
  # retrieve times --> will probably move to Rcpp in near future
  time <- as.POSIXct(GetSwmmTimes(), tz = "GMT", origin = "1899-12-30")
  
  # if iType is either subc, nodes or links ...
  if (iType < 3) {
    # get Index, i.e. the position of object
    iIndex <- .get_iIndex(list_of_results, iType, object_name)
  } else {
    # case system variables
    iIndex  <- list(iIndex = 777, names = "system_variable")
  }

  # for each iIndex, i.e. for each subcatchment, nodes or links ...
  list_of_xts <- lapply(seq_len(length(iIndex$iIndex)), FUN = function(x) {

    # get vIndex, i.e. the type of variables 
    vIndex <- .get_vIndex(iType = iType, vIndex = vIndex, PollNames = PollNames)
    
    # for each vIndex
    data <- lapply(seq_len(length(vIndex$vIndex)),
                   FUN = function(y) GetSwmmResult(iType = iType,
                                                   iIndex = iIndex$iIndex[x],
                                                   vIndex = vIndex$vIndex[y]))
    # create xts objects
    res <- lapply(data, function(z) xts::xts(x = z, order.by = time))
    
    names(res) <- vIndex$names

    return(res)
    
  })

  # give list elements name of subcathments|nodes|links|sysvar
  names(list_of_xts) <- iIndex$names
  
  return(list_of_xts)

}

#' Get the swmm version the .out file was generated with
#' 
#' This function opens an .out file and extract the swmm version the file was 
#' generated with. It belongs to a set of helper functions which aim to simplify 
#' the work with .out files. The lifecycle of this function is considered 
#' experimental.
#' 
#' @inheritParams read_out
#' @return A vector of type integer
#' @examples
#' \dontrun{
#' version <- get_out_version("model.out")
#' } 
#' @rdname get_out_version
#' @export
get_out_version <- function(file = "") {
  
  # get the content
  list_of_results <- get_out_content(file)
  
  # extract version information
  version <- list_of_results$meta$version
  
  return(version)
  
}

#' Get the content of an .out file.
#' 
#' This function opens an .out file and lists all available time series data.
#' Currently, the list is returned 'as is' which might change in future. 
#' It belongs to a set of helper functions which aim to simplify 
#' the work with .out files. The lifecycle of this function is considered 
#' experimental.
#' 
#' @inheritParams read_out
#' @return A list showing the available content.
#' @examples
#' \dontrun{
#' content <- get_out_content("model.out")
#' } 
#' @rdname get_out_content
#' @export
get_out_content <- function(file = "") {
  
  # open swmm out file
  list_of_results <- OpenSwmmOutFile(outFile = file)
  
  # close swmm out file
  on.exit(CloseSwmmOutFile())
  
  # check error
  if (exists("error", list_of_results)) {
    warning("error reading out file")
  }
  
  return(list_of_results)
}

Try the swmmr package in your browser

Any scripts or data that you put into this service are public.

swmmr documentation built on March 2, 2020, 5:09 p.m.