Skip to content
Snippets Groups Projects
Commit fca50120 authored by Mads M. Pedersen's avatar Mads M. Pedersen
Browse files

fix section levels in notebooks/WindTurbines.ipynb

parent 708d0cf4
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags:
# WindTurbine
%% Cell type:markdown id: tags:
For a given wind turbine type and effective wind speed (WSeff), the `WindTurbine` object provides the power and thrust coefficient (CT), as well as the wind turbine hub height (H) and diameter (D).
%% Cell type:markdown id: tags:
## Setting up Windturbine objects
%% Cell type:markdown id: tags:
### Predefined example WindTurbines
PyWake contains a few predefined turbines, e.g. the V80 from Hornsrev1, the 3.35MW from IEA task 37 and the DTU10MW.
%% Cell type:code id: tags:
``` python
# Install PyWake if needed
try:
import py_wake
except ModuleNotFoundError:
!pip install git+https://gitlab.windenergy.dtu.dk/TOPFARM/PyWake.git
```
%% Cell type:code id: tags:
``` python
import os
import numpy as np
import matplotlib.pyplot as plt
from py_wake.wind_turbines import WindTurbines
from py_wake.examples.data.hornsrev1 import V80
from py_wake.examples.data.iea37 import IEA37_WindTurbines, IEA37Site
from py_wake.examples.data.dtu10mw import DTU10MW
v80 = V80()
iea37 = IEA37_WindTurbines()
dtu10mw = DTU10MW()
```
%% Cell type:markdown id: tags:
### Import from WAsP wtg files
%% Cell type:code id: tags:
``` python
from py_wake.examples.data import wtg_path
wtg_file = os.path.join(wtg_path, 'NEG-Micon-2750.wtg')
neg2750 = WindTurbines.from_WAsP_wtg(wtg_file)
```
%% Cell type:markdown id: tags:
### User-defined WindTurbine
%% Cell type:code id: tags:
``` python
from py_wake.wind_turbines import WindTurbine
from py_wake.wind_turbines.power_ct_functions import PowerCtTabular
u = [0,3,12,25,30]
ct = [0,8/9,8/9,.3, 0]
power = [0,0,2000,2000,0]
my_wt = WindTurbine(name='MyWT',
diameter=123,
hub_height=321,
powerCtFunction=PowerCtTabular(u,power,'kW',ct))
```
%% Cell type:markdown id: tags:
### Generic WindTurbine
PyWake has a `GenericWindTurbine` class which make a wind turbine where the power is computed by a analytical model based on diameter and nominal power.
The model takes a lot of optional inputs which default to empirical values, e.g.
`air_density=1.225, max_cp=.49, constant_ct=.8, gear_loss_const=.01, gear_loss_var=.014, generator_loss=0.03, converter_loss=.03`.
%% Cell type:code id: tags:
``` python
from py_wake.wind_turbines.generic_wind_turbines import GenericWindTurbine
gen_wt = GenericWindTurbine('G10MW', 178.3, 119, power_norm=10000, turbulence_intensity=.1)
```
%% Cell type:markdown id: tags:
## Multi-type Wind Turbines
You can collect a list of different turbine types into a single WindTurbines object
%% Cell type:code id: tags:
``` python
wts = WindTurbines.from_WindTurbine_lst([v80,iea37,dtu10mw,my_wt,gen_wt,neg2750])
```
%% Cell type:code id: tags:
``` python
types = wts.types()
print ("Name:\t\t%s" % "\t".join(wts.name(types)))
print('Diameter[m]\t%s' % "\t".join(map(str,wts.diameter(type=types))))
print('Hubheigt[m]\t%s' % "\t".join(map(str,wts.hub_height(type=types))))
```
%% Output
Name: V80 3.35MW DTU10MW MyWT G10MW NEG-Micon 2750/92 (2750 kW)
Diameter[m] 80.0 130.0 178.3 123.0 178.3 92.0
Hubheigt[m] 70.0 110.0 119.0 321.0 119.0 70.0
%% Cell type:markdown id: tags:
#### Power curve
### Power curve
%% Cell type:code id: tags:
``` python
ws = np.arange(3,25)
plt.xlabel('Wind speed [m/s]')
plt.ylabel('Power [kW]')
for t in types:
plt.plot(ws, wts.power(ws, type=t)*1e-3,'.-', label=wts.name(t))
plt.legend(loc=1)
```
%% Output
<matplotlib.legend.Legend at 0x2b3ddcf0310>
%% Cell type:markdown id: tags:
#### CT curve
### CT curve
%% Cell type:code id: tags:
``` python
plt.xlabel('Wind speed [m/s]')
plt.ylabel('Ct [-]')
for t in types:
plt.plot(ws, wts.ct(ws, type=t)*1e-3,'.-', label=wts.name(t))
plt.legend(loc=1)
```
%% Output
<matplotlib.legend.Legend at 0x2b3d87e0c40>
%% Cell type:markdown id: tags:
## Multidimensional Power/Ct curves
%% Cell type:markdown id: tags:
Some WAsP wtg files defines multiple wind turbine modes. E.g. the `Vestas V112-3.0 MW.wtg` which has 12 modes representing different levels of air density. In this case, the mode defaults to 0.
%% Cell type:code id: tags:
``` python
wtg_file = os.path.join(wtg_path, 'Vestas V112-3.0 MW.wtg')
v112 = WindTurbines.from_WAsP_wtg(wtg_file)
required_inputs, optional_inputs = v112.function_inputs
upct = {}
for m in [0,1,5]:
plt.plot(v112.power(ws, mode=m)/1000, label=f'mode: {m}')
p0,ct0 = v112.power_ct(ws, mode=0)
p1,ct1 = v112.power_ct(ws, mode=1)
plt.ylabel('Power [kW]')
plt.xlabel('Wind speed [m/s]')
plt.legend()
```
%% Output
<matplotlib.legend.Legend at 0x2b3dd8bdc70>
%% Cell type:markdown id: tags:
### Discrete dimensions (e.g. operational mode)
WindTurbines can be defined using a `PowerCtFunctionList`. In fact this is the approach used by multi-mode WAsP wind turbines and also when creating multi-type wind turbine (in which case the key is `type`)
%% Cell type:code id: tags:
``` python
from py_wake.wind_turbines.power_ct_functions import PowerCtFunctionList
mode0_power_ct=PowerCtTabular(ws, p0, 'w', ct0)
mode1_power_ct=PowerCtTabular(ws, p1, 'w', ct1)
multimode_power_ct = PowerCtFunctionList(key='my_mode',
powerCtFunction_lst=[mode0_power_ct, mode1_power_ct],
default_value=None)
wt = WindTurbine('MultimodeWT', 112, 84, powerCtFunction=multimode_power_ct)
for m in [0,1]:
plt.plot(wt.power(ws, my_mode=m)/1000, label=f'my_mode: {m}')
plt.ylabel('Power [kW]')
plt.xlabel('Wind speed [m/s]')
plt.legend()
```
%% Output
<matplotlib.legend.Legend at 0x2b3de1986d0>
%% Cell type:markdown id: tags:
### Multidimentional power/ct tabulars
It is also possible to setup a wind turbine using a multidimensional power and ct tabular array. In this case the power can ct values will be calculated using multidimensional linear interpolation.
%% Cell type:code id: tags:
``` python
from py_wake.wind_turbines.power_ct_functions import PowerCtNDTabular
# setup multidimensional power and ct tabulars
# p0,ct0 ~ rho=0.95
# p1,ct1 ~ rho=1.225
power_array = np.array([p1,p0]).T
ct_array = np.array([ct1,ct0]).T
density = [0.95,1.225]
powerCtFunction = PowerCtNDTabular(input_keys=['ws','rho'],
value_lst=[ws,density],
power_arr=power_array, power_unit='w',
ct_arr=ct_array)
wt = WindTurbine('AirDensityDependentWT', 112, 84, powerCtFunction=powerCtFunction)
for r in [0.995,1.1,1.225]:
plt.plot(wt.power(ws, rho=r)/1000, label=f'Air density: {r}')
plt.ylabel('Power [kW]')
plt.xlabel('Wind speed [m/s]')
plt.legend()
```
%% Output
<matplotlib.legend.Legend at 0x2b3de1984c0>
%% Cell type:markdown id: tags:
Alternatively, the data can be passed as an xarray dataset. The dataset must have the data variables, `power` and `ct`, and the coordinate, `ws`
%% Cell type:code id: tags:
``` python
import xarray as xr
from py_wake.wind_turbines.power_ct_functions import PowerCtXr
ds = xr.Dataset(
data_vars={'power': (['ws', 'rho'], np.array([p1,p0]).T),
'ct': (['ws', 'boost'], np.array([ct1, ct0]).T)},
coords={'rho': [0.95,1.225], 'ws': ws})
curve = PowerCtXr(ds, 'w')
wt = WindTurbine('AirDensityDependentWT', 112, 84, powerCtFunction=powerCtFunction)
for r in [0.995,1.1,1.225]:
plt.plot(wt.power(ws, rho=r)/1000, label=f'Air density: {r}')
plt.ylabel('Power [kW]')
plt.xlabel('Wind speed [m/s]')
plt.legend()
```
%% Output
<matplotlib.legend.Legend at 0x2b3de1c8f70>
%% Cell type:markdown id: tags:
### Continous Power/Ct functions
Finally, the Power can Ct can be calculated using a function which may take multiple input variables.
%% Cell type:code id: tags:
``` python
from py_wake.wind_turbines.power_ct_functions import PowerCtFunction
def density_scaled_power_ct(u, rho=1.225):
# function to calculate power and ct
rated_power = 3e6
density_scale=rho/.95
return (np.minimum(np.interp(u,ws, p0) * density_scale, rated_power), # density scaled power, limited by rated power
u*0) #dummy ct
powerCtFunction = PowerCtFunction(
input_keys=['ws','rho'],
power_ct_func=density_scaled_power_ct,
power_unit='w',
optional_inputs=['rho'], # allowed to be optional as a default value is speficifyed in density_scaled_power_ct
)
wt = WindTurbine('AirDensityDependentWT', 112, 84, powerCtFunction=powerCtFunction)
for r in [0.995,1.1,1.5]:
plt.plot(wt.power(ws, rho=r)/1000, label=f'Air density: {r}')
plt.ylabel('Power [kW]')
plt.xlabel('Wind speed [m/s]')
plt.legend()
```
%% Output
<matplotlib.legend.Legend at 0x2b3de2e9310>
%% Cell type:markdown id: tags:
### GenericTIRhoWindTurbine
The `GenericTIRhoWindTurbine` extends the [`GenericWindTurbine`](#Generic-WindTurbine) by with multidimensional power/ct curves that depends on turbulence intensity, `TI_eff` and the air density, `Air_density`.
%% Cell type:code id: tags:
``` python
from py_wake.wind_turbines.generic_wind_turbines import GenericTIRhoWindTurbine
wt = GenericTIRhoWindTurbine('2MW', 80, 70, power_norm=2000,
TI_eff_lst=np.linspace(0, .5, 6), default_TI_eff=.1,
Air_density_lst=np.linspace(.9, 1.5, 5), default_Air_density=1.225)
u = np.arange(3, 28, .1)
ax1 = plt.gca()
ax2 = plt.twinx()
for ti in [0,.1,.3]:
p, ct = wt.power_ct(u, TI_eff=ti)
ax1.plot(u, p / 1e6, label='TI=%f' % ti)
ax2.plot(u, ct, '--')
ax1.legend(loc='center right')
ax1.set_ylabel('Power [MW]')
ax2.set_ylabel('Ct')
plt.figure()
u = np.arange(3, 28, .1)
ax1 = plt.gca()
ax2 = plt.twinx()
for rho in [.9,1.2,1.5]:
p, ct = wt.power_ct(u, Air_density=rho)
ax1.plot(u, p / 1e6, label='Air density=%f' % rho)
ax2.plot(u, ct, '--')
ax1.legend(loc='center right')
ax1.set_ylabel('Power [MW]')
ax2.set_ylabel('Ct')
```
%% Output
Text(0, 0.5, 'Ct')
%% Cell type:markdown id: tags:
## Power/Ct input arguments
The input arguments for the Power and Ct curves can be obtained from:
- Arguments passed when calling the WindFarmModel
- Data present in the site
- Values computed in the simulation, i.e. `WS_eff` and `TI_eff`. Note that `WS_eff` is passed as `ws`
%% Cell type:markdown id: tags:
### Arguments passed to WindFarmModel call
%% Cell type:code id: tags:
``` python
from py_wake.examples.data.hornsrev1 import Hornsrev1Site
from py_wake.deficit_models.noj import NOJ
wfm = NOJ(site=Hornsrev1Site(), windTurbines=wt)
for rho in [0.95,1.225]:
sim_res = wfm([0], [0], wd=0, Air_density=rho) # rho passed to WindFarmModel call
power = sim_res.Power.squeeze() / 1000
plt.plot(power.ws, power, label=f'rho {rho}')
plt.xlabel('Wind speed [m/s]')
plt.ylabel('Power [kW]')
plt.legend()
```
%% Output
<matplotlib.legend.Legend at 0x2b3de4fa910>
%% Cell type:markdown id: tags:
### Data present in Site
%% Cell type:code id: tags:
``` python
from py_wake.examples.data.hornsrev1 import Hornsrev1Site
from py_wake.deficit_models.noj import NOJ
site = Hornsrev1Site()
site.ds['Air_density'] = ('wd',np.linspace(.95,1.225,13)) # wd-dependent rho added to site
wfm = NOJ(site=site, windTurbines=wt)
for wd in [0,330]:
sim_res = wfm([0], [0], wd=wd)
power = sim_res.Power.squeeze() / 1000
plt.plot(power.ws, power, label=f'wd: {wd}')
plt.xlabel('Wind speed [m/s]')
plt.ylabel('Power [kW]')
plt.legend()
```
%% Output
<matplotlib.legend.Legend at 0x2b3de5b0760>
%% Cell type:markdown id: tags:
## Interpolation method
%% Cell type:markdown id: tags:
### PowerCtTabular
`PowerCtTabular` which is used by most predefined wind turbines takes a `method` argument which can be
- `linear`: Linear interpolation (default)
- `pchip`: Piecewise Cubic Hermite Interpolating Polynomial. Smooth interpolation with continous first order derivatives and not overshoots
- `spline`: Smooth interpolation with continous first and second order derivatives. Closer to original piecewise linear curve, but may have overshoots
%% Cell type:code id: tags:
``` python
wt_lst = [(m, V80(method=m)) for m in ['linear','pchip','spline']]
_ws = np.linspace(14.8,20,1000)
for n, _wt in wt_lst:
plt.plot(_ws, _wt.power(_ws)/1e3, label=n)
plt.ylabel('Power [kW]')
plt.xlabel('Wind speed [m/s]')
plt.legend()
```
%% Output
<matplotlib.legend.Legend at 0x2b3de614cd0>
%% Cell type:markdown id: tags:
### PowerCtNDTabular
When using the N-dimensional `PowerCtNDTabular`, only linear interpolation is supported
%% Cell type:markdown id: tags:
## Plot
%% Cell type:code id: tags:
``` python
# Top-view plot
from py_wake.examples.data.hornsrev1 import Hornsrev1Site
s = IEA37Site(16)
x,y = s.initial_position.T
wts.plot(x,y,type=np.arange(len(x))%len(types))
```
%% Output
%% Cell type:code id: tags:
``` python
# Side-view plot
wts.plot_yz(np.array([-600,0,600]), wd=0, types=[0,1,2], yaw=[-30, 10, 90])
```
%% Output
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment