Advanced Wind Turbine Simulation Workflow#
A more advanced turbine workflow will include many steps (Which have been showcased in previous examples)
Workflow:
Weather data extraction from a MERRA dataset (windspeed, pressure, temperature)
Spatial adjustment of the windspeeds
Vertical projection of the wind speeds
Wind speed density correction
Power curve convolution
Capacity Factor Estimation
import reskit as rk
import numpy as np
import matplotlib.pyplot as plt
Simulate a Single Location#
# Set some constants for later
TURBINE_CAPACITY = 4200 # kW
TURBINE_HUB_HEIGHT = 120 # meters
TURBINE_ROTOR_DIAMETER = 136 # meters
TURBINE_LOCATION = (6.0, 50.5) # (lon, lat)
# 1. Create a weather source, load, and extract weather variables
src = rk.weather.MerraSource(rk.TEST_DATA["merra-like"], bounds=[5, 49, 7, 52], verbose=False)
src.sload_elevated_wind_speed()
src.sload_surface_pressure()
src.sload_surface_air_temperature()
raw_windspeeds = src.get("elevated_wind_speed", locations=TURBINE_LOCATION, interpolation="bilinear")
raw_pressure = src.get("surface_pressure", locations=TURBINE_LOCATION, interpolation="bilinear")
raw_temperature = src.get("surface_air_temperature", locations=TURBINE_LOCATION, interpolation="bilinear")
print(raw_windspeeds.head())
2015-01-01 00:30:00+00:00 5.383743
2015-01-01 01:30:00+00:00 5.323299
2015-01-01 02:30:00+00:00 5.232418
2015-01-01 03:30:00+00:00 5.160997
2015-01-01 04:30:00+00:00 5.439261
Name: (6.0, 50.5), dtype: float64
# 2. Vertically project wind speeds to hub height
roughness = rk.wind.roughness_from_clc(clc_path=rk.TEST_DATA["clc-aachen_clipped.tif"], loc=TURBINE_LOCATION)
projected_windspeed = rk.wind.apply_logarithmic_profile_projection(
measured_wind_speed=raw_windspeeds,
measured_height=50, # The MERRA dataset offers windspeeds at 50m
target_height=TURBINE_HUB_HEIGHT,
roughness=roughness,
)
print(projected_windspeed.head())
2015-01-01 00:30:00+00:00 6.506035
2015-01-01 01:30:00+00:00 6.432992
2015-01-01 02:30:00+00:00 6.323166
2015-01-01 03:30:00+00:00 6.236856
2015-01-01 04:30:00+00:00 6.573127
Name: (6.0, 50.5), dtype: float64
# 3. Apply density correction
pressure_corrected_windspeeds = rk.wind.apply_air_density_adjustment(
wind_speed=projected_windspeed,
pressure=raw_pressure,
temperature=raw_temperature,
height=TURBINE_HUB_HEIGHT,
)
pressure_corrected_windspeeds.head()
2015-01-01 00:30:00+00:00 6.560702
2015-01-01 01:30:00+00:00 6.485689
2015-01-01 02:30:00+00:00 6.374120
2015-01-01 03:30:00+00:00 6.287352
2015-01-01 04:30:00+00:00 6.626462
Name: (6.0, 50.5), dtype: float64
# 4. Power curve estimation and convolution
power_curve = rk.wind.PowerCurve.from_capacity_and_rotor_diam(
capacity=TURBINE_CAPACITY, rotor_diam=TURBINE_ROTOR_DIAMETER
)
convoluted_power_curve = power_curve.convolute_by_gaussian(scaling=0.06, base=0.1)
# 5. Capacity factor estimation
capacity_factors = convoluted_power_curve.simulate(wind_speed=pressure_corrected_windspeeds)
capacity_factors
array([0.27273363, 0.26315142, 0.24928885, 0.23878838, 0.2813027 ,
0.38840875, 0.46433861, 0.50707569, 0.55526571, 0.49867274,
0.5716173 , 0.71244977, 0.70559868, 0.61191423, 0.70556453,
0.91621572, 0.98436881, 0.98905482, 0.99521448, 0.99879609,
0.99956091, 0.99987679, 0.99996843, 0.99999171, 0.99999641,
0.99999844, 0.99999941, 0.99999979, 0.99999986, 0.99999954,
0.99999577, 0.99996633, 0.99986441, 0.99835949, 0.99779936,
0.98064443, 0.94692822, 0.97454365, 0.97228814, 0.97970383,
0.97176293, 0.93889837, 0.87918241, 0.82917666, 0.78503089,
0.73943709, 0.6327937 , 0.60788396, 0.56244002, 0.49216547,
0.48407326, 0.55137321, 0.66608584, 0.71491774, 0.71633097,
0.77210396, 0.8345534 , 0.76770054, 0.56405061, 0.42807357,
0.41323894, 0.41240108, 0.32953804, 0.23966265, 0.13567885,
0.12706234, 0.32103426, 0.49467238, 0.26512148, 0.20028125,
0.37167453])
plt.plot(capacity_factors)
plt.xlabel("Time")
plt.ylabel("Capacity Factor")
plt.grid()
plt.show()
Simulate multiple locations at once (recommended)#
TURBINE_CAPACITY = 4200 # kW
TURBINE_HUB_HEIGHT = 120 # meters
TURBINE_ROTOR_DIAMETER = 136 # meters
TURBINE_LOCATION = np.array([(6.25, 51.0), (6.50, 51.0), (6.25, 50.75)]) # (lon,lat)
# 1
raw_windspeeds = src.get("elevated_wind_speed", locations=TURBINE_LOCATION, interpolation="bilinear")
raw_pressure = src.get("surface_pressure", locations=TURBINE_LOCATION, interpolation="bilinear")
raw_temperature = src.get("surface_air_temperature", locations=TURBINE_LOCATION, interpolation="bilinear")
# 2
roughness = rk.wind.roughness_from_clc(clc_path=rk.TEST_DATA["clc-aachen_clipped.tif"], loc=TURBINE_LOCATION)
projected_windspeed = rk.wind.apply_logarithmic_profile_projection(
measured_wind_speed=raw_windspeeds,
measured_height=50, # The MERRA dataset offers windspeeds at 50m
target_height=TURBINE_HUB_HEIGHT,
roughness=roughness,
)
# 3
pressure_corrected_windspeeds = rk.wind.apply_air_density_adjustment(
wind_speed=projected_windspeed,
pressure=raw_pressure,
temperature=raw_temperature,
height=TURBINE_HUB_HEIGHT,
)
convoluted_power_curve = power_curve.convolute_by_gaussian(scaling=0.06, base=0.1)
# 4
power_curve = rk.wind.PowerCurve.from_capacity_and_rotor_diam(
capacity=TURBINE_CAPACITY, rotor_diam=TURBINE_ROTOR_DIAMETER
)
# 5
capacity_factors = convoluted_power_curve.simulate(wind_speed=pressure_corrected_windspeeds)
# Print result
capacity_factors
| (6.25, 51.0) | (6.5, 51.0) | (6.25, 50.75) | |
|---|---|---|---|
| 2015-01-01 00:30:00+00:00 | 0.395655 | 0.265948 | 0.271238 |
| 2015-01-01 01:30:00+00:00 | 0.401460 | 0.266013 | 0.263638 |
| 2015-01-01 02:30:00+00:00 | 0.392434 | 0.262133 | 0.248822 |
| 2015-01-01 03:30:00+00:00 | 0.355571 | 0.242042 | 0.227111 |
| 2015-01-01 04:30:00+00:00 | 0.371400 | 0.258994 | 0.247654 |
| ... | ... | ... | ... |
| 2015-01-03 18:30:00+00:00 | 0.050925 | 0.006616 | 0.116428 |
| 2015-01-03 19:30:00+00:00 | 0.068637 | 0.054866 | 0.204342 |
| 2015-01-03 20:30:00+00:00 | 0.174980 | 0.163084 | 0.207436 |
| 2015-01-03 21:30:00+00:00 | 0.335079 | 0.337258 | 0.250530 |
| 2015-01-03 22:30:00+00:00 | 0.616502 | 0.553001 | 0.451090 |
71 rows × 3 columns
capacity_factors.plot()
plt.show()