def test_IEA37_ex16_windFarmModel(windFarmModel, aep_ref): site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() wf_model = windFarmModel(site, windTurbines, turbulenceModel=GCLTurbulence()) wf_model.superpositionModel = SquaredSum() aep_ilk = wf_model(x, y, wd=np.arange(0, 360, 22.5), ws=[9.8]).aep_ilk(normalize_probabilities=True) aep_MW_l = aep_ilk.sum((0, 2)) * 1000 # check if ref is reasonable aep_est = 16 * 3.35 * 24 * 365 * .8 # n_wt * P_rated * hours_pr_year - 20% wake loss = 375628.8 npt.assert_allclose(aep_ref[0], aep_est, rtol=.11) npt.assert_allclose(aep_ref[1], [ 9500, 8700, 11500, 14300, 21300, 25900, 39600, 44300, 23900, 13900, 15200, 33000, 72100, 18300, 12500, 8000 ], rtol=.15) npt.assert_almost_equal(aep_MW_l.sum(), aep_ref[0], 5) npt.assert_array_almost_equal(aep_MW_l, aep_ref[1], 5)
def test_interp(h, wd, ws, h_i, wd_l, ws_k): ds = xr.Dataset({ 'TI': 1, 'P': 1, 'XYHLK': (['x', 'y', 'h', 'wd', 'ws'], np.random.rand(10, 20, len(h), len(wd), len(ws))), 'XYHL': (['x', 'y', 'h', 'wd'], np.random.rand(10, 20, len(h), len(wd))), 'XYHK': (['x', 'y', 'h', 'ws'], np.random.rand(10, 20, len(h), len(ws))), 'K': (['ws'], np.random.rand(len(ws))), 'L': (['wd'], np.random.rand(len(wd))), 'KL': (['wd', 'ws'], np.random.rand(len(wd), len(ws))), 'XY': (['x', 'y'], np.random.rand(10, 20)), 'H': (['h'], np.random.rand(len(h))), 'XYH': (['x', 'y', 'h'], np.random.rand(10, 20, len(h))), 'XYL': (['x', 'y', 'wd'], np.random.rand(10, 20, len(wd))), 'XYK': (['x', 'y', 'ws'], np.random.rand(10, 20, len(ws))), 'I': (['i'], np.random.rand(2)), 'IL': (['i', 'wd'], np.random.rand(2, len(wd))), 'IK': (['i', 'ws'], np.random.rand(2, len(ws))), 'ILK': (['i', 'wd', 'ws'], np.random.rand(2, len(wd), len(ws))), }, coords={'x': np.linspace(0, 100, 10), 'y': np.linspace(200, 300, 20), 'h': h, 'wd': wd, 'ws': ws, 'i': [0, 1]} ) site = XRSite(ds) lw = LocalWind(x_i=[25, 50], y_i=[225, 250], h_i=h_i, wd=wd_l, ws=ws_k, time=False, wd_bin_size=1) for n in ['XYHLK', 'XYHL', 'XYHK', 'K', 'L', 'KL', 'XY', 'H', 'XYH', 'XYL', 'XYK', 'I', 'IL', 'IK', 'ILK']: ip1 = site.interp(site.ds[n], lw.coords) ip2 = ds[n].sel_interp_all(lw.coords) npt.assert_array_equal(ip1.shape, ip2.shape) if not np.isnan(ip2).sum(): npt.assert_array_almost_equal(ip1.data, ip2.data)
def test_flat_distances_src_neq_dst(distance): x = [0, 50, 100] y = [100, 100, 0] h = [0, 10, 20] wdirs = [0, 30] site = FlatSite(distance=distance) site.distance.setup(src_x_i=x, src_y_i=y, src_h_i=h, dst_xyh_j=(x, y, [1, 2, 3])) dw_ijl, hcw_ijl, dh_ijl = site.distance(wd_il=np.array(wdirs)[na]) dw_indices_l = distance.dw_order_indices(wdirs) if 0: distance.plot(wd_il=np.array(wdirs)[na]) plt.show() # check down wind distance wind from North and 30 deg npt.assert_array_almost_equal(dw_ijl[:, :, 0], [[0, 0, 100], [0, 0, 100], [-100, -100, 0]]) npt.assert_array_almost_equal(dw_ijl[:, :, 1], [[0, -25, 36.60254038], [25, 0, 61.60254038], [-36.60254038, -61.60254038, 0]]) # check cross wind distance wind from North and 30 deg npt.assert_array_almost_equal(hcw_ijl[:, :, 0], [[0, 50, 100], [-50, 0, 50], [-100, -50, 0]]) npt.assert_array_almost_equal(hcw_ijl[:, :, 1], [[0, 43.30127019, 136.60254038], [-43.30127019, 0., 93.30127019], [-136.60254038, -93.30127019, 0.]]) # check cross wind distance wind from North npt.assert_array_almost_equal(dh_ijl[:, :, 0], [[1, 2, 3], [-9, -8, -7], [-19, -18, -17]]) # check dw indices npt.assert_array_equal(dw_indices_l, [[1, 0, 2], [1, 0, 2]])
def test_grid_interpolator_2d(): x = [5, 10, 15] y = [200, 300, 400, 500] v = np.arange(12).reshape(3, 4) eq = GridInterpolator([x, y], v) xp = [[i, 200] for i in np.arange(5, 16)] npt.assert_array_almost_equal(eq(xp), np.linspace(0, 8, 11)) npt.assert_array_almost_equal(eq(xp, 'nearest'), np.round(np.linspace(0, 8, 11) / 4) * 4) X, Y = np.meshgrid(x, y) xp, yp = np.linspace(5, 15, 11), np.linspace(200, 500, 13) Xp, Yp = np.meshgrid(xp, yp) co = np.array([Xp, Yp]).T.reshape(-1, 2) for method in ['nearest', 'linear']: Z = eq(co, method).reshape(Xp.T.shape) plt.figure() c = plt.contourf(Xp, Yp, Z.T, np.arange(12)) plt.plot(X, Y, 'xw',) plt.colorbar(c) if 0: plt.show() plt.close()
def test_set_gradients(): wt = IEA37_WindTurbines() wt.set_gradient_funcs( lambda ws: np.where( (ws > 4) & (ws <= 9.8), 100000 * ws, # not the right gradient, but similar to the reference 0), lambda ws: 0) with use_autograd_in([WindTurbines, iea37_reader]): ws_lst = np.arange(3, 25, .1) plt.plot(ws_lst, wt.power(ws_lst)) ws_pts = np.array([3., 6., 9., 12.]) dpdu_lst = np.diag(autograd(wt.power)(ws_pts)) if 0: for dpdu, ws in zip(dpdu_lst, ws_pts): plot_gradients(wt.power(ws), dpdu, ws, "", 1) plt.show() dpdu_ref = np.where((ws_pts > 4) & (ws_pts <= 9.8), 100000 * ws_pts, 0) npt.assert_array_almost_equal(dpdu_lst, dpdu_ref)
def test_YZGrid_variables(): site = IEA37Site(16) x, y = [0], [0] windTurbines = IEA37_WindTurbines() wf_model = IEA37SimpleBastankhahGaussian(site, windTurbines) sim_res = wf_model(x, y) fm = sim_res.flow_map(grid=YZGrid(x=100, y=None, resolution=100, extend=.1), wd=270, ws=None) fm.WS_eff.plot() plt.plot(fm.y[::10], fm.y[::10] * 0 + 110, '.') if 0: print(np.round(fm.WS_eff.interp(h=110)[::10].squeeze().values, 4)) plt.show() plt.close() npt.assert_array_almost_equal( fm.WS_eff.interp(h=110)[::10].squeeze(), [ 9.1461, 8.4157, 7.3239, 6.058, 5.022, 4.6455, 5.1019, 6.182, 7.446, 8.506 ], 4)
def test_wake_map(): site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() wake_model = NOJ(site, windTurbines) aep = AEPCalculator(wake_model) x_j = np.linspace(-1500, 1500, 200) y_j = np.linspace(-1500, 1500, 100) X, Y, Z = aep.wake_map(x_j, y_j, 110, x, y, wd=[0], ws=[9]) m = 49, slice(100, 133, 2) # print(np.round(Z[m], 2).tolist()) # ref if 0: import matplotlib.pyplot as plt c = plt.contourf(X, Y, Z) # , np.arange(2, 10, .01)) plt.colorbar(c) windTurbines.plot(x, y) plt.plot(X[m], Y[m], '.-r') plt.show() ref = [ 3.27, 3.27, 9.0, 7.46, 7.46, 7.46, 7.46, 7.31, 7.31, 7.31, 7.31, 8.3, 8.3, 8.3, 8.3, 8.3, 8.3 ] npt.assert_array_almost_equal(Z[m], ref, 2)
def test_RotorGaussQuadratureGridAvgModel(): m = GQGridRotorAvg(4, 3) npt.assert_array_almost_equal(m.nodes_x, [-0.34, 0.34, -0.86, -0.34, 0.34, 0.86, -0.34, 0.34], 2) npt.assert_array_almost_equal(m.nodes_y, [-0.77, -0.77, 0.0, 0.0, 0.0, 0.0, 0.77, 0.77], 2) npt.assert_array_almost_equal(m.nodes_weight, [0.11, 0.11, 0.1, 0.18, 0.18, 0.1, 0.11, 0.11], 2) if 0: for v in [m.nodes_x, m.nodes_y, m.nodes_weight]: print(np.round(v, 2).tolist()) c = plt.scatter(m.nodes_x, m.nodes_y, c=m.nodes_weight) plt.colorbar(c) plt.axis('equal') plt.gca().add_artist(plt.Circle((0, 0), 1, fill=False)) plt.ylim([-1, 1]) plt.show()
def test_grid_interpolator_non_regular(): x = [6, 10, 14] y = [200, 300, 400, 500] v = np.arange(12).reshape(3, 4) eq = GridInterpolator([x, y], v) xp = [[i, 200] for i in np.linspace(6, 14, 9)] npt.assert_array_almost_equal(eq(xp), np.linspace(0, 8, 9)) x = [6, 12, 14] y = [200, 300, 400, 500] v = np.arange(12).reshape(3, 4) v[1, 0] = 6 eq = GridInterpolator([x, y], v) xp = [[i, 200] for i in np.linspace(6, 14, 9)] npt.assert_array_almost_equal(eq(xp), np.linspace(0, 8, 9)) xp = [[i, 200] for i in np.linspace(6, 14, 10)] npt.assert_array_almost_equal(eq(xp), np.linspace(0, 8, 10)) npt.assert_array_almost_equal(eq(xp, 'nearest'), [0., 0., 0., 0., 6., 6., 6., 6., 8., 8.])
def test_CGIRotorAvg(n, x, y, w): m = CGIRotorAvg(n) if 0: for v in [m.nodes_x, m.nodes_y, m.nodes_weight]: print(np.round(v, 2).tolist()) plt.scatter(m.nodes_x, m.nodes_y, c=m.nodes_weight) plt.axis('equal') plt.gca().add_artist(plt.Circle((0, 0), 1, fill=False)) plt.ylim([-1, 1]) plt.show() assert (len(m.nodes_weight) == len(m.nodes_x) == len(m.nodes_y) == n) npt.assert_almost_equal(m.nodes_weight.sum(), 1) npt.assert_array_almost_equal(m.nodes_x, x, 2) npt.assert_array_almost_equal(m.nodes_y, y, 2) npt.assert_array_almost_equal(m.nodes_weight, w, 2)
def test_polar_gauss_quadrature(): m = PolarGridRotorAvg(*polar_gauss_quadrature(4, 3)) if 0: for v in [m.nodes_x, m.nodes_y, m.nodes_weight]: print(np.round(v, 2).tolist()) plt.scatter(m.nodes_x, m.nodes_y, c=m.nodes_weight) plt.axis('equal') plt.gca().add_artist(plt.Circle((0, 0), 1, fill=False)) plt.ylim([-1, 1]) plt.show() npt.assert_array_almost_equal(m.nodes_x, [-0.05, -0.21, -0.44, -0.61, -0.0, -0.0, -0.0, -0.0, 0.05, 0.21, 0.44, 0.61], 2) npt.assert_array_almost_equal(m.nodes_y, [-0.05, -0.25, -0.51, -0.71, 0.07, 0.33, 0.67, 0.93, -0.05, -0.25, -0.51, -0.71], 2) npt.assert_array_almost_equal(m.nodes_weight, [0.05, 0.09, 0.09, 0.05, 0.08, 0.14, 0.14, 0.08, 0.05, 0.09, 0.09, 0.05], 2)
def test_superposition_model_indices(): class WTSite(UniformSite): def local_wind(self, x_i=None, y_i=None, h_i=None, wd=None, ws=None, time=False, wd_bin_size=None, ws_bins=None): lw = UniformSite.local_wind(self, x_i=x_i, y_i=y_i, h_i=h_i, wd=wd, ws=ws, wd_bin_size=wd_bin_size, ws_bins=ws_bins) lw['TI'] = xr.DataArray(lw.TI_ilk + np.arange(len(x_i))[:, np.newaxis, np.newaxis] * .1, [('wt', [0, 1, 2]), ('wd', np.atleast_1d(wd)), ('ws', np.atleast_1d(ws))]) return lw site = WTSite([1], 0.1) x_i = [0, 0, 0] y_i = [0, -40, -100] h_i = [50, 50, 50] # WS_ilk different at each wt position TI_ilk = site.local_wind(x_i, y_i, h_i, wd=0, ws=8.1).TI_ilk npt.assert_array_almost_equal(TI_ilk, np.reshape([0.1, 0.2, 0.3], (3, 1, 1)), 10) def get_wf_model(cls): return cls(site, NibeA0, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), turbulenceModel=STF2017TurbulenceModel()) for wake_model in [get_wf_model(PropagateDownwind), get_wf_model(All2AllIterative)]: # No wake (ct = 0), i.e. WS_eff == WS TI_eff_ilk = wake_model.calc_wt_interaction(x_i, y_i, h_i, [1, 1, 1], 0.0, 8.1)[1] npt.assert_array_equal(TI_eff_ilk, TI_ilk) # full wake (CT=8/9) ref_TI_eff_ilk = TI_ilk + np.reshape([0, 0.33738364, np.sum([0.19369135, 0.21239116])], (3, 1, 1)) TI_eff_ilk = wake_model.calc_wt_interaction(x_i, y_i, h_i, [0, 0, 0], 0.0, 8.1)[1] npt.assert_array_almost_equal(TI_eff_ilk, ref_TI_eff_ilk) sim_res = wake_model(x_i, y_i, h_i, [0, 0, 0], 0.0, 8.1) TI_eff_ilk = sim_res.flow_map(HorizontalGrid(x=[0], y=y_i, h=50)).TI_eff_xylk[:, 0] npt.assert_array_almost_equal(TI_eff_ilk, ref_TI_eff_ilk)
def test_gradients(): wt = IEA37_WindTurbines() wt.enable_autograd() ws_lst = np.arange(3, 25, .1) ws_pts = np.array([3., 6., 9., 12.]) dpdu_lst = autograd(wt.power)(ws_pts) if 0: plt.plot(ws_lst, wt.power(ws_lst)) for dpdu, ws in zip(dpdu_lst, ws_pts): plot_gradients(wt.power(ws), dpdu, ws, "", 1) plt.show() dpdu_ref = np.where((ws_pts > 4) & (ws_pts <= 9.8), 3 * 3350000 * (ws_pts - 4)**2 / (9.8 - 4)**3, 0) npt.assert_array_almost_equal(dpdu_lst, dpdu_ref) fd_dpdu_lst = fd(wt.power)(ws_pts) npt.assert_array_almost_equal(fd_dpdu_lst, dpdu_ref, 0) cs_dpdu_lst = cs(wt.power)(ws_pts) npt.assert_array_almost_equal(cs_dpdu_lst, dpdu_ref)
def test_MultiPowerCtCurve(): u_p, p, ct = v80_upct.copy() curve = PowerCtFunctionList('mode', [ PowerCtTabular(ws=u_p, power=p, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p * 1.1, power_unit='w', ct=ct + .1) ]) u = np.arange(0, 30, .1) wfm = get_wfm(curve) ri, oi = wfm.windTurbines.function_inputs npt.assert_array_equal(ri, ['mode']) npt.assert_array_equal(oi, ['Air_density', 'tilt', 'yaw']) sim_res = wfm([0], [0], ws=u, wd=0, mode=0) p0, ct0 = sim_res.Power.squeeze().values, sim_res.CT.squeeze().values, sim_res = wfm([0], [0], ws=u, wd=0, mode=1) p1, ct1 = sim_res.Power.squeeze().values, sim_res.CT.squeeze().values, npt.assert_array_almost_equal(p0, p1 / 1.1) npt.assert_array_almost_equal(ct0, ct1 - .1) mode_16 = (np.arange(16) > 7) mode_16_360 = np.broadcast_to(mode_16[:, na], (16, 360)) mode_16_360_23 = np.broadcast_to(mode_16[:, na, na], (16, 360, 23)) ref_p = np.array( np.broadcast_to(hornsrev1.power_curve[:, 1][na, na], (16, 360, 23))) ref_p[8:] *= 1.1 for m in [mode_16, mode_16_360, mode_16_360_23]: sim_res = wfm(np.arange(16) * 1e3, [0] * 16, wd=np.arange(360) % 5, mode=m) # no wake effects p = sim_res.Power.values npt.assert_array_almost_equal(p, ref_p)
def test_plot_ws_distribution(site): p = site.plot_ws_distribution(wd=[0, 90, 180, 270]) npt.assert_array_almost_equal(p.ws[p.argmax('ws')], [7.35, 8.25, 7.95, 9.75]) npt.assert_array_almost_equal( p.max('ws'), [0.01063067, 0.01048959, 0.01081972, 0.00893762]) plt.figure() p = site.plot_ws_distribution(wd=[0, 90, 180, 270], include_wd_distribution=True) npt.assert_array_almost_equal(p.ws[p.argmax('ws')], [7.75, 8.25, 8.15, 9.55]) npt.assert_array_almost_equal(p.max('ws'), [0.001269, 0.002169, 0.002771, 0.003548]) with pytest.raises(AssertionError, match="Wind directions must be equidistant"): p = site.plot_ws_distribution(wd=[0, 180, 270], include_wd_distribution=True) plt.figure() p = site.plot_ws_distribution(wd=[90, 180, 270, 0], include_wd_distribution=True) npt.assert_array_almost_equal(p.ws[p.argmax('ws')], [ 8.25, 8.15, 9.55, 7.75, ]) npt.assert_array_almost_equal(p.max('ws'), [0.002182, 0.002771, 0.003548, 0.001257]) if 0: plt.show() plt.close('all')
def test_fuga(): # move turbine 1 600 300 wt_x = [-250, 600, -500, 0, 500, -250, 250] wt_y = [433, 300, 0, 0, 0, -433, -433] wts = HornsrevV80() path = tfp + 'fuga/2MW/Z0=0.03000000Zi=00401Zeta0=0.00E+00/' site = UniformSite([1, 0, 0, 0], ti=0.075) wake_model = Fuga(path, site, wts) res, _ = timeit(wake_model.__call__, verbose=0, line_profile=0, profile_funcs=[ FugaDeficit.interpolate, LUTInterpolator.__call__, GridInterpolator.__call__ ])(x=wt_x, y=wt_y, wd=[30], ws=[10]) npt.assert_array_almost_equal(res.WS_eff_ilk.flatten(), [ 10.00669629, 10., 8.47606501, 10.03143097, 9.37288077, 8.49301941, 8.07462708 ], 8) npt.assert_array_almost_equal(res.ct_ilk.flatten(), [ 0.7926384, 0.793, 0.80647607, 0.79130273, 0.80177967, 0.80649302, 0.80607463 ], 8) x_j = np.linspace(-1500, 1500, 500) y_j = np.linspace(-1500, 1500, 300) wake_model = Fuga(path, site, wts) sim_res = wake_model(wt_x, wt_y, wd=[30], ws=[10]) flow_map70 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=70)) flow_map73 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=73)) X, Y = flow_map70.XY Z70 = flow_map70.WS_eff_xylk[:, :, 0, 0] Z73 = flow_map73.WS_eff_xylk[:, :, 0, 0] if 0: flow_map70.plot_wake_map(levels=np.arange(6, 10.5, .1)) plt.plot(X[0], Y[140]) plt.figure() plt.plot(X[0], Z70[140, :], label="Z=70m") plt.plot(X[0], Z73[140, :], label="Z=73m") plt.plot(X[0, 100:400:10], Z70[140, 100:400:10], '.') print(list(np.round(Z70.data[140, 100:400:10], 4))) print(list(np.round(Z73.data[140, 100:400:10], 4))) plt.legend() plt.show() npt.assert_array_almost_equal(Z70[140, 100:400:10], [ 10.0407, 10.0438, 10.0438, 10.013, 9.6847, 7.8787, 6.9561, 9.2251, 9.9686, 10.0382, 10.0498, 10.0569, 10.0325, 9.1787, 7.4004, 9.1384, 10.0329, 10.0297, 10.0232, 9.9265, 9.3163, 8.0768, 6.8858, 8.3754, 9.9592, 10.0197, 10.0118, 10.0141, 10.0118, 10.0095 ], 4) npt.assert_array_almost_equal(Z73[140, 100:400:10], [ 10.0404, 10.0435, 10.0433, 10.0113, 9.6836, 7.9206, 7.0218, 9.2326, 9.9665, 10.0376, 10.0494, 10.0563, 10.0304, 9.1896, 7.4515, 9.15, 10.0317, 10.0294, 10.0226, 9.9245, 9.3252, 8.1192, 6.9462, 8.3988, 9.9574, 10.0194, 10.0117, 10.014, 10.0117, 10.0094 ], 4)
def test_fuga(): # move turbine 1 600 300 wt_x = [-250, 600, -500, 0, 500, -250, 250] wt_y = [433, 300, 0, 0, 0, -433, -433] wts = HornsrevV80() path = tfp + 'fuga/2MW/Z0=0.03000000Zi=00401Zeta0=0.00E+0/' site = UniformSite([1, 0, 0, 0], ti=0.075) wake_model = Fuga(path, site, wts) res, _ = timeit(wake_model.__call__, verbose=0, line_profile=0, profile_funcs=[ FugaDeficit.interpolate, LUTInterpolator.__call__, GridInterpolator.__call__ ])(x=wt_x, y=wt_y, wd=[30], ws=[10]) npt.assert_array_almost_equal(res.WS_eff_ilk.flatten(), [ 10.002683492812844, 10.0, 8.413483643142389, 10.036952526815286, 9.371203842245153, 8.437429367715435, 8.012759083790058 ], 8) npt.assert_array_almost_equal(res.ct_ilk.flatten(), [ 0.79285509, 0.793, 0.80641348, 0.79100456, 0.80180315, 0.80643743, 0.80601276 ], 8) x_j = np.linspace(-1500, 1500, 500) y_j = np.linspace(-1500, 1500, 300) wake_model = Fuga(path, site, wts) sim_res = wake_model(wt_x, wt_y, wd=[30], ws=[10]) flow_map70 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=70)) flow_map73 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=73)) X, Y = flow_map70.XY Z70 = flow_map70.WS_eff_xylk[:, :, 0, 0] Z73 = flow_map73.WS_eff_xylk[:, :, 0, 0] if 0: flow_map70.plot_wake_map(levels=np.arange(6, 10.5, .1)) plt.plot(X[0], Y[140]) plt.figure() plt.plot(X[0], Z70[140, :], label="Z=70m") plt.plot(X[0], Z73[140, :], label="Z=73m") plt.plot(X[0, 100:400:10], Z70[140, 100:400:10], '.') print(list(np.round(Z70.data[140, 100:400:10], 4))) print(list(np.round(Z73.data[140, 100:400:10], 4))) plt.legend() plt.show() npt.assert_array_almost_equal(Z70[140, 100:400:10], [ 10.0467, 10.0473, 10.0699, 10.0093, 9.6786, 7.8589, 6.8539, 9.2199, 9.9837, 10.036, 10.0796, 10.0469, 10.0439, 9.1866, 7.2552, 9.1518, 10.0449, 10.0261, 10.0353, 9.9256, 9.319, 8.0062, 6.789, 8.3578, 9.9393, 10.0332, 10.0183, 10.0186, 10.0191, 10.0139 ], 4) npt.assert_array_almost_equal(Z73[140, 100:400:10], [ 10.0463, 10.0468, 10.0688, 10.0075, 9.6778, 7.9006, 6.9218, 9.228, 9.9808, 10.0354, 10.0786, 10.0464, 10.0414, 9.1973, 7.3099, 9.1629, 10.0432, 10.0257, 10.0344, 9.9236, 9.3274, 8.0502, 6.8512, 8.3813, 9.9379, 10.0325, 10.018, 10.0183, 10.019, 10.0138 ], 4)
def test_superposition_model_indices(superpositionModel, sum_func): class WTSite(UniformSite): def local_wind(self, x_i=None, y_i=None, h_i=None, wd=None, ws=None, wd_bin_size=None, ws_bins=None): lw = UniformSite.local_wind(self, x_i=x_i, y_i=y_i, h_i=h_i, wd=wd, ws=ws, wd_bin_size=wd_bin_size, ws_bins=ws_bins) lw['WS'] = xr.DataArray( lw.WS_ilk + np.arange(len(x_i))[:, np.newaxis, np.newaxis], [('wt', [0, 1, 2]), ('wd', np.atleast_1d(wd)), ('ws', np.atleast_1d(ws))]) return lw site = WTSite([1], 0.1) x_i = [0, 0, 0] y_i = [0, -40, -100] h_i = [50, 50, 50] # WS_ilk different at each wt position WS_ilk = site.local_wind(x_i, y_i, h_i, wd=0, ws=8.1).WS_ilk npt.assert_array_equal(WS_ilk, np.reshape([8.1, 9.1, 10.1], (3, 1, 1))) for wake_model in [ PropagateDownwind(site, NibeA0, wake_deficitModel=NOJDeficit(), superpositionModel=superpositionModel), All2AllIterative(site, NibeA0, wake_deficitModel=NOJDeficit(), superpositionModel=superpositionModel) ]: # No wake (ct = 0), i.e. WS_eff == WS WS_eff_ilk = wake_model.calc_wt_interaction(x_i, y_i, h_i, [1, 1, 1], 0.0, 8.1)[0] npt.assert_array_equal(WS_eff_ilk, WS_ilk) ref = WS_ilk - np.reshape( [0, 3.75, sum_func([2.4, 3.58974359])], (3, 1, 1)) # full wake (CT=8/9) WS_eff_ilk = wake_model.calc_wt_interaction(x_i, y_i, h_i, [0, 0, 0], 0.0, 8.1)[0] npt.assert_array_almost_equal(WS_eff_ilk, ref) sim_res = wake_model(x_i, y_i, h_i, [0, 0, 0], 0.0, 8.1) WS_eff_ilk = sim_res.flow_map(HorizontalGrid(x=[0], y=y_i, h=50)).WS_eff_xylk[:, 0] npt.assert_array_almost_equal(WS_eff_ilk, ref)
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 ] # 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 # 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) ] # 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 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) # pdf 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) 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) npt.assert_array_almost_equal((P * 1 / 2 * rho * lw.WS_ilk**3).sum((0, 2)), wasp_p_air, 2) # AEP 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)
def test_mirror(): path = tfp + 'fuga/2MW/Z0=0.03000000Zi=00401Zeta0=0.00E+0/' fuga_utils = FugaUtils(path, on_mismatch='input_par') npt.assert_array_almost_equal(fuga_utils.mirror([0, 1, 3]), [3, 1, 0, 1, 3]) npt.assert_array_almost_equal(fuga_utils.mirror([0, 1, 3], anti_symmetric=True), [-3, -1, 0, 1, 3])
def test_selfsimilarity_reference_figures(setup): ss = setup[2] ss20 = setup[3] ws = 10 D = 80 R = D / 2 WS_ilk = np.array([[[ws]]]) D_src_il = np.array([[D]]) ct_ilk = np.array([[[.8]]]) x1, y1 = -np.arange(200), np.array([0]) deficit_centerline = ss.calc_deficit(WS_ilk=WS_ilk, D_src_il=D_src_il, dw_ijlk=x1.reshape((1, len(x1), 1, 1)), cw_ijlk=y1.reshape((1, len(y1), 1, 1)), ct_ilk=ct_ilk)[0, :, 0, 0] deficit20_centerline = ss20.calc_deficit(WS_ilk=WS_ilk, D_src_il=D_src_il, dw_ijlk=x1.reshape((1, len(x1), 1, 1)), cw_ijlk=y1.reshape((1, len(y1), 1, 1)), ct_ilk=ct_ilk)[0, :, 0, 0] x2, y2 = np.array([-2 * R]), np.arange(200) deficit_radial = ss.calc_deficit(WS_ilk=WS_ilk, D_src_il=D_src_il, dw_ijlk=x2.reshape((1, len(x2), 1, 1)), cw_ijlk=y2.reshape((1, len(y2), 1, 1)), ct_ilk=ct_ilk)[0, :, 0, 0] deficit20_radial = ss20.calc_deficit(WS_ilk=WS_ilk, D_src_il=D_src_il, dw_ijlk=x2.reshape((1, len(x2), 1, 1)), cw_ijlk=y2.reshape((1, len(y2), 1, 1)), ct_ilk=ct_ilk)[0, :, 0, 0] # r12 = np.sqrt(ss.lambda_ * (ss.eta + (x2 / R) ** 2)) # Eq. (13) from [1] r12 = ss.r12(x2 / R) r12_20 = ss20.r12(x2 / R) if debug: plt.title('Fig 11 from [1]') plt.xlabel('x/R') plt.ylabel('a') plt.plot(x1 / R, deficit_centerline / ws) plt.plot(x1 / R, deficit20_centerline / ws, '--') print(list(np.round(deficit_centerline[::20], 6))) print(list(np.round(deficit20_centerline[::20], 6))) plt.figure() plt.title('Fig 10 from [1]') print(list(np.round(deficit_radial[::20] / deficit_radial[0], 6))) print(list(np.round(deficit20_radial[::20] / deficit20_radial[0], 6))) plt.xlabel('y/R12 (epsilon)') plt.ylabel('f') plt.plot((y2 / R) / r12, deficit_radial / deficit_radial[0]) plt.plot((y2 / R) / r12_20, deficit20_radial / deficit20_radial[0], '--') plt.show() fig11_ref = np.array([[-0.025, -1, -2, -3, -4, -5], [0.318, 0.096, 0.035, 0.017, 0.010, 0.0071]]).T npt.assert_array_almost_equal(np.interp(-fig11_ref[:, 0], -x1 / R, deficit_centerline / ws), fig11_ref[:, 1], 1) npt.assert_array_almost_equal(deficit_centerline[::20], [0.0, 1.780159, 0.943215, 0.540855, 0.33998, 0.230329, 0.165257, 0.123906, 0.096151, 0.076686]) npt.assert_array_almost_equal(deficit20_centerline[::20], [0.0, 1.758202, 0.931581, 0.562763, 0.362938, 0.249322, 0.180358, 0.135934, 0.105854, 0.08463]) fig10_ref = np.array([[0, 1, 2, 3], [1, .5, .15, .045]]).T npt.assert_array_almost_equal(np.interp(fig10_ref[:, 0], (y2 / R) / r12, deficit_radial / deficit_radial[0]), fig10_ref[:, 1], 1) npt.assert_array_almost_equal(deficit_radial[::20] / deficit_radial[0], [1.0, 0.933011, 0.772123, 0.589765, 0.430823, 0.307779, 0.217575, 0.153065, 0.107446, 0.075348]) npt.assert_array_almost_equal(deficit20_radial[::20] / deficit20_radial[0], [1.0, 0.937523, 0.78531, 0.608956, 0.451715, 0.32748, 0.23477, 0.167415, 0.119088, 0.084613])
def test_grid_interpolator_2d_plus_2d(): eq = GridInterpolator([[5, 10, 15], [200, 300, 400, 500]], np.arange(12).repeat(10).reshape(3, 4, 2, 5)) x = [[i, 200] for i in np.arange(5, 16)] npt.assert_array_almost_equal(eq(x).sum((1, 2)), np.linspace(0, 8, 11) * 10) npt.assert_array_equal(eq(x).shape, (11, 2, 5))
def test_wec(): # move turbine 1 600 300 wt_x = [-250, 600, -500, 0, 500, -250, 250] wt_y = [433, 300, 0, 0, 0, -433, -433] wts = HornsrevV80() site = UniformSite([1, 0, 0, 0], ti=0.075) wake_model = Fuga(LUT_path_2MW_z0_0_03, site, wts) aep = AEPCalculator(wake_model) x_j = np.linspace(-1500, 1500, 500) y_j = np.linspace(-1500, 1500, 300) _, _, Z_wec1 = aep.wake_map(x_j, y_j, 70, wt_x, wt_y, wt_height=70, wd=[30], ws=[10]) aep.wake_model.wec = 2 X, Y, Z_wec2 = aep.wake_map(x_j, y_j, 70, wt_x, wt_y, wt_height=70, wd=[30], ws=[10]) if 0: import matplotlib.pyplot as plt c = plt.contourf(X, Y, Z_wec1, np.arange(6, 10.5, .1)) plt.colorbar(c) plt.plot(X[0], Y[140]) wts.plot(wt_x, wt_y) plt.figure() c = plt.contourf(X, Y, Z_wec2, np.arange(6, 10.5, .1)) plt.colorbar(c) plt.plot(X[0], Y[140]) wts.plot(wt_x, wt_y) plt.figure() plt.plot(X[0], Z_wec1[140, :], label="Z=70m") plt.plot(X[0], Z_wec2[140, :], label="Z=70m") plt.plot(X[0, 100:400:10], Z_wec1[140, 100:400:10], '.') plt.plot(X[0, 100:400:10], Z_wec2[140, 100:400:10], '.') plt.legend() plt.show() npt.assert_array_almost_equal(Z_wec1[140, 100:400:10], [ 10.0547, 10.0519, 10.0718, 10.0093, 9.6786, 7.8589, 6.8539, 9.2199, 9.9837, 10.036, 10.0796, 10.0469, 10.0439, 9.1866, 7.2552, 9.1518, 10.0449, 10.0261, 10.0353, 9.9256, 9.319, 8.0062, 6.789, 8.3578, 9.9393, 10.0332, 10.0191, 10.0186, 10.0191, 10.0139 ], 4) npt.assert_array_almost_equal(Z_wec2[140, 100:400:10], [ 10.0297, 9.9626, 9.7579, 9.2434, 8.2318, 7.008, 6.7039, 7.7303, 9.0101, 9.6877, 9.9068, 9.7497, 9.1127, 7.9505, 7.26, 7.9551, 9.2104, 9.7458, 9.6637, 9.1425, 8.2403, 7.1034, 6.5109, 7.2764, 8.7653, 9.7139, 9.9718, 10.01, 10.0252, 10.0357 ], 4)
kwargs = {k: 1 for k in wt.function_inputs[0]} dpdu_lst = grad_method(wt.power)(ws_pts, **kwargs) dctdu_lst = grad_method(wt.ct)(ws_pts, **kwargs) if 0: gradients.color_dict = {'power': 'b', 'ct': 'r'} plt.plot(ws_lst, wt.power(ws_lst, **kwargs), label='power') c = plt.plot([], label='ct')[0].get_color() for dpdu, ws in zip(dpdu_lst, ws_pts): plot_gradients(wt.power(ws, **kwargs), dpdu, ws, "power", 1) ax = plt.twinx() ax.plot(ws_lst, wt.ct(ws_lst, **kwargs), color=c) for dctdu, ws in zip(dctdu_lst, ws_pts): plot_gradients(wt.ct(ws, **kwargs), dctdu, ws, "ct", 1, ax=ax) plt.title(case) plt.show() npt.assert_array_almost_equal(dpdu_lst, dpdu_ref, (0, 4)[grad_method == autograd]) npt.assert_array_almost_equal(dctdu_lst, dctdu_ref, (4, 6)[grad_method == autograd]) if __name__ == '__main__': x = np.linspace(0, 2 * np.pi, 100) import matplotlib.pyplot as plt import numpy as np plt.plot(x, np.sin(x) / x) plt.plot(x, np.sin(x)) plt.show()
def test_get_model_input(): site, windTurbines = IEA37Site(16), IEA37_WindTurbines() wfm = IEA37SimpleBastankhahGaussian(site, windTurbines) args = get_model_input(wfm, [1000], [0], ws=10, wd=270) npt.assert_array_almost_equal(args['dw_ijl'], [[[1000]]]) npt.assert_array_almost_equal(args['hcw_ijl'], [[[0]]]) npt.assert_array_almost_equal(args['dh_ijl'], [[[0]]]) npt.assert_array_almost_equal(args['yaw_ilk'], [[[0]]]) npt.assert_array_almost_equal(args['WS_ilk'], [[[10]]]) npt.assert_array_almost_equal(args['ct_ilk'], [[[8 / 9]]])
def test_fuga(): # move turbine 1 600 300 wt_x = [-250, 600, -500, 0, 500, -250, 250] wt_y = [433, 300, 0, 0, 0, -433, -433] wts = HornsrevV80() path = tfp + 'fuga/2MW/Z0=0.03000000Zi=00401Zeta0=0.00E+0/' site = UniformSite([1, 0, 0, 0], ti=0.075) wake_model = Fuga(path, site, wts) res = wake_model(x=wt_x, y=wt_y, wd=[30], ws=[10]) npt.assert_array_almost_equal(res.WS_eff_ilk.flatten(), [ 10.002683492812844, 10.0, 8.413483643142389, 10.036952526815286, 9.371203842245153, 8.437429367715435, 8.012759083790058 ], 8) npt.assert_array_almost_equal(res.ct_ilk.flatten(), [ 0.79285509, 0.793, 0.80641348, 0.79100456, 0.80180315, 0.80643743, 0.80601276 ], 8) x_j = np.linspace(-1500, 1500, 500) y_j = np.linspace(-1500, 1500, 300) wake_model = Fuga(path, site, wts) sim_res = wake_model(wt_x, wt_y, wd=[30], ws=[10]) flow_map70 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=70)) flow_map73 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=73)) X, Y = flow_map70.XY Z70 = flow_map70.WS_eff_xylk[:, :, 0, 0] Z73 = flow_map73.WS_eff_xylk[:, :, 0, 0] if 0: import matplotlib.pyplot as plt flow_map70.plot_wake_map(levels=np.arange(6, 10.5, .1)) plt.plot(X[0], Y[140]) plt.figure() plt.plot(X[0], Z70[140, :], label="Z=70m") plt.plot(X[0], Z73[140, :], label="Z=73m") plt.plot(X[0, 100:400:10], Z70[140, 100:400:10], '.') print(list(np.round(Z70[140, 100:400:10], 4))) print(list(np.round(Z73[140, 100:400:10], 4))) plt.legend() plt.show() # npt.assert_array_almost_equal( # Z70[140, 100:400:10], # [10.0547, 10.0519, 10.0741, 10.0099, 9.6774, 7.8538, 6.8484, 9.2134, 9.9749, 10.0232, 10.0658, 10.0189, 10.0187, # 9.1496, 7.2077, 9.1154, 10.0183, 10.0008, 10.0146, 9.8838, 9.2848, 7.9681, 6.7412, 8.3149, 9.9114, 10.0119, # 10.0011, 9.9979, 10.0002, 9.9981], 4) npt.assert_array_almost_equal(Z70[140, 100:400:10], [ 10.0547, 10.0519, 10.0718, 10.0093, 9.6786, 7.8589, 6.8539, 9.2199, 9.9837, 10.036, 10.0796, 10.0469, 10.0439, 9.1866, 7.2552, 9.1518, 10.0449, 10.0261, 10.0353, 9.9256, 9.319, 8.0062, 6.789, 8.3578, 9.9393, 10.0332, 10.0191, 10.0186, 10.0191, 10.0139 ], 4) npt.assert_array_almost_equal(Z73[140, 100:400:10], [ 10.0542, 10.0514, 10.0706, 10.0075, 9.6778, 7.9006, 6.9218, 9.228, 9.9808, 10.0354, 10.0786, 10.0464, 10.0414, 9.1973, 7.3099, 9.1629, 10.0432, 10.0257, 10.0344, 9.9236, 9.3274, 8.0502, 6.8512, 8.3813, 9.9379, 10.0325, 10.0188, 10.0183, 10.019, 10.0138 ], 4)
def test_gauss_quadrature(): x, _, w = gauss_quadrature(4, 1) npt.assert_array_almost_equal(x, [-0.861136, -0.339981, 0.339981, 0.861136]) npt.assert_array_almost_equal(w, np.array([0.347855, 0.652145, 0.652145, 0.347855]) / 2)