---
title: "Quickstart for reval"
author: "Michael Koohafkan"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Quickstart for reval}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 6,
  fig.height = 4
)
```

## 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: 

```{r single}
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)
head(myprofile)
```

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:

```{r}
library(reval)
library(dplyr)
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)
)
```

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: 

```{r plot-single, echo = FALSE}
library(tidyr)
library(ggplot2)

ggplot(unnest(results, output)) +
  aes(x = x, y = y, color = factor(n)) +
  geom_line() +
  scale_color_viridis_d("Manning's n")
```

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.

```{r}
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))
```

```{r plot-curves}
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!
