Gap Analysis Step 4: Compare the Energy Yield Assessment to the Operational Assessment (Gap Analysis)#

This notebook will explore the use of the energy yield assessment (EYA) gap analysis method in OpenOA. This method attributes differences in an EYA-estimate and an operational assessment (OA) estimate of annual energy production (AEP; or net energy, P50). Differences in availability loss estimates, electrical loss estimates, and turbine ideal energy estimates are analyzed. The latter metric incorporates many aspects of an EYA, including the wind resource estimate, wake loss estimate, turbine performance, and blade degradation.

The gap analysis is based on comparing the following three key metrics:

  1. Availability loss

  2. Electrical loss

  3. Sum of turbine ideal energy

Here turbine ideal energy is defined as the energy produced during ‘normal’ or ‘ideal’ turbine operation, i.e., no downtime or considerable underperformance events. This value encompasses several different aspects of an EYA (wind resource estimate, wake losses, turbine performance, and blade degradation) and in most cases should have the largest impact in a gap analysis relative to the first two metrics.

This gap analysis method is fairly straighforward. Relevant EYA and OA metrics are passed in when defining the class, differences in EYA estimates and OA results are calculated, and then a ‘waterfall’ plot is created showing the differences between the EYA and OA-estimated AEP values and how they are linked from differences in the three key metrics.

# Import required packages
from openoa.utils import plot

import project_ENGIE

%load_ext autoreload
%autoreload 2
# Load plant object and process plant data
project = project_ENGIE.prepare('./data/la_haute_borne', use_cleansed=False)

# Add the analysis workflow validations needed below and re-validate
project.analysis_type.extend(["TurbineLongTermGrossEnergy", "ElectricalLosses"])
project.validate()

Calculate AEP, TIE, and electrical losses from operational data#

The first step is to calculate annual energy production (AEP) for the wind farm (Example 02), turbine ideal energy (TIE) for the wind farm (Example 03) and calculate electrical losses (Example 04). Please refer to detailed documentation of these methods in the previous example notebooks.

# Calculate AEP
pa = project.MonteCarloAEP(reanalysis_products = ['era5', 'merra2'])
pa.run(num_sim=20000, reanalysis_products=['era5', 'merra2'])
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 20000/20000 [00:37<00:00, 533.08it/s]
# Calculate TIE
ta = project.TurbineLongTermGrossEnergy(
    UQ=True,
    num_sim=75,
    max_power_filter=(0.8, 0.9), 
    wind_bin_threshold=(1.0, 3.0),
    correction_threshold=(0.85, 0.95),
)
ta.run(reanalysis_products=['era5', 'merra2'])
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 75/75 [02:04<00:00,  1.66s/it]
# Calculate electrical losses
el = project.ElectricalLosses()
el.run()
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1042.58it/s]

Now that we’ve calculated the key operational metrics, we setup some arrays that the gap analysis method needs to run.

Summarize operational results and create EYA data for comparison#

# First summarize key operational results
aep = pa.results.aep_GWh.mean()
avail = pa.results.avail_pct.mean()
elec = el.electrical_losses[0][0]
tie = ta.plant_gross[0][0]/1e6

print(f"AEP = {aep:21.2f} GWh/yr")
print(f"Availability Losses = {avail:.2%}")
print(f"Electrical Losses = {elec:7.2%}")
print(f"TIE = {tie:21.2f} GWh/yr")
AEP =                 12.53 GWh/yr
Availability Losses = 1.17%
Electrical Losses =   2.00%
TIE =                 14.31 GWh/yr
# Define operational data
oa_results = dict(
    aep=aep,  # AEP (GWh/yr)
    availability_losses=avail,  # Availability loss (fraction)
    electrical_losses=elec,  # Electrical loss (fraction)
    turbine_ideal_energy=tie  # Turbine ideal energy (GWh/yr)
)

# Define EYA data (we are fabricating these data as an example)
eya_estimates = dict(
    aep=16.46,  # AEP (GWh/yr)
    gross_energy=20.0,  # Gross energy (GWh/yr)
    availability_losses=0.04,  # Availability loss (fraction)
    electrical_losses=0.014,  # Electrical loss (Fraction)
    turbine_losses=0.037,  # Turbine performance loss (fraction)
    blade_degradation_losses=0.011,  # Blade degradation loss (fraction)
    wake_losses=0.087,  # Wake loss (fraction)
)

Perform gap analysis#

Now that we have the data we need, we first create a gap analysis object

eya_gap = project.EYAGapAnalysis(eya_estimates=eya_estimates, oa_results=oa_results)

Now we run the analysis, which by default outputs a waterfall plot showing how the gap between EYA-reported AEP and plant-measured AEP can be explained:

eya_gap.run()

In this example, they EYA estimate of AEP was about 4 GWh/yr higher than the OA result. This difference is largely explained by a large difference in turbine ideal energy (overestimated in EYA), and smaller differences in availability (underestimated in EYA) and electrical losses (overestimated in EYA). A total of about 1 GWh/yr is left unexplained or uncertain using this method.

eya_gap.plot_waterfall(ylim=(0, 20))

# # Notice that we can also use the plotting library to get the same results!
# plot.plot_waterfall(
#     eya_gap.compiled_data,
#     index=["EYA AEP", "TIE",  "Availability\nLosses", "Electrical\nLosses", "Unexplained", "OA AEP"],
#     ylim=(0, 20),
# )
../_images/c62eda7c3cafadb905a408fd116b557c9113d5dccf2f67cb3da55a5074afef5e.png