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 power_curve = hornsrev1.power_curve wts = WindTurbines(names=['V80', 'V88'], diameters=[80, 88], hub_heights=[70, 77], ct_funcs=[v80.ct_funcs[0], v80.ct_funcs[0]], power_funcs=[lambda ws, yaw: np.interp(ws, power_curve[:, 0], power_curve[:, 1]), lambda ws, yaw: np.interp(ws, power_curve[:, 0], power_curve[:, 1]) * 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_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) if 0: plt.show()
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 import NOJ # setup site, turbines and flow model site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() import matplotlib.pyplot as plt _, (ax1, ax2) = plt.subplots(1, 2) for ax, wf_model, lbl in [ (ax1, NOJ(site, windTurbines, turbulenceModel=STF2005TurbulenceModel()), 'STF2005'), (ax2, NOJ(site, windTurbines, turbulenceModel=STF2017TurbulenceModel()), 'STF2017') ]: sim_res = wf_model(x, y) print(sim_res.TI_eff_ilk[:, 0]) # plot wake map flow_map = sim_res.flow_map(wd=0, ws=9.8) c = flow_map.plot_ti_map(ax=ax) ax.set_title('Turbulence intensity calculated by %s' % lbl) plt.show()
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_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_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_NOJ_6_turbines_in_row(): n_wt = 6 x = [0] * n_wt y = -np.arange(n_wt) * 40 * 2 site = UniformSite([1], 0.1) wake_model = NOJ(site, NibeA0) WS_eff_ilk = wake_model.calc_wt_interaction(x, y, [50] * n_wt, [0.0] * n_wt, 0.0, 11.0)[0] np.testing.assert_array_almost_equal( WS_eff_ilk[1:, 0, 0], 11 - np.sqrt( np.cumsum( ((11 * 2 / 3 * 20**2)**2) / (20 + 8 * np.arange(1, 6))**4)))
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 site = UniformSite([1], 0.1) wfm = NOJ(site, windTurbines) wfm.verbose = False h_i = [50, 50, 50] WS_eff_ilk = wfm.calc_wt_interaction(x, y, h_i, [0, 0, 0], wdir, 8.1)[0] ws_wt3 = 8.1 - np.hypot(8.1 * 2 / 3 * (20 / 26)**2, 8.1 * 2 / 3 * (20 / 30)**2) npt.assert_array_almost_equal(WS_eff_ilk[:, 0, 0], [8.1, 4.35, ws_wt3])
def test_aep(): site = UniformSite([1], ti=0) windTurbines = IEA37_WindTurbines() wfm = NOJ(site, windTurbines) sim_res = wfm([0], [0], wd=270) npt.assert_almost_equal(sim_res.aep().sum(), 3.35 * 24 * 365 / 1000) npt.assert_almost_equal(sim_res.aep(normalize_probabilities=True).sum(), 3.35 * 24 * 365 / 1000) npt.assert_equal(sim_res.aep().data.sum(), wfm.aep([0], [0], wd=270)) npt.assert_almost_equal(sim_res.aep(normalize_probabilities=True).sum(), wfm.aep([0], [0], wd=270, normalize_probabilities=True)) npt.assert_almost_equal(sim_res.aep(with_wake_loss=False).sum(), wfm.aep([0], [0], wd=270, with_wake_loss=False))
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_distance_over_rectangle(): x, y = [-100, 50], [200, -100] windTurbines = IEA37_WindTurbines() site = Rectangle(height=200, width=100, distance_resolution=100) wf_model = NOJ(site, windTurbines) sim_res = wf_model(x, y, wd=[270], ws=[9]) x_j = np.linspace(-100, 500, 100) y_j = np.linspace(-200, 300, 100) flow_map = sim_res.flow_map(HorizontalGrid(x_j, y_j)) Z = flow_map.WS_eff_xylk[:, :, 0, 0] X, Y = flow_map.X, flow_map.Y my = np.argmin(np.abs(Y[:, 0] - 200)) my2 = np.argmin(np.abs(Y[:, 0] + 100)) if 0: import matplotlib.pyplot as plt flow_map.plot_wake_map() H = site.elevation(X, Y) plt.plot(X[my], Z[my] * 10, label='wsp*10') plt.plot(X[my2], Z[my2] * 10, label='wsp*10') plt.contour(X, Y, H) plt.plot(X[my, :50:4], Z[my, :50:4] * 10, '.') plt.plot(x_j, site.elevation(x_j, x_j * 0), label='terrain level') plt.legend() plt.show() ref = [ 9., 3.42, 3.8, 6.02, 6.17, 6.31, 6.43, 7.29, 7.35, 7.41, 7.47, 7.53, 7.58 ] npt.assert_array_almost_equal(Z[my, :50:4], ref, 2)
def test_ti_map(): site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() wake_model = NOJ(site, windTurbines, turbulenceModel=STF2017TurbulenceModel()) aep = AEPCalculator(wake_model) x_j = np.linspace(-1500, 1500, 200) y_j = np.linspace(-1500, 1500, 100) X, Y, Z = aep.ti_map(x_j, y_j, 110, x, y, wd=[0], ws=[9]) m = 49, slice(100, 133, 2) if 0: print(np.round(Z[m], 2).tolist()) # ref import matplotlib.pyplot as plt c = plt.contourf(X, Y, Z, np.arange(.075, .50, .001)) plt.colorbar(c) windTurbines.plot(x, y) plt.plot(X[m], Y[m], '.-r') plt.show() ref = [ 0.48, 0.08, 0.08, 0.13, 0.16, 0.18, 0.19, 0.19, 0.2, 0.18, 0.17, 0.12, 0.13, 0.13, 0.13, 0.12, 0.12 ] npt.assert_array_almost_equal(Z[m], ref, 2)
def test_wake_model(): site = IEA37Site(16) windTurbines = IEA37_WindTurbines() wake_model = NOJ(site, windTurbines) with pytest.raises(ValueError, match="Turbines 0 and 1 are at the same position"): wake_model([0, 0], [0, 0], wd=np.arange(0, 360, 22.5), ws=[9.8])
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 import NOJ import matplotlib.pyplot as plt # setup site, turbines and wakemodel site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() wf_model = NOJ(site, windTurbines, turbulenceModel=GCLTurbulenceModel()) # calculate AEP sim_res = wf_model(x, y) print(sim_res.TI_eff_ilk.flatten()) # plot wake mape aep = sim_res.aep() flow_map = sim_res.flow_map(wd=0, ws=9.8) flow_map.plot_ti_map() plt.title('AEP: %.2f GWh' % aep) plt.show()
def main(): if __name__ == '__main__': from py_wake.examples.data.iea37 import iea37_path from py_wake.examples.data.iea37._iea37 import IEA37Site from py_wake.examples.data.iea37._iea37 import IEA37_WindTurbines from py_wake import NOJ # setup site, turbines and flow model site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines(iea37_path + 'iea37-335mw.yaml') wake_model = NOJ(site, windTurbines) # calculate AEP aep_calculator = AEPCalculator(wake_model) aep = aep_calculator.calculate_AEP(x, y)[0].sum() print(aep_calculator.WS_eff_ilk.shape) # plot wake map import matplotlib.pyplot as plt aep_calculator.plot_wake_map(wt_x=x, wt_y=y, wd=[0], ws=[9]) plt.title('AEP: %.2f GWh' % aep) windTurbines.plot(x, y) plt.show()
def main(): if __name__ == '__main__': site = ParqueFicticioSite() windTurbines = IEA37_WindTurbines() wf_model = NOJ(site, windTurbines) x, y = site.initial_position.T print(wf_model(x, y).aep)
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 main(): if __name__ == '__main__': import matplotlib.pyplot as plt wt = HornsrevV80() site = Hornsrev1Site() wt.plot(wt_x, wt_y) wf_model = NOJ(site, wt) aep = wf_model(wt_x, wt_y).aep() plt.title('AEP: %.1fGWh' % aep.sum()) plt.show()
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_aep_mixed_type(): site = UniformSite([1], ti=0) wt = WindTurbines.from_WindTurbines( [IEA37_WindTurbines(), IEA37_WindTurbines()]) wfm = NOJ(site, wt) sim_res = wfm([0, 500], [0, 0], type=[0, 1], wd=270) npt.assert_almost_equal( sim_res.aep(with_wake_loss=False).sum(), 2 * wfm([0], [0], wd=270).aep(with_wake_loss=False).sum())
def test_aep_no_wake_loss_hornsrev(): wt = hornsrev1.V80() x, y = hornsrev1.wt_x, hornsrev1.wt_y site = UniformWeibullSite([1], [10], [2], .75) site.default_ws = np.arange(3, 25) aep = AEPCalculator(NOJ(site, wt)) aep_nowake = aep.calculate_AEP_no_wake_loss(x, y).sum() npt.assert_almost_equal(aep_nowake / 80, 8.260757098) cap_factor = aep.calculate_AEP(x, y).sum() / aep_nowake # print(cap_factor) npt.assert_almost_equal(cap_factor, 0.947175839142014)
def test_huge_flow_map(deflectionModel): site = IEA37Site(16) windTurbines = IEA37_WindTurbines() wake_model = NOJ(site, windTurbines, deflectionModel=deflectionModel, turbulenceModel=STF2005TurbulenceModel()) n_wt = 2 flow_map = wake_model(*site.initial_position[:n_wt].T, wd=0).flow_map(HorizontalGrid(resolution=1000)) # check that deficit matrix > 10MB (i.e. it enters the memory saving loop) assert (np.prod(flow_map.WS_eff_xylk.shape) * n_wt * 8 / 1024**2) > 10 assert flow_map.WS_eff_xylk.shape == (1000, 1000, 1, 1)
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_DeprecatedWindTurbines(): for wts in [ V80Deprecated(), WindTurbines( names=['V80'], diameters=[80], hub_heights=[70], ct_funcs=[ lambda ws: np.interp(ws, hornsrev1.ct_curve[:, 0], hornsrev1.ct_curve[:, 1]) ], power_funcs=[ lambda ws: np.interp(ws, hornsrev1.power_curve[:, 0], hornsrev1.power_curve[:, 1]) ], power_unit='w') ]: types0 = [0] * 9 wfm = NOJ(Hornsrev1Site(), wts) npt.assert_array_equal(wts.types(), [0]) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types0), 81.2066072392765)
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_NOJ_Nibe_result_wake_map(): # Replicate result from: Jensen, Niels Otto. "A note on wind generator interaction." (1983). def ct_func(_): return 8 / 9 def power_func(*_): return 0 windTurbines = NibeA0 site = UniformSite([1], 0.1) wake_model = NOJ(site, windTurbines) sim_res = wake_model(x=[0], y=[0], wd=[0], ws=[8.1]) WS_eff_xy = sim_res.flow_map(HorizontalGrid( x=[0], y=[0, -40, -100], h=50)).WS_eff_xylk.mean(['wd', 'ws']) npt.assert_array_almost_equal(WS_eff_xy[:, 0], [8.1, 4.35, 5.7])
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_two_wt_aep(): site = Hornsrev1Site() windTurbines = IEA37_WindTurbines() wake_model = NOJ(site, windTurbines) sim_res1 = wake_model([0], [0], wd=270) sim_res2 = wake_model([0, 0], [0, 500], wd=270) # one wt, wind from west ~ 5845 hours of full load npt.assert_almost_equal(sim_res1.aep(normalize_probabilities=True).sum(), 3.35 * 5.845, 2) # No wake, two wt = 2 x one wt npt.assert_almost_equal(sim_res1.aep().sum() * 2, sim_res2.aep().sum()) # same for normalized propabilities npt.assert_almost_equal(sim_res1.aep(normalize_probabilities=True).sum() * 2, sim_res2.aep(normalize_probabilities=True).sum())
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_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_wake_map(): site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines(iea37_path + 'iea37-335mw.yaml') wake_model = NOJ(site, windTurbines) x_j = np.linspace(-1500, 1500, 200) y_j = np.linspace(-1500, 1500, 100) flow_map = wake_model(x, y, wd=[0], ws=[9]).flow_map(HorizontalGrid(x_j, y_j, 110)) Z = flow_map.WS_eff_xylk.mean((2, 3)) if 0: flow_map.plot_wake_map() plt.show() ref = [ 3.27, 3.27, 9.0, 7.46, 7.46, 7.46, 7.46, 7.31, 7.31, 7.31, 7.31, 8.3, 8.3, 8.3, 8.3, 8.3, 8.3 ] npt.assert_array_almost_equal(Z[49, 100:133:2], ref, 2)