def test_double_wind_farm_model_All2AllIterative(): """Check that a new wind farm model does not change results of previous""" site = IEA37Site(64) x, y = site.initial_position.T x, y = wt_x, wt_y windTurbines = IEA37_WindTurbines() wfm = All2AllIterative(site, windTurbines, wake_deficitModel=IEA37SimpleBastankhahGaussianDeficit()) aep_ref = wfm(x, y).aep().sum() All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit())(x, y) aep = wfm(x, y).aep().sum() npt.assert_array_equal(aep, aep_ref)
def test_own_turbulence_is_zero(turbulenceModel): site = Hornsrev1Site() windTurbines = IEA37_WindTurbines() wf_model = All2AllIterative(site, windTurbines, wake_deficitModel=IEA37SimpleBastankhahGaussianDeficit(), turbulenceModel=turbulenceModel()) sim_res = wf_model([0], [0]) npt.assert_array_equal(sim_res.TI_eff, sim_res.TI.broadcast_like(sim_res.TI_eff))
def test_blockage_map(setup): site, windTurbines, ss = setup wm = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=ss) flow_map = wm(x=[0], y=[0], wd=[270], ws=[10]).flow_map() X_j, Y_j = flow_map.XY WS_eff = flow_map.WS_eff_xylk[:, :, 0, 0] if 0: plt.contourf(X_j, Y_j, WS_eff) plt.plot(X_j[200, ::50], Y_j[200, ::50], '.-') plt.plot(X_j[250, ::50], Y_j[250, ::50], '.-') print(list(np.round(WS_eff[200, ::50], 6))) print(list(np.round(WS_eff[250, ::50], 6))) ss.windTurbines.plot([0], [0], wd=[270]) plt.show() npt.assert_array_almost_equal(WS_eff[200, ::50], [ 9.940967, 9.911659, 9.855934, 9.736016, 9.44199, 10.0, 10.0, 10.0, 10.0, 10.0 ]) npt.assert_array_almost_equal(WS_eff[250, ::50], [ 9.937601, 9.90397, 9.834701, 9.659045, 9.049764, 10.0, 10.0, 10.0, 10.0, 10.0 ])
def test_wake_and_blockage(setup): site, windTurbines, ss = setup noj_ss = All2AllIterative(site, windTurbines, wake_deficitModel=NOJDeficit(), blockage_deficitModel=ss, superpositionModel=LinearSum()) flow_map = noj_ss(x=[0], y=[0], wd=[270], ws=[10]).flow_map() X_j, Y_j = flow_map.XY WS_eff = flow_map.WS_eff_xylk[:, :, 0, 0] npt.assert_array_almost_equal(WS_eff[200, ::50], [ 9.940967, 9.911659, 9.855934, 9.736016, 9.44199, 4.560631, 5.505472, 6.223921, 6.782925, 7.226399 ]) npt.assert_array_almost_equal(WS_eff[250, ::50], [ 9.937601, 9.90397, 9.834701, 9.659045, 9.049764, 4.560631, 5.505472, 6.223921, 6.782925, 7.226399 ]) if 0: plt.contourf(X_j, Y_j, WS_eff) plt.plot(X_j[200, ::50], Y_j[200, ::50], '.-') plt.plot(X_j[250, ::50], Y_j[250, ::50], '.-') print(list(np.round(WS_eff[200, ::50], 6))) print(list(np.round(WS_eff[250, ::50], 6))) ss.windTurbines.plot([0], [0], wd=[270]) plt.show()
def test_wake_blockage_split(upstream_only, ref): class MyWakeModel(WakeDeficitModel): args4deficit = [] def calc_deficit(self, dw_ijlk, **kwargs): return np.ones_like(dw_ijlk) * 2 class MyBlockageModel(BlockageDeficitModel): args4deficit = [] def calc_deficit(self, dw_ijlk, **kwargs): return np.ones_like(dw_ijlk) site = Hornsrev1Site() windTurbines = IEA37_WindTurbines() wf_model = All2AllIterative( site, windTurbines, wake_deficitModel=MyWakeModel(), blockage_deficitModel=MyBlockageModel(upstream_only=upstream_only)) sim_res = wf_model([0], [0], ws=10, wd=270) fm = sim_res.flow_map(XYGrid(x=[-100, 100], y=[-100, 0, 100])) if 0: sim_res.flow_map().plot_wake_map() print(fm.WS_eff.values.squeeze().T) plt.show() npt.assert_array_equal(fm.WS_eff.values.squeeze().T, ref)
def test_blockage_map(setup, blockage_model, center_ref, side_ref): site, windTurbines = setup wm = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=blockage_model()) xy = np.linspace(-200, 200, 500) flow_map = wm(x=[0], y=[0], wd=[270], ws=[10]).flow_map(XYGrid(x=xy[::50], y=xy[[190, 250]])) X_j, Y_j = flow_map.XY WS_eff = flow_map.WS_eff_xylk[:, :, 0, 0] if debug: flow_map_full = wm(x=[0], y=[0], wd=[270], ws=[10]).flow_map() X_j_full, Y_j_full = flow_map_full.XY WS_eff_full = flow_map_full.WS_eff_xylk[:, :, 0, 0] plt.contourf(X_j_full, Y_j_full, WS_eff_full) plt.plot(X_j.T, Y_j.T, '.-') print(list(np.round(np.array(WS_eff[0]), 6))) print(list(np.round(np.array(WS_eff[1]), 6))) plt.title(blockage_model.__name__) plt.show() npt.assert_array_almost_equal(WS_eff[0], center_ref) npt.assert_array_almost_equal(WS_eff[1], side_ref)
def test_All2AllIterativeDeflection(): site = IEA37Site(16) windTurbines = IEA37_WindTurbines() wf_model = All2AllIterative(site, windTurbines, wake_deficitModel=NOJDeficit(), superpositionModel=SquaredSum(), deflectionModel=JimenezWakeDeflection()) wf_model([0], [0])
def test_str(): site = IEA37Site(16) windTurbines = IEA37_WindTurbines() wf_model = All2AllIterative(site, windTurbines, wake_deficitModel=NOJDeficit(), superpositionModel=SquaredSum(), blockage_deficitModel=SelfSimilarityDeficit(), deflectionModel=JimenezWakeDeflection(), turbulenceModel=STF2005TurbulenceModel()) assert str(wf_model) == "All2AllIterative(EngineeringWindFarmModel, NOJDeficit-wake, SelfSimilarityDeficit-blockage, RotorCenter-rotor-average, SquaredSum-superposition, JimenezWakeDeflection-deflection, STF2005TurbulenceModel-turbulence)"
def __init__(self, LUT_path, site, windTurbines, turbulenceModel=None, convergence_tolerance=1e-6): """ Parameters ---------- LUT_path : str path to look up tables site : Site Site object windTurbines : WindTurbines WindTurbines object representing the wake generating wind turbines deflectionModel : DeflectionModel Model describing the deflection of the wake due to yaw misalignment, sheared inflow, etc. turbulenceModel : TurbulenceModel Model describing the amount of added turbulence in the wake """ fuga_deficit = FugaDeficit(LUT_path) All2AllIterative.__init__(self, site, windTurbines, wake_deficitModel=fuga_deficit, superpositionModel=LinearSum(), blockage_deficitModel=fuga_deficit, turbulenceModel=turbulenceModel, convergence_tolerance=convergence_tolerance)
def test_deficit_symmetry(wake_deficitModel, blockage_deficitModel): site = Hornsrev1Site() windTurbines = IEA37_WindTurbines() wfm = All2AllIterative(site, windTurbines, wake_deficitModel=wake_deficitModel, superpositionModel=LinearSum(), blockage_deficitModel=blockage_deficitModel, deflectionModel=None, turbulenceModel=None) power = wfm([0, 0, 500, 500], [0, 500, 0, 500], wd=[0], ws=[8]).power_ilk[:, 0, 0] npt.assert_array_almost_equal(power[:2], power[2:])
def test_own_deficit_is_zero(): for deficitModel in get_models(WakeDeficitModel): site = Hornsrev1Site() windTurbines = IEA37_WindTurbines() wf_model = All2AllIterative(site, windTurbines, wake_deficitModel=deficitModel(), turbulenceModel=STF2017TurbulenceModel()) sim_res = wf_model([0], [0]) npt.assert_array_equal(sim_res.WS_eff, sim_res.WS.broadcast_like(sim_res.WS_eff))
def test_NOJ_Nibe_result(): # Replicate result from: Jensen, Niels Otto. "A note on wind generator interaction." (1983). site = UniformSite([1], 0.1) x_i = [0, 0, 0] y_i = [0, -40, -100] h_i = [50, 50, 50] wfm = All2AllIterative(site, NibeA0, wake_deficitModel=NOJDeficit(), superpositionModel=LinearSum()) WS_eff_ilk = wfm.calc_wt_interaction(x_i, y_i, h_i, [0, 1, 1], 0.0, 8.1)[0] npt.assert_array_almost_equal(WS_eff_ilk[:, 0, 0], [8.1, 4.35, 5.7])
def test_All2AllIterativeDeflection(): site = IEA37Site(16) windTurbines = IEA37_WindTurbines() wf_model = All2AllIterative(site, windTurbines, wake_deficitModel=NOJDeficit(), superpositionModel=SquaredSum(), deflectionModel=JimenezWakeDeflection()) sim_res = wf_model([0, 500], [0, 0], wd=270, ws=10, yaw=30) if 0: sim_res.flow_map( XYGrid(x=np.linspace(-200, 1000, 100))).plot_wake_map() plt.show()
def __init__(self, LUT_path, site, windTurbines, rotorAvgModel=RotorCenter(), deflectionModel=None, turbulenceModel=None, convergence_tolerance=1e-6, remove_wriggles=False): """ Parameters ---------- LUT_path : str path to look up tables site : Site Site object windTurbines : WindTurbines WindTurbines object representing the wake generating wind turbines rotorAvgModel : RotorAvgModel Model defining one or more points at the down stream rotors to calculate the rotor average wind speeds from.\n Defaults to RotorCenter that uses the rotor center wind speed (i.e. one point) only deflectionModel : DeflectionModel Model describing the deflection of the wake due to yaw misalignment, sheared inflow, etc. turbulenceModel : TurbulenceModel Model describing the amount of added turbulence in the wake """ fuga_deficit = FugaDeficit(LUT_path, remove_wriggles=remove_wriggles) All2AllIterative.__init__(self, site, windTurbines, wake_deficitModel=fuga_deficit, rotorAvgModel=rotorAvgModel, superpositionModel=LinearSum(), deflectionModel=deflectionModel, blockage_deficitModel=fuga_deficit, turbulenceModel=turbulenceModel, convergence_tolerance=convergence_tolerance)
def test_aep_two_turbines(setup, blockage_model, blockage_loss): site, windTurbines = setup nwm_ss = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), blockage_deficitModel=blockage_model(), superpositionModel=LinearSum()) sim_res = nwm_ss(x=[0, 80 * 3], y=[0, 0]) aep_no_blockage = sim_res.aep_ilk(with_wake_loss=False).sum(2) aep = sim_res.aep_ilk().sum(2) # blockage reduce aep(wd=270) by .5% npt.assert_almost_equal((aep_no_blockage[0, 270] - aep[0, 270]) / aep_no_blockage[0, 270] * 100, blockage_loss) if debug: plt.plot(sim_res.WS_eff_ilk[:, :, 7].T) plt.title(blockage_model.__name__) plt.show()
def test_stf(turbulence_model, ref_ti): # setup site, turbines and wind farm model site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() for wake_model in [ NOJ(site, windTurbines, turbulenceModel=turbulence_model), All2AllIterative(site, windTurbines, wake_deficitModel=NOJDeficit(), superpositionModel=SquaredSum(), turbulenceModel=turbulence_model) ]: res = wake_model(x, y) # print(np.round(res.TI_eff_ilk[:, 0, 0], 3).tolist()) npt.assert_array_almost_equal(res.TI_eff_ilk[:, 0, 0], ref_ti, 3)
def test_RotorGridAvg_deficit(): site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() wfm = IEA37SimpleBastankhahGaussian(site, windTurbines) flow_map = wfm([0, 500], [0, 0], wd=270, ws=10).flow_map(HorizontalGrid(x=[500], y=np.arange(-100, 100))) plt.plot(flow_map.Y[:, 0], flow_map.WS_eff_xylk[:, 0, 0, 0]) R = windTurbines.diameter() / 2 for name, rotorAvgModel, ref1 in [ ('RotorCenter', RotorCenter(), 7.172723970425709), ('RotorGrid2', EqGridRotorAvg(2), 7.495889360682771), ('RotorGrid3', EqGridRotorAvg(3), 7.633415167369133), ('RotorGrid4', EqGridRotorAvg(4), 7.710215921858325), ('RotorGrid100', EqGridRotorAvg(100), 7.820762402628349), ('RotorGQGrid_4,3', GQGridRotorAvg(4, 3), 7.826105012683896), ('RotorCGI4', CGIRotorAvg(4), 7.848406907726826), ('RotorCGI4', CGIRotorAvg(7), 7.819900693605533), ('RotorCGI4', CGIRotorAvg(9), 7.82149363932618), ('RotorCGI4', CGIRotorAvg(21), 7.821558905416136)]: # test with PropagateDownwind wfm = IEA37SimpleBastankhahGaussian(site, windTurbines, rotorAvgModel=rotorAvgModel) sim_res = wfm([0, 500], [0, 0], wd=270, ws=10) npt.assert_almost_equal(sim_res.WS_eff_ilk[1, 0, 0], ref1) # test with All2AllIterative wfm = All2AllIterative(site, windTurbines, IEA37SimpleBastankhahGaussianDeficit(), rotorAvgModel=rotorAvgModel, superpositionModel=SquaredSum()) sim_res = wfm([0, 500], [0, 0], wd=270, ws=10) npt.assert_almost_equal(sim_res.WS_eff_ilk[1, 0, 0], ref1) plt.plot([-R, R], [sim_res.WS_eff_ilk[1, 0, 0]] * 2, label=name) if 0: plt.legend() plt.show() plt.close('all')
def test_models_with_noj(turbulence_model, ref_ti): # setup site, turbines and wind farm model site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() for wake_model in [NOJ(site, windTurbines, turbulenceModel=turbulence_model), All2AllIterative(site, windTurbines, wake_deficitModel=NOJDeficit(), superpositionModel=SquaredSum(), turbulenceModel=turbulence_model), ]: res = wake_model(x, y) # print(turbulence_model.__class__.__name__, np.round(res.TI_eff_ilk[:, 0, 0], 3).tolist()) if 0: res.flow_map(wd=0).plot_ti_map() plt.show() npt.assert_array_almost_equal(res.TI_eff_ilk[:, 0, 0], ref_ti, 3)
def test_RotorGridAvg_ti(): site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() wfm = IEA37SimpleBastankhahGaussian(site, windTurbines, turbulenceModel=STF2017TurbulenceModel()) flow_map = wfm([0, 500], [0, 0], wd=270, ws=10).flow_map(HorizontalGrid(x=[500], y=np.arange(-100, 100))) plt.plot(flow_map.Y[:, 0], flow_map.TI_eff_xylk[:, 0, 0, 0]) R = windTurbines.diameter() / 2 for name, rotorAvgModel, ref1 in [ ('RotorCenter', RotorCenter(), 0.22292190804089568), ('RotorGrid2', EqGridRotorAvg(2), 0.2111162769995657), ('RotorGrid3', EqGridRotorAvg(3), 0.2058616982653193), ('RotorGrid4', EqGridRotorAvg(4), 0.2028701990648858), ('RotorGrid100', EqGridRotorAvg(100), 0.1985255601976247), ('RotorGQGrid_4,3', GQGridRotorAvg(4, 3), 0.1982984399750206)]: # test with PropagateDownwind wfm = IEA37SimpleBastankhahGaussian(site, windTurbines, rotorAvgModel=rotorAvgModel, turbulenceModel=STF2017TurbulenceModel()) sim_res = wfm([0, 500], [0, 0], wd=270, ws=10) npt.assert_almost_equal(sim_res.TI_eff_ilk[1, 0, 0], ref1) # test with All2AllIterative wfm = All2AllIterative(site, windTurbines, IEA37SimpleBastankhahGaussianDeficit(), rotorAvgModel=rotorAvgModel, superpositionModel=SquaredSum(), turbulenceModel=STF2017TurbulenceModel()) sim_res = wfm([0, 500], [0, 0], wd=270, ws=10) npt.assert_almost_equal(sim_res.TI_eff_ilk[1, 0, 0], ref1) plt.plot([-R, R], [sim_res.TI_eff_ilk[1, 0, 0]] * 2, label=name) if 0: plt.legend() plt.show() plt.close('all')
def test_deficitModel_wake_map_convection_all2all(deficitModel, ref): site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() wf_model = All2AllIterative(site, windTurbines, wake_deficitModel=deficitModel, superpositionModel=WeightedSum(), blockage_deficitModel=VortexDipole(), turbulenceModel=STF2017TurbulenceModel()) x_j = np.linspace(-1500, 1500, 200) y_j = np.linspace(-1500, 1500, 100) flow_map = wf_model(x, y, wd=0, ws=9).flow_map(HorizontalGrid(x_j, y_j)) X, Y = flow_map.X, flow_map.Y Z = flow_map.WS_eff_xylk[:, :, 0, 0] mean_ref = [ 3.2, 4.9, 8., 8.2, 7.9, 7.4, 7., 7., 7.4, 7.9, 8.1, 8.1, 8., 7.8, 7.9, 8.1, 8.4 ] if 0: flow_map.plot_wake_map() plt.plot(X[49, 100:133:2], Y[49, 100:133:2], '.-') windTurbines.plot(x, y) plt.figure() plt.plot(Z[49, 100:133:2], label='Actual') plt.plot(ref, label='Reference') plt.plot(mean_ref, label='Mean ref') plt.legend() plt.show() # check that ref is reasonable npt.assert_allclose(ref[2:], mean_ref[2:], atol=2.6) npt.assert_array_almost_equal(Z[49, 100:133:2], ref, 2)
def test_RotorAvg_deficit(): site = IEA37Site(16) windTurbines = IEA37_WindTurbines() wfm = IEA37SimpleBastankhahGaussian(site, windTurbines, turbulenceModel=STF2017TurbulenceModel()) flow_map = wfm([0, 500], [0, 0], wd=270, ws=10).flow_map(HorizontalGrid(x=[500], y=np.arange(-100, 100))) plt.plot(flow_map.Y[:, 0], flow_map.TI_eff_xylk[:, 0, 0, 0]) R = windTurbines.diameter() / 2 for name, rotorAvgModel, ref1 in [ ('None', None, 0.22292190804089568), ('RotorCenter', RotorCenter(), 0.22292190804089568), ('RotorGrid100', EqGridRotorAvg(100), 0.1989725533174574), ('RotorGQGrid_4,3', GQGridRotorAvg(4, 3), 0.19874837617113356), ('RotorCGI4', CGIRotorAvg(4), 0.19822024411411204), ('RotorCGI4', CGIRotorAvg(21), 0.1989414764606653)]: # test with PropagateDownwind wfm = IEA37SimpleBastankhahGaussian(site, windTurbines, turbulenceModel=STF2017TurbulenceModel(rotorAvgModel=rotorAvgModel)) sim_res = wfm([0, 500], [0, 0], wd=270, ws=10) npt.assert_almost_equal(sim_res.TI_eff_ilk[1, 0, 0], ref1, err_msg=name) # test with All2AllIterative wfm = All2AllIterative(site, windTurbines, IEA37SimpleBastankhahGaussianDeficit(), turbulenceModel=STF2017TurbulenceModel(rotorAvgModel=rotorAvgModel), superpositionModel=SquaredSum()) sim_res = wfm([0, 500], [0, 0], wd=270, ws=10) npt.assert_almost_equal(sim_res.TI_eff_ilk[1, 0, 0], ref1) plt.plot([-R, R], [sim_res.WS_eff_ilk[1, 0, 0]] * 2, label=name) if 0: plt.legend() plt.show() plt.close()
def test_blockage_map(setup, blockage_model, center_ref, side_ref): site, windTurbines = setup wm = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=blockage_model()) flow_map = wm(x=[0], y=[0], wd=[270], ws=[10]).flow_map() X_j, Y_j = flow_map.XY WS_eff = flow_map.WS_eff_xylk[:, :, 0, 0] if debug: plt.contourf(X_j, Y_j, WS_eff) plt.plot(X_j[190, ::50], Y_j[190, ::50], '.-') plt.plot(X_j[250, ::50], Y_j[250, ::50], '.-') print(list(np.round(np.array(WS_eff[190, ::50]), 6))) print(list(np.round(np.array(WS_eff[250, ::50]), 6))) plt.title(blockage_model.__name__) plt.show() npt.assert_array_almost_equal(WS_eff[190, ::50], center_ref) npt.assert_array_almost_equal(WS_eff[250, ::50], side_ref)
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 get_wfms(wt, site=Hornsrev1Site(), wake_model=NOJDeficit(), superpositionModel=SquaredSum()): wfm1 = PropagateDownwind(site, wt, wake_model, superpositionModel=superpositionModel) wfm2 = All2AllIterative(site, wt, wake_model, superpositionModel=superpositionModel) wfm2.verbose = False wfm1.verbose = False return wfm1, wfm2