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 initialise_wind_turbines(): r""" Initialises two :class:`~.wind_turbine.WindTurbine` objects. Function shows two ways to initialise a WindTurbine object. You can either specify your own turbine, as done below for 'myTurbine', or fetch power and/or power coefficient curve data from data files provided by the windpowerlib, as done for the 'enerconE126'. Execute ``windpowerlib.wind_turbine.get_turbine_types()`` or ``windpowerlib.wind_turbine.get_turbine_types( filename='power_coefficient_curves.csv')`` to get a list of all wind turbines for which power and power coefficient curves respectively are provided. Returns ------- Tuple (WindTurbine, WindTurbine) """ # specification of own wind turbine (Note: power coefficient values and # nominal power have to be in Watt) myTurbine = { 'turbine_name': 'myTurbine', 'nominal_power': 3e6, # in W 'hub_height': 105, # in m 'rotor_diameter': 90, # in m 'power_curve': pd.DataFrame( data={ 'values': [p * 1000 for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], # in W 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0] }) # in m/s } # initialise WindTurbine object my_turbine = WindTurbine(**myTurbine) # specification of wind turbine where power curve is provided # if you want to use the power coefficient curve change the value of # 'fetch_curve' to 'power_coefficient_curve' enerconE126 = { 'turbine_name': 'ENERCON E 126 7500', # turbine name as in register 'hub_height': 135, # in m 'rotor_diameter': 127, # in m 'fetch_curve': 'power_curve' # fetch power curve } # initialise WindTurbine object e126 = WindTurbine(**enerconE126) return my_turbine, e126
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_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 initialize_wind_turbines(): r""" Initializes three :class:`~.wind_turbine.WindTurbine` objects. This function shows three ways to initialize a WindTurbine object. You can either use turbine data from the OpenEnergy Database (oedb) turbine library that is provided along with the windpowerlib, as done for the 'enercon_e126', or specify your own turbine by directly providing a power (coefficient) curve, as done below for 'my_turbine', or provide your own turbine data in csv files, as done for 'dummy_turbine'. To get a list of all wind turbines for which power and/or power coefficient curves are provided execute ` `windpowerlib.wind_turbine.get_turbine_types()``. Returns ------- Tuple (:class:`~.wind_turbine.WindTurbine`, :class:`~.wind_turbine.WindTurbine`, :class:`~.wind_turbine.WindTurbine`) """ # ************************************************************************ # **** Data is provided in the oedb turbine library ********************** enercon_e126 = { "turbine_type": "E-126/4200", # turbine type as in register "hub_height": 135, # in m } e126 = WindTurbine(**enercon_e126) # ************************************************************************ # **** Specification of wind turbine with your own data ****************** # **** NOTE: power values and nominal power have to be in Watt my_turbine = { "nominal_power": 3e6, # in W "hub_height": 105, # in m "power_curve": pd.DataFrame( data={ "value": [p * 1000 for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], # in W "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], }), # in m/s } my_turbine = WindTurbine(**my_turbine) return my_turbine, e126
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_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_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 get_wind_turbine(self): r""" fetch power and/or power coefficient curve data from the OpenEnergy Database (oedb) Execute ``windpowerlib.wind_turbine.get_turbine_types()`` to get a table including all wind turbines for which power and/or power coefficient curves are provided. Returns ------- WindTurbine """ # specification of wind turbine where power curve is provided in the oedb # if you want to use the power coefficient curve change the value of # 'fetch_curve' to 'power_coefficient_curve' wind_turbine = { 'turbine_type': self.turbine_type, # turbine type as in register 'hub_height': self.hub_height, # in m 'rotor_diameter': self.rotor_diameter, # in m 'fetch_curve': self.fetch_curve, # fetch power curve 'data_source': self.data_source # data source oedb or name of csv file } # initialize WindTurbine object self.wind_turbine = WindTurbine(**wind_turbine) return self.wind_turbine
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_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_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_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_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_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)
3e6, # in W 'hub_height': 105, # in m 'rotor_diameter': 90, # in m 'power_curve': pd.DataFrame( data={ 'value': [p * 1000 for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], # in W 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0] }) # in m/s } # initialize WindTurbine object my_turbine = WindTurbine(**my_turbine) # specification of wind turbine where power curve is provided # if you want to use the power coefficient curve change the value of # 'fetch_curve' to 'power_coefficient_curve' enercon_e126 = { 'name': 'E-126/4200', # turbine name as in register 'hub_height': 135, # in m 'rotor_diameter': 127, # in m 'fetch_curve': 'power_curve', # fetch power curve # 'data_source': 'oedb' # data source oedb or name of csv file } # initialize WindTurbine object e126 = WindTurbine(**enercon_e126) ##########################################################################
def initialize_wind_turbines(): r""" Initializes three :class:`~.wind_turbine.WindTurbine` objects. This function shows three ways to initialize a WindTurbine object. You can either use turbine data from the OpenEnergy Database (oedb) turbine library that is provided along with the windpowerlib, as done for the 'enercon_e126', or specify your own turbine by directly providing a power (coefficient) curve, as done below for 'my_turbine', or provide your own turbine data in csv files, as done for 'dummy_turbine'. To get a list of all wind turbines for which power and/or power coefficient curves are provided execute ` `windpowerlib.wind_turbine.get_turbine_types()``. Returns ------- Tuple (:class:`~.wind_turbine.WindTurbine`, :class:`~.wind_turbine.WindTurbine`, :class:`~.wind_turbine.WindTurbine`) """ # specification of wind turbine where data is provided in the oedb # turbine library enercon_e126 = { 'turbine_type': 'E-126/4200', # turbine type as in register 'hub_height': 135 # in m } # initialize WindTurbine object e126 = WindTurbine(**enercon_e126) # specification of own wind turbine (Note: power values and nominal power # have to be in Watt) my_turbine = { 'nominal_power': 3e6, # in W 'hub_height': 105, # in m 'power_curve': pd.DataFrame( data={ 'value': [p * 1000 for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], # in W 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0] }) # in m/s } # initialize WindTurbine object my_turbine = WindTurbine(**my_turbine) # specification of wind turbine where power coefficient curve and nominal # power is provided in an own csv file csv_path = os.path.join(os.path.dirname(__file__), 'data') dummy_turbine = { 'turbine_type': "DUMMY 1", 'hub_height': 100, # in m 'rotor_diameter': 70, # in m 'path': csv_path } # initialize WindTurbine object dummy_turbine = WindTurbine(**dummy_turbine) return my_turbine, e126, dummy_turbine
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')
def initialize_wind_turbines(): r""" Initializes three :class:`~.wind_turbine.WindTurbine` objects. This function shows three ways to initialize a WindTurbine object. You can either use turbine data from the OpenEnergy Database (oedb) turbine library that is provided along with the windpowerlib, as done for the 'enercon_e126', or specify your own turbine by directly providing a power (coefficient) curve, as done below for 'my_turbine', or provide your own turbine data in csv files, as done for 'my_turbine2'. To get a list of all wind turbines for which power and/or power coefficient curves are provided execute ` `windpowerlib.wind_turbine.get_turbine_types()``. Returns ------- Tuple (:class:`~.wind_turbine.WindTurbine`, :class:`~.wind_turbine.WindTurbine`, :class:`~.wind_turbine.WindTurbine`) """ # ************************************************************************ # **** Data is provided in the oedb turbine library ********************** enercon_e126 = { "turbine_type": "E-126/4200", # turbine type as in register "hub_height": 135, # in m } e126 = WindTurbine(**enercon_e126) # ************************************************************************ # **** Specification of wind turbine with your own data ****************** # **** NOTE: power values and nominal power have to be in Watt my_turbine = { "nominal_power": 3e6, # in W "hub_height": 105, # in m "power_curve": pd.DataFrame( data={ "value": [p * 1000 for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], # in W "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], }), # in m/s } my_turbine = WindTurbine(**my_turbine) # ************************************************************************ # **** Specification of wind turbine with data in own file *************** # Read your turbine data from your data file using functions like # pandas.read_csv(). # >>> import pandas as pd # >>> my_data = pd.read_csv("path/to/my/data/file") # >>> my_power = my_data["my_power"] # >>> my_wind_speed = my_data["my_wind_speed"] my_power = pd.Series( [0.0, 39000.0, 270000.0, 2250000.0, 4500000.0, 4500000.0]) my_wind_speed = (0.0, 3.0, 5.0, 10.0, 15.0, 25.0) my_turbine2 = { "nominal_power": 6e6, # in W "hub_height": 115, # in m "power_curve": create_power_curve(wind_speed=my_wind_speed, power=my_power), } my_turbine2 = WindTurbine(**my_turbine2) return my_turbine, e126, my_turbine2
def initialize_wind_turbines(): r""" Initializes two :class:`~.wind_turbine.WindTurbine` objects. Function shows three ways to initialize a WindTurbine object. You can either specify your own turbine, as done below for 'my_turbine', or fetch power and/or power coefficient curve data from the OpenEnergy Database (oedb), as done for the 'enercon_e126', or provide your turbine data in csv files as done for 'dummy_turbine' with an example file. Execute ``windpowerlib.wind_turbine.get_turbine_types()`` to get a table including all wind turbines for which power and/or power coefficient curves are provided. Returns ------- Tuple (WindTurbine, WindTurbine, WindTurbine) """ # specification of own wind turbine (Note: power values and nominal power # have to be in Watt) my_turbine = { 'name': 'myTurbine', 'nominal_power': 3e6, # in W 'hub_height': 105, # in m 'rotor_diameter': 90, # in m 'power_curve': pd.DataFrame( data={ 'value': [p * 1000 for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], # in W 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0] }) # in m/s } # initialize WindTurbine object my_turbine = WindTurbine(**my_turbine) # specification of wind turbine where power curve is provided in the oedb # if you want to use the power coefficient curve change the value of # 'fetch_curve' to 'power_coefficient_curve' enercon_e126 = { 'name': 'E-126/4200', # turbine type as in register # 'hub_height': 135, # in m 'rotor_diameter': 127, # in m 'fetch_curve': 'power_curve', # fetch power curve # 'data_source': 'oedb' # data source oedb or name of csv file } # initialize WindTurbine object e126 = WindTurbine(**enercon_e126) # specification of wind turbine where power coefficient curve is provided # by a csv file csv_file = os.path.join(os.path.dirname(__file__), 'data', 'example_power_coefficient_curves.csv') dummy_turbine = { 'name': 'DUMMY 1', # turbine type as in file # 'hub_height': 100, # in m 'rotor_diameter': 70, # in m 'fetch_curve': 'power_coefficient_curve', # fetch cp curve # 'data_source': csv_file # data source } # initialize WindTurbine object dummy_turbine = WindTurbine(**dummy_turbine) return my_turbine, e126, dummy_turbine