Getting started with REPRA

The Renewable Energy Probabilistic Resource Adequacy tool (REPRA) can be used to answer resource adequacy questions in the presence of variable generation (VG). This document shows an example of the basic capabilities of the package. The examples utilize part of the built-in datasets that are included in the package.

First load the package into memory, along with others that are used in this demonstration.

library(repra)
library(dplyr)
library(reshape2)
library(ggplot2)

Input data

All the calculations require two basic inputs, which are introduced in this section: an outage table and time series data.

Outage table

An outage table combines existing conventional generation and indicates the loss-of-load probability (LOLP) for different load levels. This object is created with the outage_table function, which requires input to be formatted as a data.frame with a column of capacity and expected forced outage rates (EFOR). For more information on the function, consult the help ?outage_table.

gens <- repragen %>%
  filter(Area == "AZ-NM-NV")
head(gens)
#>       Area Capacity   EFOR
#> 1 AZ-NM-NV      6.9 0.0000
#> 2 AZ-NM-NV      6.9 0.0000
#> 3 AZ-NM-NV      3.0 0.0000
#> 4 AZ-NM-NV    170.1 0.0380
#> 5 AZ-NM-NV    117.8 0.0380
#> 6 AZ-NM-NV    113.6 0.0248
out.table <- outage_table(gens)
head(out.table)
#>    Level     Area Capacity Capacity2      Prob      LOLP   BaseEUE
#> 1:  Area AZ-NM-NV    66462     66462 2.755e-09 1.002e-06 0.000e+00
#> 2:  Area AZ-NM-NV    66463     66463 2.763e-09 1.004e-06 2.755e-09
#> 3:  Area AZ-NM-NV    66464     66464 2.770e-09 1.007e-06 8.273e-09
#> 4:  Area AZ-NM-NV    66465     66465 2.777e-09 1.010e-06 1.656e-08
#> 5:  Area AZ-NM-NV    66466     66466 2.785e-09 1.013e-06 2.763e-08
#> 6:  Area AZ-NM-NV    66467     66467 2.792e-09 1.015e-06 4.147e-08

An outage table can be easily plotted and summarized.

plot(out.table)

plot of chunk unnamed-chunk-4

summary(out.table)
#>    Level     Area   Max  Mean   SD
#> 1:  Area AZ-NM-NV 75700 73246 1008

Time series data

Time series need to be formatted with the format_timedata function before they can be used by other functions in the package. Time series must contain, at least, load data. Additional columns will be assumed to be VG and will be automatically be used in the other calculations.

tdata <- repratime %>% filter(Area == "AZ-NM-NV")
head(tdata)
#>       Area Time  Load CSP PV Wind
#> 1 AZ-NM-NV    1 14204   0  0 1219
#> 2 AZ-NM-NV    2 13864   0  0 1355
#> 3 AZ-NM-NV    3 13778   0  0 1437
#> 4 AZ-NM-NV    4 13777   0  0 1184
#> 5 AZ-NM-NV    5 14233   0  0 1419
#> 6 AZ-NM-NV    6 15371   0  0 1876
td <- format_timedata(tdata)
head(td)
#>   Level     Area Time Day WinProb  Load CSP PV Wind
#> 1  Area AZ-NM-NV    1   1       1 14204   0  0 1219
#> 2  Area AZ-NM-NV    2   1       1 13864   0  0 1355
#> 3  Area AZ-NM-NV    3   1       1 13778   0  0 1437
#> 4  Area AZ-NM-NV    4   1       1 13777   0  0 1184
#> 5  Area AZ-NM-NV    5   1       1 14233   0  0 1419
#> 6  Area AZ-NM-NV    6   1       1 15371   0  0 1876

Calculate metrics

To calculate reliability metrics, a time series with a NetLoad column must be provided to calculate_metrics. For example, here are the metrics for load (in this case the load is scaled or otherwise all values would be zero).

td2 <- td %>%
  mutate(NetLoad = 2.02 * Load)
calculate_metrics(td2, out.table)
#> Source: local data frame [1 x 6]
#> Groups: Level, Area
#> 
#>   Level     Area     LOLE    LOLH PeakLOLP   EUE
#> 1  Area AZ-NM-NV 0.008366 0.01385 0.004195 6.382

The raw parameter allows us to see the actual values of LOLP and EUE for each hour.

cv <- calculate_metrics(td2, out.table, raw = TRUE)
cv %>%
  arrange(-Capacity) %>%
  as.data.frame() %>%
  head()
#>   Level     Area Capacity Capacity2      Prob      LOLP BaseEUE Time Day
#> 1  Area AZ-NM-NV    69997     69997 8.127e-06 0.0041950  2.0356 4912 205
#> 2  Area AZ-NM-NV    69694     69694 4.641e-06 0.0023038  1.0788 5824 243
#> 3  Area AZ-NM-NV    69688     69687 4.580e-06 0.0022715  1.0629 4913 205
#> 4  Area AZ-NM-NV    69502     69502 3.211e-06 0.0015570  0.7132 4889 204
#> 5  Area AZ-NM-NV    69488     69488 3.125e-06 0.0015126  0.6917 4888 204
#> 6  Area AZ-NM-NV    68904     68904 9.571e-07 0.0004337  0.1851 5825 243
#>   WinProb  Load  CSP   PV   Wind    EUE
#> 1       1 34652 1660 1688  71.78 2.0357
#> 2       1 34502 1677 1632 183.99 1.0789
#> 3       1 34499 1521 1197  53.91 1.0651
#> 4       1 34407 1611 1326 180.83 0.7134
#> 5       1 34400 1682 1706 178.12 0.6917
#> 6       1 34111 1600 1201 225.46 0.1852

These metrics can also be calcuated after adding wind.

td2.wind <- td %>%
  mutate(NetLoad = 2.02 * Load - Wind)
calculate_metrics(td2.wind, out.table)
#> Source: local data frame [1 x 6]
#> Groups: Level, Area
#> 
#>   Level     Area     LOLE    LOLH PeakLOLP   EUE
#> 1  Area AZ-NM-NV 0.006542 0.01076 0.003646 4.907

Calculate ELCC

Effective load carrying capacity (ELCC) is the maximum load that can be served at a give reliability metric (by default 1 day in 10 years daily LOLE). For this calculations, the load shape is modified until the desired level is reached. For more information on this process consult the help page for calculate_elcc.

elcc <- calculate_elcc(td, out.table)
as.data.frame(elcc)
#>   Level     Area Metric Objective ActualObj  ErrorObj Multiplier  ELCC
#> 1  Area AZ-NM-NV   LOLE       0.1       0.1 0.0004429      2.134 73940
#>                VG LoadMethod LOLE   LOLH PeakLOLP   EUE
#> 1 CSP + PV + Wind Flat block  0.1 0.3026  0.02621 151.9

By default, ELCC is calculated with all the available VG data. The following example takes the series Wind out of the calculations.

elcc2 <- calculate_elcc(td, out.table, ignore = "Wind")
as.data.frame(elcc2)
#>   Level     Area Metric Objective ActualObj  ErrorObj Multiplier  ELCC
#> 1  Area AZ-NM-NV   LOLE       0.1       0.1 0.0002675      2.129 73777
#>         VG LoadMethod LOLE   LOLH PeakLOLP   EUE
#> 1 CSP + PV Flat block  0.1 0.3031  0.02184 151.3

ELCC can be calculated for different metrics and different objective values.

elcc3 <- calculate_elcc(td, out.table, obj.metric = "LOLH", obj.value = 1.0)
as.data.frame(elcc3)
#>   Level     Area Metric Objective ActualObj  ErrorObj Multiplier  ELCC
#> 1  Area AZ-NM-NV   LOLH         1         1 6.448e-05      2.153 74608
#>                VG LoadMethod   LOLE LOLH PeakLOLP   EUE
#> 1 CSP + PV + Wind Flat block 0.3172    1  0.07408 544.9

Calculate capacity value

Capacity value is the increase in ELCC (measured with the same risk level) when a new resource is added to the system. The capacity_value function automatically calculates capacity value for each of the VG time series and adds it to the load in order.

cv <- capacity_value(td, out.table)
as.data.frame(cv)
#>   Level     Area Metric Objective ActualObj   ErrorObj Multiplier  ELCC
#> 1  Area AZ-NM-NV   LOLE       0.1       0.1  2.850e-04      2.050 71022
#> 2  Area AZ-NM-NV   LOLE       0.1       0.1 -4.327e-05      2.096 72614
#> 3  Area AZ-NM-NV   LOLE       0.1       0.1  2.675e-04      2.129 73777
#> 4  Area AZ-NM-NV   LOLE       0.1       0.1  4.429e-04      2.134 73940
#>                VG LoadMethod LOLE   LOLH PeakLOLP   EUE   CVTech      CV
#> 1                 Flat block  0.1 0.2386  0.02656 120.7 BaseELCC 71022.4
#> 2             CSP Flat block  0.1 0.2595  0.02371 130.0      CSP  1591.7
#> 3        CSP + PV Flat block  0.1 0.3031  0.02184 151.3       PV  1162.4
#> 4 CSP + PV + Wind Flat block  0.1 0.3026  0.02621 151.9     Wind   163.2

This information can be reformatted and presented in a more pleseant format. It can also be easily plotted.

dcast(cv, Level + Area + Metric + Objective ~ CVTech, value.var = "CV")
#>   Level     Area Metric Objective BaseELCC  CSP   PV  Wind
#> 1  Area AZ-NM-NV   LOLE       0.1    71022 1592 1162 163.2
ggplot(cv, aes(x = paste(Level, Area, sep = ", "), weight = CV, fill = CVTech)) +
  geom_bar() +
  labs(x = "Area", y = "Capacity Value (MW)", fill = "Type")

plot of chunk unnamed-chunk-13

The previous example calculated the cumulative capacity value by iteratively adding VG profiles. An alternative would be to calculate the capacity value by removing only one VG profile from the total mix. The parameter marginal is used to change this behavior.

cv.mar <- capacity_value(td, out.table, marginal = TRUE)
as.data.frame(cv.mar)
#>   Level     Area Metric Objective ActualObj  ErrorObj Multiplier  ELCC
#> 1  Area AZ-NM-NV   LOLE       0.1       0.1 0.0003172      2.093 72517
#> 2  Area AZ-NM-NV   LOLE       0.1       0.1 0.0000939      2.100 72762
#> 3  Area AZ-NM-NV   LOLE       0.1       0.1 0.0002675      2.129 73777
#>           VG LoadMethod LOLE   LOLH PeakLOLP   EUE CVTech     CV
#> 1  PV + Wind Flat block  0.1 0.2593  0.03084 131.4    CSP 1422.3
#> 2 CSP + Wind Flat block  0.1 0.2550  0.02709 128.6     PV 1177.5
#> 3   CSP + PV Flat block  0.1 0.3031  0.02184 151.3   Wind  163.2