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
In [1]:
Copied!
import reskit as rk
import numpy as np
import matplotlib.pyplot as plt
import reskit as rk
import numpy as np
import matplotlib.pyplot as plt
Simulate a Single Location¶
In [2]:
Copied!
# 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)
# 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)
In [3]:
Copied!
# 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())
# 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
In [4]:
Copied!
# 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())
# 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
In [5]:
Copied!
# 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()
# 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()
Out[5]:
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
In [6]:
Copied!
# 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)
# 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)
In [7]:
Copied!
# 5. Capacity factor estimation
capacity_factors = convoluted_power_curve.simulate(wind_speed=pressure_corrected_windspeeds)
capacity_factors
# 5. Capacity factor estimation
capacity_factors = convoluted_power_curve.simulate(wind_speed=pressure_corrected_windspeeds)
capacity_factors
Out[7]:
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])
In [8]:
Copied!
plt.plot(capacity_factors)
plt.xlabel("Time")
plt.ylabel("Capacity Factor")
plt.grid()
plt.show()
plt.plot(capacity_factors)
plt.xlabel("Time")
plt.ylabel("Capacity Factor")
plt.grid()
plt.show()
Simulate multiple locations at once (recommended)¶
In [9]:
Copied!
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
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
Out[9]:
| (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
In [10]:
Copied!
capacity_factors.plot()
plt.show()
capacity_factors.plot()
plt.show()