def __init__(self, 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 ], mean_wsp=8): UniformSite.__init__(self, p_wd=f, ti=0.1, ws=mean_wsp)
def test_uniform_site_probability(): """check that the uniform site recovers probability""" p_wd = np.array([0.1, 0.2, 0.1, 0.2, 0.1, 0.2, 0.1]) wd_l = np.linspace(0, 360, p_wd.size, endpoint=False) ws_k = np.array([12]) site = UniformSite(p_wd, ti=1) actual = site.probability(0, 0, 0, wd_l[na, :, na], ws_k[na, na], 360 / p_wd.size, None) npt.assert_array_almost_equal(actual.squeeze(), p_wd)
def __init__(self, n_wt, ti=.075, shear=None): assert n_wt in [9, 16, 36, 64] from py_wake.examples.data.iea37.iea37_reader import \ read_iea37_windfarm, read_iea37_windrose _, wsp, freq = read_iea37_windrose(iea37_path + "iea37-windrose.yaml") UniformSite.__init__(self, freq, ti, ws=wsp, shear=shear) self.initial_position = np.array(read_iea37_windfarm(iea37_path + 'iea37-ex%d.yaml' % n_wt)[:2]).T
def test_smart_start_aep_map_PyWakeAEP(): site = IEA37Site(16) n_wt = 4 x, y = site.initial_position[:n_wt].T wd_lst = np.arange(0, 360, 45) ws_lst = [10] turbines = hornsrev1.HornsrevV80() site = UniformSite([1], .75) site.default_ws = ws_lst site.default_wd = wd_lst aep = PyWakeAEP(wake_model=NOJ(site, turbines)) aep_1wt = aep.calculate_AEP([0], [0]).sum() tf = TopFarmProblem(design_vars={ 'x': x, 'y': y }, cost_comp=aep.get_TopFarm_cost_component(n_wt), driver=EasyScipyOptimizeDriver(), constraints=[ SpacingConstraint(160), CircleBoundaryConstraint((0, 0), 500) ]) x = np.arange(-500, 500, 10) y = np.arange(-500, 500, 10) XX, YY = np.meshgrid(x, y) tf.smart_start(XX, YY, aep.get_aep4smart_start(wd=wd_lst, ws=ws_lst), radius=40, seed=1) tf.evaluate() if 0: wt_x, wt_y = tf['x'], tf['y'] for i, _ in enumerate(wt_x, 1): print(aep.calculate_AEP(wt_x[:i], wt_y[:i]).sum((1, 2))) X_j, Y_j, aep_map = aep.aep_map(x, y, 0, wt_x, wt_y, ws=ws_lst, wd=wd_lst) print(tf.evaluate()) import matplotlib.pyplot as plt c = plt.contourf(X_j, Y_j, aep_map, 100) plt.colorbar(c) plt.plot(wt_x, wt_y, '2r') for c in tf.model.constraint_components: c.plot() plt.axis('equal') plt.show() npt.assert_almost_equal(aep_1wt * n_wt, tf['AEP'], 5)
def test_uniform_site_probability(): """check that the uniform site recovers probability""" p_wd = np.array([0.1, 0.2, 0.1, 0.2, 0.1, 0.2, 0.1]) site = UniformSite(p_wd, ti=1) lw = site.local_wind(0, 0, 0, wd=np.linspace(0, 360, p_wd.size, endpoint=False), ws=12) npt.assert_array_almost_equal(lw.P, p_wd)
def test_NOJ_Nibe_result(): # Replicate result from: Jensen, Niels Otto. "A note on wind generator interaction." (1983). wake_model = NOJ(NibeA0) WS_ilk = np.array([[[8.1]], [[8.1]], [[8.1]]]) TI_ilk = np.zeros_like(WS_ilk) site = UniformSite([1], 0.1) dw_iil, cw_iil, dh_iil, dw_order_indices_l = site.wt2wt_distances( x_i=[0, 0, 0], y_i=[0, -40, -100], h_i=[50, 50, 50], wd_il=[[0]]) WS_eff_ilk = wake_model.calc_wake(WS_ilk, TI_ilk, dw_iil, cw_iil, dh_iil, dw_order_indices_l, [0, 1, 1])[0] npt.assert_array_almost_equal(WS_eff_ilk[:, 0, 0], [8.1, 4.35, 5.7])
def __init__(self, n_wt, ti=.75): assert n_wt in [16, 36, 64] from py_wake.examples.data.iea37.iea37_reader import read_iea37_windfarm,\ read_iea37_windrose _, _, freq = read_iea37_windrose(iea37_path + "iea37-windrose.yaml") self.initial_position = np.array( read_iea37_windfarm(iea37_path + 'iea37-ex%d.yaml' % n_wt)[:2]).T UniformSite.__init__(self, freq, ti)
def test_NOJ_two_turbines_in_row(wdir, x, y): # Two turbines in a row, North-South # Replicate result from: Jensen, Niels Otto. "A note on wind generator interaction." (1983). windTurbines = NibeA0 wake_model = NOJ(windTurbines) WS_ilk = np.array([[[8.1]], [[8.1]], [[8.1]]]) TI_ilk = np.zeros_like(WS_ilk) site = UniformSite([1], 0.1) dw_iil, cw_iil, dh_iil, dw_order_indices_l = site.wt2wt_distances(x_i=x, y_i=y, h_i=[50, 50, 50], wd_il=[[wdir]]) WS_eff_ilk = wake_model.calc_wake(WS_ilk, TI_ilk, dw_iil, cw_iil, dh_iil, dw_order_indices_l, [0, 0, 0])[0] ws_wt3 = 8.1 - np.sqrt((8.1 * 2 / 3 * (20 / 26)**2)**2 + (8.1 * 2 / 3 * (20 / 30)**2)**2) npt.assert_array_almost_equal(WS_eff_ilk[:, 0, 0], [8.1, 4.35, ws_wt3])
def test_smart_start_aep_map(seed, radius, resolution, tol): site = IEA37Site(16) n_wt = 4 x, y = site.initial_position[:n_wt].T wd_lst = np.arange(0, 360, 45) ws_lst = [10] turbines = hornsrev1.HornsrevV80() site = UniformSite([1], .75) site.default_ws = ws_lst site.default_wd = wd_lst wfm = NOJ(site, turbines) aep_comp = PyWakeAEPCostModelComponent(wfm, n_wt=n_wt) aep_1wt = wfm([0], [0]).aep().sum() tf = TopFarmProblem(design_vars={ 'x': x, 'y': y }, cost_comp=aep_comp, driver=EasyScipyOptimizeDriver(), constraints=[ SpacingConstraint(160), CircleBoundaryConstraint((0, 0), radius) ]) x = np.arange(-radius, radius, resolution) y = np.arange(-radius, radius, resolution) XX, YY = np.meshgrid(x, y) tf.smart_start(XX, YY, aep_comp.get_aep4smart_start(wd=wd_lst, ws=ws_lst), radius=40, plot=0, seed=seed) tf.evaluate() if 0: wt_x, wt_y = tf['x'], tf['y'] for i, _ in enumerate(wt_x, 1): print(wfm(wt_x[:i], wt_y[:i]).aep().sum(['wd', 'ws'])) aep_comp.windFarmModel(wt_x, wt_y, ws=ws_lst, wd=wd_lst).flow_map().aep_xy().plot() print(tf.evaluate()) import matplotlib.pyplot as plt plt.plot(wt_x, wt_y, '2r') for c in tf.model.constraint_components: c.plot() plt.axis('equal') plt.show() npt.assert_almost_equal(aep_1wt * n_wt, tf['AEP'], tol)
def from_case_dict(name, case_dict): site = UniformSite(p_wd=[1], ti=case_dict['TItot'] / 0.8, ws=case_dict['U0']) site.default_wd = np.linspace(-30, 30, 61) % 360 windTurbines = WindTurbine(name="", diameter=case_dict['D'], hub_height=case_dict['zH'], powerCtFunction=PowerCtFunction( input_keys=['ws'], power_ct_func=lambda ws, run_only, ct=case_dict['CT']: ws * 0 + ct, power_unit='w')) xD = case_dict['xDown'] x = xD * case_dict['sDown'] return SingleWakeValidationCase(name, site, windTurbines, xD, x)
def from_case_dict(name, case_dict): site = UniformSite(p_wd=[1], ti=case_dict['TItot'] / 0.8, ws=case_dict['U0']) site.default_wd = np.linspace(-30, 30, 61) % 360 windTurbines = OneTypeWindTurbines( name="", diameter=case_dict['D'], hub_height=case_dict['zH'], ct_func=lambda ws, ct=case_dict['CT']: ws * 0 + ct, power_func=lambda ws: ws * 0 + 1, power_unit='W') xD = case_dict['xDown'] x = xD * case_dict['sDown'] return SingleWakeValidationCase(name, site, windTurbines, xD, x)
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_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_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 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
def test_interpolation(): wts = HornsrevV80() path = tfp + 'fuga/2MW/Z0=0.00408599Zi=00400Zeta0=0.00E+00/' site = UniformSite([1, 0, 0, 0], ti=0.075) plot = 0 if plot: ax1 = plt.gca() ax2 = plt.twinx() for wdm, n_d_values in ( (FugaDeficit(path, method='linear'), 4), (FugaDeficit(path, method='spline'), 20), (FugaYawDeficit(path, method='linear'), 4), (FugaYawDeficit(path, method='spline'), 20), ): wfm = PropagateDownwind(site, wts, wdm) sim_res = wfm(x=[0], y=[0], wd=[270], ws=[10], yaw=[[[10]]]) fm = sim_res.flow_map(XYGrid(x=[200], y=np.arange(-10, 11))) fm = sim_res.flow_map( XYGrid(x=np.arange(-100, 800, 10), y=np.arange(-10, 11))) # linear has 4 line segments with same gradient, while spline has 20 different gradient values npt.assert_equal( len(np.unique(np.round(np.diff(fm.WS_eff.sel(x=500).squeeze()), 6))), n_d_values) if plot: ax1.plot(fm.y, fm.WS_eff.sel(x=500).squeeze()) ax2.plot(fm.y[:-1], np.diff(fm.WS_eff.sel(x=500).squeeze()), '--') if plot: plt.show() plt.close('all')
def test_fuga_downwind(): wts = HornsrevV80() path = tfp + 'fuga/2MW/Z0=0.00408599Zi=00400Zeta0=0.00E+00' site = UniformSite([1, 0, 0, 0], ti=0.075) wfm_UL = Fuga(path, site, wts) wfm_ULT = PropagateDownwind(site, wts, FugaYawDeficit(path)) (ax1, ax2), (ax3, ax4) = plt.subplots(2, 2)[1] def plot(wfm, yaw, ax, min_ws): levels = np.arange(6.5, 10.5, .5) sim_res = wfm([0], [0], wd=270, ws=10, yaw=[[[yaw]]]) fm = sim_res.flow_map(XYGrid(x=np.arange(-100, 500, 5))) npt.assert_almost_equal(fm.WS_eff.min(), min_ws) fm.plot_wake_map(ax=ax, levels=levels) fm.min_WS_eff(fm.x, 70).plot(ax=ax, color='r') plt.axhline(0, color='k') plot(wfm_UL, 0, ax1, 7.15853738) plot(wfm_UL, 30, ax2, 7.83219266) plot(wfm_ULT, 0, ax3, 7.15853738) plot(wfm_ULT, 30, ax4, 8.12261872) if 0: plt.show() plt.close('all')
def main(): if __name__ == '__main__': from py_wake.examples.data.iea37 import iea37_path from py_wake.examples.data.iea37.iea37_reader import read_iea37_windfarm,\ read_iea37_windrose from py_wake.examples.data.iea37._iea37 import IEA37_WindTurbines from py_wake.site._site import UniformSite from py_wake.aep_calculator import AEPCalculator class MyWakeModel(SquaredSum, WakeModel): args4deficit = ['WS_lk', 'dw_jl'] def calc_deficit(self, WS_lk, dw_jl): # 10% deficit downstream return (WS_lk * .1)[na] * (dw_jl > 0)[:, :, na] _, _, freq = read_iea37_windrose(iea37_path + "iea37-windrose.yaml") n_wt = 16 x, y, _ = read_iea37_windfarm(iea37_path + 'iea37-ex%d.yaml' % n_wt) site = UniformSite(freq, ti=0.75) windTurbines = IEA37_WindTurbines(iea37_path + 'iea37-335mw.yaml') wake_model = MyWakeModel(windTurbines) aep_calculator = AEPCalculator(site, windTurbines, wake_model) import matplotlib.pyplot as plt aep_calculator.plot_wake_map(wt_x=x, wt_y=y, wd=[0, 30], ws=[9], levels=np.linspace(5, 9, 100)) windTurbines.plot(x, y) plt.show()
def test_fuga_downwind_vs_notebook(): powerCtFunction = PowerCtTabular([0, 100], [0, 0], 'w', [0.850877, 0.850877]) wt = WindTurbine(name='', diameter=80, hub_height=70, powerCtFunction=powerCtFunction) path = tfp + 'fuga/2MW/Z0=0.00001000Zi=00400Zeta0=0.00E+00' site = UniformSite([1, 0, 0, 0], ti=0.075) wfm_ULT = PropagateDownwind(site, wt, FugaYawDeficit(path)) WS = 10 p = Path(tfp) / "fuga/v80_wake_4d_y_no_deflection.csv" y, notebook_deficit_4d = np.array( [v.split(",") for v in p.read_text().strip().split("\n")], dtype=float).T sim_res = wfm_ULT([0], [0], wd=270, ws=WS, yaw=[[[17.4493]]]) fm = sim_res.flow_map(XYGrid(4 * wt.diameter(), y=y)) npt.assert_allclose(fm.WS_eff.squeeze() - WS, notebook_deficit_4d, atol=1e-6) if 0: plt.plot(y, notebook_deficit_4d, label='Notebook deficit 4d') plt.plot(y, fm.WS_eff.squeeze() - WS) plt.show() plt.close('all')
def test_wake_model(): _, _, freq = read_iea37_windrose(iea37_path + "iea37-windrose.yaml") site = UniformSite(freq, ti=0.75) windTurbines = IEA37_WindTurbines(iea37_path + 'iea37-335mw.yaml') wake_model = NOJ(windTurbines) aep = AEPCalculator(site, windTurbines, wake_model) with pytest.raises(ValueError, match="Turbines 0 and 1 are at the same position"): aep.calculate_AEP([0, 0], [0, 0], wd=np.arange(0, 360, 22.5), ws=[9.8])
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.75) wake_model = Fuga(path, wts) aep = AEPCalculator(site, wts, wake_model) x_j = np.linspace(-1500, 1500, 500) y_j = np.linspace(-1500, 1500, 300) _, _, Z70 = aep.wake_map(x_j, y_j, 70, wt_x, wt_y, wt_height=70, wd=[30], ws=[10]) X, Y, Z73 = aep.wake_map(x_j, y_j, 73, wt_x, wt_y, wt_height=70, wd=[30], ws=[10]) if 0: import matplotlib.pyplot as plt c = plt.contourf(X, Y, Z70, 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], 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], '.') plt.legend() plt.show() 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_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)
def test_fuga_new_format(): # 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.00014617Zi=00399Zeta0=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.00725165, 10., 7.92176401, 10.02054952, 9.40501317, 7.92609363, 7.52384558 ], 8) npt.assert_array_almost_equal(res.ct_ilk.flatten(), [ 0.79260841, 0.793, 0.80592176, 0.79189033, 0.80132982, 0.80592609, 0.80552385 ], 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.values[140, 100:400:10], 4))) print(list(np.round(Z73.values[140, 100:400:10], 4))) plt.legend() plt.show() npt.assert_array_almost_equal(Z70[140, 100:400:10], [ 10.0458, 10.0309, 10.065, 10.0374, 9.7865, 7.7119, 6.4956, 9.2753, 10.0047, 10.0689, 10.0444, 10.0752, 10.0699, 9.1852, 6.9783, 9.152, 10.0707, 10.0477, 10.0365, 9.9884, 9.2867, 7.5714, 6.4451, 8.3276, 9.9976, 10.0251, 10.0264, 10.023, 10.0154, 9.9996 ], 4) npt.assert_array_almost_equal(Z73[140, 100:400:10], [ 10.0458, 10.0309, 10.065, 10.0374, 9.7865, 7.7119, 6.4956, 9.2753, 10.0047, 10.0689, 10.0444, 10.0752, 10.0699, 9.1852, 6.9783, 9.152, 10.0707, 10.0477, 10.0365, 9.9884, 9.2867, 7.5714, 6.4451, 8.3276, 9.9976, 10.0251, 10.0264, 10.023, 10.0154, 9.9996 ], 4)
def test_fuga_new_format(): # 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.00408599Zi=00400Zeta0=0.00E+00/' 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.00647891, 10., 8.21713928, 10.03038884, 9.36889964, 8.23084088, 7.80662141 ], 8) npt.assert_array_almost_equal(res.ct_ilk.flatten(), [ 0.79265014, 0.793, 0.80621714, 0.791359, 0.80183541, 0.80623084, 0.80580662 ], 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.values[140, 100:400:10], 4))) print(list(np.round(Z73.values[140, 100:400:10], 4))) plt.legend() plt.show() npt.assert_array_almost_equal(Z70[140, 100:400:10], [ 10.0384, 10.042, 10.044, 10.0253, 9.7194, 7.7561, 6.7421, 9.2308, 9.9894, 10.0413, 10.0499, 10.0579, 10.0437, 9.1626, 7.2334, 9.1208, 10.0396, 10.0322, 10.0276, 9.9504, 9.2861, 7.8375, 6.6608, 8.3343, 9.9756, 10.0229, 10.0136, 10.0142, 10.0118, 10.0094 ], 4) npt.assert_array_almost_equal(Z73[140, 100:400:10], [ 10.0384, 10.042, 10.044, 10.0253, 9.7194, 7.7561, 6.7421, 9.2308, 9.9894, 10.0413, 10.0499, 10.0579, 10.0437, 9.1626, 7.2334, 9.1208, 10.0396, 10.0322, 10.0276, 9.9504, 9.2861, 7.8375, 6.6608, 8.3343, 9.9756, 10.0229, 10.0136, 10.0142, 10.0118, 10.0094 ], 4)
def test_aep(): site = UniformSite([1], ti=0) windTurbines = IEA37_WindTurbines() wake_model = NOJ(site, windTurbines) sim_res = wake_model([0], [0], wd=270) npt.assert_almost_equal(sim_res.aep(), 3.35 * 24 * 365 / 360 / 1000) npt.assert_almost_equal(sim_res.aep(normalize_probabilities=True), 3.35 * 24 * 365 / 1000)
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) x_j = np.linspace(-1500, 1500, 500) y_j = np.linspace(-1500, 1500, 300) flow_map_wec1 = wake_model(wt_x, wt_y, 70, wd=[30], ws=[10]).flow_map(HorizontalGrid(x_j, y_j)) Z_wec1 = flow_map_wec1.WS_eff_xylk[:, :, 0, 0] wake_model.wec = 2 flow_map_wec2 = wake_model(wt_x, wt_y, 70, wd=[30], ws=[10]).flow_map(HorizontalGrid(x_j, y_j)) X, Y = flow_map_wec1.XY Z_wec2 = flow_map_wec2.WS_eff_xylk[:, :, 0, 0] if 0: print(list(np.round(Z_wec1[140, 100:400:10].values, 4))) print(list(np.round(Z_wec2[140, 100:400:10].values, 4))) flow_map_wec1.plot_wake_map(levels=np.arange(6, 10.5, .1), plot_colorbar=False) plt.plot(X[0], Y[140]) wts.plot(wt_x, wt_y) plt.figure() c = flow_map_wec2.plot_wake_map(levels=np.arange(6, 10.5, .1), plot_colorbar=False) 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.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(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)
def test_NOJ_Nibe_result(): # Replicate result from: Jensen, Niels Otto. "A note on wind generator interaction." (1983). site = UniformSite([1], 0.1) wake_model = NOJ(site, NibeA0) x_i = [0, 0, 0] y_i = [0, -40, -100] h_i = [50, 50, 50] WS_eff_ilk = wake_model.calc_wake(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 cmp_fuga_with_colonel(): # 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() xy, Z = [ v for _, v in np.load(tfp + "fuga/U_XY_70m_.txt_30deg.npz").items() ] x_min, x_max, x_step, y_min, y_max, y_step = xy x_j = np.arange( x_min, np.round((x_max - x_min) / x_step) * x_step + x_min + x_step, x_step) y_j = np.arange( y_min, np.round((y_max - y_min) / y_step) * y_step + y_min + y_step, y_step) path = tfp + 'fuga/2MW/Z0=0.03000000Zi=00401Zeta0=0.00E+0/' site = UniformSite([1, 0, 0, 0], ti=0.75) wake_model = Fuga(path, wts) aep = AEPCalculator(site, wts, wake_model) X, Y, Z2 = aep.wake_map(x_j, y_j, 70, wt_x, wt_y, h_i=70, wd=[30], ws=[10]) print(x_j) print(y_j) m = (X == 500) & (Y == -880) print(Z[m]) print(Z2[m]) if 1: import matplotlib.pyplot as plt plt.clf() c = plt.contourf(X, Y, Z, np.arange(6, 10.5, .1)) plt.colorbar(c, label="m/s") plt.axis('equal') plt.tight_layout() wts.plot(wt_x, wt_y) plt.figure() c = plt.contourf(X, Y, Z2, np.arange(6, 10.5, .1)) plt.colorbar(c) wts.plot(wt_x, wt_y) plt.figure() c = plt.contourf(X, Y, Z2 - Z, np.arange(-.01, .01, .001)) plt.colorbar(c, label="m/s") wts.plot(wt_x, wt_y) plt.show() npt.assert_array_almost_equal(Z, Z2, 2)
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) wfm = BastankhahGaussian(site, wts) x_j = np.linspace(-1500, 1500, 500) y_j = np.linspace(-1500, 1500, 300) flow_map_wec1 = wfm(wt_x, wt_y, 70, wd=[30], ws=[10]).flow_map(HorizontalGrid(x_j, y_j)) Z_wec1 = flow_map_wec1.WS_eff_xylk[:, :, 0, 0] wfm.wec = 2 flow_map_wec2 = wfm(wt_x, wt_y, 70, wd=[30], ws=[10]).flow_map(HorizontalGrid(x_j, y_j)) X, Y = flow_map_wec1.XY Z_wec2 = flow_map_wec2.WS_eff_xylk[:, :, 0, 0] if 0: print(list(np.round(Z_wec1[140, 100:400:10].values, 2))) print(list(np.round(Z_wec2[140, 100:400:10].values, 2))) flow_map_wec1.plot_wake_map(levels=np.arange(6, 10.5, .1), plot_colorbar=False) plt.plot(X[0], Y[140]) wts.plot(wt_x, wt_y) plt.figure() c = flow_map_wec2.plot_wake_map(levels=np.arange(6, 10.5, .1), plot_colorbar=False) 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.0, 10.0, 10.0, 9.99, 9.8, 6.52, 1.47, 9.44, 9.98, 10.0, 10.0, 10.0, 10.0, 9.05, 0.03, 9.11, 10.0, 10.0, 10.0, 9.97, 9.25, 7.03, 2.35, 6.51, 9.99, 10.0, 10.0, 10.0, 10.0, 10.0 ], 2) npt.assert_array_almost_equal(Z_wec2[140, 100:400:10], [ 9.99, 9.96, 9.84, 9.47, 7.82, 2.24, 0.21, 6.21, 9.22, 9.82, 9.98, 9.92, 9.05, 4.45, 0.01, 4.53, 9.35, 9.95, 9.75, 9.13, 7.92, 5.14, 0.32, 2.2, 8.38, 9.94, 10.0, 10.0, 10.0, 10.0 ], 2)
def test_aep_map_no_turbines(): _, _, freq = read_iea37_windrose(iea37_path + "iea37-windrose.yaml") site = UniformSite(freq, ti=0.075) windTurbines = IEA37_WindTurbines(iea37_path + 'iea37-335mw.yaml') wake_model = IEA37SimpleBastankhahGaussian(site, windTurbines) aep = AEPCalculator(wake_model) x_j = np.arange(-150, 150, 20) y_j = np.arange(-250, 250, 20) X, Y, Z = aep.aep_map(x_j, y_j, 0, [], [], wd=[0]) expect = (3.35 * 1e6) * 24 * 365 * (1e-9) npt.assert_array_almost_equal(Z, expect, 2)