def initialize_wind_farms(my_turbine, e126): r""" Initializes two :class:`~.wind_farm.WindFarm` objects. This function shows how to initialize a WindFarm object. A WindFarm needs a wind turbine fleet specifying the wind turbines and their number or total installed capacity (in Watt) in the farm. Optionally, you can provide a wind farm efficiency (which can be constant or dependent on the wind speed) and a name as an identifier. See :class:`~.wind_farm.WindFarm` for more information. Parameters ---------- my_turbine : :class:`~.wind_turbine.WindTurbine` WindTurbine object with self provided power curve. e126 : :class:`~.wind_turbine.WindTurbine` WindTurbine object with power curve from the OpenEnergy Database turbine library. Returns ------- tuple(:class:`~.wind_farm.WindFarm`, :class:`~.wind_farm.WindFarm`) """ # specification of wind farm data where turbine fleet is provided in a # pandas.DataFrame # for each turbine type you can either specify the number of turbines of # that type in the wind farm (float values are possible as well) or the # total installed capacity of that turbine type in W wind_turbine_fleet = pd.DataFrame( { "wind_turbine": [my_turbine, e126], # as windpowerlib.WindTurbine "number_of_turbines": [6, None], "total_capacity": [None, 12.6e6], } ) # initialize WindFarm object example_farm = WindFarm( name="example_farm", wind_turbine_fleet=wind_turbine_fleet ) # specification of wind farm data (2) containing a wind farm efficiency # wind turbine fleet is provided using the to_group function example_farm_2_data = { "name": "example_farm_2", "wind_turbine_fleet": [ my_turbine.to_group(6), e126.to_group(total_capacity=12.6e6), ], "efficiency": 0.9, } # initialize WindFarm object example_farm_2 = WindFarm(**example_farm_2_data) return example_farm, example_farm_2
def test_wind_farm_efficiency_with_missing_efficiency(self): """Test WindFarm.assign_power_curve() with missing efficiency while `wake_losses_model` is 'wind_farm_efficiency'.""" wind_turbine_fleet = [{ "wind_turbine": WindTurbine(**self.test_turbine), "number_of_turbines": 3, }] windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) msg = "If you use `wake_losses_model`" with pytest.raises(ValueError, match=msg): windfarm.assign_power_curve()
def test_repr(self): """Test string representation of WindFarm""" test_fleet = [{ 'wind_turbine': WindTurbine(**self.test_turbine), 'number_of_turbines': 2 }] assert 'E-126/4200' in repr(WindFarm(wind_turbine_fleet=test_fleet))
def test_repr(self): """Test string representation of WindFarm""" test_fleet = [{ "wind_turbine": WindTurbine(**self.test_turbine), "number_of_turbines": 2, }] assert "E-126/4200" in repr(WindFarm(wind_turbine_fleet=test_fleet))
def test_initialization_4(self, recwarn): """test overwriting and raising warning when number_of_turbines and total_capacity in wind turbine fleet do not fit""" wt1 = WindTurbine(**self.test_turbine) wt2 = WindTurbine(**self.test_turbine_2) wind_turbine_fleet = pd.DataFrame( data={ "wind_turbine": [wt1, wt2], "number_of_turbines": [3, 2], "total_capacity": [3, np.nan], }, index=[0, 1], ) windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) total_cap_wt1_expected = ( wt1.nominal_power * wind_turbine_fleet.loc[0, "number_of_turbines"]) assert (windfarm.wind_turbine_fleet.loc[0, "total_capacity"] == total_cap_wt1_expected) total_cap_wt2_expected = ( wt2.nominal_power * wind_turbine_fleet.loc[1, "number_of_turbines"]) assert (windfarm.wind_turbine_fleet.loc[1, "total_capacity"] == total_cap_wt2_expected) assert recwarn.pop(WindpowerlibUserWarning)
def test_mean_hub_height(self): """tests mean_hub_height method""" test_farm = { "wind_turbine_fleet": [ { "wind_turbine": WindTurbine(**self.test_turbine), "number_of_turbines": 2, }, { "wind_turbine": WindTurbine(**self.test_turbine_2), "total_capacity": 3e6, }, ] } windfarm = WindFarm(**test_farm) assert 97.265 == pytest.approx(windfarm.mean_hub_height().hub_height, 1e-3)
def test_aggregation_of_power_curve_with_missing_power_curve(self): """Test WindFarm.assign_power_curve() with missing power_curve.""" wt1 = WindTurbine(**self.test_turbine) wt1.power_curve = None wind_turbine_fleet = [{ 'wind_turbine': wt1, 'number_of_turbines': 3 }, { 'wind_turbine': WindTurbine(**self.test_turbine_2), 'number_of_turbines': 2 }] windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) msg = 'For an aggregated wind farm power curve each wind' with pytest.raises(ValueError, match=msg): windfarm.assign_power_curve()
def test_mean_hub_height(self): """tests mean_hub_height method""" test_farm = { 'wind_turbine_fleet': [{ 'wind_turbine': WindTurbine(**self.test_turbine), 'number_of_turbines': 2 }, { 'wind_turbine': WindTurbine(**self.test_turbine_2), 'total_capacity': 3e6 }] } windfarm = WindFarm(**test_farm) assert 97.265 == pytest.approx(windfarm.mean_hub_height().hub_height, 1e-3)
def test_initialization_1(self): """test catching error when wind_turbine_fleet not provided as list""" msg = 'Wind turbine must be provided as WindTurbine object' with pytest.raises(ValueError, match=msg): WindFarm(wind_turbine_fleet={ 'wind_turbine': 'turbine', 'number_of_turbines': 2 }, name='dummy')
def test_initialization_1(self): """test catching error when wind_turbine_fleet not provided as list""" msg = "Wind turbine must be provided as WindTurbine object" with pytest.raises(ValueError, match=msg): WindFarm( wind_turbine_fleet={ "wind_turbine": "turbine", "number_of_turbines": 2, }, name="dummy", )
def test_initialization_dataframe(self): """test simple initialization with wind turbine fleet dataframe""" wind_turbine_fleet = pd.DataFrame( data={ 'wind_turbine': [ WindTurbine(**self.test_turbine), WindTurbine(**self.test_turbine_2) ], 'number_of_turbines': [3, 2] }) windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power
def test_initialization_2(self): """test catching error when WindTurbine in wind_turbine_fleet not initialized""" test_farm = { 'wind_turbine_fleet': [{ 'wind_turbine': None, 'number_of_turbines': 3 }] } msg = 'Wind turbine must be provided as WindTurbine object' with pytest.raises(ValueError, match=msg): WindFarm(**test_farm)
def test_initialization_list(self): """test simple initialization with wind turbine fleet list""" wind_turbine_fleet = [{ 'wind_turbine': WindTurbine(**self.test_turbine), 'number_of_turbines': 3 }, { 'wind_turbine': WindTurbine(**self.test_turbine_2), 'number_of_turbines': 2 }] windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power
def test_initialization_5(self): """test catching error when number of turbines cannot be deduced""" wt = WindTurbine(**self.test_turbine) wt.nominal_power = None test_farm = { "wind_turbine_fleet": [{ "wind_turbine": wt, "total_capacity": 3e6 }] } msg = "Number of turbines of type" with pytest.raises(ValueError, match=msg): WindFarm(**test_farm)
def test_initialization_7(self): """test catching error when total capacity cannot be deduced""" wt = WindTurbine(**self.test_turbine) wt.nominal_power = None test_farm = { 'wind_turbine_fleet': [{ 'wind_turbine': wt, 'number_of_turbines': 3 }] } msg = 'Total capacity of turbines of type' with pytest.raises(ValueError, match=msg): WindFarm(**test_farm)
def test_initialization_3(self): """test catching error when wind_turbine not specified in wind_turbine_fleet""" wind_turbine_fleet = pd.DataFrame( data={ 'wind_turbines': [ WindTurbine(**self.test_turbine), WindTurbine(**self.test_turbine_2) ], 'number_of_turbines': [3, 2] }) msg = 'Missing wind_turbine key/column in wind_turbine_fleet' with pytest.raises(KeyError, match=msg): WindFarm(wind_turbine_fleet=wind_turbine_fleet)
def test_initialization_6(self): """test catching error when neither number_of_turbines nor total_capacity is provided""" test_farm = { 'wind_turbine_fleet': [{ 'wind_turbine': WindTurbine(**self.test_turbine), 'number_of_turbine': 3e6 }] } msg = 'Number of turbines of type ' with pytest.raises(ValueError, match=msg): WindFarm(**test_farm)
def test_initialization_list_2(self): """test simple initialization with wind turbine fleet list where once number of turbines and once total capacity is provided""" wind_turbine_fleet = [{ 'wind_turbine': WindTurbine(**self.test_turbine), 'number_of_turbines': 3 }, { 'wind_turbine': WindTurbine(**self.test_turbine_2), 'total_capacity': 2 * 2e6 }] windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power
def test_initialization_4(self, recwarn): """test overwriting and raising warning when number_of_turbines and total_capacity in wind turbine fleet do not fit""" wt1 = WindTurbine(**self.test_turbine) wt2 = WindTurbine(**self.test_turbine_2) wind_turbine_fleet = pd.DataFrame(data={ 'wind_turbine': [wt1, wt2], 'number_of_turbines': [3, 2], 'total_capacity': [3, np.nan] }, index=[0, 1]) windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) total_cap_wt1_expected = \ wt1.nominal_power * wind_turbine_fleet.loc[0, 'number_of_turbines'] assert windfarm.wind_turbine_fleet.loc[0, 'total_capacity'] == \ total_cap_wt1_expected total_cap_wt2_expected = \ wt2.nominal_power * wind_turbine_fleet.loc[1, 'number_of_turbines'] assert windfarm.wind_turbine_fleet.loc[1, 'total_capacity'] == \ total_cap_wt2_expected assert recwarn.pop(WindpowerlibUserWarning)
def initialize_wind_farms(my_turbine, e126): r""" Initializes two :class:`~.wind_farm.WindFarm` objects. This function shows how to initialize a WindFarm object. You need to provide at least a name and a the wind farm's wind turbine fleet as done below for 'example_farm'. Optionally you can provide a wind farm efficiency (which can be constant or dependent on the wind speed) and coordinates as done for 'example_farm_2'. In this example the coordinates are not being used as just a single weather data set is provided as example data. Parameters ---------- my_turbine : WindTurbine WindTurbine object with self provided power curve. e126 : WindTurbine WindTurbine object with power curve from data file provided by the windpowerlib. Returns ------- Tuple (WindFarm, WindFarm) """ # specification of wind farm data example_farm_data = { 'name': 'example_farm', 'wind_turbine_fleet': [{ 'wind_turbine': my_turbine, 'number_of_turbines': 6 }, { 'wind_turbine': e126, 'number_of_turbines': 3 }] } # initialize WindFarm object example_farm = WindFarm(**example_farm_data) # specification of wind farm data (2) containing a wind farm efficiency # and coordinates example_farm_2_data = { 'name': 'example_farm_2', 'wind_turbine_fleet': [{ 'wind_turbine': my_turbine, 'number_of_turbines': 6 }, { 'wind_turbine': e126, 'number_of_turbines': 3 }], 'efficiency': 0.9, 'coordinates': [52.2, 13.1] } # initialize WindFarm object example_farm_2 = WindFarm(**example_farm_2_data) return example_farm, example_farm_2
def __init__( self, wind_turbines: list = [], pv_arrays: list = [], latitude: float = 57.6568, longitude: float = -3.5818, altitude: float = 10, roughness_length: float = 0.15, # roughness length (bit of a guess) hellman_exp: float = 0.2): """ Set up the renewable energy generation """ # This needs to be repeated in every forecast self.roughness_length = roughness_length # Initialise empty forecast dataframe, just so nothing complains self.wind_forecast = pd.DataFrame() self.pv_forecast = pd.DataFrame() # Wind turbine(s) turbines = [] for turbine in wind_turbines: turbines.append({ 'wind_turbine': WindTurbine(turbine['name'], turbine['hub_height'], nominal_power=turbine['nominal_power'], rotor_diameter=turbine['rotor_diameter'], power_curve=turbine['power_curve']), 'number_of_turbines': turbine['qty'] }) local_wind_farm = WindFarm('Local windfarm', turbines, [latitude, longitude]) # TODO - check for learned local data & overwrite power_curve self.wind_modelchain = TurbineClusterModelChain( local_wind_farm, smoothing=False, hellman_exp=hellman_exp, ) # Initialise PV models self.pv_location = Location(latitude=latitude, longitude=longitude, altitude=altitude) # Now set up the PV array & system. cec_pv_model_params = pvlib.pvsystem.retrieve_sam('CECMod') sandia_pv_model_params = pvlib.pvsystem.retrieve_sam('SandiaMod') cec_inverter_model_params = pvlib.pvsystem.retrieve_sam('CECInverter') adr_inverter_model_params = pvlib.pvsystem.retrieve_sam('ADRInverter') self.pv_modelchains = {} for pv_array in pv_arrays: # Try to find the module names in the libraries if pv_array['module_name'] in cec_pv_model_params: pv_array['module_parameters'] = cec_pv_model_params[ pv_array['module_name']] elif pv_array['module_name'] in sandia_pv_model_params: pv_array['module_parameters'] = sandia_pv_model_params[ pv_array['module_name']] else: raise RenewablesException('Could not retrieve PV module data') # Do the same with the inverter(s) if pv_array['inverter_name'] in cec_inverter_model_params: pv_array['inverter_parameters'] = cec_inverter_model_params[ pv_array['inverter_name']] elif pv_array['inverter_name'] in adr_inverter_model_params: pv_array['inverter_parameters'] = adr_inverter_model_params[ pv_array['inverter_name']] else: raise RenewablesException('Could not retrieve PV module data') self.pv_modelchains[pv_array['name']] = ModelChain( PVSystem(**pv_array), self.pv_location, aoi_model='physical', spectral_model='no_loss')