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)
All the calculations require two basic inputs, which are introduced in this section: an outage table and time series data.
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)
summary(out.table)
#> Level Area Max Mean SD
#> 1: Area AZ-NM-NV 75700 73246 1008
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
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
Equivalent 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
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")
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