Site Object
For a given position, reference wind speed (WSref) and wind direction (WDref), Site
provides the local wind condition in terms of wind speed (WS), wind direction (WD), turbulence intensity (TI) and the probability of each combination of wind direction and wind speed. Furthermore, Site
is responsible for calculating the down-wind, cross-wind and vertical distance between wind turbines (which in non-flat terrain is different from the straight-line distances).
Intall PyWake if needed
[1]:
# Install PyWake if needed
try:
import py_wake
except ModuleNotFoundError:
!pip install git+https://gitlab.windenergy.dtu.dk/TOPFARM/PyWake.git
Predefined example sites
PyWake contains a few predefined sites of different complexities:
IEA37Site:
UniformSite
(fix wind speed (9.8m/s), predefined wind sector probability).Hornsrev1:
UniformWeibullSite
(Weibull distributed wind speed, predefined wind sector propability, uniform wind a over flat wind area).ParqueFicticioSite:
WaspGridSite
(position-dependent Weibull distributed wind speed and sector probability. Terrain following distances over non-flat terrain). Loaded from a set of *.grd files exported from WAsP.
First we import all sites and Python elements for later use
[2]:
import numpy as np
import matplotlib.pyplot as plt
[3]:
from py_wake.examples.data.hornsrev1 import Hornsrev1Site
from py_wake.examples.data.iea37 import IEA37Site
from py_wake.examples.data.ParqueFicticio import ParqueFicticioSite
sites = {"IEA37": IEA37Site(n_wt=16),
"Hornsrev1": Hornsrev1Site(),
"ParqueFicticio": ParqueFicticioSite()}
PyWake also allows for user-defined sites
You can define your own site using one of the Site
classes:
UniformWeibullSite: Site with uniform sector-dependent Weibull distributed wind speed.
WaspGridSite: Site with gridded non-uniform inflow based on *.grd files exported from WAsP.
XRSite: The flexible general base class behind all Sites.
For more information on these classes, please see the API reference on the Site object.
UniformWeibullSite
[4]:
from py_wake.site import UniformWeibullSite
#specifying the necessary parameters for the UniformWeibullSite object
site = UniformWeibullSite(p_wd = [.20,.25,.35,.25], # sector frequencies
a = [9.176929, 9.782334, 9.531809, 9.909545], # Weibull scale parameter
k = [2.392578, 2.447266, 2.412109, 2.591797], # Weibull shape parameter
ti = 0.1 # turbulence intensity, optional
)
WaspGridSite
[5]:
from py_wake.site import WaspGridSite
from py_wake.examples.data.ParqueFicticio import ParqueFicticio_path
site = WaspGridSite.from_wasp_grd(ParqueFicticio_path)
XRSite
The XRSite
is the most general and flexible Site
. For the input dataset there are some required and optional data variables, such as:
Required data variables:
P
: probability of flow case(s)
or
Weibull_A
: Weibull scale parameter(s)Weibull_k
: Weibull shape parameter(s)Sector_frequency
: Probability of each wind direction sector
Optional data variables:
WS
: Wind speed, if not present, the reference wind speedws
is usedSpeedup
: Factor multiplied to the wind speedTurning
: Wind direction turningTI
: Turbulence intensityxxx: Custom variables needed by the wind turbines to compute power, ct or loads
Each data variable may be constant or depend on a combination of the following inputs (Note, the input variables must be ordered according to the list, i.e.
P(wd,ws)
is ok, whileP(ws,wd)
is not):i
: Wind turbine position (one position per wind turbine)x
,y
: Gridded 2d positionx
,y
,h
: Gridded 3d positiontime
: Timewd
: Refernce wind directionws
: Reference wind speed
[6]:
from py_wake.site import XRSite
from py_wake.site.shear import PowerShear
import xarray as xr
import numpy as np
from py_wake.utils import weibull
from numpy import newaxis as na
f = [0.036, 0.039, 0.052, 0.07, 0.084, 0.064, 0.086, 0.118, 0.152, 0.147, 0.1, 0.052]
A = [9.177, 9.782, 9.532, 9.91, 10.043, 9.594, 9.584, 10.515, 11.399, 11.687, 11.637, 10.088]
k = [2.393, 2.447, 2.412, 2.592, 2.756, 2.596, 2.584, 2.549, 2.471, 2.607, 2.627, 2.326]
wd = np.linspace(0, 360, len(f), endpoint=False)
ti = .1
# Site with constant wind speed, sector frequency, constant turbulence intensity and power shear
uniform_site = XRSite(
ds=xr.Dataset(data_vars={'WS': 10, 'P': ('wd', f), 'TI': ti},
coords={'wd': wd}),
shear=PowerShear(h_ref=100, alpha=.2))
# Site with wind direction dependent weibull distributed wind speed
uniform_weibull_site = XRSite(
ds=xr.Dataset(data_vars={'Sector_frequency': ('wd', f), 'Weibull_A': ('wd', A), 'Weibull_k': ('wd', k), 'TI': ti},
coords={'wd': wd}))
# Site with a speedup and a turning value per WT
x_i, y_i = np.arange(5) * 100, np.zeros(5) # WT positions
complex_fixed_pos_site = XRSite(
ds=xr.Dataset(
data_vars={'Speedup': ('i', np.arange(.8, 1.3, .1)),
'Turning': ('i', np.arange(-2, 3)),
'P': ('wd', f)},
coords={'i': np.arange(5), 'wd': wd}),
initial_position=np.array([x_i, y_i]).T)
# Site with gridded speedup information
complex_grid_site = XRSite(
ds=xr.Dataset(
data_vars={'Speedup': (['x', 'y'], np.arange(.8, 1.4, .1).reshape((3, 2))),
'P': ('wd', f)},
coords={'x': [0, 500, 1000], 'y': [0, 500], 'wd': wd}))
# Site with ws dependent speedup and wd- and ws distributed probability
P_ws = weibull.cdf(np.array([3, 5, 7, 9, 11, 13]), 10, 2) - weibull.cdf(np.array([0, 3, 5, 7, 9, 11]), 10, 2)
P_wd_ws = P_ws[na, :] * np.array(f)[:, na]
complex_ws_site = XRSite(
ds=xr.Dataset(
data_vars={'Speedup': (['ws'], np.arange(.8, 1.4, .1)),
'P': (('wd', 'ws'), P_wd_ws), 'TI': ti},
coords={'ws': [1.5, 4, 6, 8, 10, 12], 'wd': wd}))
Gridded non-uniform wind resources as time series with XRSite
This example creates a site with 2D non-uniform time series resources for wind speed (ws), wind direction (wd), and turbulence intensity (ti). The data is provided as arrays with dimensions corresponding to spatial coordinates (x, y) and time.
[7]:
site_x, site_y = np.meshgrid(np.arange(0.1, 1000, 100), np.arange(0.1, 2000, 100))
site_x, site_y = site_x.flatten(), site_y.flatten()
site_time = np.arange(100)
site_ws = np.random.uniform(3.0, 21.0, (len(site_x), len(site_y), len(site_time)))
site_wd = np.random.uniform(0.0, 360.0, (len(site_x), len(site_y), len(site_time)))
ds = xr.Dataset(
data_vars=dict(
WS=(["x", "y", "time"], site_ws),
WD=(["x", "y", "time"], site_wd),
TI=(["x", "y", "time"], np.ones_like(site_ws) * 0.1), # hardcoded TI=0.1
P=1, # deterministic wind resource
),
coords=dict(
x=("x", site_x),
y=("y", site_y),
time=("time", site_time),
),
)
non_uniform_ts_site = XRSite(ds)
wss_at_mean_loc = non_uniform_ts_site.local_wind(
site_x.mean(), site_y.mean(), time=site_time
)["WS_ilk"]
print(f"Mean wind speed at the mean location: {wss_at_mean_loc.mean():.2f} m/s")
# check the map of the mean wind speed at the site
mean_resource = ds.WS.mean(dim="time").values
plt.contourf(site_x, site_y, mean_resource)
plt.colorbar()
plt.title("Mean wind speed [m/s]")
plt.xlabel("x [m]")
_ = plt.ylabel("y [m]")
Mean wind speed at the mean location: 12.08 m/s

Wake effects from neighbouring wind farms
In some cases, calculation of wake interaction between the wind farm to optimize and neighbouring wind farms considerably slow down an optimization work flow. To avoid this, a site, which includes wake effects from neighbouring wind farms, can be pre-generated and used for the optimization.
The speed up of this solution depends on the number of turbines in both the current and neighbouring wind farms, as well as the type of sites. If the original site is a uniform site, then a pre-generated site with wake effects from neighbouring wind farms may slow down the workflow as it adds interpolation of inflow characteristics in space.
Note also, that a pre-generated site with wake effects from neighbouring wind farms is only eqivalent to the full simulation if the applied deficit model uses the effective wind speed (some models have an option to switch between effective and free-stream local wind speed).
[8]:
# import and setup site and windTurbines
from py_wake.examples.data.iea37 import IEA37Site, IEA37_WindTurbines
from py_wake.deficit_models.gaussian import BastankhahGaussianDeficit
from py_wake.wind_turbines import WindTurbine, WindTurbines
from py_wake.wind_farm_models import PropagateDownwind
from py_wake.superposition_models import LinearSum
site = IEA37Site(16)
# setup current, neighbour and all positions
wt_x, wt_y = site.initial_position.T
neighbour_x, neighbour_y = wt_x-4000, wt_y
all_x, all_y = np.r_[wt_x,neighbour_x], np.r_[wt_y,neighbour_y]
windTurbines = WindTurbines.from_WindTurbine_lst([IEA37_WindTurbines(),IEA37_WindTurbines()])
windTurbines._names = ["Current wind farm","Neighbour wind farm"]
types = [0]*len(wt_x) + [1]*len(neighbour_x)
wf_model = PropagateDownwind(site, windTurbines,
wake_deficitModel=BastankhahGaussianDeficit(use_effective_ws=True),
superpositionModel=LinearSum())
# Consider wd=270 +/- 30 deg only
wd_lst = np.arange(240,301)
[9]:
#plotting the wake maps for the desired flow case
wsp = 9.8
wdir = 267
plt.figure(figsize=(16, 6))
wf_model(all_x, all_y, type=types, wd=wdir, ws=wsp, h=110).flow_map().plot_wake_map()
plt.xlabel('x [m]')
plt.ylabel('y [m]')
plt.title('Wake map for'+ f' {wdir} deg and {wsp} m/s')
[9]:
Text(0.5, 1.0, 'Wake map for 267 deg and 9.8 m/s')

Now, we run the simulation of all wind turbines and calculate AEP of current wind farm
[10]:
print("Total AEP: %f GWh"%wf_model(all_x, all_y, type=types, ws=[wsp], wd=wd_lst).aep().isel(wt=np.arange(len(wt_x))).sum())
Total AEP: 85.187662 GWh
We can also calculate the AEP of the current wind farm by enclosing it in a flow box and setting up a new wind farm model
[11]:
#making a flow box covering the area of interest (i.e the current wind farm + 100m)
ext = 1000
flow_box = wf_model(neighbour_x, neighbour_y, wd=wd_lst).flow_box(
x=np.linspace(min(wt_x) - ext, max(wt_x) + ext, 101),
y=np.linspace(min(wt_y) - ext, max(wt_y) + ext, 101),
h=110)
#creating new site based on the flow box
from py_wake.site.xrsite import XRSite
wake_site = XRSite.from_flow_box(flow_box)
Now, we plot the “free-stream” inflow wind speed of the current wind farm.
[12]:
plt.figure(figsize=(16, 6))
wake_site.ds.WS.sel(wd=267).plot(y='y', cmap = 'Blues_r')
windTurbines.plot(all_x, all_y, types, wd=270)

Then, we setup a new wind farm model with the new pre-generated site and calculate the AEP.
[13]:
wf_model_wake_site = PropagateDownwind(wake_site, windTurbines,
wake_deficitModel=BastankhahGaussianDeficit(use_effective_ws=True),
superpositionModel=LinearSum())
[14]:
print("Total AEP: %f GWh"%wf_model_wake_site(wt_x, wt_y, ws=[wsp], wd=wd_lst).aep().sum())
Total AEP: 85.187032 GWh
Note that the AEP is not exactly equal due to interpolation errors. The discrepancy can be lowered by increasing the resolution of the flow box.
Lastly, we plot the flow map of the current wind farm with the selected flow box.
[15]:
plt.figure(figsize=(16, 6))
wf_model_wake_site(wt_x, wt_y, wd=wdir, ws=wsp, h=110).flow_map().plot_wake_map()
windTurbines.plot(neighbour_x, neighbour_y, type=1, wd=wdir)
plt.xlabel('x [m]')
plt.ylabel('y [m]')
[15]:
Text(0, 0.5, 'y [m]')

Local wind
The method local_wind
is used to calculate the local wind in a wind farm given certain turbine positions or coordinates. The class returns a LocalWind
-dictionary.
[16]:
localWinds = {name: site.local_wind(x=site.initial_position[:,0], # x position
y = site.initial_position[:,1], # y position
h=site.initial_position[:,0]*0+70, # height
ws=None, # defaults to 3,4,..,25
wd=None, # defaults to 0,1,...,360
) for name, site in sites.items()}
LocalWind.coords
contains the current coordinates, e.g.:
i: Point number. Points can be wind turbine position or just points in a flow map
wd: Ambient reference wind direction
ws: Ambient reference wind speed
x,y,h: position and height of points
while the dictionary itself contains some data variables:
WD: Local wind direction
WS: Local wind speed
TI: Local turbulence intensity
P: Probability of flow case (wind direction and wind speed)
The IEA37
site has 16 wind turbines on a uniform site with a fixed wind speed of 9.8 m/s and the data variables therefore only depend on wind direction.
[17]:
print (localWinds['IEA37'].coords.keys())
localWinds['IEA37'].P
dict_keys(['wd', 'ws', 'i', 'x', 'y', 'h'])
[17]:
<xarray.DataArray (wd: 360)> Size: 3kB array([0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00106667, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.00128889, 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0016 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , 0.0028 , ... 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00946667, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00204444, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00142222, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00097778, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111, 0.00111111]) Coordinates: * wd (wd) int64 3kB 0 1 2 3 4 5 6 7 ... 352 353 354 355 356 357 358 359 Attributes: description: Probability of wind flow case (i.e. wind direction and wind...
The Hornsrev1
site has 80 wind turbines on a uniform site and the data variables therefore depend on wind direction and wind speed.
[18]:
localWinds['Hornsrev1'].P
[18]:
<xarray.DataArray (wd: 360, ws: 23)> Size: 66kB array([[6.14682576e-05, 8.55902794e-05, 1.05949549e-04, ..., 1.41427496e-07, 5.73800241e-08, 2.19294217e-08], [6.14682576e-05, 8.55902794e-05, 1.05949549e-04, ..., 1.41427496e-07, 5.73800241e-08, 2.19294217e-08], [6.14682576e-05, 8.55902794e-05, 1.05949549e-04, ..., 1.41427496e-07, 5.73800241e-08, 2.19294217e-08], ..., [6.14682576e-05, 8.55902794e-05, 1.05949549e-04, ..., 1.41427496e-07, 5.73800241e-08, 2.19294217e-08], [6.14682576e-05, 8.55902794e-05, 1.05949549e-04, ..., 1.41427496e-07, 5.73800241e-08, 2.19294217e-08], [6.14682576e-05, 8.55902794e-05, 1.05949549e-04, ..., 1.41427496e-07, 5.73800241e-08, 2.19294217e-08]]) Coordinates: * wd (wd) int64 3kB 0 1 2 3 4 5 6 7 ... 352 353 354 355 356 357 358 359 * ws (ws) int64 184B 3 4 5 6 7 8 9 10 11 ... 17 18 19 20 21 22 23 24 25 Attributes: description: Probability of wind flow case (i.e. wind direction and wind...
Finally, the ParqueFicticio
site has 8 turbines in a complex terrain and the data variables therefore depend on wind direction, wind speed, and position.
[19]:
localWinds['ParqueFicticio'].P
[19]:
<xarray.DataArray (i: 8, wd: 360, ws: 23)> Size: 530kB array([[[3.30521189e-04, 2.90945174e-04, 2.24051965e-04, ..., 2.17151164e-12, 4.18358259e-13, 7.59823194e-14], [3.29678728e-04, 2.89724248e-04, 2.22255957e-04, ..., 1.42378793e-12, 2.62971871e-13, 4.56948366e-14], [3.28803760e-04, 2.88465466e-04, 2.20425575e-04, ..., 9.24548089e-13, 1.63531488e-13, 2.71554012e-14], ..., [3.30774594e-04, 2.93358503e-04, 2.28869097e-04, ..., 6.51548667e-12, 1.39516685e-12, 2.82983824e-13], [3.30714479e-04, 2.92588913e-04, 2.27298658e-04, ..., 4.55200242e-12, 9.41737928e-13, 1.84263977e-13], [3.30630133e-04, 2.91784558e-04, 2.25692881e-04, ..., 3.15619870e-12, 6.30371964e-13, 1.18883000e-13]], [[3.26402880e-04, 2.87997698e-04, 2.21675061e-04, ..., 1.33860940e-12, 2.44544435e-13, 4.19923483e-14], [3.25122046e-04, 2.86441420e-04, 2.19674768e-04, ..., 8.78625057e-13, 1.53854068e-13, 2.52708344e-14], [3.23807130e-04, 2.84847122e-04, 2.17641857e-04, ..., 5.71244313e-13, 9.57776275e-14, 1.50306673e-14], ... [2.67779644e-04, 2.42876825e-04, 1.93108505e-04, ..., 4.16918542e-12, 8.45231139e-13, 1.61577818e-13], [2.64604401e-04, 2.39695129e-04, 1.89957454e-04, ..., 2.80824529e-12, 5.47526848e-13, 1.00466686e-13], [2.61389307e-04, 2.36466495e-04, 1.86766787e-04, ..., 1.87054990e-12, 3.50331881e-13, 6.16267761e-14]], [[2.68959764e-04, 2.42025369e-04, 1.89572325e-04, ..., 1.01396181e-12, 1.78631113e-13, 2.94758748e-14], [2.67147742e-04, 2.40179522e-04, 1.87608989e-04, ..., 7.02329489e-13, 1.19181235e-13, 1.89068219e-14], [2.65308930e-04, 2.38304775e-04, 1.85622456e-04, ..., 4.82828262e-13, 7.88535765e-14, 1.20155220e-14], ..., [2.81699963e-04, 2.54713471e-04, 2.01754861e-04, ..., 3.67828002e-12, 7.34988224e-13, 1.38414208e-13], [2.77506454e-04, 2.50543880e-04, 1.97741116e-04, ..., 2.42517629e-12, 4.65286805e-13, 8.39650246e-14], [2.73260191e-04, 2.46314760e-04, 1.93680118e-04, ..., 1.57862026e-12, 2.90422137e-13, 5.01516262e-14]]]) Coordinates: * wd (wd) int64 3kB 0 1 2 3 4 5 6 7 ... 352 353 354 355 356 357 358 359 * ws (ws) int64 184B 3 4 5 6 7 8 9 10 11 ... 17 18 19 20 21 22 23 24 25 * i (i) int64 64B 0 1 2 3 4 5 6 7 Attributes: description: Probability of wind flow case (i.e. wind direction and wind...
Wind speeds at the wind turbines for reference wind speed of 3m/s (k=0):
IEA37
: Constant wind speed of 9.8m/sHornsrev1
: Constant wind speed over the site, 3 m/sParqueFicticio
: Winds speed depends on both wind direction and position
[20]:
for name, lw in localWinds.items():
print (name)
print (lw.WS.values, 'm/s')
print ("="*100)
IEA37
9.8 m/s
====================================================================================================
Hornsrev1
[ 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25] m/s
====================================================================================================
ParqueFicticio
[[[ 3.78471012 5.04628015 6.30785019 ... 29.01611089 30.27768093
31.53925096]
[ 3.80282588 5.07043451 6.33804314 ... 29.15499845 30.42260708
31.69021571]
[ 3.82094165 5.09458887 6.36823609 ... 29.29388601 30.56753323
31.84118045]
...
[ 3.73730114 4.98306819 6.22883524 ... 28.6526421 29.89840915
31.1441762 ]
[ 3.75310413 5.00413885 6.25517356 ... 28.77379836 30.02483307
31.27586779]
[ 3.76890713 5.0252095 6.28151188 ... 28.89495463 30.151257
31.40755938]]
[[ 3.95569235 5.27425647 6.59282059 ... 30.3269747 31.64553882
32.96410294]
[ 3.97160588 5.29547451 6.61934314 ... 30.44897845 31.77284708
33.0967157 ]
[ 3.98751942 5.31669256 6.64586569 ... 30.5709822 31.90015533
33.22932847]
...
[ 3.9194794 5.22597253 6.53246567 ... 30.04934207 31.35583521
32.66232834]
[ 3.93155038 5.24206718 6.55258397 ... 30.14188628 31.45240308
32.76291987]
[ 3.94362137 5.25816182 6.57270228 ... 30.23443049 31.54897095
32.8635114 ]]
[[ 3.54177811 4.72237081 5.90296351 ... 27.15363216 28.33422487
29.51481757]
[ 3.56318035 4.75090714 5.93863392 ... 27.31771603 28.50544282
29.6931696 ]
[ 3.5845826 4.77944346 5.97430433 ... 27.4817999 28.67666076
29.87152163]
...
[ 3.53682328 4.71576437 5.89470547 ... 27.11564514 28.29458624
29.47352733]
[ 3.53847489 4.71796652 5.89745815 ... 27.12830748 28.30779911
29.48729074]
[ 3.5401265 4.72016867 5.90021083 ... 27.14096982 28.32101199
29.50105416]]
...
[[ 3.38782152 4.51709536 5.6463692 ... 25.97329831 27.10257215
28.23184598]
[ 3.39601996 4.52802661 5.66003327 ... 26.03615302 27.16815968
28.30016633]
[ 3.4042184 4.53895787 5.67369734 ... 26.09900774 27.23374721
28.36848668]
...
[ 3.41634561 4.55512748 5.69390936 ... 26.19198304 27.33076491
28.46954678]
[ 3.40683758 4.54245011 5.67806264 ... 26.11908813 27.25470065
28.39031318]
[ 3.39732955 4.52977273 5.66221592 ... 26.04619322 27.1786364
28.31107958]]
[[ 2.90165596 3.86887461 4.83609327 ... 22.24602903 23.21324768
24.18046634]
[ 2.90889396 3.87852528 4.8481566 ... 22.30152035 23.27115167
24.24078299]
[ 2.91613196 3.88817594 4.86021993 ... 22.35701167 23.32905566
24.30109964]
...
[ 2.93079949 3.90773265 4.88466582 ... 22.46946275 23.44639592
24.42332908]
[ 2.92108498 3.89477997 4.86847497 ... 22.39498485 23.36867984
24.34237483]
[ 2.91137047 3.88182729 4.85228412 ... 22.32050694 23.29096376
24.26142059]]
[[ 2.93723526 3.91631367 4.89539209 ... 22.51880362 23.49788204
24.47696046]
[ 2.94254094 3.92338792 4.9042349 ... 22.55948056 23.54032754
24.52117452]
[ 2.94784663 3.93046217 4.91307772 ... 22.6001575 23.58277304
24.56538859]
...
[ 2.97948279 3.97264372 4.96580465 ... 22.84270139 23.83586232
24.82902325]
[ 2.96540028 3.95386704 4.9423338 ... 22.73473547 23.72320223
24.71166898]
[ 2.95131777 3.93509036 4.91886294 ... 22.62676954 23.61054213
24.59431472]]] m/s
====================================================================================================
The ParqueFicticio site models variations within the site, so the local wind speed varies over the area.
[21]:
s = sites["ParqueFicticio"]
x = np.linspace(262878,264778,300)
y = np.linspace(6504714,6506614,300)
X,Y = np.meshgrid(x,y)
lw = s.local_wind(X.flatten(),Y.flatten(),30, ws=[10],wd=[0])
Z = lw.WS_ilk.reshape(X.shape)
c = plt.contourf(X,Y,Z, levels=100)
plt.colorbar(c,label='Wind speed [m/s]')
plt.title("Local wind speed at 10m/s and 0deg")
plt.xlabel('x [m]')
plt.ylabel('y [m]')
plt.axis('equal')
[21]:
(262878.0, 264778.0, 6504714.0, 6506614.0)

Distance
We can also calculate the distance between points of a specific site for either flat or complex terrain.
For the IEA37Site
and the Hornsrev1
sites the distances between points are straight line distances, as these sites are characterized by flat terrain.
For the ParqueFicticioSite
, on the other hand, the down-wind distance is larger as it follows the non-flat terrain.
[22]:
wd = [0, 30,90] # wind direction at source
for name, site in sites.items():
print ("------- %s -------"%name)
wt_x, wt_y = site.initial_position[0]
site.distance.setup(src_x_ilk=[wt_x, wt_x], src_y_ilk=[wt_y, wt_y-1000], src_h_ilk=[70,90], src_z_ilk=[0,0]) # wt2 1000m to the south
dw_ijlk, cw_ijlk, dh_ijlk = site.distance(wd_l=wd, src_idx=[0], dst_idx=[[1,1,1]])
print ('Wind direction: \t\t%d deg\t\t%d deg\t\t%d deg'%tuple(wd))
print ('Down wind distance [m]: \t%.1f\t\t%.1f\t\t%.1f'%tuple(dw_ijlk[0,0,:,0]))
print ('Cross wind distance [m]: \t%.1f\t\t%.1f\t\t%.1f'%tuple(cw_ijlk[0,0,:,0]))
print ('Height difference [m]: \t\t%.1f\t\t%.1f\t\t%.1f'%tuple(dh_ijlk[0,0,:,0]))
print()
------- IEA37 -------
Wind direction: 0 deg 30 deg 90 deg
Down wind distance [m]: 1000.0 866.0 0.0
Cross wind distance [m]: 0.0 500.0 1000.0
Height difference [m]: 20.0 20.0 20.0
------- Hornsrev1 -------
Wind direction: 0 deg 30 deg 90 deg
Down wind distance [m]: 1000.0 866.0 0.0
Cross wind distance [m]: 0.0 500.0 1000.0
Height difference [m]: 20.0 20.0 20.0
------- ParqueFicticio -------
Wind direction: 0 deg 30 deg 90 deg
Down wind distance [m]: 1023.6 886.5 -0.0
Cross wind distance [m]: 0.0 500.0 1000.0
Height difference [m]: 20.0 20.0 20.0
Wind resource distribution plots
The Site
object has a few plot function to visualize its properties, mainly the wind resource given by the wind rose and the probability functions.
[23]:
import matplotlib.pyplot as plt
site = sites['Hornsrev1']
Plotting wind rose.
[24]:
_ = site.plot_wd_distribution(n_wd=12, ws_bins=[0,5,10,15,20,25])

Plotting probability density function for the four sectors studied.
[25]:
_ = site.plot_ws_distribution(wd=[0,90,180,270])

Plotting probablity density function for the four sector studied \(\pm\) 45 degrees.
If include_wd_distribution=true, the wind speed probability distributions are multiplied by the wind direction probability.
The sector size is set to 360 / len(wd). This only makes sense if the wd array is evenly distributed
[26]:
_ = site.plot_ws_distribution(wd=[0,90,180,270], include_wd_distribution=True)
