Source code for windpowerlib.wind_turbine

"""
The ``wind_turbine`` module contains the class WindTurbine that implements
a wind turbine in the windpowerlib and functions needed for the modelling of a
wind turbine.

"""

__copyright__ = "Copyright oemof developer group"
__license__ = "GPLv3"

import pandas as pd
import logging
import sys
import requests


[docs]class WindTurbine(object): r""" Defines a standard set of wind turbine attributes. Parameters ---------- name : string Name of the wind turbine type. Use :py:func:`~.get_turbine_types` to see a table of all wind turbines for which power (coefficient) curve data is provided. hub_height : float Hub height of the wind turbine in m. rotor_diameter : None or float Diameter of the rotor in m. Default: None. power_coefficient_curve : None, pandas.DataFrame or dictionary Power coefficient curve of the wind turbine. DataFrame/dictionary must have 'wind_speed' and 'value' columns/keys with wind speeds in m/s and the corresponding power coefficients. Default: None. power_curve : None, pandas.DataFrame or dictionary Power curve of the wind turbine. DataFrame/dictionary must have 'wind_speed' and 'value' columns/keys with wind speeds in m/s and the corresponding power curve value in W. Default: None. nominal_power : None or float The nominal output of the wind turbine in W. Default: None. fetch_curve : string Parameter to specify whether a power or power coefficient curve should be retrieved from the provided turbine data. Valid options are 'power_curve' and 'power_coefficient_curve'. Default: None. coordinates : list or None List of coordinates [lat, lon] of location for loading data. Default: None. data_source : string Specifies whether turbine data (f.e. nominal power, power curve, power coefficient curve) is loaded from the OpenEnergy Database ('oedb') or from a csv file ('<path including file name>'). Default: 'oedb'. See `example_power_curves.csv' and `example_power_coefficient_curves.csv` in example/data for the required form of a csv file (more columns can be added). Attributes ---------- name : string Name of the wind turbine type. Use :py:func:`~.get_turbine_types` to see a table of all wind turbines for which power (coefficient) curve data is provided. hub_height : float Hub height of the wind turbine in m. rotor_diameter : None or float Diameter of the rotor in m. Default: None. power_coefficient_curve : None, pandas.DataFrame or dictionary Power coefficient curve of the wind turbine. DataFrame/dictionary must have 'wind_speed' and 'value' columns/keys with wind speeds in m/s and the corresponding power coefficients. Default: None. power_curve : None, pandas.DataFrame or dictionary Power curve of the wind turbine. DataFrame/dictionary must have 'wind_speed' and 'value' columns/keys with wind speeds in m/s and the corresponding power curve value in W. Default: None. nominal_power : None or float The nominal output of the wind turbine in W. Default: None. coordinates : list or None List of coordinates [lat, lon] of location for loading data. Default: None. power_output : pandas.Series The calculated power output of the wind turbine. Default: None. Notes ------ Your wind turbine object should have a power coefficient or power curve. You can set the `fetch_curve` parameter and the `data_source` parameter if you want to automatically fetch a curve from a data set provided in the OpenEnergy Database (oedb) or want to read a csv file that you provide. See `example_power_curves.csv' and `example_power_coefficient_curves.csv` in example/data for the required form of such a csv file (more columns can be added). Examples -------- >>> from windpowerlib import wind_turbine >>> enerconE126 = { ... 'hub_height': 135, ... 'rotor_diameter': 127, ... 'name': 'E-126/4200', ... 'fetch_curve': 'power_curve', ... 'data_source': 'oedb'} >>> e126 = wind_turbine.WindTurbine(**enerconE126) >>> print(e126.nominal_power) 4200000.0 """
[docs] def __init__(self, name, hub_height, rotor_diameter=None, power_coefficient_curve=None, power_curve=None, nominal_power=None, fetch_curve=None, coordinates=None, data_source='oedb'): self.name = name self.hub_height = hub_height self.rotor_diameter = rotor_diameter self.power_coefficient_curve = power_coefficient_curve self.power_curve = power_curve self.nominal_power = nominal_power self.coordinates = coordinates self.power_output = None if self.power_coefficient_curve is None and self.power_curve is None: self.fetch_turbine_data(fetch_curve, data_source)
[docs] def fetch_turbine_data(self, fetch_curve, data_source): r""" Fetches data of the requested wind turbine. Method fetches nominal power as well as power coefficient curve or power curve from a data set provided in the OpenEnergy Database (oedb). You can also import your own power (coefficient) curves from a file. For that the wind speeds in m/s have to be in the first row and the corresponding power coefficient curve values or power curve values in W in a row where the first column contains the turbine name. See `example_power_curves.csv' and `example_power_coefficient_curves.csv` in example/data for the required form of a csv file (more columns can be added). See :py:func:`~.get_turbine_data_from_file` for an example reading data from a csv file. Parameters ---------- fetch_curve : string Parameter to specify whether a power or power coefficient curve should be retrieved from the provided turbine data. Valid options are 'power_curve' and 'power_coefficient_curve'. Default: None. data_source : string Specifies whether turbine data (f.e. nominal power, power curve, power coefficient curve) is loaded from the OpenEnergy Database ('oedb') or from a csv file ('<path including file name>'). Default: 'oedb'. Returns ------- self Examples -------- >>> from windpowerlib import wind_turbine >>> enerconE126 = { ... 'hub_height': 135, ... 'rotor_diameter': 127, ... 'name': 'E-126/4200', ... 'fetch_curve': 'power_coefficient_curve', ... 'data_source': 'oedb'} >>> e126 = wind_turbine.WindTurbine(**enerconE126) >>> print(e126.power_coefficient_curve['value'][5]) 0.44 >>> print(e126.nominal_power) 4200000.0 """ if data_source == 'oedb': curve_df, nominal_power = get_turbine_data_from_oedb( turbine_type=self.name, fetch_curve=fetch_curve) else: curve_df, nominal_power = get_turbine_data_from_file( turbine_type=self.name, file_=data_source) if fetch_curve == 'power_curve': self.power_curve = curve_df elif fetch_curve == 'power_coefficient_curve': self.power_coefficient_curve = curve_df else: raise ValueError("'{0}' is an invalid value. ".format( fetch_curve) + "`fetch_curve` must be " + "'power_curve' or 'power_coefficient_curve'.") if self.nominal_power is None: self.nominal_power = nominal_power return self
[docs]def get_turbine_data_from_file(turbine_type, file_): r""" Fetches power (coefficient) curve data from a csv file. See `example_power_curves.csv' and `example_power_coefficient_curves.csv` in example/data for the required format of a csv file. The self-provided csv file may contain more columns than the example files. Only columns containing wind speed and the corresponding power or power coefficient as well as the column 'nominal_power' are taken into account. Parameters ---------- turbine_type : string Specifies the turbine type data is fetched for. file_ : string Specifies the source of the turbine data. See the example below for how to use the example data. Returns ------- Tuple (pandas.DataFrame, float) Power curve or power coefficient curve (pandas.DataFrame) and nominal power (float). Power (coefficient) curve DataFrame contains power coefficient curve values (dimensionless) or power curve values in W as column names with the corresponding wind speeds in m/s. Examples -------- >>> from windpowerlib import wind_turbine >>> import os >>> source = os.path.join(os.path.dirname(__file__), '../example/data', ... 'example_power_curves.csv') >>> example_turbine = { ... 'hub_height': 100, ... 'rotor_diameter': 70, ... 'name': 'DUMMY 3', ... 'fetch_curve': 'power_curve', ... 'data_source': source} >>> e_t_1 = wind_turbine.WindTurbine(**example_turbine) >>> print(e_t_1.power_curve['value'][7]) 18000.0 >>> print(e_t_1.nominal_power) 150000 """ def isfloat(x): try: float(x) return x except: return False try: df = pd.read_csv(file_, index_col=0) except FileNotFoundError: raise FileNotFoundError("The file '{}' was not found.".format(file_)) wpp_df = df[df.turbine_id == turbine_type] # if turbine not in data file if wpp_df.shape[0] == 0: pd.set_option('display.max_rows', len(df)) logging.info('Possible types: \n{0}'.format(df.turbine_id)) pd.reset_option('display.max_rows') sys.exit('Cannot find the wind converter type: {0}'.format( turbine_type)) # if turbine in data file select power (coefficient) curve columns and # drop nans cols = [_ for _ in wpp_df.columns if isfloat(_)] curve_data = wpp_df[cols].dropna(axis=1) df = curve_data.transpose().reset_index() df.columns = ['wind_speed', 'value'] df['wind_speed'] = df['wind_speed'].apply(lambda x: float(x)) nominal_power = wpp_df['p_nom'].iloc[0] return df, nominal_power
[docs]def get_turbine_data_from_oedb(turbine_type, fetch_curve): r""" Gets turbine data from the OpenEnergy Database (oedb). Parameters ---------- turbine_type : string Specifies the turbine type data is fetched for. Use :py:func:`~.get_turbine_types` to see a table of all wind turbines for which power (coefficient) curve data is provided. fetch_curve : string Parameter to specify whether a power or power coefficient curve should be retrieved from the provided turbine data. Valid options are 'power_curve' and 'power_coefficient_curve'. Default: None. Returns ------- Tuple (pandas.DataFrame, float) Power curve or power coefficient curve (pandas.DataFrame) and nominal power (float). Power (coefficient) curve DataFrame contains power coefficient curve values (dimensionless) or power curve values in W with the corresponding wind speeds in m/s. """ # Extract data turbine_data = load_turbine_data_from_oedb() turbine_data.set_index('turbine_type', inplace=True) # Set `curve` depending on `fetch_curve` to match names in oedb curve = ('cp_curve' if fetch_curve == 'power_coefficient_curve' else fetch_curve) # Select curve and nominal power of turbine type try: df = pd.DataFrame(turbine_data.loc[turbine_type][curve]) except KeyError: raise KeyError("Turbine type '{}' not in database. ".format( turbine_type) + "Use 'get_turbine_types()' to see a table of " + "possible wind turbine types.") nominal_power = turbine_data.loc[turbine_type][ 'installed_capacity_kw'] * 1000 df.columns = ['wind_speed', 'value'] if fetch_curve == 'power_curve': # power in W df['value'] = df['value'] * 1000 return df, nominal_power
[docs]def load_turbine_data_from_oedb(): r""" Loads turbine data from the OpenEnergy Database (oedb). Returns ------- turbine_data : pd.DataFrame Contains turbine data of different turbines such as 'manufacturer', 'turbine_type', nominal power ('installed_capacity_kw'). """ # url of OpenEnergy Platform that contains the oedb oep_url = 'http://oep.iks.cs.ovgu.de/' # location of data schema = 'model_draft' table = 'openfred_windpower_powercurve' # load data result = requests.get( oep_url + '/api/v0/schema/{}/tables/{}/rows/?'.format( schema, table), ) if result.status_code == 200: logging.info("Database connection successful.") else: raise ConnectionError("Database connection not successful. " + "Error: ".format(result.status_code)) # extract data turbine_data = pd.DataFrame(result.json()) return turbine_data
[docs]def get_turbine_types(print_out=True): r""" Get the names of all possible wind turbine types for which the power coefficient curve or power curve is provided in the OpenEnergy Data Base (oedb). Parameters ---------- print_out : boolean Directly prints a tabular containing the turbine types in column 'turbine_type', the manufacturer in column 'manufacturer' and information about whether a power (coefficient) curve exists (True) or not (False) in columns 'has_power_curve' and 'has_cp_curve'. Default: True. Returns ------- curves_df : pd.DataFrame Contains turbine types in column 'turbine_type', the manufacturer in column 'manufacturer' and information about whether a power (coefficient) curve exists (True) or not (False) in columns 'has_power_curve' and 'has_cp_curve'. Examples -------- >>> from windpowerlib import wind_turbine >>> df = wind_turbine.get_turbine_types(print_out=False) >>> print(df[df["turbine_type"].str.contains("E-126")].iloc[0]) manufacturer Enercon turbine_type E-126/4200 has_power_curve True has_cp_curve True Name: 5, dtype: object >>> print(df[df["manufacturer"].str.contains("Enercon")].iloc[0]) manufacturer Enercon turbine_type E-101/3050 has_power_curve True has_cp_curve True Name: 1, dtype: object """ df = load_turbine_data_from_oedb() cp_curves_df = df.iloc[df.loc[df['has_cp_curve'] == True].index][ ['manufacturer', 'turbine_type', 'has_cp_curve']] p_curves_df = df.iloc[df.loc[df['has_power_curve'] == True].index][ ['manufacturer', 'turbine_type', 'has_power_curve']] curves_df = pd.merge(p_curves_df, cp_curves_df, how='outer', sort=True).fillna(False) if print_out: pd.set_option('display.max_rows', len(curves_df)) print(curves_df) pd.reset_option('display.max_rows') return curves_df