Author: Michael Koohafkan

# Quickstart for reval

#### Michael Koohafkan

## Introduction

The `reval` package is a redesign of the `reval` package that takes advantage of functionality provided by `tidyverse`, `furrr`, and the `future` package. The original `reval` package attempted to provide a one-size-fits-all wrapper function combining packages `doParallel` and `foreach` along with the argument combination logic. In contrast, `reval` provides the basic building blocks for generating argument sets in a format that will work with the `tidyverse` and `furrr` framework.

The basic procedure is

1. Generate argument sets using the `reval` functions `args_set()`, `args_ofat()`, or `args_permute()`.
2. Define a plan using `future::plan()`.
3. Evaluate the function and argument sets using `furrr::pmap`.

## Example: Channel design sensitivity analysis

In-stream structures such as dams, weirs and culverts modify flows in a river. In large rivers with tranquil flows, such structures can affect the river stage (water depth) many miles upstream. These water surface profiles or "backwater curves" can be modelled using well-understood hydraulic relationships. One important parameter---a coefficient representing the texture or "roughness" of the river bed---is empirical and cannot be easily measured. Therefore it is often important for engineers to compute these backwater curves for a range of roughness values in order to establish confidence limits for planning and management purposes.

The `rivr` package provides the function `compute_profile` for modelling backwater curves in prismatic channels given a known water depth at a specified location. Computing a single profile would look something like this:

    library(rivr)
    myprofile = compute_profile(So = 0.001, n = 0.045, Q = 250, y0 = 2.5,
      Cm = 1.486, g = 32.2, B = 100, SS = 0, stepdist = 50, totaldist = 3000)
    #> M1 profile specified. Computing upstream profile
    head(myprofile)
    #>      x    z        y        v        A           Sf        E        Fr
    #> 1    0 0.00 2.500000 1.000000 250.0000 0.0002884384 2.515528 0.1114556
    #> 2  -50 0.05 2.464316 1.014480 246.4316 0.0003023231 2.530297 0.1138852
    #> 3 -100 0.10 2.429331 1.029090 242.9331 0.0003167995 2.545775 0.1163542
    #> 4 -150 0.15 2.395073 1.043809 239.5073 0.0003318679 2.561992 0.1188595
    #> 5 -200 0.20 2.361575 1.058616 236.1575 0.0003475244 2.578977 0.1213974
    #> 6 -250 0.25 2.328865 1.073484 232.8865 0.0003637600 2.596759 0.1239640

In order to perform a sensitivity analysis on the effect of the roughness parameter on the backwater curve, we need to compare a variety of roughness values (the argument "n") and compile the results for comparison. Following the procedure described above, we might come up with something like this:

    library(reval)
    library(dplyr)
    #>
    #> Attaching package: 'dplyr'
    #> The following objects are masked from 'package:stats':
    #>
    #>     filter, lag
    #> The following objects are masked from 'package:base':
    #>
    #>     intersect, setdiff, setequal, union
    library(future)
    library(furrr)

    # generate the argument table
    arg_tbl = args_set(n = seq(0.03, 0.06, by = 0.005))

    # define the plan (from 'future' package)
    # could also use e.g. 'callr', 'multicore', etc.
    plan(sequential)

    # get output as list-column of argument table
    # using furrr:future_pmap
    results = mutate(arg_tbl,
      output = future_pmap(arg_tbl, compute_profile,
      So = 0.001, Q = 250, y0 = 2.5, Cm = 1.486, g = 32.2,
      B = 100, SS = 0, stepdist = 50, totaldist = 3000)
    )
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile

Wrapping the `future_pmap()` call in a `dplyr::mutate()` statement adds the results (as a list column) to the argument table. This keeps the outputs associated with the arguments, allowing you to use the argument values as identifiers as you do further transformations on the outputs. For example, `compute_profile()` returns a dataframe which can be unnested using `tidyr::unnest()` to quickly prepare the data for plotting:

Other factors can also influence the water surface profile, such as the channel slope and the angle of the channel walls. Here we use `args_permute()` to generate a table of all possible permutations of the three parameters.

    arg_tbl = args_permute(n = seq(0.03, 0.06, by = 0.005),
      So = seq(0.001, 0.0015, by = 0.00025),
      SS = seq(0, 6, by = 2)
    )
    results = mutate(arg_tbl,
      output = future_pmap(arg_tbl, compute_profile,
        Q = 250, y0 = 2.5, Cm = 1.486, g = 32.2,
        B = 100, stepdist = 50, totaldist = 3000))
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile
    #> M1 profile specified. Computing upstream profile

    ggplot(unnest(results, output)) +
      aes(x = x, y = y, color = factor(n)) + geom_line() +
      facet_grid(SS ~ So) +
      scale_color_viridis_d("Manning's n")

That's it!