def __init__(self): WindTurbine.__init__(self, name='ValidationWindTurbines', diameter=0, hub_height=0, powerCtFunction=PowerCtFunction(input_keys=['ws'], power_ct_func=None, power_unit='w') )
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_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 __init__(self, name, diameter, hub_height, power_norm, TI_eff_lst=np.linspace(0, .5, 6), default_TI_eff=.1, Air_density_lst=np.linspace(.9, 1.5, 5), default_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, wsp_lst=np.arange(.1, 30, .5), 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 The power and ct curves depends on turbulence intensity(TI_eff) and air density(Air_density) 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] TI_eff_lst : array_like List of turbulence intensities to include in tabular default_TI_eff : float, optional Default turbulence intensity, default is 10% Air_density_lst : array_like List of air densities [kg/m^3] to include in tabular default_Air_density : float, optional Default air_density [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 [%] additional_models : list, optional list of additional models. """ data = np.moveaxis([[standard_power_ct_curve(power_norm, diameter, ti, rho, max_cp, constant_ct, gear_loss_const, gear_loss_var, generator_loss, converter_loss, wsp_lst)[1:] for rho in Air_density_lst] for ti in TI_eff_lst], -1, 0) p = data[:, :, :, 0] ct = data[:, :, :, 1] powerCtFunction = PowerCtNDTabular( input_keys=['ws', 'TI_eff', 'Air_density'], value_lst=[wsp_lst, TI_eff_lst, Air_density_lst], power_arr=p * 1000, power_unit='w', ct_arr=ct, default_value_dict={k: v for k, v in [('TI_eff', default_TI_eff), ('Air_density', default_Air_density)] if v is not None}, additional_models=additional_models) WindTurbine.__init__(self, name, diameter, hub_height, powerCtFunction)
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_GenericWindTurbine(): for ref, ti, cut_in, cut_out, p_tol, ct_tol in [(V80(), .1, 4, None, 0.03, .14), (WindTurbine.from_WAsP_wtg(wtg_path + "Vestas V112-3.0 MW.wtg"), .05, 3, 25, 0.035, .07), (DTU10MW(), .05, 4, 25, 0.06, .12)]: power_norm = ref.power(np.arange(10, 20)).max() wt = GenericWindTurbine('Generic', ref.diameter(), ref.hub_height(), power_norm / 1e3, turbulence_intensity=ti, ws_cutin=cut_in, ws_cutout=cut_out) if 0: u = np.arange(0, 30, .1) p, ct = wt.power_ct(u) plt.plot(u, p / 1e6, label='Generic') plt.plot(u, ref.power(u) / 1e6, label=ref.name()) plt.ylabel('Power [MW]') plt.legend(loc='center left') ax = plt.twinx() ax.plot(u, ct, '--') ax.plot(u, ref.ct(u), '--') ax.set_ylim([0, 1]) plt.ylabel('Ct') plt.show() u = np.arange(5, 25) p, ct = wt.power_ct(u) p_ref, ct_ref = ref.power_ct(u) # print(np.abs(p_ref - p).max() / power_norm) npt.assert_allclose(p, p_ref, atol=power_norm * p_tol) # print(np.abs(ct_ref - ct).max()) npt.assert_allclose(ct, ct_ref, atol=ct_tol)
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 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 __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)