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 import IEA37Site, IEA37_WindTurbines from py_wake.deficit_models.selfsimilarity import SelfSimilarityDeficit from py_wake.deficit_models.gaussian import ZongGaussianDeficit from py_wake.turbulence_models.stf import STF2017TurbulenceModel from py_wake.flow_map import XYGrid import matplotlib.pyplot as plt site = IEA37Site(16) x, y = site.initial_position.T windTurbines = IEA37_WindTurbines() from py_wake.deficit_models.noj import NOJDeficit from py_wake.superposition_models import SquaredSum # NOJ wake model noj = PropagateDownwind(site, windTurbines, wake_deficitModel=NOJDeficit(), superpositionModel=SquaredSum()) # NOJ wake and selfsimilarity blockage noj_ss = All2AllIterative( site, windTurbines, wake_deficitModel=NOJDeficit(), superpositionModel=SquaredSum(), blockage_deficitModel=SelfSimilarityDeficit()) # Zong convection superposition zongp_ss = PropagateDownwind(site, windTurbines, wake_deficitModel=ZongGaussianDeficit(), superpositionModel=WeightedSum(), turbulenceModel=STF2017TurbulenceModel()) # Zong convection superposition zong_ss = All2AllIterative( site, windTurbines, wake_deficitModel=ZongGaussianDeficit(), superpositionModel=WeightedSum(), blockage_deficitModel=SelfSimilarityDeficit(), turbulenceModel=STF2017TurbulenceModel()) for wm in [noj, noj_ss, zongp_ss, zong_ss]: sim = wm(x=x, y=y, wd=[30], ws=[9]) plt.figure() sim.flow_map(XYGrid(resolution=200)).plot_wake_map() plt.title(' AEP: %.3f GWh' % sim.aep().sum()) plt.show()
def test_TIFromWFM(): u_p, p_c, ct_c = v80_upct.copy() tab_powerct_curve = PowerCtTabular(ws=u_p, power=p_c, power_unit='w', ct=ct_c) def _power_ct(ws, run_only, TI_eff): return tab_powerct_curve( ws, run_only) * [TI_eff, np.ones_like(TI_eff)][run_only] curve = PowerCtFunction(['ws', 'TI_eff'], _power_ct, 'w') wfm = get_wfm(curve) ri, oi = wfm.windTurbines.function_inputs npt.assert_array_equal(ri, ['TI_eff']) npt.assert_array_equal(oi, ['Air_density', 'tilt', 'yaw']) u = np.arange(4, 25, .1) with pytest.raises( KeyError, match= 'Argument, TI_eff, needed to calculate power and ct requires a TurbulenceModel' ): wfm([0], [0], wd=[2], ws=u) wfm = get_wfm(curve, turbulenceModel=STF2017TurbulenceModel()) u = np.arange(4, 25, .1) sim_res = wfm([0], [0], wd=[2], ws=u) p = sim_res.Power.values.squeeze() npt.assert_array_almost_equal( p, np.interp(u, u_p, p_c) * sim_res.TI_eff.squeeze())
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_two_turbine_case0_time_series(): # same as test_two_turbine_case0 ws, ti, shear, wdir, dist = [10.9785338191, 0.2623204277, 0.4092031776, -38.4114616871 % 360, 5.123719529] # ref from simulation statistic (not updated yet) ws_ref = 1.103937e+01 thrust_ref = 4.211741e+02 power_ref = 3.399746e+06 ref_dels = [4546, 5931, 11902, 7599, 2407] wt = IEA34_130_2WT_Surrogate() site = UniformSite(p_wd=[1], ti=ti, ws=ws) wfm = NOJ(site, wt, turbulenceModel=STF2017TurbulenceModel()) sim_res = wfm([0, 0], [0, dist * 130], wd=wdir, time=True, Alpha=shear) assert sim_res.dw_ijl.dims == ('wt', 'wt', 'time') npt.assert_allclose(ws, ws_ref, rtol=.006) # npt.assert_allclose(ti, ws_std_ref / ws_ref, atol=.19) npt.assert_allclose(sim_res.Power.sel(wt=0), power_ref, rtol=0.002) npt.assert_allclose(sim_res.CT.sel(wt=0), thrust_ref * 1e3 / (1 / 2 * 1.225 * (65**2 * np.pi) * ws_ref**2), rtol=0.03) sim_res['duration'] = ('time', [3600 * 24 * 365 * 20]) loads = sim_res.loads(method='TwoWT') npt.assert_allclose(loads.DEL.sel(wt=0).squeeze(), ref_dels, rtol=.05) f = 20 * 365 * 24 * 3600 / 1e7 m = loads.m.values npt.assert_array_almost_equal(loads.LDEL.sel(wt=0).squeeze(), (loads.DEL.sel(wt=0).squeeze()**m * f)**(1 / m)) loads = sim_res.loads(method='TwoWT', softmax_base=100) npt.assert_allclose(loads.DEL.sel(wt=0).squeeze(), ref_dels, rtol=.05) npt.assert_array_almost_equal(loads.LDEL.sel(wt=0).squeeze(), (loads.DEL.sel(wt=0).squeeze()**m * f)**(1 / m))
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 run_wfm(mwc, test_cases=['Wieringermeer', 'Lillgrund', 'Hornsrev1'], deficit_setups=[{ 'deficit_model': NOJDeficit(), 'superpositionModel': SquaredSum(), 'rotorAvgModel': RotorCenter(), 'turbulenceModel': STF2017TurbulenceModel() }], gaussian_filter=True): ''' Evaluate wake models for the different test cases ''' mwc_out = {} for i in range(len(deficit_setups)): deficit_setups[i]['setup_name'] = get_setup_name(deficit_setups[i]) for case in test_cases: mwc_out[case] = mwc[case] mwc_out[case]['deficit_setups'] = deficit_setups # mwc_out[case]['deficit_models'] = [] if case == 'Wieringermeer': sigma = 2.5 * np.ones((len(mwc[case]['wt_x']))) elif case == 'Lillgrund': sigma = 3.3 * np.ones((len(mwc[case]['wt_x']))) elif case == 'Hornsrev1': sigma = sigma_hornsrev('vanderLaan', mwc[case]['wt_x'], mwc[case]['wt_y']) for i in range(len(deficit_setups)): # set up model wfm = PropagateDownwind( mwc[case]['site'], mwc[case]['wt'], deficit_setups[i]['deficit_model'], superpositionModel=deficit_setups[i]['superpositionModel'], rotorAvgModel=deficit_setups[i]['rotorAvgModel'], turbulenceModel=deficit_setups[i]['turbulenceModel']) # simulation sim_res = wfm(mwc[case]['wt_x'], mwc[case]['wt_y'], ws=mwc[case]['U0']) # Gaussian averaging if gaussian_filter: powerGA = np.zeros(sim_res.Power.shape) for iAD in range(len(mwc[case]['wt_x'])): powerGA[iAD, :, 0] = GaussianFilter( sim_res.Power.values[iAD, :, 0], np.arange(0, 360.0, 1), int(np.ceil(3 * sigma[iAD])), sigma[iAD]) sim_res['PowerGA'] = xr.DataArray(powerGA, dims=['wt', 'wd', 'ws']) sim_res['PowerGA'].attrs[ 'Description'] = 'Gaussian averaged power production [W]' mwc_out[case][deficit_setups[i]['setup_name']] = sim_res mwc_out[case][deficit_setups[i] ['setup_name']]['gaussian_filter'] = gaussian_filter
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_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_NOJLocal_6_turbines_in_row(): n_wt = 6 x = [0] * n_wt y = -np.arange(n_wt) * 40 * 2 site = UniformSite([1], 0.1) wfm = NOJLocal(site, NibeA0, turbulenceModel=STF2017TurbulenceModel()) wfm.verbose = False WS_eff_ilk = wfm.calc_wt_interaction(x, y, [50] * n_wt, [0] * n_wt, 0.0, 11.0)[0] np.testing.assert_array_almost_equal( WS_eff_ilk[1:, 0, 0], [5.62453869, 5.25806829, 5.64808912, 6.07792364, 6.44549094])
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_two_turbine_case0(): if 0: i = 0 f = r'C:\mmpe\programming\python\Topfarm\iea-3_4-130-rwt\turbine_model\res/' print(list(pd.DataFrame(eval(Path(f + 'input_two_turbines_dist.json').read_text())).iloc[i])) # [10.9785338191, 0.2623204277, 0.4092031776, -38.4114616871, 5.123719529] print(pd.concat([pd.read_csv(f + 'stats_two_turbines_mean.csv').iloc[i, [12, 14, 322]], pd.read_csv(f + 'stats_two_turbines_std.csv').iloc[i, [12, 14, 322]]], axis=1)) # Free wind speed Abs_vhor, gl. coo, of gl. pos ... 1.103937e+01 0.914252 # Aero rotor thrust 4.211741e+02 41.015962 # generator_servo inpvec 2 2: pelec [w] 3.399746e+06 3430.717100 print(pd.read_csv(f + 'stats_two_turbines_del.csv').iloc[i, [28, 29, 1, 2, 9]]) # MomentMx Mbdy:blade1 nodenr: 1 coo: blade1 blade root moment blade1 4546.998501 # MomentMy Mbdy:blade1 nodenr: 1 coo: blade1 blade root moment blade1 5931.157693 # MomentMx Mbdy:tower nodenr: 1 coo: tower tower bottom moment 11902.153031 # MomentMy Mbdy:tower nodenr: 1 coo: tower tower bottom moment 7599.336676 # MomentMz Mbdy:tower nodenr: 11 coo: tower tower top/yaw bearing moment 2407.279074 ws, ti, shear, wdir, dist = [10.9785338191, 0.2623204277, 0.4092031776, -38.4114616871 % 360, 5.123719529] # ref from simulation statistic (not updated yet) ws_ref = 1.103937e+01 ws_std_ref = 0.914252 thrust_ref = 4.211741e+02 power_ref = 3.399746e+06 ref_dels = [4546, 5931, 11902, 7599, 2407] wt = IEA34_130_2WT_Surrogate() site = UniformSite(p_wd=[1], ti=ti, ws=ws) sim_res = NOJ(site, wt, turbulenceModel=STF2017TurbulenceModel())([0, 0], [0, dist * 130], wd=wdir, Alpha=shear) npt.assert_allclose(ws, ws_ref, rtol=.006) # npt.assert_allclose(ti, ws_std_ref / ws_ref, atol=.19) npt.assert_allclose(sim_res.Power.sel(wt=0), power_ref, rtol=0.002) npt.assert_allclose(sim_res.CT.sel(wt=0), thrust_ref * 1e3 / (1 / 2 * 1.225 * (65**2 * np.pi) * ws_ref**2), rtol=0.03) loads = sim_res.loads(method='TwoWT') npt.assert_allclose(loads.DEL.sel(wt=0).squeeze(), ref_dels, rtol=.05) f = 20 * 365 * 24 * 3600 / 1e7 m = loads.m.values npt.assert_array_almost_equal(loads.LDEL.sel(wt=0).squeeze(), (loads.DEL.sel(wt=0).squeeze()**m * f)**(1 / m)) loads = sim_res.loads(method='TwoWT', softmax_base=100) npt.assert_allclose(loads.DEL.sel(wt=0).squeeze(), ref_dels, rtol=.05) npt.assert_array_almost_equal(loads.LDEL.sel(wt=0).squeeze(), (loads.DEL.sel(wt=0).squeeze()**m * f)**(1 / m))
def run_wms(swc, test_cases=[ 'Wieringermeer-West', 'Wieringermeer-East', 'Nibe', 'Nordtank-500', 'NREL-5MW_TIlow', 'NREL-5MW_TIhigh' ], deficit_models=[NOJDeficit(), BastankhahGaussianDeficit()], wds=np.linspace(-30, 30, 61)): ''' Run the different wake models for the specified sites and output simulation results ''' swc_out = {} for case in test_cases: swc_out[case] = swc[case] x_j = swc[case]['sDown'] * (np.dot( swc[case]['xDown'][:, na], np.cos(wds / 180.0 * np.pi)[na, :])).flatten() y_j = swc[case]['sDown'] * (np.dot( swc[case]['xDown'][:, na], np.sin(wds / 180.0 * np.pi)[na, :])).flatten() ii, jj = len(swc[case]['xDown']), len(wds) swc_out[case]['x'] = x_j.reshape(ii, jj) swc_out[case]['y'] = y_j.reshape(ii, jj) swc_out[case]['wds'] = wds swc_out[case]['deficit_models'] = [] for model in deficit_models: # set up model tmp = {} wfm = PropagateDownwind(swc[case]['site'], swc[case]['wt'], model, superpositionModel=SquaredSum(), rotorAvgModel=RotorCenter(), turbulenceModel=STF2017TurbulenceModel()) # simulation sim_res = wfm([0], [0], h=[100], wd=[270]) lw_j, WS_eff_jlk, TI_eff_jlk = wfm._flow_map( x_j, y_j, np.ones_like(x_j) * 100, sim_res) deficit_name = modify_deficit_name_sw(wfm.wake_deficitModel, TI_eff_jlk) tmp['bar_label'] = modify_deficit_name(wfm.wake_deficitModel) tmp['WS_eff'] = WS_eff_jlk[:, 0, 0].reshape(ii, jj) tmp['TI_eff'] = TI_eff_jlk[:, 0, 0].reshape(ii, jj) swc_out[case][deficit_name] = tmp swc_out[case]['deficit_models'].append(deficit_name) return swc_out
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.turbulence_models.stf import STF2017TurbulenceModel 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 = NOJ(site, windTurbines) wf_model_local = NOJLocal(site, windTurbines, turbulenceModel=STF2017TurbulenceModel()) # run wind farm simulation sim_res = wf_model(x, y) sim_res_local = wf_model_local(x, y) # calculate AEP aep = sim_res.aep().sum() aep_local = sim_res_local.aep().sum() # plot wake map fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 4.5), tight_layout=True) levels = np.arange(0, 10.5, 0.5) print(wf_model) flow_map = sim_res.flow_map(wd=30, ws=9.8) flow_map.plot_wake_map(levels=levels, ax=ax1, plot_colorbar=False) flow_map.plot_windturbines(ax=ax1) ax1.set_title('Original Jensen, AEP: %.2f GWh' % aep) # plot wake map print(wf_model_local) flow_map = sim_res_local.flow_map(wd=30, ws=9.8) flow_map.plot_wake_map(levels=levels, ax=ax2, plot_colorbar=False) flow_map.plot_windturbines(ax=ax2) ax2.set_title('Local Jensen, AEP: %.2f GWh' % aep_local) plt.figure() flow_map.plot_ti_map() plt.title('TI map for NOJLocal with STF2017 turbulence model') plt.show()
def test_one_turbine_case0(): ws, ti, shear = 9.2984459862, 0.0597870198, 0.2 if 0: f = r'C:\mmpe\programming\python\Topfarm\iea-3_4-130-rwt\turbine_model\res/' print(pd.concat([pd.read_csv(f + 'stats_one_turbine_mean.csv').iloc[0, [10, 14, 322]], pd.read_csv(f + 'stats_one_turbine_std.csv').iloc[0, [10, 14, 322]]], axis=1)) # Free wind speed Vy, gl. coo, of gl. pos 0.00... 9.309756e+00 0.401308 # Aero rotor thrust 5.408776e+02 11.489005 # generator_servo inpvec 2 2: pelec [w] 2.931442e+06 116491.192548 print(pd.read_csv(f + 'stats_one_turbine_del.csv').iloc[0, [28, 29, 1, 2, 9]]) # MomentMx Mbdy:blade1 nodenr: 1 coo: blade1 blade root moment blade1 1822.247387 # MomentMy Mbdy:blade1 nodenr: 1 coo: blade1 blade root moment blade1 5795.166623 # MomentMx Mbdy:tower nodenr: 1 coo: tower tower bottom moment 4385.405881 # MomentMy Mbdy:tower nodenr: 1 coo: tower tower bottom moment 2468.357017 # MomentMz Mbdy:tower nodenr: 11 coo: tower tower top/yaw bearing moment 1183.884786 ws_ref = 9.309756e+00 ws_std_ref = 0.401308 power_ref = 2.931442e+06 thrust_ref = 5.408776e+02 ref_dels = [1822, 5795, 4385, 2468, 1183] wt = IEA34_130_1WT_Surrogate() assert wt.loadFunction.output_keys[1] == 'del_blade_edge' assert wt.loadFunction.wohler_exponents == [10, 10, 4, 4, 7] site = UniformSite(p_wd=[1], ti=ti, ws=ws) sim_res = NOJ(site, wt, turbulenceModel=STF2017TurbulenceModel())([0], [0], wd=0, Alpha=shear) npt.assert_allclose(ws, ws_ref, rtol=.0013) npt.assert_allclose(ti, ws_std_ref / ws_ref, atol=.02) npt.assert_allclose(sim_res.Power, power_ref, rtol=0.003) npt.assert_allclose(sim_res.CT, thrust_ref * 1e3 / (1 / 2 * 1.225 * (65**2 * np.pi) * ws_ref**2), rtol=0.011) loads = sim_res.loads(method='OneWT') npt.assert_allclose(loads.DEL.squeeze(), ref_dels, rtol=.11) f = 20 * 365 * 24 * 3600 / 1e7 m = np.array([10, 10, 4, 4, 7]) npt.assert_array_almost_equal(loads.LDEL.squeeze(), (loads.DEL.squeeze()**m * f)**(1 / m)) loads = sim_res.loads(method='OneWT_WDAvg') npt.assert_allclose(loads.DEL.squeeze(), ref_dels, rtol=.11) npt.assert_array_almost_equal(loads.LDEL.squeeze(), (loads.DEL.squeeze()**m * f)**(1 / m))
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 __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)
all_turbulence_modules = [] for loader, module_name, _ in pkgutil.walk_packages([os.path.dirname(turbulence_models.__file__)]): _module = loader.find_module(module_name).load_module(module_name) for n in dir(_module): v = _module.__dict__[n] if inspect.isclass(v) and issubclass(v, TurbulenceModel) and \ v not in [TurbulenceModel]: all_turbulence_modules.append(v) return all_turbulence_modules @pytest.mark.parametrize('turbulence_model,ref_ti', [ (STF2005TurbulenceModel(), [0.075, 0.075, 0.075, 0.104, 0.167, 0.124, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.104, 0.136, 0.098, 0.104]), (STF2017TurbulenceModel(), [0.075, 0.075, 0.075, 0.114, 0.197, 0.142, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.115, 0.158, 0.108, 0.115]), (STF2017TurbulenceModel(weight_function=IECWeight()), [0.075, 0.075, 0.075, 0.215, 0.229, 0.179, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.215, 0.075, 0.075]), (GCLTurbulence(), [0.075, 0.075, 0.075, 0.117, 0.151, 0.135, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.128, 0.127, 0.117, 0.128]), (CrespoHernandez(), [0.075, 0.075, 0.075, 0.129, 0.17, 0.151, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.143, 0.141, 0.13, 0.143]) ]) 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),
from py_wake.tests import npt from py_wake.turbulence_models.stf import STF2005TurbulenceModel, STF2017TurbulenceModel from py_wake import NOJ import numpy as np from py_wake.wind_farm_models.engineering_models import All2AllIterative from py_wake.deficit_models.noj import NOJDeficit from py_wake.superposition_models import SquaredSum @pytest.mark.parametrize( 'turbulence_model,ref_ti', [(STF2005TurbulenceModel(), [ 0.075, 0.075, 0.075, 0.104, 0.149, 0.114, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.104, 0.104, 0.088, 0.104 ]), (STF2017TurbulenceModel(), [ 0.075, 0.075, 0.075, 0.114, 0.171, 0.129, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.115, 0.114, 0.094, 0.115 ])]) 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(),
def get_wf_model(cls): return cls(site, NibeA0, wake_deficitModel=NoWakeDeficit(), superpositionModel=LinearSum(), turbulenceModel=STF2017TurbulenceModel())
all_turbulence_modules = [] for loader, module_name, _ in pkgutil.walk_packages([os.path.dirname(turbulence_models.__file__)]): _module = loader.find_module(module_name).load_module(module_name) for n in dir(_module): v = _module.__dict__[n] if inspect.isclass(v) and issubclass(v, TurbulenceModel) and \ v not in [TurbulenceModel]: all_turbulence_modules.append(v) return all_turbulence_modules @pytest.mark.parametrize('turbulence_model,ref_ti', [ (STF2005TurbulenceModel(), [0.075, 0.075, 0.075, 0.104, 0.167, 0.124, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.104, 0.136, 0.098, 0.104]), (STF2017TurbulenceModel(), [0.075, 0.075, 0.075, 0.114, 0.197, 0.142, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.115, 0.158, 0.108, 0.115]), (GCLTurbulence(), [0.075, 0.075, 0.075, 0.117, 0.151, 0.135, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.128, 0.127, 0.117, 0.128]), (CrespoHernandez(), [0.075, 0.075, 0.075, 0.129, 0.17, 0.151, 0.075, 0.075, 0.075, 0.075, 0.075, 0.075, 0.143, 0.141, 0.13, 0.143]) ]) 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(),
def main(): if __name__ == '__main__': from py_wake.examples.data.hornsrev1 import Hornsrev1Site from py_wake.turbulence_models.stf import STF2017TurbulenceModel from py_wake import NOJ import matplotlib.pyplot as plt u = np.arange(3, 28, 1) # =============================================================================================================== # IEA34_130_1WT_Surrogate # =============================================================================================================== wt = IEA34_130_1WT_Surrogate() # plot power/ct curves ax1 = plt.gca() ax2 = plt.twinx() for ti in [0.01, .05, .1, .3]: power, ct = wt.power_ct(u, TI_eff=ti) ax1.plot(u, power / 1000, label=f'TI={ti}') ax2.plot(u, ct, '--') ax1.legend() ax1.set_ylabel('Power [kW]') ax2.set_ylabel('Ct') plt.figure() ax1 = plt.gca() ax2 = plt.twinx() for alpha in [-0.09, .1, .3, .49]: power, ct = wt.power_ct(u, TI_eff=.1, Alpha=alpha) ax1.plot(u, power / 1000, label=f'Alpha={alpha}') ax2.plot(u, ct, '--') ax1.legend() ax1.set_ylabel('Power [kW]') ax2.set_ylabel('Ct') # plot load curves sensors = wt.loadFunction.output_keys axes = [plt.figure().gca() for _ in sensors] for ti in [0.01, .05, .1, .3]: loads = wt.loads(u, TI_eff=ti) for ax, l in zip(axes, loads): ax.plot(u, l, label=f'TI={ti}') for alpha in [-0.09, .1, .3, .49]: loads = wt.loads(u, TI_eff=.1, Alpha=alpha) for ax, l in zip(axes, loads): ax.plot(u, l, '--', label=f'Alpha={alpha}') for ax, s in zip(axes, sensors): ax.set_title(s) ax.legend() # plot loads as function of wd and ws plt.figure() site = Hornsrev1Site() x, y = [0, 1000], [0, 0] sim_res = NOJ(site, wt, turbulenceModel=STF2017TurbulenceModel())(x, y, ws=np.arange( 3, 28), Alpha=.12) load_wd_averaged = sim_res.loads(normalize_probabilities=True, method='OneWT_WDAvg') loads = sim_res.loads(normalize_probabilities=True, method='OneWT') loads.DEL.isel(sensor=0, wt=0).plot() for s in load_wd_averaged.sensor: print(s.item(), load_wd_averaged.LDEL.sel(sensor=s, wt=0).item(), loads.LDEL.sel(sensor=s, wt=0).item()) # plt.show() # ======================================================================================================================= # IEA34_130_2WTSurrogate # ======================================================================================================================= wt = IEA34_130_2WT_Surrogate() # plot power/ct curves plt.figure() ax1 = plt.gca() ax2 = plt.twinx() for ti in [0.01, .05, .1, .3]: power, ct = wt.power_ct(u, TI=ti) ax1.plot(u, power, label=f'TI={ti}') ax2.plot(u, ct, '--') ax1.legend() ax1.set_ylabel('Power [kW]') ax2.set_ylabel('Ct') plt.figure() ax1 = plt.gca() ax2 = plt.twinx() for alpha in [-0.09, .1, .3, .49]: power, ct = wt.power_ct(u, TI=.1, Alpha=alpha) ax1.plot(u, power / 1000, label=f'Alpha={alpha}') ax2.plot(u, ct, '--') ax1.set_ylabel('Power [kW]') ax2.set_ylabel('Ct') ax1.legend() # plot load curves sensors = wt.loadFunction.output_keys axes = [plt.figure().gca() for _ in sensors] for ti in [0.01, .05, .1, .3]: loads = wt.loads(u, TI=ti, Alpha=.12, dw_ijl=0, hcw_ijl=0) for ax, l in zip(axes, loads): ax.plot(u, l, label=f'TI={ti}') for alpha in [-0.09, .1, .3, .49]: loads = wt.loads(u, TI=.1, Alpha=alpha, dw_ijl=np.array([1000]), hcw_ijl=0) for ax, l in zip(axes, loads): ax.plot(u, l, '--', label=f'Alpha={alpha}') for ax, s in zip(axes, sensors): ax.set_title(s) ax.legend() # plot loads as function of wd and ws plt.figure() site = Hornsrev1Site() x, y = [0, 1000], [0, 0] sim_res = NOJ(site, wt, turbulenceModel=STF2017TurbulenceModel())(x, y, ws=np.arange( 3, 28), Alpha=.12) loads = sim_res.loads(normalize_probabilities=True, method='TwoWT') loads.DEL.isel(sensor=0, wt=0).plot() for s in loads.sensor: print(s.item(), loads.LDEL.sel(sensor=s, wt=0).item())
from py_wake.examples.data.iea34_130rwt import IEA34_130_1WT_Surrogate from py_wake.superposition_models import MaxSum site = LillgrundSite() x, y = site.initial_position.T #keeping only every second turbine as lillegrund turbines are approx. half the size of the iea 3.4MW x = x[::2] y = y[::2] x_init = x y_init = y # # Wind turbines and wind farm model definition windTurbines = IEA34_130_1WT_Surrogate() wfm = IEA37SimpleBastankhahGaussian( site, windTurbines, turbulenceModel=STF2017TurbulenceModel( addedTurbulenceSuperpositionModel=MaxSum())) load_signals = [ 'del_blade_flap', 'del_blade_edge', 'del_tower_bottom_fa', 'del_tower_bottom_ss', 'del_tower_top_torsion' ] wsp = np.asarray([10, 15]) wdir = np.arange(0, 360, 45) n_wt = x.size i = n_wt k = wsp.size l = wdir.size yaw_zero = np.zeros((i, l, k)) maxiter = 10
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.turbulence_models.stf import STF2017TurbulenceModel 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 = NOJ(site, windTurbines) wf_model_local = NOJLocal(site, windTurbines, turbulenceModel=STF2017TurbulenceModel()) wf_model_turbo = PropagateDownwind( site, windTurbines, rotorAvgModel=RotorCenter(), wake_deficitModel=TurboNOJDeficit(use_effective_ws=True, use_effective_ti=False), superpositionModel=LinearSum(), turbulenceModel=STF2017TurbulenceModel()) # wf_model_turbo = NOJLocal( # site, windTurbines, turbulenceModel=STF2017TurbulenceModel()) # run wind farm simulation sim_res = wf_model(x, y) sim_res_local = wf_model_local(x, y) sim_res_turbo = wf_model_turbo(x, y) # calculate AEP aep = sim_res.aep().sum() aep_local = sim_res_local.aep().sum() aep_turbo = sim_res_turbo.aep().sum() # plot wake map fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(11, 4.5), tight_layout=True) levels = np.arange(0, 10.5, 0.5) print(wf_model) flow_map = sim_res.flow_map(wd=30, ws=9.8) flow_map.plot_wake_map(levels=levels, ax=ax1, plot_colorbar=False) flow_map.plot_windturbines(ax=ax1) ax1.set_title('Original Jensen, AEP: %.2f GWh' % aep) # plot wake map print(wf_model_local) flow_map = sim_res_local.flow_map(wd=30, ws=9.8) flow_map.plot_wake_map(levels=levels, ax=ax2, plot_colorbar=False) flow_map.plot_windturbines(ax=ax2) ax2.set_title('Local Jensen, AEP: %.2f GWh' % aep_local) # plot wake map print(wf_model_turbo) flow_map = sim_res_turbo.flow_map(wd=30, ws=9.8) flow_map.plot_wake_map(levels=levels, ax=ax3, plot_colorbar=False) flow_map.plot_windturbines(ax=ax3) ax3.set_title('Turbo Jensen, AEP: %.2f GWh' % aep_turbo) plt.figure() flow_map.plot_ti_map() plt.title('TI map for NOJLocal with STF2017 turbulence model') plt.show() # plot wake width as in Nygaard 2020 D = 1 D_src_il = np.array([[D]]) x = np.linspace(0, 60, 100) dw_ijlk = x[na, :, na, na] noj = NOJDeficit(k=0.04) noj_wr = noj.wake_radius(D_src_il, dw_ijlk) ct_ilk = np.array([[[8 / 9]]]) # thrust coefficient TI_ilk = np.array([[[0.06]]]) TI_eff_ilk = np.array([[[0.06]]]) tj = TurboNOJDeficit() tj_wr = tj.wake_radius(D_src_il, dw_ijlk, ct_ilk=ct_ilk, TI_ilk=TI_ilk, TI_eff_ilk=TI_eff_ilk) plt.figure() plt.title( 'Wake width comparison, NOJ orig and TurboNOJ (Nygaard2020) TI=6%') plt.plot(x, noj_wr[0, :, 0, 0], label='NOJ, k=0.04') plt.plot(x, tj_wr[0, :, 0, 0], label='TurboNOJ') plt.xlabel('x/D') plt.ylabel('y/D') plt.grid() plt.legend() plt.show()