def __init__(self, names, diameters, hub_heights, powerCtFunctions, loadFunctions=None): """Initialize WindTurbines Parameters ---------- names : array_like Wind turbine names diameters : array_like Diameter of wind turbines hub_heights : array_like Hub height of wind turbines powerCtFunctions : list of powerCtFunction objects Wind turbine ct functions; func(ws) -> ct """ self._names = np.array(names) self._diameters = np.array(diameters) self._hub_heights = np.array(hub_heights) assert len(names) == len(diameters) == len(hub_heights) == len( powerCtFunctions) self.powerCtFunction = PowerCtFunctionList('type', powerCtFunctions)
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_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_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 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_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_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 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
class WindTurbines(): """Set of multiple type wind turbines""" def __new__(cls, *args, **kwargs): from py_wake.wind_turbines.wind_turbines_deprecated import DeprecatedWindTurbines if cls != WindTurbines: return super(WindTurbines, cls).__new__(cls) try: inspect.getcallargs(DeprecatedWindTurbines.__init__, None, *args, **kwargs) warnings.warn( """WindTurbines(names, diameters, hub_heights, ct_funcs, power_funcs, power_unit=None) is deprecated. Use WindTurbines(names, diameters, hub_heights, power_ct_funcs) instead""", DeprecationWarning, stacklevel=2) return DeprecatedWindTurbines(*args, **kwargs) except TypeError: return super(WindTurbines, cls).__new__(cls) def __init__(self, names, diameters, hub_heights, powerCtFunctions, loadFunctions=None): """Initialize WindTurbines Parameters ---------- names : array_like Wind turbine names diameters : array_like Diameter of wind turbines hub_heights : array_like Hub height of wind turbines powerCtFunctions : list of powerCtFunction objects Wind turbine ct functions; func(ws) -> ct """ self._names = np.array(names) self._diameters = np.array(diameters) self._hub_heights = np.array(hub_heights) assert len(names) == len(diameters) == len(hub_heights) == len( powerCtFunctions) self.powerCtFunction = PowerCtFunctionList('type', powerCtFunctions) # if loadFunctions: # self.loadfunction = @property def function_inputs(self): ri, oi = self.powerCtFunction.required_inputs, self.powerCtFunction.optional_inputs if hasattr(self, 'loadFunction'): ri += self.loadFunction.required_inputs oi += self.loadFunction.optional_inputs return ri, oi def _info(self, var, type): return var[np.asarray(type, int)] def hub_height(self, type=0): """Hub height of the specified type(s) of wind turbines""" return self._info(self._hub_heights, type) def diameter(self, type=0): """Rotor diameter of the specified type(s) of wind turbines""" return self._info(self._diameters, type) def name(self, type=0): """Name of the specified type(s) of wind turbines""" return self._info(self._names, type) def power(self, ws, **kwargs): """Power in watt Parameters ---------- ws : array_like Wind speed kwargs : keyword arguments required and optional inputs """ return self.powerCtFunction(ws, run_only=0, **kwargs) def ct(self, ws, **kwargs): """Thrust coefficient Parameters ---------- ws : array_like Wind speed kwargs : keyword arguments required and optional inputs """ return self.powerCtFunction(ws, run_only=1, **kwargs) def power_ct(self, ws, **kwargs): return [self.power(ws, **kwargs), self.ct(ws, **kwargs)] def loads(self, ws, **kwargs): return self.loadFunction(ws, **kwargs) def types(self): return np.arange(len(self._names)) def get_defaults(self, N, type_i=0, h_i=None, d_i=None): """ Parameters ---------- N : int number of turbines type_i : array_like or None, optional Turbine type. If None, all turbines is type 0 h_i : array_like or None, optional hub heights. If None: default hub heights (set in WindTurbines) d_i : array_lie or None, optional Rotor diameter. If None: default diameter (set in WindTurbines) """ type_i = np.zeros(N, dtype=int) + type_i if h_i is None: h_i = self.hub_height(type_i) elif isinstance(h_i, (int, float)): h_i = np.zeros(N) + h_i if d_i is None: d_i = self.diameter(type_i) elif isinstance(d_i, (int, float)): d_i = np.zeros(N) + d_i return np.asarray(h_i), np.asarray(d_i) def enable_autograd(self): self.powerCtFunction.enable_autograd() def plot_xy(self, x, y, types=None, wd=None, yaw=0, tilt=0, normalize_with=1, ax=None): """Plot wind farm layout including type name and diameter Parameters ---------- x : array_like x position of wind turbines y : array_like y position of wind turbines types : int or array_like type of the wind turbines wd : int, float, array_like or None - if int, float or array_like: wd is assumed to be the wind direction(s) and a line\ indicating the perpendicular rotor is plotted. - if None: An circle indicating the rotor diameter is plotted ax : pyplot or matplotlib axes object, default None """ import matplotlib.pyplot as plt if types is None: types = np.zeros_like(x) if ax is None: ax = plt.gca() markers = np.array(list("213v^<>o48spP*hH+xXDd|_")) colors = ['gray', 'r', 'g', 'k'] * 5 from matplotlib.patches import Circle assert len(x) == len(y) types = (np.zeros_like(x) + types).astype( int) # ensure same length as x yaw = np.zeros_like(x) + yaw tilt = np.zeros_like(x) + tilt x, y, D = [ np.asarray(v) / normalize_with for v in [x, y, self.diameter(types)] ] R = D / 2 for i, (x_, y_, r, t, yaw_, tilt_) in enumerate(zip(x, y, R, types, yaw, tilt)): if wd is None or len(np.atleast_1d(wd)) > 1: circle = Circle((x_, y_), r, ec=colors[t], fc="None") ax.add_artist(circle) ax.plot( x_, y_, 'None', ) else: for wd_ in np.atleast_1d(wd): circle = Ellipse((x_, y_), 2 * r * np.sin(np.deg2rad(tilt_)), 2 * r, angle=90 - wd_ + yaw_, ec=colors[t], fc="None") ax.add_artist(circle) for t, m, c in zip(np.unique(types), markers, colors): # ax.plot(np.asarray(x)[types == t], np.asarray(y)[types == t], '%sk' % m, label=self._names[int(t)]) ax.plot([], [], '2', color=colors[t], label=self._names[int(t)]) for i, (x_, y_, r) in enumerate(zip(x, y, R)): ax.annotate(i, (x_ + r, y_ + r), fontsize=7) ax.legend(loc=1) ax.axis('equal') def plot_yz(self, y, z=None, h=None, types=None, wd=270, yaw=0, tilt=0, normalize_with=1, ax=None): """Plot wind farm layout in yz-plane including type name and diameter Parameters ---------- y : array_like y position of wind turbines types : int or array_like type of the wind turbines wd : int, float, array_like or None - if int, float or array_like: wd is assumed to be the wind direction(s) and a line\ indicating the perpendicular rotor is plotted. - if None: An circle indicating the rotor diameter is plotted ax : pyplot or matplotlib axes object, default None """ import matplotlib.pyplot as plt if z is None: z = np.zeros_like(y) if types is None: types = np.zeros_like(y).astype(int) else: types = (np.zeros_like(y) + types).astype( int) # ensure same length as x if h is None: h = np.zeros_like(y) + self.hub_height(types) else: h = np.zeros_like(y) + h if ax is None: ax = plt.gca() markers = np.array(list("213v^<>o48spP*hH+xXDd|_")) colors = ['gray', 'k', 'r', 'g', 'k'] * 5 from matplotlib.patches import Circle yaw = np.zeros_like(y) + yaw tilt = np.zeros_like(y) + tilt y, z, h, D = [ v / normalize_with for v in [y, z, h, self.diameter(types)] ] for i, (y_, z_, h_, d, t, yaw_, tilt_) in enumerate(zip(y, z, h, D, types, yaw, tilt)): circle = Ellipse((y_, h_ + z_), d * np.sin(np.deg2rad(wd - yaw_)), d, angle=-tilt_, ec=colors[t], fc="None") ax.add_artist(circle) ax.plot([y_, y_], [z_, z_ + h_], 'k') ax.plot(y_, h_, 'None') for t, m, c in zip(np.unique(types), markers, colors): ax.plot([], [], '2', color=c, label=self._names[int(t)]) for i, (y_, z_, h_, d) in enumerate(zip(y, z, h, D)): ax.annotate(i, (y_ + d / 2, z_ + h_ + d / 2), fontsize=7) ax.legend(loc=1) ax.axis('equal') def plot(self, x, y, type=None, wd=None, yaw=0, tilt=0, normalize_with=1, ax=None): return self.plot_xy(x, y, type, wd, yaw, tilt, normalize_with, ax) @staticmethod def from_WindTurbine_lst(wt_lst): """Generate a WindTurbines object from a list of (Onetype)WindTurbines Parameters ---------- wt_lst : array_like list of (OneType)WindTurbines """ def get(att): lst = [] for wt in wt_lst: lst.extend(getattr(wt, att)) return lst return WindTurbines( *[get(n) for n in ['_names', '_diameters', '_hub_heights']] + [[getattr(wt, 'powerCtFunction') for wt in wt_lst]]) @staticmethod def from_WindTurbines(wt_lst): from py_wake.wind_turbines.wind_turbines_deprecated import DeprecatedWindTurbines assert not any([ isinstance(wt, DeprecatedWindTurbines) for wt in wt_lst ]), "from_WindTurbines no longer supports DeprecatedWindTurbines" warnings.simplefilter('default', DeprecationWarning) warnings.warn( """WindTurbines.from_WindTurbines is deprecated. Use WindTurbines.from_WindTurbine_lst instead""", DeprecationWarning, stacklevel=2) return WindTurbines.from_WindTurbine_lst(wt_lst) @staticmethod 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
], [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])]) @pytest.mark.parametrize('grad_method', [autograd, cs, fd]) def test_gradients(case, wt, dpdu_ref, dctdu_ref, grad_method): ws_pts = np.array([3.1, 6., 9., 12.]) if isinstance(dpdu_ref, FunctionType): dpdu_ref, dctdu_ref = dpdu_ref(ws_pts), dctdu_ref(ws_pts) with use_autograd_in([ WindTurbines, iea37_reader, power_ct_functions, wind_turbines_deprecated