Skip to content
Snippets Groups Projects
Commit 3186ba28 authored by Mikkel Friis-Møller's avatar Mikkel Friis-Møller Committed by Mads M. Pedersen
Browse files

updated docs

parent 17b161b7
No related branches found
Tags v1.0.11
No related merge requests found
%% Cell type:markdown id: tags:
# IEA37 Simple Bastankhah Gaussian WakeModel
%% Cell type:code id: tags:
``` python
import numpy as np
import matplotlib.pyplot as plt
from py_wake.examples.data.hornsrev1 import V80, Hornsrev1Site, wt9_x, wt9_y
from py_wake.wake_models import IEA37SimpleBastankhahGaussian
site = Hornsrev1Site()
windTurbines = V80()
wake_model = IEA37SimpleBastankhahGaussian(site, windTurbines)
```
%% Cell type:markdown id: tags:
The `IEA37SimpleBastankhahGaussian` is a subclass of the general `WakeModel` class, see documentation [here](https://topfarm.pages.windenergy.dtu.dk/PyWake/wake_models/WakeModel.html)
Implemented according to [IEA37](https://github.com/byuflowlab/iea37-wflo-casestudies/blob/master/iea37-wakemodel.pdf) and is equivalent to `BastankhahGaussian` for $beta=1/\sqrt{8} \sim ct=0.9637188$
Implemented according to [IEA37](https://github.com/byuflowlab/iea37-wflo-casestudies/blob/master/cs1-2/iea37-wakemodel.pdf) and is equivalent to `BastankhahGaussian` for $beta=1/\sqrt{8} \sim ct=0.9637188$
The implementation of `WakeModel` is highly vectorized and therefore suffixes are used to indicate the dimension of variables. The suffixes used in this context are:
- i: turbines ordered by id
- k: wind speeds
- l: wind directions
This means that `WS_ilk[0,1,2]` holds the wind speed at the first turbine for the second wind direction and third wind speed
%% Cell type:markdown id: tags:
`WakeModel` contains a method, [`calc_wake`](https://topfarm.pages.windenergy.dtu.dk/PyWake/wake_models/WakeModel.html#py_wake.wake_model.WakeModel.calc_wake), to calculate the effective wind speed, turbulence intensity (not implemented yet), power and thrust coefficient.
Let us try to calculate the effective wind speed for two V80 turbines separated by 200m in 10m/s and wind direction parallel to a line between the two turbines
%% Cell type:code id: tags:
``` python
WS_eff_ilk, TI_eff_ilk, power_ilk, ct_ilk,*_ = wake_model.calc_wake(
x_i=[0,0],
y_i=[200,0],
ws=10,
wd=0)
for i in [0,1]:
print ('Turbine', i)
print ('Effective wind speed %fm/s'%WS_eff_ilk[i,0,0])
print ('Power production %.2fW'%power_ilk[i,0,0])
print ('Thrust coefficient %f'%ct_ilk[i,0,0])
print()
```
%% Output
Turbine 0
Effective wind speed 10.000000m/s
Power production 1341000.00W
Thrust coefficient 0.793000
Turbine 1
Effective wind speed 6.895002m/s
Power production 441310.28W
Thrust coefficient 0.804895
%% Cell type:markdown id: tags:
To calculate this, `calc_wake`, uses two wake-model specific methods, `calc_deficit` and `calc_effective_WS`.
`calc_deficit` calculates the deficit:
%% Cell type:code id: tags:
``` python
deficit = wake_model.calc_deficit(
WS_lk=np.array([[10]]), # wind speed at current turbine
D_src_l=np.array([80]), # diameter of current turbine
dw_jl=np.array([[200]]), # down wind distance
cw_jl=np.array([[0]]), # cross wind distance (both horizontal and vertical)
ct_lk=np.array([[0.793000]])) # thrust coefficient
print (deficit[0,0,0])
```
%% Output
3.1049984549612297
%% Cell type:code id: tags:
``` python
x = np.arange(-300,301,1.)
y = np.arange(-100,1001,1)
X,Y = np.meshgrid(x,y)
down_stream = Y>0
deficit_map=np.zeros_like(X)
deficit_map[down_stream] = wake_model.calc_deficit(
WS_lk=np.array([[10]]), # wind speed at current turbine
D_src_l=np.array([80]), # diameter of current turbine
dw_jl=Y[down_stream][:,np.newaxis], # down wind distance
cw_jl=np.abs(X[down_stream])[:,np.newaxis], # cross wind distance (both horizontal and vertical)
ct_lk=np.array([[0.793000]]))[:,0,0] # thrust coefficient
c = plt.contourf(Y,X,deficit_map,100)
plt.colorbar(c)
plt.plot([0,0],[-40,40],'r',lw=3)
```
%% Output
[<matplotlib.lines.Line2D at 0x29bda53db38>]
%% Cell type:markdown id: tags:
while `calc_effective_WS` calculates the effective wind speed by subtracting the deficits from all upstream turbines from the local wind speed. For `NOJ` it subtracts the square root of the sum of squared deficits
%% Cell type:code id: tags:
``` python
wake_model.calc_effective_WS(
WS_lk=np.array([[10]]),
deficit_ilk=deficit)
```
%% Output
array([[6.89500155]])
%% Cell type:markdown id: tags:
Finally, `WakeModel`, contains the method `wake_map` to find the effective wind speed at arbitrary positions
%% Cell type:code id: tags:
``` python
#calculate the wake 200m down stream of a V80
X_j, Y_j, WS_eff_jlk, WS_jlk, P_ilk = wake_model.ws_map(x_j=[200], y_j=[0], h=70,
wt_x_i=[0], wt_y_i=[0], wt_type_i=[0], wt_h_i=[70],
wd=270, ws=10)
print (WS_eff_jlk)
```
%% Output
[[[6.89500155]]]
%% Cell type:markdown id: tags:
For standard purposes, however, we do not call these methods manually. Instead we use the functions in `AEPCalculator`
%% Cell type:markdown id: tags:
**Calculate AEP**
%% Cell type:code id: tags:
``` python
from py_wake.aep_calculator import AEPCalculator
site = Hornsrev1Site()
aep_calc = AEPCalculator(wake_model)
aep_gwh_ilk = aep_calc.calculate_AEP(x_i=[0,0], y_i=[0,-200])
aep_gwh_noloss_ilk = aep_calc.calculate_AEP_no_wake_loss(x_i=[0,0], y_i=[0,-200])
# AEP pr turbine
print ('AEP pr turbine:', aep_gwh_ilk.sum((1,2)))
# AEP pr wind direction
plt.plot(aep_gwh_noloss_ilk[:,:,7].sum(0), label='Without wake loss')
plt.plot(aep_gwh_ilk[:,:,7].sum(0), label='With wake loss')
plt.title('Wind speed: 10m/s')
plt.xlabel('Wind direction [deg]')
plt.ylabel('AEP [GWh]')
plt.legend()
# AEP pr wind speed
plt.figure()
plt.plot(site.default_ws, aep_gwh_noloss_ilk[:,0].sum(0), label='Without wake loss')
plt.plot(site.default_ws, aep_gwh_ilk[:,0].sum(0), label='With wake loss')
plt.title('Wind direction: 0deg')
plt.xlabel('Wind speed [deg]')
plt.ylabel('AEP [GWh]')
plt.legend()
```
%% Output
AEP pr turbine: [9.01126077 9.18331398]
<matplotlib.legend.Legend at 0x29bdb44a048>
%% Cell type:markdown id: tags:
**Wake map**
%% Cell type:code id: tags:
``` python
import matplotlib.pyplot as plt
x,y = wt9_x, wt9_y
aep_calc.plot_wake_map(wt_x=x, wt_y=y, wd=[0], ws=[10])
windTurbines.plot(x, y)
plt.show()
```
%% Output
%% Cell type:markdown id: tags:
**Effective wind speed, power and thrust coefficient**
%% Cell type:code id: tags:
``` python
# wind from 0 deg(index=0) and 10m/s (index=7)
aep_calc.calculate_AEP(x_i=[0,0], y_i=[0,-200])
print ("Effective wind speed: wt0: %f\twt1: %f"%tuple(aep_calc.WS_eff_ilk[:,0,7]))
print ("Power: wt0: %dW\twt1: %dW"%tuple(aep_calc.power_ilk[:,0,7]))
print ("Thrust coefficient: wt0: %f\twt1: %f"%tuple(aep_calc.ct_ilk[:,0,7]))
print ("Probability of ws=10m/s and wd=0deg: %f"%aep_calc.P_ilk[0,0,7])
```
%% Output
Effective wind speed: wt0: 10.000000 wt1: 6.895002
Power: wt0: 1341000W wt1: 441310W
Thrust coefficient: wt0: 0.793000 wt1: 0.804895
Probability of ws=10m/s and wd=0deg: 0.000103
%% Cell type:code id: tags:
``` python
```
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
Source diff could not be displayed: it is too large. Options to address this: view the blob.
%% Cell type:markdown id: tags:
# Compare wake models
%% Cell type:markdown id: tags:
[Try this yourself](https://colab.research.google.com/github/DTUWindEnergy/PyWake/blob/master/docs/notebooks/cmp_wakemodels.ipynb) (requires google account)
%% Cell type:code id: tags:
``` python
%%capture
# Install PyWake if needed
try:
import py_wake
except ModuleNotFoundError:
!pip install py_wake
```
%% Cell type:code id: tags:
``` python
import numpy as np
import matplotlib.pyplot as plt
from py_wake.examples.data.hornsrev1 import V80, Hornsrev1Site, wt9_x, wt9_y
from py_wake.wake_models import NOJ, BastankhahGaussian, Fuga
from py_wake.tests.test_files.fuga import LUT_path_2MW_z0_0_03
site = Hornsrev1Site()
windTurbines = V80()
wake_models = [('NOJ', NOJ(windTurbines, k=0.1)),
('Fuga', Fuga(LUT_path_2MW_z0_0_03, windTurbines)),
('BastankhahGaussian', BastankhahGaussian(windTurbines))]
wake_models = [('NOJ', NOJ(site, windTurbines, k=0.1)),
('Fuga', Fuga(LUT_path_2MW_z0_0_03, site, windTurbines)),
('BastankhahGaussian', BastankhahGaussian(site, windTurbines))]
```
%% Cell type:markdown id: tags:
**Calculate AEP**
%% Cell type:code id: tags:
``` python
from py_wake.aep_calculator import AEPCalculator
site = Hornsrev1Site()
for name, wake_model in wake_models:
aep_calc = AEPCalculator(wake_model)
aep_gwh_ilk = aep_calc.calculate_AEP(x_i=[0,0], y_i=[0,-200])
def fmt(l, v):
print ("%-50s\t%-15s\t%-15s"%(l, str(v[0])[:12], str(v[1])[:12]))
fmt(name, ['WT1','WT2'])
fmt('AEP [GWh]:', aep_gwh_ilk.sum((1,2)))
fmt('Average local effective wind speed [m/s]:', aep_calc.WS_eff_ilk.mean((1,2)))
fmt('local effective wind speed, wd=0deg, ws=10m/s [m/s]:', aep_calc.WS_eff_ilk[:,0,7])
fmt('Power, wd=0deg, ws=10m/s [kW]:', aep_calc.power_ilk[:,0,7]/1000)
fmt('Thrust coefficient, wd=0deg, ws=10m/s [kW]:', aep_calc.ct_ilk[:,0,7])
print ()
```
%% Output
NOJ WT1 WT2
AEP [GWh]: 9.0064893760 9.1794854262
Average local effective wind speed [m/s]: 13.900751327 13.900751327
local effective wind speed, wd=0deg, ws=10m/s [m/s]: 10.0 7.5776556739
Power, wd=0deg, ws=10m/s [kW]: 1341.0 596.32673905
Thrust coefficient, wd=0deg, ws=10m/s [kW]: 0.793 0.8055776556
Fuga WT1 WT2
AEP [GWh]: 9.0490388105 9.2005889867
Average local effective wind speed [m/s]: 13.907948898 13.907948898
local effective wind speed, wd=0deg, ws=10m/s [m/s]: 10.0 7.3881578923
Power, wd=0deg, ws=10m/s [kW]: 1341.0 551.60526260
Thrust coefficient, wd=0deg, ws=10m/s [kW]: 0.793 0.8053881578
BastankhahGaussian WT1 WT2
AEP [GWh]: 8.8969057039 9.1411399030
Average local effective wind speed [m/s]: 13.832862789 13.832862789
local effective wind speed, wd=0deg, ws=10m/s [m/s]: 10.0 3.3412871403
Power, wd=0deg, ws=10m/s [kW]: 1341.0 22.729723546
Thrust coefficient, wd=0deg, ws=10m/s [kW]: 0.793 0.2791728807
%% Cell type:code id: tags:
``` python
from py_wake.aep_calculator import AEPCalculator
site = Hornsrev1Site()
aep_gwh_noloss_ilk = aep_calc.calculate_AEP_no_wake_loss(x_i=[0,0], y_i=[0,-200])
plt.plot(aep_gwh_noloss_ilk[:,:,7].sum(0), label='Without wake loss')
for name, wake_model in wake_models:
aep_calc = AEPCalculator(wake_model)
aep_gwh_ilk = aep_calc.calculate_AEP(x_i=[0,0], y_i=[0,-200])
# AEP pr wind direction
plt.plot(aep_gwh_ilk[:,:,7].sum(0), label=name)
plt.title('Wind speed: 10m/s')
plt.xlabel('Wind direction [deg]')
plt.ylabel('AEP [GWh]')
plt.legend()
```
%% Output
%% Cell type:code id: tags:
``` python
from py_wake.aep_calculator import AEPCalculator
site = Hornsrev1Site()
aep_gwh_noloss_ilk = aep_calc.calculate_AEP_no_wake_loss(x_i=[0,0], y_i=[0,-00])
plt.plot(site.default_ws, aep_gwh_noloss_ilk[:,0].sum(0), label='Without wake loss')
for name, wake_model in wake_models:
aep_calc = AEPCalculator(wake_model)
aep_gwh_ilk = aep_calc.calculate_AEP(x_i=[0,0], y_i=[0,-200])
# AEP pr wind speed
plt.plot(site.default_ws, aep_gwh_ilk[:,0].sum(0), label=name)
plt.title('Wind direction: 0deg')
plt.xlabel('Wind speed [deg]')
plt.ylabel('AEP [GWh]')
plt.legend()
```
%% Output
%% Cell type:markdown id: tags:
**Wake map**
%% Cell type:code id: tags:
``` python
import matplotlib.pyplot as plt
x,y = wt9_x, wt9_y
for name, wake_model in wake_models:
aep_calc = AEPCalculator(wake_model)
plt.figure()
plt.title(name)
aep_calc.plot_wake_map(wt_x=x, wt_y=y, wd=[0], ws=[10], levels=np.arange(3,11,.1))
windTurbines.plot(x, y)
```
%% Output
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
Source diff could not be displayed: it is too large. Options to address this: view the blob.
This diff is collapsed.
%% Cell type:markdown id: tags:
# Exercise: Validate NOJ
%% Cell type:markdown id: tags:
[Try this yourself](https://colab.research.google.com/github/DTUWindEnergy/PyWake/blob/master/docs/notebooks/noj_validation_exercise.ipynb) (requires google account)
%% Cell type:code id: tags:
``` python
%%capture
# Install PyWake if needed
try:
import py_wake
except ModuleNotFoundError:
!pip install py_wake
```
%% Cell type:markdown id: tags:
Validate the down stream wind speed result presented in table 1 in Jensen, Niels Otto. "A note on wind generator interaction." (1983)
%% Cell type:markdown id: tags:
Input
- Nibe turbine:
- radius: 20m
- Wind speed behind the turbine: 1/3U (corresponding to ct=8/9)
- Wake expansion factor, k: 0.1
- wind speed:
- 100m upstream: 8.1 m/s
Results
- 40m down stream: 4.35 m/s
- 100m down stream: 5.7 m/s
Hint:
- Copy the template below into a code cell
- Replace all occurences of "..." with proper values/code
- Take a look at the [refernce guide](https://topfarm.pages.windenergy.dtu.dk/PyWake/reference_guide.html)
%% Cell type:markdown id: tags:
**Template**
```python
import numpy as np
import matplotlib.pyplot as plt
from py_wake.aep_calculator import AEPCalculator
from py_wake.wind_turbines import OneTypeWindTurbines
from py_wake.wake_models import NOJ
from py_wake.site import UniformSite
def p(ws):
# power function for wind turbine
return ...
def ct(ws):
# ct function for wind turbine
return ...
wt = OneTypeWindTurbines(name=...,
diameter=...,
hub_height=...,
ct_func=ct,
power_func=p,
power_unit=...)
wake_model = NOJ(...)
site = UniformSite(p_wd=[1], ti=.1) # Dummy site (flat and uniform)
aep_calc = AEPCalculator(site, wt, wake_model)
wake_model = NOJ(...)
aep_calc = AEPCalculator(wake_model)
X,Y,WS_eff = aep_calc.wake_map(x_j = [...],
y_j=[...],
wt_x=[...],
wt_y=[...],
wd=[...],
ws=[...])
print ( WS_eff)
```
%% Cell type:code id: tags:
``` python
```
......
%% Cell type:markdown id: tags:
# Exercise: Validate NOJ (solution)
%% Cell type:markdown id: tags:
[Try this yourself](https://colab.research.google.com/github/DTUWindEnergy/PyWake/blob/master/docs/notebooks/noj_validation_exercise_solution.ipynb) (requires google account)
%% Cell type:code id: tags:
``` python
%%capture
# Install PyWake if needed
try:
import py_wake
except ModuleNotFoundError:
!pip install py_wake
```
%% Cell type:markdown id: tags:
Validate the down stream wind speed result presented in table 1 in Jensen, Niels Otto. "A note on wind generator interaction." (1983)
%% Cell type:markdown id: tags:
Input
- Nibe turbine:
- radius: 20m
- Wind speed behind the turbine: 1/3U (corresponding to ct=8/9)
- Wake expansion factor, k: 0.1
- wind speed:
- 100m upstream: 8.1 m/s
Results
- 40m down stream: 4.35 m/s
- 100m down stream: 5.7 m/s
Hint:
- Copy the template below into a code cell
- Replace all occurences of "..." with proper values/code
- Take a look at the [refernce guide](https://topfarm.pages.windenergy.dtu.dk/PyWake/reference_guide.html)
%% Cell type:code id: tags:
``` python
import numpy as np
import matplotlib.pyplot as plt
from py_wake.aep_calculator import AEPCalculator
from py_wake.wind_turbines import OneTypeWindTurbines
from py_wake.wake_models import NOJ
from py_wake.site import UniformSite
def p(ws):
return 0
def ct(ws):
return 8/9
wt = OneTypeWindTurbines(name="Nibe",
diameter=40,
hub_height=50,
ct_func= ct,
power_func = p,
power_unit='w')
wake_model = NOJ(wt, k=.1)
site = UniformSite(p_wd=[1], ti=.1) # Dummy site (flat and uniform)
aep_calc = AEPCalculator(site, wt, wake_model)
wake_model = NOJ(site, wt, k=.1)
aep_calc = AEPCalculator(wake_model)
X,Y,WS_eff = aep_calc.wake_map(x_j = [0],
y_j=[100,-40,-100],
wt_x=[0],
wt_y=[0],
wd=[0],
ws=[8.1])
print ( WS_eff)
```
%% Output
[[8.1 ]
[4.35]
[5.7 ]]
%% Cell type:code id: tags:
``` python
```
......
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