def test_with_all_deficit_models(WFM, deficitModel): site = IEA37Site(16) windTurbines = IEA37_WindTurbines() wfm = WFM(site, windTurbines, wake_deficitModel=deficitModel, rotorAvgModel=RotorCenter(), superpositionModel=LinearSum(), deflectionModel=None, turbulenceModel=STF2017TurbulenceModel()) wfm2 = WFM(site, windTurbines, wake_deficitModel=deficitModel, rotorAvgModel=EqGridRotorAvg(1), superpositionModel=LinearSum(), deflectionModel=None, turbulenceModel=STF2017TurbulenceModel()) kwargs = { 'x': [0, 0, 500, 500], 'y': [0, 500, 0, 500], 'wd': [0], 'ws': [8] } npt.assert_equal(wfm.aep(**kwargs), wfm2.aep(**kwargs))
def main(): if __name__ == '__main__': from py_wake.examples.data.iea37._iea37 import IEA37Site from py_wake.examples.data.iea37._iea37 import IEA37_WindTurbines from py_wake.superposition_models import LinearSum from py_wake.wind_farm_models import All2AllIterative from py_wake.deficit_models.no_wake import NoWakeDeficit from py_wake.deficit_models.vortexcylinder import VortexCylinder from py_wake.deficit_models.vortexdipole import VortexDipole import matplotlib.pyplot as plt from py_wake import HorizontalGrid from timeit import default_timer as timer # setup site, turbines and wind farm model site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() d = windTurbines.diameter() ra = Rathmann() grid = HorizontalGrid(x=np.linspace(-6, 6, 100) * d, y=np.linspace(0, 4, 100) * d) noj_ra = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=ra) noj_vc = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=VortexCylinder()) noj_vd = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=VortexDipole()) t1 = timer() flow_map = noj_ra(x=[0], y=[0], wd=[270], ws=[10]).flow_map(grid=grid) t2 = timer() flow_map_vc = noj_vc(x=[0], y=[0], wd=[270], ws=[10]).flow_map(grid=grid) t3 = timer() flow_map_vd = noj_vd(x=[0], y=[0], wd=[270], ws=[10]).flow_map(grid=grid) t4 = timer() print(t2 - t1, t3 - t2, t4 - t3) plt.figure() clevels = np.array([.6, .7, .8, .9, .95, .98, .99, .995, .998, .999, 1., 1.005, 1.01, 1.02, 1.05]) * 10. flow_map.plot_wake_map(levels=clevels) plt.contour(flow_map.x, flow_map.y, flow_map.WS_eff[:, :, 0, -1, 0], levels=clevels, colors='k', linewidths=1) plt.contour(flow_map.x, flow_map.y, flow_map_vc.WS_eff[:, :, 0, -1, 0], levels=clevels, colors='r', linewidths=1, linestyles='dashed') plt.contour(flow_map.x, flow_map.y, flow_map_vd.WS_eff[:, :, 0, -1, 0], levels=clevels, colors='b', linewidths=1, linestyles='dotted') plt.title('Rathmann') plt.ylabel("Crosswind distance [y/R]") plt.xlabel("Downwind distance [x/R]") plt.show() # run wind farm simulation sim_res = noj_ra(x, y, wd=[0, 30, 45, 60, 90], ws=[5, 10, 15]) # calculate AEP aep = sim_res.aep().sum() # plot wake map plt.figure() print(noj_ra) flow_map = sim_res.flow_map(wd=0, ws=10) flow_map.plot_wake_map(levels=clevels, plot_colorbar=False) plt.title('Rathmann model, AEP: %.3f GWh' % aep) plt.show()
def test_with_all_turbulence_models(WFM, turbulenceModel): site = IEA37Site(16) windTurbines = IEA37_WindTurbines() wfm = WFM(site, windTurbines, wake_deficitModel=NoWakeDeficit(), rotorAvgModel=CGIRotorAvg(4), superpositionModel=LinearSum(), turbulenceModel=turbulenceModel()) wfm2 = WFM(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), turbulenceModel=turbulenceModel(rotorAvgModel=CGIRotorAvg(4))) kwargs = {'x': [0, 0, 500, 500], 'y': [0, 500, 0, 500], 'wd': [0], 'ws': [8]} npt.assert_array_equal(wfm(**kwargs).TI_eff, wfm2(**kwargs).TI_eff, turbulenceModel.__name__)
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_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_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 __init__(self, LUT_path, site, windTurbines, rotorAvgModel=RotorCenter(), deflectionModel=None, turbulenceModel=None): """ 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 """ PropagateDownwind.__init__(self, site, windTurbines, wake_deficitModel=FugaDeficit(LUT_path), rotorAvgModel=rotorAvgModel, superpositionModel=LinearSum(), deflectionModel=deflectionModel, turbulenceModel=turbulenceModel)
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 __init__(self, c=[1.5, 0.8], addedTurbulenceSuperpositionModel=LinearSum(), weight_function=FrandsenWeight(), **kwargs): TurbulenceModel.__init__(self, addedTurbulenceSuperpositionModel, **kwargs) self.c = c self.apply_weight = weight_function.apply_weight
def main(): if __name__ == '__main__': import matplotlib.pyplot as plt from py_wake.examples.data.hornsrev1 import Hornsrev1Site from py_wake.examples.data import hornsrev1 from py_wake.superposition_models import LinearSum from py_wake.wind_farm_models import All2AllIterative site = Hornsrev1Site() windTurbines = hornsrev1.HornsrevV80() ws = 10 D = 80 R = D / 2 WS_ilk = np.array([[[ws]]]) D_src_il = np.array([[D]]) ct_ilk = np.array([[[.8]]]) ss = SelfSimilarityDeficit() x, y = -np.arange(200), np.array([0]) deficit = ss.calc_deficit(WS_ilk=WS_ilk, D_src_il=D_src_il, dw_ijlk=x.reshape((1, len(x), 1, 1)), cw_ijlk=y.reshape((1, len(y), 1, 1)), ct_ilk=ct_ilk) plt.title('Fig 11 from [1]') plt.xlabel('x/R') plt.ylabel('a') plt.plot(x / R, deficit[0, :, 0, 0] / ws) plt.figure() x, y = np.array([-2 * R]), np.arange(200) deficit = ss.calc_deficit(WS_ilk=WS_ilk, D_src_il=D_src_il, dw_ijlk=x.reshape((1, len(x), 1, 1)), cw_ijlk=y.reshape((1, len(y), 1, 1)), ct_ilk=ct_ilk) plt.title('Fig 10 from [1]') r12 = np.sqrt(ss.lambda_ * (ss.eta + (x / R)**2)) # Eq. (13) from [1] print(x, r12) plt.xlabel('y/R12 (epsilon)') plt.ylabel('f') plt.plot((y / R) / r12, deficit[0, :, 0, 0] / deficit[0, 0, 0, 0]) plt.figure() noj_ss = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=ss) flow_map = noj_ss(x=[0], y=[0], wd=[270], ws=[10]).flow_map() flow_map.plot_wake_map() flow_map.plot_windturbines() plt.show()
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_neighbour_farm_speed(): # import and setup site and windTurbines site = IEA37Site(16) # setup current, neighbour and all positions wt_x, wt_y = site.initial_position.T neighbour_x, neighbour_y = wt_x - 4000, wt_y all_x, all_y = np.r_[wt_x, neighbour_x], np.r_[wt_y, neighbour_y] windTurbines = WindTurbines.from_WindTurbines([IEA37_WindTurbines(), IEA37_WindTurbines()]) windTurbines._names = ["Current wind farm", "Neighbour wind farm"] types = [0] * len(wt_x) + [1] * len(neighbour_x) wf_model = PropagateDownwind(site, windTurbines, wake_deficitModel=BastankhahGaussianDeficit(use_effective_ws=True), superpositionModel=LinearSum()) # Consider wd=270 +/- 30 deg only wd_lst = np.arange(240, 301) sim_res, t = timeit(wf_model, verbose=False)(all_x, all_y, type=types, ws=9.8, wd=wd_lst) if 1: ext = 100 flow_box = wf_model(neighbour_x, neighbour_y, wd=wd_lst).flow_box( x=np.linspace(min(wt_x) - ext, max(wt_x) + ext, 53), y=np.linspace(min(wt_y) - ext, max(wt_y) + ext, 51), h=[100, 110, 120]) wake_site = XRSite.from_flow_box(flow_box) wake_site.save('tmp.nc') else: wake_site = XRSite.load('tmp.nc') wf_model_wake_site = PropagateDownwind(wake_site, windTurbines, wake_deficitModel=BastankhahGaussianDeficit(use_effective_ws=True), superpositionModel=LinearSum()) sim_res_wake_site, _ = timeit(wf_model_wake_site, verbose=False)(wt_x, wt_y, ws=9.8, wd=wd_lst) npt.assert_allclose(sim_res.aep().sel(wt=np.arange(len(wt_x))).sum(), sim_res_wake_site.aep().sum(), rtol=0.0005) npt.assert_array_almost_equal(sim_res.aep().sel(wt=np.arange(len(wt_x))), sim_res_wake_site.aep(), 2)
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 __init__(self, site, windTurbines, wake_deficitModel, rotorAvgModel=RotorCenter(), superpositionModel=LinearSum(), blockage_deficitModel=None, deflectionModel=None, turbulenceModel=None, groundModel=None, convergence_tolerance=1e-6): """Initialize flow model Parameters ---------- site : Site Site object windTurbines : WindTurbines WindTurbines object representing the wake generating wind turbines wake_deficitModel : DeficitModel Model describing the wake(downstream) deficit 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 superpositionModel : SuperpositionModel Model defining how deficits sum up blockage_deficitModel : DeficitModel Model describing the blockage(upstream) deficit 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 convergence_tolerance : float maximum accepted change in WS_eff_ilk [m/s] """ EngineeringWindFarmModel.__init__( self, site, windTurbines, wake_deficitModel, rotorAvgModel, superpositionModel, blockage_deficitModel=blockage_deficitModel, deflectionModel=deflectionModel, turbulenceModel=turbulenceModel, groundModel=groundModel) self.convergence_tolerance = convergence_tolerance
def __init__(self, site, windTurbines, rotorAvgModel=RotorCenter(), superpositionModel=LinearSum(), deflectionModel=None, turbulenceModel=None, groundModel=None): PropagateDownwind.__init__(self, site, windTurbines, wake_deficitModel=GCLDeficit(), rotorAvgModel=rotorAvgModel, superpositionModel=superpositionModel, deflectionModel=deflectionModel, turbulenceModel=turbulenceModel, groundModel=groundModel)
def main(): if __name__ == '__main__': from py_wake.examples.data.iea37._iea37 import IEA37Site from py_wake.examples.data.iea37._iea37 import IEA37_WindTurbines from py_wake.superposition_models import LinearSum from py_wake.wind_farm_models import All2AllIterative from py_wake.deficit_models.no_wake import NoWakeDeficit import matplotlib.pyplot as plt # setup site, turbines and wind farm model site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() hi = HybridInduction() plt.figure() noj_hi = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=hi) flow_map = noj_hi(x=[0], y=[0], wd=[270], ws=[10]).flow_map() clevels = np.array([ .6, .7, .8, .9, .95, .98, .99, .995, .998, .999, 1., 1.01, 1.02 ]) * 10. flow_map.plot_wake_map(levels=clevels) plt.title('Vortex Dipole (far-field) + Self-Similar (near-rotor)') plt.ylabel("Crosswind distance [y/R]") plt.xlabel("Downwind distance [x/R]") plt.show() # run wind farm simulation sim_res = noj_hi(x, y, wd=[0, 30, 45, 60, 90], ws=[5, 10, 15]) # calculate AEP aep = sim_res.aep().sum() # plot wake map plt.figure() print(noj_hi) flow_map = sim_res.flow_map(wd=0, ws=10) flow_map.plot_wake_map(levels=clevels, plot_colorbar=False) plt.title( 'Vortex Dipole (far-field) + Self-Similar (near-rotor), AEP: %.3f GWh' % aep) plt.show()
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_aep_two_turbines(setup): site, windTurbines, ss = setup nwm_ss = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), blockage_deficitModel=ss, 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, 0.4896853) if 0: plt.plot(sim_res.WS_eff_ilk[:, :, 7].T) plt.show()
def __init__(self, site, windTurbines, wake_deficitModel, rotorAvgModel=RotorCenter(), superpositionModel=LinearSum(), deflectionModel=None, turbulenceModel=None, groundModel=None): """Initialize flow model Parameters ---------- site : Site Site object windTurbines : WindTurbines WindTurbines object representing the wake generating wind turbines wake_deficitModel : DeficitModel Model describing the wake(downstream) deficit rotorAvgModel : RotorAvgModel, optional Model defining one or more points at the down stream rotors to calculate the rotor average wind speeds from. Default is RotorCenter, i.e. one point at rotor center superpositionModel : SuperpositionModel Model defining how deficits sum up 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 """ EngineeringWindFarmModel.__init__(self, site, windTurbines, wake_deficitModel, rotorAvgModel, superpositionModel, blockage_deficitModel=None, deflectionModel=deflectionModel, turbulenceModel=turbulenceModel, groundModel=groundModel)
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 pywake_run(blockage_models): grid = HorizontalGrid(x=np.linspace(-10 * d, 10 * d, 100), y=np.linspace(-15, 2 * d, 100)) res = {} out = {} for nam, blockage_model in blockage_models: print(nam, blockage_model) # for dum, rotor_avg_model in rotor_avg_models: wm = All2AllIterative(site, wt, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=blockage_model, rotorAvgModel=RotorCenter()) res[nam] = wm(wt_x, wt_y, wd=[180., 195., 210., 225.], ws=[1.]) tic = time.perf_counter() flow_map = res[nam].flow_map(grid=grid, ws=[1.], wd=225.) toc = time.perf_counter() elapsed_time = toc - tic out[nam] = flow_map['WS_eff'] / flow_map['WS'] out[nam]['time'] = elapsed_time return out, res
def __init__(self, site, windTurbines, rotorAvgModel=RotorCenter(), a=[0.38, 4e-3], use_effective_ws=True, superpositionModel=LinearSum(), deflectionModel=None, turbulenceModel=STF2017TurbulenceModel()): """ Parameters ---------- site : Site Site object windTurbines : WindTurbines WindTurbines object representing the wake generating wind turbines k : float, default 0.1 wake expansion factor superpositionModel : SuperpositionModel, default SquaredSum Model defining how deficits sum up blockage_deficitModel : DeficitModel, default None Model describing the blockage(upstream) deficit deflectionModel : DeflectionModel, default None Model describing the deflection of the wake due to yaw misalignment, sheared inflow, etc. turbulenceModel : TurbulenceModel, default None Model describing the amount of added turbulence in the wake """ PropagateDownwind.__init__(self, site, windTurbines, wake_deficitModel=NOJLocalDeficit( a=a, use_effective_ws=use_effective_ws), rotorAvgModel=rotorAvgModel, superpositionModel=superpositionModel, deflectionModel=deflectionModel, turbulenceModel=turbulenceModel)
def __init__(self, LUT_path, site, windTurbines, deflectionModel=None, turbulenceModel=None): """ 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 """ PropagateDownwind.__init__(self, site, windTurbines, wake_deficitModel=FugaDeficit(LUT_path), superpositionModel=LinearSum(), deflectionModel=deflectionModel, turbulenceModel=turbulenceModel)
from py_wake.site._site import UniformSite from py_wake.superposition_models import LinearSum, SquaredSum, MaxSum from py_wake.tests import npt from py_wake.wind_turbines import WindTurbines # Two turbines, 0: Nibe-A, 1:Ct=0 NibeA0 = WindTurbines(names=['Nibe-A'] * 2, diameters=[40] * 2, hub_heights=[50] * 2, ct_funcs=[lambda _: 8 / 9, lambda _: 0], power_funcs=[lambda _: 0] * 2, power_unit='w') d02 = 8.1 - 5.7 d12 = 8.1 - 4.90473373 @pytest.mark.parametrize('superpositionModel,res', [(LinearSum(), 8.1 - (d02 + d12)), (SquaredSum(), 8.1 - np.hypot(d02, d12)), (MaxSum(), 8.1 - d12)]) def test_superposition_models(superpositionModel, res): site = UniformSite([1], 0.1) wake_model = NOJ(site, NibeA0, superpositionModel=superpositionModel) x_i = [0, 0, 0] y_i = [0, -40, -100] h_i = [50, 50, 50] WS_eff_ilk = wake_model.calc_wt_interaction(x_i, y_i, h_i, [0, 0, 1], 0.0, 8.1)[0] npt.assert_array_almost_equal(WS_eff_ilk[-1, 0, 0], res)
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) @pytest.mark.parametrize('wfm_cls', [PropagateDownwind, All2AllIterative]) @pytest.mark.parametrize('groundModel,superpositionModel', [(Mirror(), LinearSum()), (MirrorSquaredSum(), SquaredSum())]) 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),
from py_wake import NOJ from py_wake.site._site import UniformSite from py_wake.superposition_models import LinearSum, SquaredSum, MaxSum from py_wake.tests import npt from py_wake.wind_farm_models.engineering_models import PropagateDownwind, All2AllIterative from py_wake.deficit_models.noj import NOJDeficit from py_wake.flow_map import HorizontalGrid from py_wake.tests.test_deficit_models.test_noj import NibeA0 import xarray as xr d02 = 8.1 - 5.7 d12 = 8.1 - 4.90473373 @pytest.mark.parametrize('superpositionModel,res', [(LinearSum(), 8.1 - (d02 + d12)), (SquaredSum(), 8.1 - np.hypot(d02, d12)), (MaxSum(), 8.1 - d12)]) def test_superposition_models(superpositionModel, res): site = UniformSite([1], 0.1) wake_model = NOJ(site, NibeA0, superpositionModel=superpositionModel) x_i = [0, 0, 0] y_i = [0, -40, -100] h_i = [50, 50, 50] WS_eff_ilk = wake_model.calc_wt_interaction(x_i, y_i, h_i, [0, 0, 1], 0.0, 8.1)[0] npt.assert_array_almost_equal(WS_eff_ilk[-1, 0, 0], res) @pytest.mark.parametrize('superpositionModel,sum_func', [(LinearSum(), np.sum),
turbulenceModel=turbulenceModel) if __name__ == '__main__': from py_wake.examples.data.iea37._iea37 import IEA37Site from py_wake.examples.data.iea37._iea37 import IEA37_WindTurbines import matplotlib.pyplot as plt # setup site, turbines and wind farm model site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() wf_model_ss = NOJ(site, windTurbines, k=0.05, superpositionModel=SquaredSum()) print(wf_model_ss) wf_model_ls = NOJ(site, windTurbines, k=0.05, superpositionModel=LinearSum()) print(wf_model_ls) wf_model_ms = NOJ(site, windTurbines, k=0.05, superpositionModel=MaxSum()) print(wf_model_ms) # run wind farm simulation sim_res_ss = wf_model_ss(x, y) # return SimulationResult(self, localWind=localWind, # x_i=x, y_i=y, h_i=h, type_i=type, yaw_ilk=yaw_ilk, # wd=wd, ws=ws, # WS_eff_ilk=WS_eff_ilk, TI_eff_ilk=TI_eff_ilk, # power_ilk=power_ilk, ct_ilk=ct_ilk) sim_res_ls = wf_model_ls(x, y) sim_res_ms = wf_model_ms(x, y) # calculate AEP
def main(): if __name__ == '__main__': from py_wake.examples.data.iea37._iea37 import IEA37Site from py_wake.examples.data.iea37._iea37 import IEA37_WindTurbines from py_wake.site._site import UniformSite from py_wake.wind_turbines import OneTypeWindTurbines from py_wake.superposition_models import LinearSum from py_wake.wind_farm_models import All2AllIterative from py_wake.deficit_models.no_wake import NoWakeDeficit from py_wake.rotor_avg_models import RotorCenter from py_wake.deficit_models.vortexcylinder import VortexCylinder from py_wake.deficit_models.vortexdipole import VortexDipole import matplotlib.pyplot as plt from py_wake import HorizontalGrid from timeit import default_timer as timer import time # setup site, turbines and wind farm model site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() d = windTurbines.diameter() ra = Rathmann() ras = RathmannScaled() grid = HorizontalGrid(x=np.linspace(-6, 6, 100) * d, y=np.linspace(0, 4, 100) * d) noj_ra = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=ra) noj_ras = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=ras) noj_vc = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=VortexCylinder()) noj_vd = All2AllIterative(site, windTurbines, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=VortexDipole()) t1 = timer() flow_map = noj_ra(x=[0], y=[0], wd=[270], ws=[10]).flow_map(grid=grid) t2 = timer() flow_map_ras = noj_ras(x=[0], y=[0], wd=[270], ws=[10]).flow_map(grid=grid) t3 = timer() flow_map_vc = noj_vc(x=[0], y=[0], wd=[270], ws=[10]).flow_map(grid=grid) t4 = timer() flow_map_vd = noj_vd(x=[0], y=[0], wd=[270], ws=[10]).flow_map(grid=grid) t5 = timer() print(t2 - t1, t3 - t2, t4 - t3, t5 - t4) plt.figure() clevels = np.array([ .6, .7, .8, .9, .95, .98, .99, .995, .998, .999, 1., 1.005, 1.01, 1.02, 1.05 ]) * 10. flow_map.plot_wake_map(levels=clevels) plt.contour(flow_map.x, flow_map.y, flow_map.WS_eff[:, :, 0, -1, 0], levels=clevels, colors='k', linewidths=1) plt.contour(flow_map.x, flow_map.y, flow_map_ras.WS_eff[:, :, 0, -1, 0], levels=clevels, colors='g', linewidths=1, linestyles='dashed') plt.contour(flow_map.x, flow_map.y, flow_map_vc.WS_eff[:, :, 0, -1, 0], levels=clevels, colors='r', linewidths=1, linestyles='dashed') plt.contour(flow_map.x, flow_map.y, flow_map_vd.WS_eff[:, :, 0, -1, 0], levels=clevels, colors='b', linewidths=1, linestyles='dotted') plt.plot([0, 0], [0, 0], 'k-', label='Rathmann') plt.plot([0, 0], [0, 0], 'g--', label='scaled Rathmann') plt.plot([0, 0], [0, 0], 'r--', label='vortex cylinder') plt.plot([0, 0], [0, 0], 'b:', label='vortex dipole') plt.title('Rathmann') plt.ylabel("Crosswind distance [y/R]") plt.xlabel("Downwind distance [x/R]") plt.legend() plt.show() # run wind farm simulation sim_res = noj_ra(x, y, wd=[0, 30, 45, 60, 90], ws=[5, 10, 15]) # calculate AEP aep = sim_res.aep().sum() # plot wake map plt.figure() print(noj_ra) flow_map = sim_res.flow_map(wd=0, ws=10) flow_map.plot_wake_map(levels=clevels, plot_colorbar=False) plt.title('Rathmann model, AEP: %.3f GWh' % aep) plt.show() # run wind farm simulation sim_res = noj_ras(x, y, wd=[0, 30, 45, 60, 90], ws=[5, 10, 15]) # calculate AEP aep = sim_res.aep().sum() # plot wake map plt.figure() print(noj_ras) flow_map = sim_res.flow_map(wd=0, ws=10) flow_map.plot_wake_map(levels=clevels, plot_colorbar=False) plt.title('Rathmann model, AEP: %.3f GWh' % aep) plt.show() class epfl_model_wt(OneTypeWindTurbines): def __init__(self): OneTypeWindTurbines.__init__(self, 'NREL 5MW', diameter=2, hub_height=1, ct_func=self._ct, power_func=self._power, power_unit='W') def _ct(self, u): ct = 0.798 return ct * u / u def _power(self, u): cp = 0.5 A = np.pi rho = 1.225 return 0.5 * rho * u**3 * A * cp wt = epfl_model_wt() d = wt.diameter() h = wt.hub_height() wt_x = np.array([-6. * d, -3. * d, 0. * d, 3. * d, 6. * d]) wt_y = np.array([0., 0., 0., 0., 0.]) class epfl_wt(UniformSite): def __init__(self): p_wd = [1] ws = [1] ti = [0.06] UniformSite.__init__(self, p_wd=p_wd, ti=ti, ws=ws) self.initial_position = np.array([wt_x, wt_y]).T site = epfl_wt() blockage_models = [('Rathmann', Rathmann()), ('RathmannScaled', RathmannScaled())] def pywake_run(blockage_models): grid = HorizontalGrid(x=np.linspace(-10 * d, 10 * d, 100), y=np.linspace(-15, 2 * d, 100)) res = {} out = {} for nam, blockage_model in blockage_models: print(nam, blockage_model) # for dum, rotor_avg_model in rotor_avg_models: wm = All2AllIterative(site, wt, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), blockage_deficitModel=blockage_model, rotorAvgModel=RotorCenter()) res[nam] = wm(wt_x, wt_y, wd=[180., 195., 210., 225.], ws=[1.]) tic = time.perf_counter() flow_map = res[nam].flow_map(grid=grid, ws=[1.], wd=225.) toc = time.perf_counter() elapsed_time = toc - tic out[nam] = flow_map['WS_eff'] / flow_map['WS'] out[nam]['time'] = elapsed_time return out, res out, res = pywake_run(blockage_models) # CFD data from Meyer Forsting et al. 2017 p_cfd = np.array([[ -1.12511646713429, 0.268977884040651, 0.712062872514373, 1.08033923355738, 1.97378837188847 ], [ -0.610410399845213, 0.355339771667814, 0.670255435929930, 0.915154608331424, 1.52808830519513 ], [ -0.0988002822865217, 0.451698279664756, 0.636987630794206, 0.751760283763044, 1.03629687168984 ], [ 0.477918399858401, 0.628396438496795, 0.663799054750132, 0.628396438496795, 0.479688468006036 ]]) plt.figure() lines = ['.-', 'o--', '^', '-.', '.-', '.-'] theta = [0, 15, 30, 45] viridis = plt.cm.viridis(np.linspace(0, 0.9, 5)) jj = 0 tno = np.arange(1, 6, 1) for i in range(4): ii = len(theta) - i - 1 plt.plot(tno, ((p_cfd[ii, :] / 100. + 1.) / (p_cfd[ii, 0] / 100. + 1.) - 1.) * 100, 's:', color=viridis[i], label='CFD: ' + str(theta[i]) + 'deg', lw=2) for nam, blockage_model in blockage_models: for i in range(4): if i == 3: plt.plot( tno, (res[nam].Power[:, i, 0] - res[nam].Power[0, i, 0]) / res[nam].Power[0, i, 0] * 100, lines[jj], label=nam, color=viridis[i], lw=1, alpha=0.8) else: plt.plot( tno, (res[nam].Power[:, i, 0] - res[nam].Power[0, i, 0]) / res[nam].Power[0, i, 0] * 100, lines[jj], color=viridis[i], lw=1, alpha=0.8) jj += 1 plt.grid(alpha=0.2) plt.xlabel('Turbine no.') plt.ylabel('Power change, $(P-P_1)/P_1$ [%]') plt.xticks([0, 1, 2, 3, 4, 5]) plt.xlim([.9, 5.1]) plt.legend(fontsize=11) plt.show()
def get_wf_model(cls): return cls(site, NibeA0, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), turbulenceModel=STF2017TurbulenceModel())
def test_check_model(): check_model(LinearSum(), SuperpositionModel)