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.900 0.0000
#> 2 AZ-NM-NV 6.900 0.0000
#> 3 AZ-NM-NV 3.000 0.0000
#> 4 AZ-NM-NV 170.100 0.0380
#> 5 AZ-NM-NV 117.847 0.0380
#> 6 AZ-NM-NV 113.636 0.0248
out.table <- outage_table(gens)
head(out.table)
#> Level Area Capacity Capacity2 Prob LOLP
#> 1: Area AZ-NM-NV 66462 66462 2.755124e-09 1.001603e-06
#> 2: Area AZ-NM-NV 66463 66463 2.762507e-09 1.004366e-06
#> 3: Area AZ-NM-NV 66464 66464 2.769909e-09 1.007136e-06
#> 4: Area AZ-NM-NV 66465 66465 2.777330e-09 1.009913e-06
#> 5: Area AZ-NM-NV 66466 66466 2.784771e-09 1.012698e-06
#> 6: Area AZ-NM-NV 66467 66467 2.792231e-09 1.015490e-06
#> BaseEUE
#> 1: 0.000000e+00
#> 2: 2.755124e-09
#> 3: 8.272754e-09
#> 4: 1.656029e-08
#> 5: 2.762516e-08
#> 6: 4.147480e-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 73245.68 1008.435
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.062
#> 2 AZ-NM-NV 2 13864 0 0 1355.490
#> 3 AZ-NM-NV 3 13778 0 0 1437.200
#> 4 AZ-NM-NV 4 13777 0 0 1183.795
#> 5 AZ-NM-NV 5 14233 0 0 1419.040
#> 6 AZ-NM-NV 6 15371 0 0 1876.116
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.062
#> 2 Area AZ-NM-NV 2 1 1 13864 0 0 1355.490
#> 3 Area AZ-NM-NV 3 1 1 13778 0 0 1437.200
#> 4 Area AZ-NM-NV 4 1 1 13777 0 0 1183.795
#> 5 Area AZ-NM-NV 5 1 1 14233 0 0 1419.040
#> 6 Area AZ-NM-NV 6 1 1 15371 0 0 1876.116
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)
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
#> Source: local data frame [1 x 6]
#> Groups: Level, Area
#>
#> Level Area LOLE LOLH PeakLOLP EUE
#> 1 Area AZ-NM-NV 0.008366165 0.01385175 0.004194993 6.382079
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)
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
cv %>%
arrange(-Capacity) %>%
as.data.frame() %>%
head()
#> Level Area Capacity Capacity2 Prob LOLP BaseEUE
#> 1 Area AZ-NM-NV 69997.04 69997 8.126892e-06 0.0041949930 2.0355772
#> 2 Area AZ-NM-NV 69694.04 69694 4.641406e-06 0.0023037889 1.0788460
#> 3 Area AZ-NM-NV 69687.98 69687 4.580319e-06 0.0022714827 1.0628560
#> 4 Area AZ-NM-NV 69502.14 69502 3.211384e-06 0.0015569827 0.7131663
#> 5 Area AZ-NM-NV 69488.00 69488 3.125047e-06 0.0015125871 0.6917169
#> 6 Area AZ-NM-NV 68904.22 68904 9.570790e-07 0.0004336834 0.1850842
#> Time Day WinProb Load CSP PV Wind EUE
#> 1 4912 205 1 34652 1659.675 1688.453 71.77685 2.0357450
#> 2 5824 243 1 34502 1677.245 1631.764 183.98950 1.0789382
#> 3 4913 205 1 34499 1520.598 1197.492 53.90890 1.0650820
#> 4 4889 204 1 34407 1610.832 1325.818 180.82596 0.7133843
#> 5 4888 204 1 34400 1681.858 1706.066 178.11592 0.6917169
#> 6 5825 243 1 34111 1599.858 1200.851 225.46483 0.1851796
These metrics can also be calcuated after adding wind.
td2.wind <- td %>%
mutate(NetLoad = 2.02 * Load - Wind)
calculate_metrics(td2.wind, out.table)
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
#> Source: local data frame [1 x 6]
#> Groups: Level, Area
#>
#> Level Area LOLE LOLH PeakLOLP EUE
#> 1 Area AZ-NM-NV 0.006542352 0.01075845 0.003645922 4.907357
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)
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
as.data.frame(elcc)
#> Level Area Metric Objective ActualObj ErrorObj Multiplier
#> 1 Area AZ-NM-NV LOLE 0.1 0.1000443 0.0004429102 2.133781
#> ELCC VG LoadMethod LOLE LOLH PeakLOLP
#> 1 73939.77 CSP + PV + Wind Flat block 0.1000443 0.3025853 0.02620607
#> EUE
#> 1 151.9246
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")
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
as.data.frame(elcc2)
#> Level Area Metric Objective ActualObj ErrorObj Multiplier
#> 1 Area AZ-NM-NV LOLE 0.1 0.1000267 0.0002674853 2.129072
#> ELCC VG LoadMethod LOLE LOLH PeakLOLP EUE
#> 1 73776.59 CSP + PV Flat block 0.1000267 0.3030752 0.02183544 151.2771
ELCC can be calculated for different metrics and different objective values.
elcc3 <- calculate_elcc(td, out.table, obj.metric = "LOLH", obj.value = 1.0)
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
as.data.frame(elcc3)
#> Level Area Metric Objective ActualObj ErrorObj Multiplier
#> 1 Area AZ-NM-NV LOLH 1 1.000064 6.448394e-05 2.153052
#> ELCC VG LoadMethod LOLE LOLH PeakLOLP
#> 1 74607.57 CSP + PV + Wind Flat block 0.3171705 1.000064 0.07408182
#> EUE
#> 1 544.8686
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)
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
as.data.frame(cv)
#> Level Area Metric Objective ActualObj ErrorObj Multiplier
#> 1 Area AZ-NM-NV LOLE 0.1 0.10002850 2.850468e-04 2.049591
#> 2 Area AZ-NM-NV LOLE 0.1 0.09999567 -4.327014e-05 2.095526
#> 3 Area AZ-NM-NV LOLE 0.1 0.10002675 2.674853e-04 2.129072
#> 4 Area AZ-NM-NV LOLE 0.1 0.10004429 4.429102e-04 2.133781
#> ELCC VG LoadMethod LOLE LOLH PeakLOLP
#> 1 71022.41 Flat block 0.10002850 0.2385582 0.02655571
#> 2 72614.15 CSP Flat block 0.09999567 0.2594986 0.02371214
#> 3 73776.59 CSP + PV Flat block 0.10002675 0.3030752 0.02183544
#> 4 73939.77 CSP + PV + Wind Flat block 0.10004429 0.3025853 0.02620607
#> EUE CVTech CV
#> 1 120.7266 BaseELCC NA
#> 2 129.9683 CSP 1591.7409
#> 3 151.2771 PV 1162.4344
#> 4 151.9246 Wind 163.1822
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 NA 1591.741 1162.434 163.1822
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)
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
#> Warning in anti_join_impl(x, y, by$x, by$y): joining character vector and
#> factor, coercing into character vector
as.data.frame(cv.mar)
#> Level Area Metric Objective ActualObj ErrorObj Multiplier
#> 1 Area AZ-NM-NV LOLE 0.1 0.1000317 3.171771e-04 2.092735
#> 2 Area AZ-NM-NV LOLE 0.1 0.1000094 9.390268e-05 2.099799
#> 3 Area AZ-NM-NV LOLE 0.1 0.1000267 2.674853e-04 2.129072
#> ELCC VG LoadMethod LOLE LOLH PeakLOLP EUE
#> 1 72517.45 PV + Wind Flat block 0.1000317 0.2593099 0.03083549 131.4253
#> 2 72762.25 CSP + Wind Flat block 0.1000094 0.2550222 0.02708797 128.5949
#> 3 73776.59 CSP + PV Flat block 0.1000267 0.3030752 0.02183544 151.2771
#> CVTech CV
#> 1 CSP 1422.3176
#> 2 PV 1177.5196
#> 3 Wind 163.1822