def test_spline(): wt_tab = V80() wt_spline = V80() wt_spline.spline_ct_power(err_tol_factor=1e-2) ws_lst = np.arange(3, 25, .001) # mean and max error assert (wt_tab.power(ws_lst) - wt_spline.power(ws_lst)).mean() < 1 assert ((wt_tab.power(ws_lst) - wt_spline.power(ws_lst)).max()) < 1400 # max change of gradient 80 times lower assert np.diff(np.diff(wt_spline.power(ws_lst))).max() * 80 < np.diff(np.diff(wt_tab.power(ws_lst))).max() ws_pts = [6.99, 7.01] dpdu_tab_pts = np.diag(fd(wt_tab.power)(np.array(ws_pts))) with use_autograd_in(): dpdu_spline_pts = np.diag(autograd(wt_spline.power)(np.array(ws_pts))) npt.assert_array_almost_equal(dpdu_spline_pts, [205555.17794162, 211859.45965873]) if 0: plt.plot(ws_lst, wt_tab.power(ws_lst)) plt.plot(ws_lst, wt_spline.power(ws_lst)) for wt, dpdu_pts, label in [(wt_tab, dpdu_tab_pts, 'V80 tabular'), (wt_spline, dpdu_spline_pts, 'V80 spline')]: for ws, dpdu in zip(ws_pts, dpdu_pts): plot_gradients(wt.power(ws), dpdu, ws, label, 1) ax = plt.gca().twinx() ax.plot(ws_lst, wt.power(ws_lst) - wt_spline.power(ws_lst)) plt.figure() plt.plot(np.diff(np.diff(wt_tab.power(ws_lst)))) plt.plot(np.diff(np.diff(wt_spline.power(ws_lst)))) plt.show()
def test_Mirror_NOJ(): # Compare points in flow map with ws of WT at same position site = UniformSite([1], ti=0.1) V80_D0 = V80() V80_D0._diameters = [0] wt = WindTurbines.from_WindTurbines([V80(), V80_D0]) wfm = NOJ(site, wt, k=.5, groundModel=Mirror()) sim_res = wfm([0], [0], h=[50], wd=0) fm_ref = sim_res.flow_map(YZGrid(x=0, y=np.arange(-70, 0, 20), z=10)) ref = fm_ref.WS_eff_xylk[:, 0, 0, 0].values res = np.array([ wfm([0, 0], [0, y], [50, 10], type=[0, 1], wd=0).WS_eff.sel(wt=1).item() for y in fm_ref.X[0] ]) if 0: fm_res = sim_res.flow_map(YZGrid(x=0, y=np.arange(-100, 10, 1))) fm_res.plot_wake_map() plt.plot(fm_ref.X[0], fm_ref.Y[0], '.') plt.plot(fm_ref.X[0], ref * 10, label='ref, WS*10') plt.plot(fm_ref.X[0], res * 10, label='Res, WS*10') plt.legend() plt.show() plt.close() npt.assert_array_equal(res, ref)
def test_method(): wt_linear = V80() wt_pchip = V80(method='pchip') wt_spline = V80(method='spline') ws_lst = np.arange(3, 25, .001) for wt in [wt_linear, wt_pchip, wt_spline]: wt.enable_autograd() ws_pts = [6.99, 7.01] with use_autograd_in(): dpdu_linear_pts = autograd(wt_linear.power)(np.array(ws_pts)) dpdu_pchip_pts = autograd(wt_pchip.power)(np.array(ws_pts)) dpdu_spline_pts = autograd(wt_spline.power)(np.array(ws_pts)) if 0: wt_dp_label_lst = [(wt_linear, dpdu_linear_pts, 'linear'), (wt_pchip, dpdu_pchip_pts, 'pchip'), (wt_spline, dpdu_spline_pts, 'spline')] for wt, dpdu_pts, label in wt_dp_label_lst: c = plt.plot(ws_lst, wt.power(ws_lst), label=label)[0].get_color() gradients.color_dict[label] = c for ws, dpdu in zip(ws_pts, dpdu_pts): plot_gradients(wt.power(ws), dpdu, ws, label) plt.legend() plt.figure() for wt, dpdu_pts, label in wt_dp_label_lst: plt.plot(ws_lst, wt_linear.power(ws_lst) - wt.power(ws_lst), label=label) plt.legend() plt.ylabel('Power difference wrt. linear') plt.figure() for wt, dpdu_pts, label in wt_dp_label_lst: plt.plot(np.diff(np.diff(wt.power(ws_lst))), label=label) plt.ylabel('Change of gradient') plt.legend() plt.show() # mean and max error for wt, mean_tol, absmean_tol, max_tol in [(wt_pchip, 213, 2323, 15632), (wt_spline, 1, 1, 1380)]: assert np.abs((wt_linear.power(ws_lst) - wt.power(ws_lst)).mean()) < mean_tol assert np.abs((wt_linear.power(ws_lst) - wt.power(ws_lst)).mean()) < absmean_tol assert np.abs((wt_linear.power(ws_lst) - wt.power(ws_lst)).max()) < max_tol for wt, diff_grad_max, dpdu_pts, ref_dpdu_pts in [(wt_linear, 64, dpdu_linear_pts, [178000.00007264, 236000.00003353]), (wt_pchip, 0.2, dpdu_pchip_pts, [ 202520.16516056, 203694.66294614]), (wt_spline, 0.8, dpdu_spline_pts, [205555.17794162, 211859.45965873])]: assert np.diff(np.diff(wt.power(ws_lst))).max() < diff_grad_max npt.assert_array_almost_equal(dpdu_pts, ref_dpdu_pts)
def test_GenericWindTurbine_cut_in_out(power_idle, ct_idle): ref = V80() power_norm = ref.power(15) wt = GenericWindTurbine('Generic', ref.diameter(), ref.hub_height(), power_norm / 1e3, turbulence_intensity=0, ws_cutin=3, ws_cutout=25, power_idle=power_idle, ct_idle=ct_idle) if 0: u = np.arange(0, 30, .1) p, ct = wt.power_ct(u) plt.plot(u, p / 1e6, label='Generic') plt.plot(u, ref.power(u) / 1e6, label=ref.name()) plt.ylabel('Power [MW]') plt.legend() ax = plt.twinx() ax.plot(u, ct, '--') ax.plot(u, ref.ct(u), '--') plt.ylabel('Ct') plt.show() assert wt.ct(2.9) == ct_idle assert wt.power(2.9) == power_idle assert wt.ct(25.1) == ct_idle assert wt.power(25.1) == power_idle
def test_time_series_operating_wrong_shape(): from py_wake.wind_turbines.power_ct_functions import PowerCtFunctionList, PowerCtTabular d = np.load(os.path.dirname(examples.__file__) + "/data/time_series.npz") wd, ws, ws_std = [d[k][:6 * 24] for k in ['wd', 'ws', 'ws_std']] ws += 3 t = np.arange(6 * 24) wt = V80() site = Hornsrev1Site() # replace powerCtFunction wt.powerCtFunction = PowerCtFunctionList( key='operating', powerCtFunction_lst=[ PowerCtTabular(ws=[0, 100], power=[0, 0], power_unit='w', ct=[0, 0]), # 0=No power and ct wt.powerCtFunction ], # 1=Normal operation default_value=1) wfm = NOJ(site, wt) x, y = site.initial_position.T operating = (t < 48) | (t > 72) with pytest.raises( ValueError, match= r"Argument, operating\(shape=\(1, 144\)\), has unsupported shape." ): wfm(x, y, ws=ws, wd=wd, time=t, operating=[operating])
def test_time_series_operating(): from py_wake.wind_turbines.power_ct_functions import PowerCtFunctionList, PowerCtTabular d = np.load(os.path.dirname(examples.__file__) + "/data/time_series.npz") wd, ws, ws_std = [d[k][:6 * 24] for k in ['wd', 'ws', 'ws_std']] ws += 3 t = np.arange(6 * 24) wt = V80() site = Hornsrev1Site() # replace powerCtFunction wt.powerCtFunction = PowerCtFunctionList( key='operating', powerCtFunction_lst=[ PowerCtTabular(ws=[0, 100], power=[0, 0], power_unit='w', ct=[0, 0]), # 0=No power and ct wt.powerCtFunction ], # 1=Normal operation default_value=1) wfm = NOJ(site, wt) x, y = site.initial_position.T operating = (t < 48) | (t > 72) sim_res = wfm(x, y, ws=ws, wd=wd, time=t, operating=operating) npt.assert_array_equal(sim_res.operating[0], operating) npt.assert_array_equal(sim_res.Power[:, operating == 0], 0) npt.assert_array_equal(sim_res.Power[:, operating != 0] > 0, True) operating = np.ones((80, 6 * 24)) operating[1] = (t < 48) | (t > 72) sim_res = wfm(x, y, ws=ws, wd=wd, time=t, operating=operating) npt.assert_array_equal(sim_res.operating, operating) npt.assert_array_equal(sim_res.Power.values[operating == 0], 0) npt.assert_array_equal(sim_res.Power.values[operating != 0] > 0, True)
def test_twotype_windturbines(): v80 = V80() def power(ws, types): power = v80.power(ws) # add 10% type 1 turbines power[types == 1] *= 1.1 return power wts = WindTurbines(names=['V80', 'V88'], diameters=[80, 88], hub_heights=[70, 77], ct_funcs=[v80.ct_funcs[0], v80.ct_funcs[0]], power_funcs=[v80.power, lambda ws: v80.power(ws) * 1.1], power_unit='w') import matplotlib.pyplot as plt types0 = [0] * 9 types1 = [0, 0, 0, 1, 1, 1, 0, 0, 0] types2 = [1] * 9 wts.plot(wt9_x, wt9_y, types1) wfm = NOJ(Hornsrev1Site(), wts) npt.assert_almost_equal( wfm(wt9_x, wt9_y, type=types0).aep(), 81.2066072392765) npt.assert_almost_equal( wfm(wt9_x, wt9_y, type=types1).aep(), 83.72420504573488) npt.assert_almost_equal( wfm(wt9_x, wt9_y, type=types2).aep(), 88.87227386796884) if 0: plt.show()
def test_yaw_wrong_name(): wfm = NOJ(Hornsrev1Site(), V80()) for k in ['yaw_ilk', 'Yaw']: with pytest.raises( ValueError, match=r'Custom \*yaw\*\-keyword arguments not allowed'): wfm([0], [0], **{k: [[[30]]]})
def test_yaw_tilt(yaw, tilt, cx, cz): site = IEA37Site(16) x, y = [0], [0] windTurbines = V80() D = windTurbines.diameter() wfm = IEA37SimpleBastankhahGaussian( site, windTurbines, deflectionModel=JimenezWakeDeflection()) x_lst = np.linspace(-200, 1000, 100) y_lst = np.linspace(-100, 100, 201) z_lst = np.arange(10, 200, 1) fm_yz = wfm(x, y, wd=270, ws=10, yaw=yaw, tilt=tilt).flow_map(YZGrid(x=5 * D, y=y_lst, z=z_lst)) fm_xz = wfm(x, y, wd=180, ws=10, yaw=yaw, tilt=tilt).flow_map(YZGrid(x=0, y=x_lst, z=z_lst)) fm_xy = wfm(x, y, wd=270, ws=10, yaw=yaw, tilt=tilt).flow_map(XYGrid(x=x_lst)) if 0: axes = plt.subplots(3, 1)[1].flatten() fm_xy.plot_wake_map(ax=axes[0]) axes[0].axvline(5 * D) fm_xz.plot_wake_map(ax=axes[1]) axes[1].axvline(5 * D) fm_yz.plot_wake_map(ax=axes[2]) plt.show() wake_center = fm_yz.WS_eff.where(fm_yz.WS_eff == fm_yz.WS_eff.min(), drop=True).squeeze() npt.assert_allclose(wake_center.y, cx, atol=.1) npt.assert_allclose(wake_center.h, cz, atol=.24)
def test_Mirror(wfm_cls): # Compare points in flow map with ws of WT at same position. All2Alliterative failing with NOJ and WT.diameter=0 # and therefore this cannot be tested above site = UniformSite([1], ti=0.1) wt = V80() wfm = wfm_cls(site, wt, ZongGaussianDeficit(a=[0, 1]), turbulenceModel=STF2017TurbulenceModel(), groundModel=Mirror()) sim_res = wfm( [0], [0], h=[50], wd=0, ) fm_ref = sim_res.flow_map(YZGrid(x=0, y=np.arange(-70, 0, 20), z=10)) ref = fm_ref.WS_eff_xylk[:, 0, 0, 0].values res = np.array([ wfm([0, 0], [0, y], [50, 10], wd=0).WS_eff.sel(wt=1).item() for y in fm_ref.X[0] ]) if 0: fm_res = sim_res.flow_map(YZGrid(x=0, y=np.arange(-100, 10, 1))) fm_res.plot_wake_map() plt.plot(fm_ref.X[0], fm_ref.Y[0], '.') plt.plot(fm_ref.X[0], ref * 10, label='ref, WS*10') plt.plot(fm_ref.X[0], res * 10, label='Res, WS*10') plt.legend() plt.show() plt.close() npt.assert_array_equal(res, ref)
def test_Mirror_flow_map(wfm_cls, groundModel, superpositionModel): site = UniformSite([1], ti=0.1) wt = V80() wfm = NOJ(site, wt, k=.5, superpositionModel=superpositionModel) fm_ref = wfm([0, 0 + 1e-20], [0, 0 + 1e-20], wd=0, h=[50, -50]).flow_map( YZGrid(x=0, y=np.arange(-100, 100, 1) + .1, z=np.arange(1, 100))) fm_ref.plot_wake_map() plt.title("Underground WT added manually") plt.figure() wfm = wfm_cls(site, wt, NOJDeficit(k=.5), groundModel=groundModel, superpositionModel=superpositionModel) fm_res = wfm([0], [0], wd=0, h=[50]).flow_map( YZGrid(x=0, y=np.arange(-100, 100, 1) + .1, z=np.arange(1, 100))) fm_res.plot_wake_map() plt.title("With Mirror GroundModel") if 0: plt.show() plt.close() npt.assert_array_equal(fm_ref.WS_eff, fm_res.WS_eff)
def test_from_flow_box_2wt(): site = Hornsrev1Site() windTurbines = V80() # simulate current and neighbour wt wfm = BastankhahGaussian(site, windTurbines) wd = np.arange(30) sim_res = wfm([0, 0], [0, 500], wd=wd) ref_aep = sim_res.aep().sel(wt=0) wt_x, wt_y = [0], [0] neighbour_x, neighbour_y = [0], [500] # make site with effects of neighbour wt sim_res = wfm(neighbour_x, neighbour_y, wd=wd) e = 100 box = sim_res.flow_box(x=np.linspace(min(wt_x) - e, max(wt_x) + e, 21), y=np.linspace(min(wt_y) - e, max(wt_y) + e, 21), h=windTurbines.hub_height(windTurbines.types())) site = XRSite.from_flow_box(box) # Simujlate current wt and compare aep wfm = BastankhahGaussian(site, windTurbines) sim_res = wfm(wt_x, wt_y, wd=wd) aep = sim_res.aep() if 0: site.ds.WS.sel(ws=10, wd=3).plot() windTurbines.plot(wt_x, wt_y) windTurbines.plot(neighbour_x, neighbour_y) plt.show() npt.assert_array_almost_equal(ref_aep, aep.sel(wt=0))
def test_GenericWindTurbine(): for ref, ti, cut_in, cut_out, p_tol, ct_tol in [(V80(), .1, 4, None, 0.03, .14), (WindTurbine.from_WAsP_wtg(wtg_path + "Vestas V112-3.0 MW.wtg"), .05, 3, 25, 0.035, .07), (DTU10MW(), .05, 4, 25, 0.06, .12)]: power_norm = ref.power(np.arange(10, 20)).max() wt = GenericWindTurbine('Generic', ref.diameter(), ref.hub_height(), power_norm / 1e3, turbulence_intensity=ti, ws_cutin=cut_in, ws_cutout=cut_out) if 0: u = np.arange(0, 30, .1) p, ct = wt.power_ct(u) plt.plot(u, p / 1e6, label='Generic') plt.plot(u, ref.power(u) / 1e6, label=ref.name()) plt.ylabel('Power [MW]') plt.legend(loc='center left') ax = plt.twinx() ax.plot(u, ct, '--') ax.plot(u, ref.ct(u), '--') ax.set_ylim([0, 1]) plt.ylabel('Ct') plt.show() u = np.arange(5, 25) p, ct = wt.power_ct(u) p_ref, ct_ref = ref.power_ct(u) # print(np.abs(p_ref - p).max() / power_norm) npt.assert_allclose(p, p_ref, atol=power_norm * p_tol) # print(np.abs(ct_ref - ct).max()) npt.assert_allclose(ct, ct_ref, atol=ct_tol)
def test_get_defaults(): v80 = V80() npt.assert_array_equal(np.array(v80.get_defaults(1))[:, 0], [0, 70, 80]) npt.assert_array_equal( np.array(v80.get_defaults(1, h_i=100))[:, 0], [0, 100, 80]) npt.assert_array_equal( np.array(v80.get_defaults(1, d_i=100))[:, 0], [0, 70, 100])
def test_GCL_ex80(): site = Hornsrev1Site() x, y = site.initial_position.T windTurbines = V80() wfm = PropagateDownwind(site, windTurbines, wake_deficitModel=GCLDeficit(), superpositionModel=LinearSum()) if 0: windTurbines.plot(x, y) plt.show() sim_res = timeit(wfm.__call__, line_profile=0, profile_funcs=[get_dU], verbose=0)(x, y, ws=np.arange(10, 15))[0] # test that the result is equal to previuos runs (no evidens that these number are correct) aep_ref = 1055.956615887197 npt.assert_almost_equal( sim_res.aep_ilk(normalize_probabilities=True).sum(), aep_ref, 5) sim_res = wfm(x, y, ws=np.arange(3, 10)) npt.assert_array_almost_equal( sim_res.aep_ilk(normalize_probabilities=True).sum(), 261.6143039016946, 5)
def test_i_time_dependent_WS(): t = np.arange(4) WS_it = t[na] / 10 + np.array([9, 10])[:, na] ds = xr.Dataset( data_vars={'WS': (('i', 'time'), WS_it), 'P': ('wd', f), 'TI': 0.1}, coords={'wd': np.linspace(0, 360, len(f), endpoint=False)}) site = XRSite(ds) wfm = NOJ(site, V80()) sim_res = wfm([0, 200], [0, 0], ws=WS_it.mean(0), wd=np.zeros(4), time=t) npt.assert_array_equal(sim_res.WS, WS_it)
def test_time_series_aep(): d = np.load(os.path.dirname(examples.__file__) + "/data/time_series.npz") wd, ws = [d[k][::100] for k in ['wd', 'ws']] wt = V80() site = Hornsrev1Site() x, y = site.initial_position.T wfm = NOJ(site, wt) sim_res = wfm(x, y, ws=ws, wd=wd, time=True, verbose=False) npt.assert_allclose(sim_res.aep().sum(), 545, atol=1)
def test_yaw(): v80 = V80() yaw = np.deg2rad(np.arange(-30, 31)) ws = np.zeros_like(yaw) + 8 P0 = v80.power(ws[0]) if 0: plt.plot(yaw, v80.power(ws, 0, yaw) / P0) plt.plot(yaw, np.cos(yaw)**3) plt.grid() plt.show() npt.assert_array_almost_equal(v80.power(ws, 0, yaw) / P0, np.cos(yaw)**3, 2)
def test_time_series_override_WD(): d = np.load(os.path.dirname(examples.__file__) + "/data/time_series.npz") wd, ws = [d[k][:6 * 24] for k in ['wd', 'ws']] t = pd.date_range("2000-01-01", freq="10T", periods=24 * 6) WD_it = (np.arange(80) / 100)[:, na] + wd[na] wt = V80() site = Hornsrev1Site() x, y = site.initial_position.T wfm = NOJ(site, wt) sim_res = wfm(x, y, ws=ws, wd=wd, time=t, WD=WD_it, verbose=False) npt.assert_array_equal(sim_res.WS, ws) npt.assert_array_equal(sim_res.WD, WD_it) npt.assert_array_equal(sim_res.time, t)
def test_plot_yz2_types(): wt = WindTurbines.from_WindTurbines([IEA37_WindTurbines(), V80()]) yaw_lst = np.array([-30, 0, 30]) for wd in 0, 45, 90: plt.figure() wt.plot_yz(yaw_lst * 20, types=[0, 1, 0], wd=wd, yaw=yaw_lst) for i, yaw in enumerate(yaw_lst): plt.plot([], 'gray', label="WT %d yaw: %d deg" % (i, yaw)) plt.legend() plt.title("WD: %s" % wd) if 0: plt.show() plt.close()
def test_time_series_values(): wt = V80() site = Hornsrev1Site() x, y = site.initial_position.T wfm = NOJ(site, wt) wd = np.arange(350, 360) ws = np.arange(5, 10) wd_t, ws_t = [v.flatten() for v in np.meshgrid(wd, ws)] sim_res_t = wfm(x, y, ws=ws_t, wd=wd_t, time=True, verbose=False) sim_res = wfm(x, y, wd=wd, ws=ws) for k in ['WS_eff', 'TI_eff', 'Power', 'CT']: npt.assert_array_equal( np.moveaxis(sim_res_t[k].values.reshape((80, 5, 10)), 1, 2), sim_res[k].values)
def test_time_series_override_TI(): d = np.load(os.path.dirname(examples.__file__) + "/data/time_series.npz") wd, ws, ws_std = [d[k][:6 * 24] for k in ['wd', 'ws', 'ws_std']] ti = np.minimum(ws_std / ws, .5) t = pd.date_range("2000-01-01", freq="10T", periods=24 * 6) wt = V80() site = Hornsrev1Site() x, y = site.initial_position.T wfm = NOJ(site, wt) sim_res = wfm(x, y, ws=ws, wd=wd, time=t, TI=ti, verbose=False) npt.assert_array_equal(sim_res.WS, ws) npt.assert_array_equal(sim_res.WD, wd) npt.assert_array_equal(sim_res.time, t) npt.assert_array_equal(sim_res.TI[0], ti)
def test_yaw(): v80 = V80() yaw = np.arange(-30, 31) ws = np.zeros_like(yaw) + 8 P0 = v80.power(ws[0]) if 0: plt.plot(yaw, v80.power(ws, yaw=yaw) / P0) plt.plot(yaw, np.cos(np.deg2rad(yaw))**3) plt.grid() plt.figure() plt.plot(yaw, v80.ct(ws, yaw=yaw)) plt.plot(yaw, v80.ct(ws) * np.cos(np.deg2rad(yaw))**2) plt.grid() plt.show() # Power in cube region npt.assert_array_almost_equal(v80.power(ws, yaw=yaw) / P0, np.cos(np.deg2rad(yaw))**3, 2) # ct in constant region npt.assert_array_almost_equal(v80.ct(ws, yaw=yaw), v80.ct(ws) * np.cos(np.deg2rad(yaw))**2, 3)
def test_turning_mean(complex_grid_site, wfm): ds = xr.Dataset( data_vars={'Turning': (['x', 'y'], np.arange(-2, 4, 1).reshape((2, 3)).T), 'Sector_frequency': ('wd', f), 'Weibull_A': ('wd', A), 'Weibull_k': ('wd', k), 'TI': .1}, coords={'x': [0, 500, 1000], 'y': [0, 500], 'wd': np.linspace(0, 360, len(f), endpoint=False)}) site = XRSite(ds) wt = V80() wfm = wfm(site, wt, NOJDeficit()) sim_res = wfm([500, 500], [100, 400], wd=0, ws=10) print(sim_res.Power) if 0: sim_res.flow_map(XYGrid(y=np.linspace(0, 500, 100))).plot_wake_map() plt.show() assert sim_res.WS_eff.sel(wt=0).item() < sim_res.WS_eff.sel(wt=1).item() fm = sim_res.flow_map(Points([500, 500], [100, 400], [70, 70])) assert fm.WS_eff.sel(i=0).item() < fm.WS_eff.sel(i=1).item()
def test_twotype_windturbines(): v80 = V80() v88 = WindTurbine('V88', 88, 77, powerCtFunction=PowerCtTabular( hornsrev1.power_curve[:, 0], hornsrev1.power_curve[:, 1] * 1.1, 'w', hornsrev1.ct_curve[:, 1])) wts = WindTurbines.from_WindTurbines([v80, v88]) types0 = [0] * 9 types1 = [0, 0, 0, 1, 1, 1, 0, 0, 0] types2 = [1] * 9 for wfm in get_wfms(wts): npt.assert_array_equal(wts.types(), [0, 1]) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types0), 81.2066072392765) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types1), 83.72420504573488) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types2), 88.87227386796884)
def test_deflection_model(deflectionModel, dy10d): site = IEA37Site(16) x, y = [0], [0] windTurbines = V80() D = windTurbines.diameter() wfm = IEA37SimpleBastankhahGaussian(site, windTurbines, deflectionModel=deflectionModel()) yaw_ilk = np.reshape([-30], (1, 1, 1)) sim_res = wfm(x, y, yaw=yaw_ilk, wd=270, ws=10) fm = sim_res.flow_map(XYGrid(x=np.arange(-D, 10 * D + 10, 10))) min_WS_line = fm.min_WS_eff() if 0: plt.figure(figsize=(14, 3)) fm.plot_wake_map() min_WS_line.plot() plt.plot(10 * D, dy10d * D, '.', label="Ref, 10D") plt.legend() plt.show() npt.assert_almost_equal(min_WS_line.interp(x=10 * D).item() / D, dy10d)
def test_plot_deflection_grid(deflectionModel): site = IEA37Site(16) x, y = [0], [0] windTurbines = V80() D = windTurbines.diameter() wfm = IEA37SimpleBastankhahGaussian(site, windTurbines, deflectionModel=deflectionModel()) yaw_ilk = np.reshape([-30], (1, 1, 1)) sim_res = wfm(x, y, yaw=yaw_ilk, wd=270, ws=10) fm = sim_res.flow_map(XYGrid(x=np.arange(-D, 10 * D + 10, 10))) plt.figure(figsize=(14, 3)) fm.plot_wake_map() fm.plot_deflection_grid() min_WS_line = fm.min_WS_eff() min_WS_line.plot() plt.legend() plt.title(wfm.deflectionModel) if 0: plt.show() plt.close('all')
import matplotlib.pyplot as plt import numpy as np from autograd import numpy as anp from py_wake.examples.data.iea37 import iea37_reader from py_wake.examples.data.iea37._iea37 import IEA37_WindTurbines from py_wake.utils.gradients import use_autograd_in, autograd, plot_gradients, fd, cs from py_wake.tests import npt from py_wake.wind_turbines import WindTurbines from py_wake import wind_turbines from py_wake.examples.data.hornsrev1 import V80 import pytest @pytest.mark.parametrize('obj', [wind_turbines, WindTurbines, V80().power, wind_turbines.__dict__]) def test_use_autograd_in(obj): assert wind_turbines.np == np with use_autograd_in([obj]): assert wind_turbines.np == anp assert wind_turbines.np == np def test_gradients(): wt = IEA37_WindTurbines() with use_autograd_in([WindTurbines, iea37_reader]): ws_lst = np.arange(3, 25, .1) ws_pts = np.array([3., 6., 9., 12.]) dpdu_lst = np.diag(autograd(wt.power)(ws_pts)) if 0: plt.plot(ws_lst, wt.power(ws_lst)) for dpdu, ws in zip(dpdu_lst, ws_pts):
def main(): if __name__ == '__main__': try: import matplotlib.pyplot as plt plt.gcf() plot_comp = XYPlotComp plot = True except RuntimeError: plot_comp = NoPlot plot = False # ------------------------ INPUTS ------------------------ # ------------------------ DEFINE WIND RESOURCE ------------------------ # wind resource info (wdir frequency, weibull a and k) f = [ 3.597152, 3.948682, 5.167395, 7.000154, 8.364547, 6.43485, 8.643194, 11.77051, 15.15757, 14.73792, 10.01205, 5.165975 ] a = [ 9.176929, 9.782334, 9.531809, 9.909545, 10.04269, 9.593921, 9.584007, 10.51499, 11.39895, 11.68746, 11.63732, 10.08803 ] k = [ 2.392578, 2.447266, 2.412109, 2.591797, 2.755859, 2.595703, 2.583984, 2.548828, 2.470703, 2.607422, 2.626953, 2.326172 ] site = UniformWeibullSite(p_wd=f, a=a, k=k, ti=0.075) wt = V80() # ------------------------ setup problem ____--------------------------- rot_diam = 80.0 # rotor diameter [m] init_pos = np.array([(0, 2 * rot_diam), (0, 0), (0, -2 * rot_diam)]) # initial turbine positions b = 2 * rot_diam + 10 # boundary size boundary = [(-b, -b), (-b, b), (b, b), (b, -b)] # corners of wind farm boundary min_spacing = 2.0 * rot_diam # minimum spacing between turbines [m] # ------------------------ OPTIMIZATION ------------------------ def get_tf(windFarmModel): return TopFarmProblem(design_vars=dict(zip('xy', init_pos.T)), cost_comp=PyWakeAEPCostModelComponent( windFarmModel, n_wt=3, ws=10, wd=np.arange(0, 360, 12)), constraints=[ SpacingConstraint(min_spacing), XYBoundaryConstraint(boundary) ], driver=EasyScipyOptimizeDriver(), plot_comp=plot_comp()) # GCL: define the wake model and optimization problem tf_gcl = get_tf(GCL(site, wt)) # NOJ: define the wake model and optimization problem tf_noj = get_tf(NOJ(site, wt)) # run the optimization cost_gcl, state_gcl, recorder_gcl = tf_gcl.optimize() cost_noj, state_noj, recorder_noj = tf_noj.optimize() # ------------------------ POST-PROCESS ------------------------ # get the optimized locations opt_gcl = tf_gcl.turbine_positions opt_noj = tf_noj.turbine_positions # create the array of costs for easier printing costs = np.diag([cost_gcl, cost_noj]) costs[0, 1] = tf_noj.evaluate(state_gcl)[0] # noj cost of gcl locs costs[1, 0] = tf_gcl.evaluate(state_noj)[0] # gcl cost of noj locs # ------------------------ PRINT STATS ------------------------ aep_diffs = 200 * (costs[:, 0] - costs[:, 1]) / (costs[:, 0] + costs[:, 1]) loc_diffs = 200 * (costs[0, :] - costs[1, :]) / (costs[0, :] + costs[1, :]) print('\nComparison of cost models vs. optimized locations:') print('\nCost | GCL_aep NOJ_aep') print('---------------------------------') print(f'GCL_loc |{costs[0,0]:11.2f} {costs[0,1]:11.2f}' + f' ({aep_diffs[0]:.2f}%)') print(f'NOJ_loc |{costs[1,0]:11.2f} {costs[1,1]:11.2f}' + f' ({aep_diffs[1]:.2f}%)') print(f' ({loc_diffs[0]:.2f}%) ({loc_diffs[1]:.2f}%)') # ------------------------ PLOT (if possible) ------------------------ if plot: # initialize the figure and axes fig = plt.figure(1, figsize=(7, 5)) plt.clf() ax = plt.axes() # plot the boundary and desired locations ax.add_patch(Polygon(boundary, fill=False, label='Boundary')) # boundary ax.plot(init_pos[:, 0], init_pos[:, 1], 'xk', label='Initial') ax.plot(opt_gcl[:, 0], opt_gcl[:, 1], 'o', label='GCL') ax.plot(opt_noj[:, 0], opt_noj[:, 1], '^', label='NOJ') # make a few adjustments to the plot ax.autoscale_view() # autoscale the boundary plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=4, mode='expand', borderaxespad=0.) # add a legend plt.tight_layout() # zoom the plot in plt.axis('off') # remove the axis # save the png folder, file = os.path.split(__file__) fig.savefig(folder + "/figures/" + file.replace('.py', '.png'))
@pytest.mark.parametrize( 'case,wt,dpdu_ref,dctdu_ref', [('CubePowerSimpleCt', WindTurbine('Test', 130, 110, CubePowerSimpleCt(4, 25, 9.8, 3.35e6, 'W', 8 / 9, 0, [])), lambda ws_pts: np.where((ws_pts > 4) & (ws_pts <= 9.8), 3 * 3350000 * (ws_pts - 4)**2 / (9.8 - 4)**3, 0), lambda ws_pts: [0, 0, 0, 2 * 12 * 0.0038473376423514938 + -0.1923668821175747]), ('CubePowerSimpleCt_MW', WindTurbine('Test', 130, 110, CubePowerSimpleCt(4, 25, 9.8, 3.35, 'MW', 8 / 9, 0, [])), lambda ws_pts: np.where((ws_pts > 4) & (ws_pts <= 9.8), 3 * 3350000 * (ws_pts - 4)**2 / (9.8 - 4)**3, 0), lambda ws_pts: [0, 0, 0, 2 * 12 * 0.0038473376423514938 + -0.1923668821175747]), ('PowerCtTabular_linear', V80(), [ 66600.00000931, 178000.00001444, 344999.99973923, 91999.99994598 ], [0.818, 0.001, -0.014, -0.3]), ('PowerCtTabular_pchip', V80(method='pchip'), [ 58518.7948, 148915.03267974, 320930.23255814, 127003.36700337 ], [1.21851, 0., 0., -0.05454545]), ('PowerCtTabular_spline', V80(method='spline'), [ 69723.7929, 158087.18190692, 324012.9604669, 156598.55856862 ], [8.176490e-01, -3.31076624e-05, -7.19353708e-03, -1.66006862e-01]), ('PowerCtTabular_kW', get_wt(PowerCtTabular( v80_upct[0], v80_upct[1] / 1000, 'kW', v80_upct[2])), [ 66600.00000931, 178000.00001444, 344999.99973923, 91999.99994598 ], [0.818, 0.001, -0.014, -0.3]), ('PowerCtFunctionList', get_wt(