Newer
Older

Mads M. Pedersen
committed
from py_wake.examples.data.ParqueFicticio import ParqueFicticio_path, ParqueFicticioSite
from py_wake.site.wasp_grid_site import WaspGridSite
import os
import time
from py_wake.tests.test_files.wasp_grid_site import one_layer

Mads M. Pedersen
committed
from py_wake.site.distance import TerrainFollowingDistance, StraightDistance, TerrainFollowingDistance2

Mads M. Pedersen
committed
from py_wake import NOJ
from py_wake.wind_turbines import OneTypeWindTurbines
from py_wake.flow_map import HorizontalGrid
from py_wake.tests.check_speed import timeit
import matplotlib.pyplot as plt
@pytest.fixture
def site():
return ParqueFicticioSite()

Mads M. Pedersen
committed
@pytest.fixture
def site2():
site = ParqueFicticioSite(distance=TerrainFollowingDistance2())
x, y = site.initial_position.T
return site, x, y
def test_WaspGridSiteDistanceClass(site):
wgs = WaspGridSite(site._ds, distance=TerrainFollowingDistance(distance_resolution=2000))

Mads M. Pedersen
committed
assert wgs.distance.distance_resolution == 2000
assert wgs.distance.__call__.__func__ == TerrainFollowingDistance().__call__.__func__

Mads M. Pedersen
committed
wgs = WaspGridSite(site._ds, distance=StraightDistance())

Mads M. Pedersen
committed
assert wgs.distance.__call__.__func__ == StraightDistance().__call__.__func__

Mads M. Pedersen
committed
def test_local_wind(site):
x_i, y_i = site.initial_position.T
h_i = x_i * 0 + 70
wdir_lst = np.arange(0, 360, 90)
wsp_lst = np.arange(3, 6)

Mads M. Pedersen
committed
WS_ilk = site.local_wind(x_i=x_i, y_i=y_i, h_i=h_i, wd=wdir_lst, ws=wsp_lst).WS_ilk

Mads M. Pedersen
committed
WS_ilk = site.local_wind(x_i=x_i, y_i=y_i, h_i=h_i).WS_ilk
npt.assert_array_equal(WS_ilk.shape, (8, 360, 23))
# check probability local_wind()[-1]
npt.assert_almost_equal(site.local_wind(x_i=x_i, y_i=y_i, h_i=h_i, wd=[0], ws=[10], wd_bin_size=1).P_ilk,

Mads M. Pedersen
committed
site.local_wind(x_i=x_i, y_i=y_i, h_i=h_i, wd=[0], ws=[10], wd_bin_size=2).P_ilk / 2, 6)
def test_shear(site):
npt.assert_array_almost_equal(site._ds['spd'].sel(x=262878, y=6504714, sec=1), [.6240589, .8932919])
x = [262878.0001] * 3
y = [6504714.0001] * 3

Mads M. Pedersen
committed
ws = site.local_wind(x_i=x, y_i=y, h_i=z, wd=[0], ws=[10]).WS_ilk[:, 0, 0]
# linear interpolation
npt.assert_array_almost_equal(ws, [6.240589, np.mean([6.240589, 8.932919]), 8.932919])
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
def test_wasp_resources_grid_point(site):
# x = np.array([l.split() for l in """0.6010665 -10.02692 32.71442 -6.746912
# 0.5007213 -4.591617 37.10247 -11.0699
# 0.3104101 -1.821247 59.18301 -12.56743
# 0.4674515 16.14293 44.84665 -9.693183
# 0.8710347 5.291974 26.01634 -6.154611
# 0.9998786 -2.777032 15.72486 1.029988
# 0.9079611 -7.882853 16.33216 6.42329
# 0.759553 -5.082487 17.23354 10.18187
# 0.7221162 4.606324 17.96417 11.45838
# 0.8088576 8.196074 16.16308 9.277925
# 0.8800673 3.932325 14.82337 5.380589
# 0.8726974 -3.199536 19.99724 -1.433086""".split("\n")], dtype=np.float)
# for x_ in x.T:
# print(list(x_))
x = [262978]
y = [6504814]
npt.assert_almost_equal(site.elevation(x, y), 227.8, 1)
# Data from WAsP:
# - add turbine (262878,6504814,30)
# - Turbine (right click) - reports - Turbine Site Report full precision
wasp_A = [2.197305, 1.664085, 1.353185, 2.651781, 5.28438, 5.038289,
4.174325, 4.604496, 5.043066, 6.108261, 6.082033, 3.659798]
wasp_k = [1.771484, 2.103516, 2.642578, 2.400391, 2.357422, 2.306641,
2.232422, 2.357422, 2.400391, 2.177734, 1.845703, 1.513672]
wasp_f = [5.188083, 2.509297, 2.869334, 4.966141, 13.16969, 9.514355,
4.80275, 6.038354, 9.828702, 14.44174, 16.60567, 10.0659]
wasp_spd = [0.6010665, 0.5007213, 0.3104101, 0.4674515, 0.8710347, 0.9998786,
0.9079611, 0.759553, 0.7221162, 0.8088576, 0.8800673, 0.8726974]
wasp_trn = [-10.02692, -4.591617, -1.821247, 16.14293, 5.291974, -
2.777032, -7.882853, -5.082487, 4.606324, 8.196074, 3.932325, -3.199536]
wasp_inc = [-6.746912, -11.0699, -12.56743, -9.693183, -6.154611,
1.029988, 6.42329, 10.18187, 11.45838, 9.277925, 5.380589, -1.433086]
wasp_ti = [32.71442, 37.10247, 59.18301, 44.84665, 26.01634, 15.72486,
16.33216, 17.23354, 17.96417, 16.16308, 14.82337, 19.99724]
rho = 1.179558
wasp_u_mean = [1.955629, 1.473854, 1.202513, 2.350761, 4.683075,
4.463644, 3.697135, 4.080554, 4.470596, 5.409509, 5.402648, 3.300305]
wasp_p_air = [9.615095, 3.434769, 1.556282, 12.45899, 99.90289,
88.03519, 51.41135, 66.09097, 85.69466, 164.5592, 193.3779, 56.86945]

Mads M. Pedersen
committed
# wasp_aep = np.array([3725293.0, 33722.71, 0.3093564, 3577990.0, 302099600.0, 188784100.0,
# 48915640.0, 84636210.0, 189009800.0, 549195100.0, 691258600.0, 120013000.0]) / 1000
wasp_aep_no_density_correction = np.array([3937022.0, 36046.93, 0.33592, 3796496.0, 314595600.0,
196765700.0, 51195440.0, 88451200.0, 197132700.0, 568584400.0, 712938400.0, 124804600.0]) / 1000

Mads M. Pedersen
committed
# wasp_aep_total = 2.181249024
wasp_aep_no_density_correction_total = 2.26224
wt_u = np.array([3.99, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25])
wt_p = np.array([0, 55., 185., 369., 619., 941., 1326., 1741., 2133., 2436., 2617., 2702., 2734.,
2744., 2747., 2748., 2748., 2750., 2750., 2750., 2750., 2750., 2750.])
wt_ct = np.array([0, 0.871, 0.853, 0.841, 0.841, 0.833, 0.797, 0.743, 0.635, 0.543, 0.424,
0.324, 0.258, 0.21, 0.175, 0.147, 0.126, 0.109, 0.095, 0.083, 0.074, 0.065, 0.059])
wt = OneTypeWindTurbines.from_tabular(name="NEG-Micon 2750/92 (2750 kW)", diameter=92, hub_height=70,
ws=wt_u, ct=wt_ct, power=wt_p, power_unit='kw')
A_lst, k_lst, f_lst, spd_lst, orog_trn_lst, flow_inc_lst, tke_lst = [site.interp_funcs[n](
(x, y, 30, range(0, 360, 30))) for n in ['A', 'k', 'f', 'spd', 'orog_trn', 'flow_inc', 'tke']]
f_lst = f_lst * 360 / 12
pdf_lst = [lambda x, A=A, k=k: k / A * (x / A)**(k - 1) * np.exp(-(x / A)**k) * (x[1] - x[0])
for A, k in zip(A_lst, k_lst)]

Mads M. Pedersen
committed
# cdf_lst = [lambda x, A=A, k=k: 1 - np.exp(-(x / A) ** k) for A, k in zip(A_lst, k_lst)]
dx = .1
ws = np.arange(dx / 2, 35, dx)
# compare to wasp data
npt.assert_array_equal(A_lst, wasp_A)
npt.assert_array_equal(k_lst, wasp_k)
npt.assert_array_almost_equal(f_lst, np.array(wasp_f) / 100)
npt.assert_array_almost_equal(spd_lst, wasp_spd)
npt.assert_array_almost_equal(orog_trn_lst, wasp_trn)
npt.assert_array_almost_equal(flow_inc_lst, wasp_inc)
npt.assert_array_almost_equal(tke_lst, np.array(wasp_ti) / 100)
# compare pdf, u_mean and aep to wasp

Mads M. Pedersen
committed
lw = site.local_wind(x, np.array(y) + 1e-6, 30, wd=np.arange(0, 360, 30), ws=ws)
P = lw.P_ilk / lw.P_ilk.sum(2)[:, :, na] # only wind speed probablity (not wdir)

Mads M. Pedersen
committed
for l in range(12):
npt.assert_array_almost_equal(np.interp(ws, lw.WS_ilk[0, l], np.cumsum(P[0, l])),
np.cumsum(pdf_lst[l](ws)), 1)
# u_mean
npt.assert_almost_equal([A * math.gamma(1 + 1 / k) for A, k in zip(A_lst, k_lst)], wasp_u_mean, 5)
npt.assert_almost_equal([(pdf(ws) * ws).sum() for pdf in pdf_lst], wasp_u_mean, 5)

Mads M. Pedersen
committed
npt.assert_almost_equal((P * lw.WS_ilk).sum((0, 2)), wasp_u_mean, 5)
# air power
p_air = [(pdf(ws) * 1 / 2 * rho * ws**3).sum() for pdf in pdf_lst]
npt.assert_array_almost_equal(p_air, wasp_p_air, 3)

Mads M. Pedersen
committed
npt.assert_array_almost_equal((P * 1 / 2 * rho * lw.WS_ilk**3).sum((0, 2)), wasp_p_air, 2)

Mads M. Pedersen
committed
AEP_ilk = NOJ(site, wt)(x, y, h=30, wd=np.arange(0, 360, 30), ws=ws).aep_ilk(
with_wake_loss=False, normalize_probabilities=True)
if 0:
plt.plot(wasp_aep_no_density_correction / 1000, '.-', label='WAsP')
plt.plot(AEP_ilk.sum((0, 2)) * 1e3, label='PyWake')
plt.xlabel('Sector')
plt.ylabel('AEP [MWh]')
plt.legend()
plt.show()
npt.assert_array_less(np.abs(wasp_aep_no_density_correction - AEP_ilk.sum((0, 2)) * 1e6), 300)
npt.assert_almost_equal(AEP_ilk.sum(), wasp_aep_no_density_correction_total, 3)

Mads M. Pedersen
committed
@pytest.mark.parametrize('site,dw_ref', [
(ParqueFicticioSite(distance=TerrainFollowingDistance2()),
[0., 207.3842238, 484.3998264, 726.7130743, 1039.148129, 1263.1335982, 1490.3841602, 1840.6508086]),

Mads M. Pedersen
committed
(ParqueFicticioSite(distance=TerrainFollowingDistance()),
[0, 209.803579, 480.8335365, 715.6003233, 1026.9476322, 1249.5510034, 1475.1467251, 1824.1317343]),
(ParqueFicticioSite(distance=StraightDistance()),
[-0, 207, 477, 710, 1016, 1236, 1456, 1799])])
def test_distances(site, dw_ref):

Mads M. Pedersen
committed
dw_ijl, cw_ijl, dh_ijl, _ = site.distances(src_x_i=x, src_y_i=y, src_h_i=np.array([70]),
dst_x_j=x, dst_y_j=y, dst_h_j=np.array([70]),
wd_il=np.array([[0]]))

Mads M. Pedersen
committed
npt.assert_almost_equal(dw_ijl[0, :, 0], dw_ref)
cw_ref = [236.1, 0., -131.1, -167.8, -204.5, -131.1, -131.1, -45.4]
npt.assert_almost_equal(cw_ijl[:, 1, 0], cw_ref)
npt.assert_almost_equal(dh_ijl, np.zeros_like(dh_ijl))
def test_distances_different_points(site2):
site, x, y = site2
with pytest.raises(NotImplementedError):
site.distances(src_x_i=x, src_y_i=y, src_h_i=np.array([70]),
dst_x_j=x[1:], dst_y_j=y[1:], dst_h_j=np.array([70]),
wd_il=np.array([[0]]))
# def test_distances_wd_shape():
# site = ParqueFicticioSite(distance=TerrainFollowingDistance2())
# x, y = site.initial_position.T
# dw_ijl, cw_ijl, dh_ijl, dwo = site.distances(src_x_i=x, src_y_i=y, src_h_i=np.array([70]),
# dst_x_j=x, dst_y_j=y, dst_h_j=np.array([70]),
# wd_il=np.ones((len(x), 1)) * 180)
# npt.assert_almost_equal(dw_ijl[0, :, 0], np.array([0., -207., -477., -710., -1016., -1236., -1456., -1799.]))
# npt.assert_almost_equal(cw_ijl[:, 1, 0], np.array([-236.1, 0., 131.1, 167.8, 204.5, 131.1, 131.1, 45.4]))
# npt.assert_almost_equal(dh_ijl, np.zeros_like(dh_ijl))
def test_speed_up_using_pickle():
pkl_fn = ParqueFicticio_path + "ParqueFicticio.pkl"
if os.path.exists(pkl_fn):
os.remove(pkl_fn)
start = time.time()

Mads M. Pedersen
committed
site = WaspGridSite.from_wasp_grd(ParqueFicticio_path, speedup_using_pickle=False)

Mads M. Pedersen
committed
site = WaspGridSite.from_wasp_grd(ParqueFicticio_path, speedup_using_pickle=True)

Mads M. Pedersen
committed
site = WaspGridSite.from_wasp_grd(ParqueFicticio_path, speedup_using_pickle=True)
time_w_pkl = time.time() - start
npt.assert_array_less(time_w_pkl * 10, time_wo_pkl)
def test_interp_funcs_initialization_missing_key(site):

Mads M. Pedersen
committed
site = ParqueFicticioSite(distance=TerrainFollowingDistance2())
site.interp_funcs_initialization(['missing'])
def test_one_layer():

Mads M. Pedersen
committed
site = WaspGridSite.from_wasp_grd(os.path.dirname(one_layer.__file__) + "/", speedup_using_pickle=False)
def test_missing_path():
with pytest.raises(NotImplementedError):

Mads M. Pedersen
committed
WaspGridSite.from_wasp_grd("missing_path/", speedup_using_pickle=True)
with pytest.raises(Exception, match='Path was not a directory'):

Mads M. Pedersen
committed
WaspGridSite.from_wasp_grd("missing_path/", speedup_using_pickle=False)
def test_elevation(site):
x_i, y_i = site.initial_position.T
npt.assert_array_less(np.abs(site.elevation(x_i=x_i, y_i=y_i) -
[519.4, 567.7, 583.6, 600, 574.8, 559.9, 517.7, 474.5] # ref from wasp
), 5)

Mads M. Pedersen
committed
def test_plot_map(site):
with pytest.raises(AttributeError, match="missing not found in dataset. Available data variables are:\nflow_inc,"):

Mads M. Pedersen
committed
site.plot_map('missing')
with pytest.raises(AttributeError, match=r"Sector None not found. Available sectors are: \[ 1"):
site.plot_map('ws_mean')
with pytest.raises(AttributeError, match="Height missing for 'ws_mean'"):
site.plot_map('ws_mean', sector=1)
site.plot_map('elev')
plt.figure()
site.plot_map('ws_mean', 80, sector=1)
if 0:
plt.show()

Mads M. Pedersen
committed
def test_elevation_outside_map(site):
site.plot_map('elev')
x = np.linspace(262500, 265500, 500)
y = x * 0 + 6505450
plt.plot(x, y, '--', label='Terrain line')
plt.plot(x, y + site.elevation(x, y), label='Elevation')
npt.assert_array_equal(np.round(site.elevation(x, y)[::50]),
[np.nan, np.nan, 303, 390, 491, 566, 486, 524, np.nan, np.nan])
if 0:
plt.legend()
plt.show()

Mads M. Pedersen
committed
def test_plot_ws_distribution(site):
x, y = site.initial_position[0]
p1 = site.plot_ws_distribution(x=x, y=y, h=70, wd=[0, 90, 180, 270])
p2 = site.plot_ws_distribution(x=x, y=y, h=70, wd=[0, 90, 180, 270], include_wd_distribution=True)
if 0:
print(np.round(p1[-1, ::30].data, 4).tolist())
print(np.round(p2[-1, ::30].data, 4).tolist())
npt.assert_array_almost_equal(p1[-1, ::30], [0.0001, 0.0079, 0.011, 0.0082, 0.0039,
0.0013, 0.0003, 0.0, 0.0, 0.0], 4)
npt.assert_array_almost_equal(p2[-1, ::30], [0.0001, 0.0036, 0.0047, 0.0033, 0.0014,
0.0004, 0.0001, 0.0, 0.0, 0.0], 4)
def test_plot_wd_distribution(site):
x, y = site.initial_position[0]
p = site.plot_wd_distribution(x=x, y=y, h=70, n_wd=12, ax=plt)
# print(np.round(p, 3).tolist())
if 0:
plt.show()
plt.close()
npt.assert_array_almost_equal(p, [0.052, 0.043, 0.058, 0.085, 0.089, 0.061,
0.047, 0.083, 0.153, 0.152, 0.108, 0.068], 3)
def test_plot_wd_distribution_with_ws_levels(site):
x, y = site.initial_position[0]
p = site.plot_wd_distribution(x=x, y=y, n_wd=12, ws_bins=[0, 5, 10, 15, 20, 25])
if 0:
print(np.round(p, 3).data.tolist())
npt.assert_array_almost_equal(p, [[0.039, 0.013, 0.001, 0.0, 0.0],
[0.034, 0.009, 0.0, 0.0, 0.0],
[0.035, 0.022, 0.0, 0.0, 0.0],
[0.034, 0.048, 0.003, 0.0, 0.0],
[0.031, 0.052, 0.007, 0.0, 0.0],
[0.03, 0.03, 0.002, 0.0, 0.0],
[0.027, 0.019, 0.001, 0.0, 0.0],
[0.034, 0.043, 0.006, 0.0, 0.0],
[0.047, 0.082, 0.023, 0.001, 0.0],
[0.048, 0.074, 0.026, 0.003, 0.0],
[0.044, 0.046, 0.015, 0.002, 0.0],
[0.041, 0.023, 0.003, 0.0, 0.0]], 3)
def test_additional_input():
site = ParqueFicticioSite()
wgs = WaspGridSite(site._ds, distance=TerrainFollowingDistance(distance_resolution=2000))
wgs.interp_funcs_initialization(['ws_mean'])
x, y = site.initial_position.T
h = 70 * np.ones_like(x)
ws_mean, = wgs.interpolate(['ws_mean'], x, y, h)
npt.assert_array_almost_equal(ws_mean[0, :50],
np.array([4.77080802, 4.77216214, 4.77351626, 4.77487037, 4.77622449,
4.77757861, 4.77893273, 4.78028685, 4.78164097, 4.78299508,
4.7843492, 4.78570332, 4.78705744, 4.78841156, 4.78976567,
4.79111979, 4.79247391, 4.79382803, 4.79518215, 4.79653626,
4.79789038, 4.7992445, 4.80059862, 4.80195274, 4.80330685,
4.80466097, 4.80601509, 4.80736921, 4.80872333, 4.81007744,
4.81143156, 4.87114138, 4.9308512, 4.99056102, 5.05027084,
5.10998066, 5.16969047, 5.22940029, 5.28911011, 5.34881993,
5.40852975, 5.46823957, 5.52794939, 5.5876592, 5.64736902,
5.70707884, 5.76678866, 5.82649848, 5.8862083, 5.94591812]))
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
def test_interpolation_speed():
import xarray as xr
da = xr.DataArray(np.sin(0.3 * np.arange(20).reshape(5, 4)),
[('x', np.arange(5)),
('y', [0.1, 0.2, 0.3, 0.4])])
x = xr.DataArray([0.5, 1.5, 2.5], dims='z')
y = xr.DataArray([0.15, 0.25, 0.35], dims='z')
da.interp(x=x, y=y)
site = ParqueFicticioSite()
x, y = site.initial_position.T
X, Y, x_j, y_j, h_j = HorizontalGrid()(x, y, 70)
wd = [270] # site.default_wd
ws = site.default_ws
res1, t_lst = timeit(site.interp_funcs['A'])((x_j, y_j, h_j, x_j * 0 + 270))
print(res1.shape)
res2, t_lst = timeit(lambda x, y, z, sec:
site._ds.A.interp(x=xr.DataArray(x, dims='z'),
y=xr.DataArray(y, dims='z'),
z=xr.DataArray(z, dims='z'),
sec=xr.DataArray(sec, dims='z')).data)(x_j, y_j, h_j, x_j * 0 + 10)
npt.assert_array_almost_equal(res1, res2)
if 0:
c = plt.contourf(X, Y, res1.reshape(X.shape))
plt.colorbar(c)
plt.figure()
c = plt.contourf(X, Y, res2.reshape(X.shape))
plt.colorbar(c)
plt.show()
if __name__ == '__main__':
test_wasp_resources_grid_point(ParqueFicticioSite())