def test_MultiPowerCtCurve(): u_p, p = np.asarray(hornsrev1.power_curve).T.copy() ct = hornsrev1.ct_curve[:, 1] curve = PowerCtFunctionList('mode', [ PowerCtTabular(ws=u_p, power=p, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p * 1.1, power_unit='w', ct=ct + .1) ]) npt.assert_array_equal(sorted(curve.optional_inputs), ['Air_density', 'tilt', 'yaw']) npt.assert_array_equal(list(curve.required_inputs), ['mode']) u = np.arange(0, 30, .1) p0, ct0 = curve(u, mode=0) p1, ct1 = curve(u, mode=1) npt.assert_array_almost_equal(p0, p1 / 1.1) npt.assert_array_almost_equal(ct0, ct1 - .1) # subset u = np.zeros((16, 360, 23)) + np.arange(3, 26)[na, na, :] mode_16 = (np.arange(16) > 7) mode_16_360 = np.broadcast_to(mode_16[:, na], (16, 360)) mode_16_360_23 = np.broadcast_to(mode_16[:, na, na], (16, 360, 23)) ref_p = np.array( np.broadcast_to(hornsrev1.power_curve[:, 1][na, na], (16, 360, 23))) ref_p[8:] *= 1.1 for m in [mode_16, mode_16_360, mode_16_360_23]: p, ct = curve(u, mode=m) npt.assert_array_almost_equal(p, ref_p)
def test_missing_input_PowerCtFunctionList(): u_p, p = np.asarray(hornsrev1.power_curve).T.copy() ct = hornsrev1.ct_curve[:, 1] curve = PowerCtFunctionList('mode', [ PowerCtTabular(ws=u_p, power=p + 1, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 2, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 3, power_unit='w', ct=ct) ]) u = np.zeros((16, 360, 23)) + np.arange(3, 26)[na, na, :] with pytest.raises( KeyError, match="Argument, mode, required to calculate power and ct not found" ): curve(u)
def test_fuga_deflection_time_series_gradient_evaluation(): p = Path(tfp) / "fuga/v80_wake_center_x.csv" x, notebook_wake_center = np.array([v.split(",") for v in p.read_text().strip().split("\n")], dtype=float).T 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 = PropagateDownwind( site, wt, wake_deficitModel=FugaYawDeficit(path), deflectionModel=FugaDeflection(path, 'input_par') ) WS = 10 yaw_ref = np.full((10, 1), 17) yaw_step = np.eye(10, 10) * 1e-6 + yaw_ref yaw = np.concatenate([yaw_step, yaw_ref], axis=1) sim_res = wfm(np.arange(10) * wt.diameter() * 4, [0] * 10, yaw=yaw, wd=[270] * 11, ws=[WS] * 11, time=True) print(sim_res)
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_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_DensityScaleAndSimpleYawModel(): u_p, p_c, ct_c = v80_upct.copy() curve = PowerCtTabular(ws=u_p, power=p_c, power_unit='w', ct=ct_c, method='linear') wfm = get_wfm(curve) ri, oi = wfm.windTurbines.function_inputs npt.assert_array_equal(ri, []) npt.assert_array_equal(oi, ['Air_density', 'tilt', 'yaw']) u = np.arange(4, 25, 1.1) yaw = 30 theta = np.deg2rad(yaw) yaw_ilk = (u * 0 + yaw).reshape(1, 1, len(u)) co = np.cos(theta) sim_res = wfm([0], [0], wd=0, ws=u, yaw=yaw_ilk, Air_density=1.3) p = sim_res.Power.values.squeeze() ct = sim_res.CT.values.squeeze() npt.assert_array_almost_equal(p, np.interp(u * co, u_p, p_c) * 1.3 / 1.225) npt.assert_array_almost_equal( ct, np.interp(u * co, u_p, ct_c) * co**2 * 1.3 / 1.225)
def test_TabularPowerCtCurve(method, unit, p_scale, p_ref, ct_ref): u_p, p = np.asarray(hornsrev1.power_curve).T.copy() p *= p_scale u_ct, ct = hornsrev1.ct_curve.T npt.assert_array_equal(u_p, u_ct) curve = PowerCtTabular(ws=u_p, power=p, power_unit=unit, ct=ct, ws_cutin=4, ws_cutout=25, method=method) npt.assert_array_equal(curve.optional_inputs, ['Air_density', 'tilt', 'yaw']) npt.assert_array_equal(curve.required_inputs, []) u = np.arange(0, 30, .1) p, ct = curve(u) s = slice(5, None, 30) if 0: plt.plot(u, p) plt.plot(u[s], p[s], '.') ax2 = plt.gca().twinx() ax2.plot(u, ct) ax2.plot(u[s], ct[s], '.') print(np.round(p[s], 3).tolist()) print(np.round(ct[s], 3).tolist()) plt.show() npt.assert_array_almost_equal(p[s], p_ref, 3) npt.assert_array_almost_equal(ct[s], ct_ref, 3) p, ct = curve(u, run_only=0), curve(u, run_only=1) npt.assert_array_almost_equal(p[s], p_ref, 3) npt.assert_array_almost_equal(ct[s], ct_ref, 3)
def test_DensityScaleFromSite(): ds = Hornsrev1Site().ds ds['Air_density'] = 1.3 u_p, p_c, ct_c = v80_upct.copy() for rho_ref in [1.225, 1.2]: curve = PowerCtTabular(ws=u_p, power=p_c, power_unit='w', ct=ct_c, ws_cutin=4, ws_cutout=25, method='linear', additional_models=[DensityScale(rho_ref)]) wfm = get_wfm(curve, site=XRSite(ds)) ri, oi = wfm.windTurbines.function_inputs npt.assert_array_equal(ri, []) npt.assert_array_equal(oi, ['Air_density']) u = np.arange(4, 25, .1) sim_res = wfm( [0], [0], wd=0, ws=u, ) p = sim_res.Power.values.squeeze() ct = sim_res.CT.values.squeeze() npt.assert_array_almost_equal(p, np.interp(u, u_p, p_c) * 1.3 / rho_ref) npt.assert_array_almost_equal(ct, np.interp(u, u_p, ct_c) * 1.3 / rho_ref)
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_PowerCtTabular(method, unit, p_scale, p_ref, ct_ref): u_p, p, ct = v80_upct.copy() p *= p_scale curve = PowerCtTabular(ws=u_p, power=p, power_unit=unit, ct=ct, ws_cutin=4, ws_cutout=25, method=method) u = np.arange(0, 30, .1) wfm = get_wfm(curve) ri, oi = wfm.windTurbines.function_inputs npt.assert_array_equal(ri, []) npt.assert_array_equal(oi, ['Air_density', 'tilt', 'yaw']) sim_res = wfm([0], [0], ws=u, wd=[0]).squeeze() p = sim_res.Power.values ct = sim_res.CT.values s = slice(5, None, 30) if 0: plt.plot(u, p) plt.plot(u[s], p[s], '.') ax2 = plt.gca().twinx() ax2.plot(u, ct) ax2.plot(u[s], ct[s], '.') print(np.round(p[s], 3).tolist()) print(np.round(ct[s], 3).tolist()) plt.show() npt.assert_array_almost_equal(p[s], p_ref, 3) npt.assert_array_almost_equal(ct[s], ct_ref, 3)
def test_fuga_wake_center_vs_notebook(): p = Path(tfp) / "fuga/v80_wake_center_x.csv" x, notebook_wake_center = np.array([v.split(",") for v in p.read_text().strip().split("\n")], dtype=float).T 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 = PropagateDownwind( site, wt, wake_deficitModel=FugaYawDeficit(path), deflectionModel=FugaDeflection(path, 'input_par') ) WS = 10 sim_res = wfm([0], [0], yaw=[17.4493], wd=270, ws=[WS]) y = wfm.wake_deficitModel.mirror(wfm.wake_deficitModel.y, anti_symmetric=True) fm = sim_res.flow_map(XYGrid(x=x[1:], y=y[240:271])) fuga_wake_center = [np.interp(0, InterpolatedUnivariateSpline(ws.y, ws.values).derivative()(ws.y), ws.y) for ws in fm.WS_eff.squeeze().T] if 0: plt.plot(x, notebook_wake_center, label='Notebook deflection') plt.plot(x[1:], fuga_wake_center) plt.show() plt.close('all') npt.assert_allclose(fuga_wake_center, notebook_wake_center[1:], atol=.14)
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 __init__(self, method='linear'): u, p = power_curve.T WindTurbine.__init__( self, 'DTU10MW', diameter=178.3, hub_height=119, powerCtFunction=PowerCtTabular(u, p * 1000, 'w', ct_curve[:, 1], ws_cutin=4, ws_cutout=25, ct_idle=0.059, method=method))
def test_missing_input_PowerCtFunctionList(): u_p, p, ct = v80_upct.copy() curve = PowerCtFunctionList('mode', [ PowerCtTabular(ws=u_p, power=p + 1, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 2, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 3, power_unit='w', ct=ct) ]) wfm = get_wfm(curve) ri, oi = wfm.windTurbines.function_inputs npt.assert_array_equal(ri, ['mode']) npt.assert_array_equal(oi, ['Air_density', 'tilt', 'yaw']) with pytest.raises( KeyError, match="Argument, mode, required to calculate power and ct not found" ): wfm([0], [0])
def test_WindTurbines(): u_p, p = np.asarray(hornsrev1.power_curve).T.copy() u_ct, ct = hornsrev1.ct_curve.T npt.assert_array_equal(u_p, u_ct) curve = PowerCtTabular(ws=u_p, power=p, power_unit='w', ct=ct) for wts in [WindTurbine(name='V80', diameter=80, hub_height=70, powerCtFunction=curve), WindTurbines(names=['V80'], diameters=[80], hub_heights=[70], powerCtFunctions=[curve])]: types0 = [0] * 9 for wfm in get_wfms(wts): npt.assert_array_equal(wts.types(), [0]) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types0), 81.2066072392765)
def test_MultiPowerCtCurve(): u_p, p, ct = v80_upct.copy() curve = PowerCtFunctionList('mode', [ PowerCtTabular(ws=u_p, power=p, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p * 1.1, power_unit='w', ct=ct + .1) ]) u = np.arange(0, 30, .1) wfm = get_wfm(curve) ri, oi = wfm.windTurbines.function_inputs npt.assert_array_equal(ri, ['mode']) npt.assert_array_equal(oi, ['Air_density', 'tilt', 'yaw']) sim_res = wfm([0], [0], ws=u, wd=0, mode=0) p0, ct0 = sim_res.Power.squeeze().values, sim_res.CT.squeeze().values, sim_res = wfm([0], [0], ws=u, wd=0, mode=1) p1, ct1 = sim_res.Power.squeeze().values, sim_res.CT.squeeze().values, npt.assert_array_almost_equal(p0, p1 / 1.1) npt.assert_array_almost_equal(ct0, ct1 - .1) mode_16 = (np.arange(16) > 7) mode_16_360 = np.broadcast_to(mode_16[:, na], (16, 360)) mode_16_360_23 = np.broadcast_to(mode_16[:, na, na], (16, 360, 23)) ref_p = np.array( np.broadcast_to(hornsrev1.power_curve[:, 1][na, na], (16, 360, 23))) ref_p[8:] *= 1.1 for m in [mode_16, mode_16_360, mode_16_360_23]: sim_res = wfm(np.arange(16) * 1e3, [0] * 16, wd=np.arange(360) % 5, mode=m) # no wake effects p = sim_res.Power.values npt.assert_array_almost_equal(p, ref_p)
def test_SimpleYawModel(): u_p, p_c = np.asarray(hornsrev1.power_curve).T.copy() _, ct_c = hornsrev1.ct_curve.T curve = PowerCtTabular(ws=u_p, power=p_c, power_unit='w', ct=ct_c, method='linear') u = np.arange(4, 25, 1.1) yaw = 30 theta = np.deg2rad(yaw) co = np.cos(theta) p, ct = curve(u, yaw=yaw) npt.assert_array_almost_equal(p, np.interp(u * co, u_p, p_c)) npt.assert_array_almost_equal(ct, np.interp(u * co, u_p, ct_c) * co**2)
def test_deprecated_from_WindTurbines(): v80 = V80Deprecated() v88 = WindTurbine('V88', 88, 77, powerCtFunction=PowerCtTabular( hornsrev1.power_curve[:, 0], hornsrev1.power_curve[:, 1] * 1.1, 'w', hornsrev1.ct_curve[:, 1])) with pytest.raises( AssertionError, match='from_WindTurbines no longer supports DeprecatedWindTurbines' ): WindTurbines.from_WindTurbines([v80, v88])
def __init__(self, method='linear'): """ Parameters ---------- method : {'linear', 'pchip'} linear(fast) or pchip(smooth and gradient friendly) interpolation """ WindTurbine.__init__(self, name='V80', diameter=80, hub_height=70, powerCtFunction=PowerCtTabular(power_curve[:, 0], power_curve[:, 1], 'w', ct_curve[:, 1], method=method))
def get_continuous_curve(key, optional): u_p, p = np.asarray(hornsrev1.power_curve).T.copy() ct = hornsrev1.ct_curve[:, 1] tab_powerct_curve = PowerCtTabular(ws=u_p, power=p, power_unit='w', ct=ct) def _power_ct(ws, run_only, **kwargs): try: v = fix_shape(kwargs.pop(key), ws, True) except KeyError: if optional: v = 1 else: raise return tab_powerct_curve(ws, run_only) * (v, 1)[run_only] oi = [key] if optional else [] return PowerCtFunction(['ws', key], _power_ct, 'w', optional_inputs=oi)
def test_density_scale(): u_p, p_c = np.asarray(hornsrev1.power_curve).T.copy() _, ct_c = hornsrev1.ct_curve.T for rho_ref in [1.225, 1.2]: curve = PowerCtTabular(ws=u_p, power=p_c, power_unit='w', ct=ct_c, ws_cutin=4, ws_cutout=25, method='linear', additional_models=[DensityScale(rho_ref)]) u = np.arange(4, 25, .1) p, ct = curve(u, Air_density=1.3) npt.assert_array_almost_equal(p, np.interp(u, u_p, p_c) * 1.3 / rho_ref) npt.assert_array_almost_equal(ct, np.interp(u, u_p, ct_c) * 1.3 / rho_ref)
def test_twotype_windturbines(): v80 = V80() v88 = WindTurbine('V88', 88, 77, powerCtFunction=PowerCtTabular( hornsrev1.power_curve[:, 0], hornsrev1.power_curve[:, 1] * 1.1, 'w', hornsrev1.ct_curve[:, 1])) wts = WindTurbines.from_WindTurbines([v80, v88]) types0 = [0] * 9 types1 = [0, 0, 0, 1, 1, 1, 0, 0, 0] types2 = [1] * 9 for wfm in get_wfms(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)
def test_MultiMultiPowerCtCurve_subset(): u_p, p, ct = v80_upct.copy() curves = PowerCtFunctionList('mytype', [ PowerCtFunctionList('mode', [ PowerCtTabular(ws=u_p, power=p + 1, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 2, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 3, power_unit='w', ct=ct) ]), PowerCtFunctionList('mode', [ PowerCtTabular(ws=u_p, power=p + 4, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 5, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 6, power_unit='w', ct=ct) ]), ]) wfm = get_wfm(curves) ri, oi = wfm.windTurbines.function_inputs npt.assert_array_equal(ri, ['mode', 'mytype']) npt.assert_array_equal(oi, ['Air_density', 'tilt', 'yaw']) u = np.zeros((2, 3, 4)) + np.arange(3, 7)[na, na, :] type_2 = np.array([0, 1]) type_2_3 = np.broadcast_to(type_2[:, na], (2, 3)) type_2_3_4 = np.broadcast_to(type_2[:, na, na], (2, 3, 4)) mode_2_3 = np.broadcast_to(np.array([0, 1, 2])[na, :], (2, 3)) mode_2_3_4 = np.broadcast_to(mode_2_3[:, :, na], (2, 3, 4)) ref_p = np.array( np.broadcast_to(hornsrev1.power_curve[:4, 1][na, na], (2, 3, 4))) ref_p[0, :] += np.array([1, 2, 3])[:, na] ref_p[1, :] += np.array([4, 5, 6])[:, na] for t in [type_2, type_2_3, type_2_3_4]: for m in [mode_2_3, mode_2_3_4]: sim_res = wfm([0, 1000], [0, 0], wd=np.arange(3), ws=np.arange(3, 7), mode=m, mytype=t) # no wake effects p = sim_res.Power.values npt.assert_array_almost_equal(p, ref_p)
def test_MultiMultiPowerCtCurve_subset(): u_p, p = np.asarray(hornsrev1.power_curve).T.copy() ct = hornsrev1.ct_curve[:, 1] curve = PowerCtFunctionList('type', [ PowerCtFunctionList('mode', [ PowerCtTabular(ws=u_p, power=p + 1, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 2, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 3, power_unit='w', ct=ct) ]), PowerCtFunctionList('mode', [ PowerCtTabular(ws=u_p, power=p + 4, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 5, power_unit='w', ct=ct), PowerCtTabular(ws=u_p, power=p + 6, power_unit='w', ct=ct) ]), ]) npt.assert_array_equal( sorted(curve.optional_inputs)[::-1], ['yaw', 'tilt', 'Air_density']) npt.assert_array_equal( sorted(curve.required_inputs)[::-1], ['type', 'mode']) u = np.zeros((2, 3, 4)) + np.arange(3, 7)[na, na, :] type_2 = np.array([0, 1]) type_2_3 = np.broadcast_to(type_2[:, na], (2, 3)) type_2_3_4 = np.broadcast_to(type_2[:, na, na], (2, 3, 4)) mode_2_3 = np.broadcast_to(np.array([0, 1, 2])[na, :], (2, 3)) mode_2_3_4 = np.broadcast_to(mode_2_3[:, :, na], (2, 3, 4)) ref_p = np.array( np.broadcast_to(hornsrev1.power_curve[:4, 1][na, na], (2, 3, 4))) ref_p[0, :] += np.array([1, 2, 3])[:, na] ref_p[1, :] += np.array([4, 5, 6])[:, na] for t in [type_2, type_2_3, type_2_3_4]: for m in [mode_2_3, mode_2_3_4]: p, ct = curve(u, mode=m, type=t) npt.assert_array_almost_equal(p, ref_p)
def from_WAsP_wtg(wtg_file, default_mode=0, power_unit='W'): """ Parse the one/multiple .wtg file(s) (xml) to initilize an WindTurbines object. Parameters ---------- wtg_file : string or a list of string A string denoting the .wtg file, which is exported from WAsP. Returns ------- an object of WindTurbines. Note: it is assumed that the power_unit inside multiple .wtg files is the same, i.e., power_unit. """ if isinstance(wtg_file, (list, tuple)): return WindTurbine.from_WindTurbine_lst( [WindTurbines.from_WAsP_wtg(f) for f in wtg_file]) cut_ins = [] cut_outs = [] tree = ET.parse(wtg_file) root = tree.getroot() # Reading data from wtg_file name = root.attrib['Description'] diameter = float(root.attrib['RotorDiameter']) hub_height = float(root.find('SuggestedHeights').find('Height').text) performance_tables = list(root.iter('PerformanceTable')) def fmt(v): try: return int(v) except (ValueError, TypeError): try: return float(v) except (ValueError, TypeError): return v wt_data = [{ k: fmt(perftab.attrib.get(k, None)) for k in performance_tables[0].attrib } for perftab in performance_tables] for i, perftab in enumerate(performance_tables): wt_data[i].update({ k: float(perftab.find('StartStopStrategy').attrib.get(k, None)) for k in perftab.find('StartStopStrategy').attrib }) wt_data[i].update({ k: np.array([ dp.attrib.get(k, np.nan) for dp in perftab.iter('DataPoint') ], dtype=float) for k in list(perftab.iter('DataPoint'))[0].attrib }) wt_data[i]['ct_idle'] = wt_data[i]['ThrustCoEfficient'][-1] power_ct_funcs = PowerCtFunctionList( 'mode', [ PowerCtTabular(wt['WindSpeed'], wt['PowerOutput'], power_unit, wt['ThrustCoEfficient'], ws_cutin=wt['LowSpeedCutIn'], ws_cutout=wt['HighSpeedCutOut'], ct_idle=wt['ct_idle'], additional_models=[]) for wt in wt_data ], default_value=default_mode, additional_models=[SimpleYawModel()]) char_data_tables = [ np.array([pct.ws_tab, pct.power_ct_tab[0], pct.power_ct_tab[1]]).T for pct in power_ct_funcs.windTurbineFunction_lst ] wts = WindTurbine(name=name, diameter=diameter, hub_height=hub_height, powerCtFunction=power_ct_funcs) wts.wt_data = wt_data wts.upct_tables = char_data_tables wts.cut_in = cut_ins wts.cut_out = cut_outs return wts
WindTurbine('Test', 130, 110, CubePowerSimpleCt(4, 25, 9.8, 3.35, 'MW', 8 / 9, 0, [])), lambda ws_pts: np.where((ws_pts > 4) & (ws_pts <= 9.8), 3 * 3350000 * (ws_pts - 4)**2 / (9.8 - 4)**3, 0), lambda ws_pts: [0, 0, 0, 2 * 12 * 0.0038473376423514938 + -0.1923668821175747]), ('PowerCtTabular_linear', V80(), [ 66600.00000931, 178000.00001444, 344999.99973923, 91999.99994598 ], [0.818, 0.001, -0.014, -0.3]), ('PowerCtTabular_pchip', V80(method='pchip'), [ 58518.7948, 148915.03267974, 320930.23255814, 127003.36700337 ], [1.21851, 0., 0., -0.05454545]), ('PowerCtTabular_spline', V80(method='spline'), [ 69723.7929, 158087.18190692, 324012.9604669, 156598.55856862 ], [8.176490e-01, -3.31076624e-05, -7.19353708e-03, -1.66006862e-01]), ('PowerCtTabular_kW', get_wt(PowerCtTabular( v80_upct[0], v80_upct[1] / 1000, 'kW', v80_upct[2])), [ 66600.00000931, 178000.00001444, 344999.99973923, 91999.99994598 ], [0.818, 0.001, -0.014, -0.3]), ('PowerCtFunctionList', get_wt( PowerCtFunctionList('mode', [ PowerCtTabular(ws=v80_upct[0], power=v80_upct[1], power_unit='w', ct=v80_upct[2]), PowerCtTabular(ws=v80_upct[0], power=v80_upct[1] * 1.1, power_unit='w', ct=v80_upct[2] + .1) ])), [73260., 195800., 379499.9998, 101199.9999 ], [0.818, 0.001, -0.014, -0.3])])
def __init__(self, name, diameter, hub_height, power_norm, turbulence_intensity=.1, air_density=1.225, max_cp=.49, constant_ct=.8, gear_loss_const=.01, gear_loss_var=.014, generator_loss=0.03, converter_loss=.03, ws_lst=np.arange(.1, 30, .1), ws_cutin=None, ws_cutout=None, power_idle=0, ct_idle=None, method='linear', additional_models=[SimpleYawModel()]): """Wind turbine with generic standard power curve based on max_cp, rated power and losses. Ct is computed from the basic 1d momentum theory Parameters ---------- name : str Wind turbine name diameter : int or float Diameter of wind turbine power_norm : int or float Nominal power [kW] diameter : int or float Rotor diameter [m] turbulence_intensity : float Turbulence intensity air_density : float optional Density of air [kg/m^3], defualt is 1.225 max_cp : float Maximum power coefficient constant_ct : float, optional Ct value in constant-ct region gear_loss_const : float Constant gear loss [%] gear_loss_var : float Variable gear loss [%] generator_loss : float Generator loss [%] converter_loss : float converter loss [%] ws_lst : array_like List of wind speeds. The power/ct tabular will be calculated for these wind speeds ws_cutin : number or None, optional if number, then the range [0,ws_cutin[ will be set to power_idle and ct_idle ws_cutout : number or None, optional if number, then the range ]ws_cutout,100] will be set to power_idle and ct_idle power_idle : number, optional see ws_cutin and ws_cutout ct_idle : number, optional see ws_cutin and ws_cutout method : {'linear', 'phip','spline} Interpolation method:\n - linear: fast, discontinous gradients\n - pchip: smooth\n - spline: smooth, closer to linear, small overshoots in transition to/from constant plateaus) additional_models : list, optional list of additional models. """ u, p, ct = standard_power_ct_curve(power_norm, diameter, turbulence_intensity, air_density, max_cp, constant_ct, gear_loss_const, gear_loss_var, generator_loss, converter_loss, ws_lst) if ws_cutin is not None: u, p, ct = [v[u >= ws_cutin] for v in [u, p, ct]] if ws_cutout is not None: u, p, ct = [v[u <= ws_cutout] for v in [u, p, ct]] if ct_idle is None: ct_idle = ct[-1] powerCtFunction = PowerCtTabular(u, p * 1000, 'w', ct, ws_cutin=ws_cutin, ws_cutout=ws_cutout, power_idle=power_idle, ct_idle=ct_idle, method=method, additional_models=additional_models) WindTurbine.__init__(self, name, diameter, hub_height, powerCtFunction)