Water storage and release policies for all large reservoirs of conterminous United States

Sean Turner1*, Jennie Steyaert 2, Laura Condon 2, and Nathalie Voisin 1,3

1 Pacific Northwest National Laboratory 2 University of Arizona 3 University of Washington

* corresponding author:


Journal Article: Turner, S.W., Steyaert, J.C., Condon, L. and Voisin, N., 2021. Water storage and release policies for all large reservoirs of conterminous United States. Journal of Hydrology, 603, p.126843. Generic badge

Reservoir Operating Policies Dataset: ISTARF-CONUS: DOI


Contributing software

Model Version Repository DOI
starfit 0.1.0 https://github.com/IMMM-SFA/starfit/ DOI

Data requirements

Dataset Version Link Supporting article to cite
Global Reservoir and Dam Database GRanD 1.3 http://globaldamwatch.org/grand/ Lehner et al., 2011. Frontiers in Ecology and the Environment Generic badge
Reservoir Operations for CONUS ResOpsUS 1.0 DOI Steyaert et al., 2022, Nature Scientific Data Generic badge

Example for inferring a reservoir policy using starfit

In Turner et al., 2021, reservoir operations data from ResOpsUS are used to infer the operating policies of different reservoirs. The policy inference code is contained in the starfit package.

For this example, you will need to first load some libraries:

library(dplyr)
library(ggplot2)
library(starfit)
# note: you can install `starfit` using devtools:
# devtools::install_github("IMMM-SFA/starfit")

**NOTE: ResOpsUS is currently under embargo but will be publically available after November 8, 2021. Once these data are open, the starfit function read_reservoir_data() will allow one to access the data directly using starfit function read_reservoir_data().

read_reservoir_data(
  "https://raw.githubusercontent.com/IMMM-SFA/starfit/master/inst/extdata/",
  # ^^ a placeholder example record is stored at this site pending ResOpsUS public release
  297) ->
  Libby_res_data

Libby_res_data
## # A tibble: 16,861 × 4
##    date       s_MCM i_cumecs r_cumecs
##    <date>     <dbl>    <dbl>    <dbl>
##  1 1974-11-02    NA    103.      620.
##  2 1974-11-03    NA     75.9     623.
##  3 1974-11-04    NA     85.5     623.
##  4 1974-11-05    NA     86.1     493.
##  5 1974-11-06    NA     94.0     428.
##  6 1974-11-07    NA    137.      425.
##  7 1974-11-08    NA     65.7     422.
##  8 1974-11-09    NA    117.      419.
##  9 1974-11-10    NA     87.8     411.
## 10 1974-11-11    NA    135.      419.
## # … with 16,851 more rows
Libby_res_data %>%
  ggplot(aes(date, s_MCM)) + geom_line(col = "dodgerblue") +
  theme_classic() +
  labs(y = NULL, x = NULL, title = "Daily Storage (MCM) @ Libby Dam")
## Warning: Removed 152 row(s) containing missing values (geom_path).

To convert these time series data into a normal operating range:

fit_targets(
  "https://raw.githubusercontent.com/IMMM-SFA/starfit/master/inst/extdata/",
  "../../../IM3/Phase 2/P2 WM data-driven/Data-driven reservoir rules/GRanD_Version_1_3/",
  297
) -> Libby_fitted_targets
## Reading layer `GRanD_dams_v1_3' from data source 
##   `/Users/turn652/Documents/IM3/Phase 2/P2 WM data-driven/Data-driven reservoir rules/GRanD_Version_1_3/GRanD_dams_v1_3.shp' 
##   using driver `ESRI Shapefile'
## Simple feature collection with 7320 features and 58 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -153.0266 ymin: -45.8795 xmax: 176.8151 ymax: 70.38463
## Geodetic CRS:  WGS 84
## ℹ Fitting targets for dam 297: Libby
# NOR parameters are contained in Libby_fitted_targets:
Libby_fitted_targets
## $id
## [1] 297
## 
## $`weekly storage`
## # A tibble: 1,352 × 3
##     year epiweek s_pct
##    <dbl>   <dbl> <dbl>
##  1  1995       1  47.3
##  2  1995       2  43.6
##  3  1995       3  40.8
##  4  1995       4  38.0
##  5  1995       5  35.0
##  6  1995       6  34.1
##  7  1995       7  33.7
##  8  1995       8  33.6
##  9  1995       9  33.8
## 10  1995      10  33.6
## # … with 1,342 more rows
## 
## $`NSR upper bound`
## [1]  69.485 -20.769 -10.317  79.371  53.736
## 
## $`NSR lower bound`
## [1]  50.647 -38.378  -2.731  63.778  13.631

That’s it. If we want to see what those parameters looked like when converted to storage targets:

convert_parameters_to_targets(Libby_fitted_targets$`NSR upper bound`, "upper") -> upper_bound
convert_parameters_to_targets(Libby_fitted_targets$`NSR lower bound`, "lower") -> lower_bound

# join and plot
left_join(upper_bound, lower_bound) %>% 
  ggplot(aes(epiweek)) + geom_ribbon(aes(ymax = upper, ymin = lower), col = "black", fill = "dodgerblue") +
  labs(title = "Normal operating range @ Libby Dam", x = "Week of year", y = "Storage (% of capacity)") +
  theme_classic()