Source code for feedinlib.powerplants

# -*- coding: utf-8 -*-

"""
Power plant classes for specific weather dependent renewable energy resources.

Power plant classes act as data holders for the attributes making up a
power plant's specification. These classes should only contain little logic.
Computing the actual feed-in provided by a power plant is done by the models
(see models.py). The model the feed-in is calculated with is specified in
the `model` attribute.

"""

from abc import ABC, abstractmethod

from feedinlib.models import Pvlib, WindpowerlibTurbine


[docs]class Base(ABC): """ The base class of feedinlib power plants. The class mainly serves as a data container for power plant attributes. Actual calculation of feed-in provided by the power plant is done by the chosen model. See model.py module for implemented models. This base class is an abstract class serving as a blueprint for classes that implement weather dependent renewable energy power plants. It forces implementors to implement certain properties and methods. Parameters ---------- model : A subclass or instance of subclass of :class:`~.models.Base` The `model` parameter defines the feed-in model used to calculate the power plant feed-in. If a class (or in general, any instance of :class:`type`) is provided, it is used to create the model instance encapsulating the actual mathematical model used to calculate the feed-in provided by this power plant. In any other case, the provided object is used directly. Note though, that a reference to this power plant is saved in the provided object, so sharing model instances between two power plant objects is not a good idea, as the second power plant will overwrite the reference to the first. The non-class version is only provided for users who need the extra flexibility of controlling model instantiation and who know what they are doing. In general, you'll want to provide a class for this parameter or just go with the default for the specific subclass you are using. **attributes : Besides `model` parameter provided attributes hold the technical specification used to define the power plant. See `power_plant_parameters` parameter in respective model's :meth:`feedin` method for further information on the model's required and optional plant parameters. Raises ------ AttributeError In case an attribute listed in the given model's required parameters is not present in the `parameters` parameter. """
[docs] def __init__(self, **attributes): """ """ model = attributes.pop("model") if isinstance(model, type): model = model(**attributes) self.model = model self.parameters = attributes # check if all power plant attributes required by the respective model # are provided self._check_models_power_plant_requirements(attributes.keys())
[docs] @abstractmethod def feedin(self, weather, **kwargs): """ Calculates power plant feed-in in Watt. This method delegates the actual computation to the model's :meth:`feedin` method while giving you the opportunity to override some of the inputs used to calculate the feed-in. If the respective model does calculate AC and DC feed-in, AC feed-in is returned by default. See the model's :meth:`feedin` method for information on how to overwrite this default behaviour. Parameters ---------- weather : Weather data to calculate feed-in. Check the `weather` parameter of the respective model's :meth:`feedin` method for required weather data parameters and format. **kwargs : Keyword arguments for respective model's feed-in calculation. Check the keyword arguments of the model's :meth:`feedin` for further information. Returns ------- feedin : :pandas:`pandas.Series<series>` Series with power plant feed-in in Watt. """ model = kwargs.pop("model", self.model) # in case a different model used to calculate feed-in than originally # assigned is given, self.model is overwritten and required power plant # parameters for new model are checked if not model == self.model: model = model(**self.parameters) self.model = model self._check_models_power_plant_requirements(self.parameters.keys()) # check if all arguments required by the feed-in model are given keys = kwargs.keys() for k in model.requires: if not k in keys: raise AttributeError( "The specified model '{model}' requires model " "parameter '{k}' but it's not provided as an " "argument.".format(k=k, model=model) ) # call respective model's feed-in method return model.feedin( weather=weather, power_plant_parameters=self.parameters, **kwargs )
def _check_models_power_plant_requirements(self, parameters): """ Checks if given model's required power plant parameters are provided. An error is raised if the attributes required by the given model are not contained in the provided parameters in `parameters`. Parameters ----------- parameters : list(str) List of provided power plant parameters. Raises ------ AttributeError In case an attribute listed in the given model's required parameters is not present in the `parameters` parameter. """ try: # call the given model's check function if implemented self.model._power_plant_requires_check(parameters) except NotImplementedError: for k in self.required: if k not in parameters: raise AttributeError( "The specified model '{model}' requires power plant " "parameter '{k}' but it's not provided as an " "argument.".format(k=k, model=self.model) ) @property def required(self): """ The power plant parameters the specified model requires. Check the model's :attr:`power_plant_requires` attribute for further information. """ return self.model.power_plant_requires
[docs]class Photovoltaic(Base): """ Class to define a standard set of PV system attributes. The Photovoltaic class serves as a data container for PV system attributes. Actual calculation of feed-in provided by the PV system is done by the chosen PV model. So far there is only one PV model, :class:`~.models.Pvlib`. Parameters ---------- model : A subclass or instance of subclass of \ :class:`~.models.PhotovoltaicModelBase` The `model` parameter defines the feed-in model used to calculate the PV system feed-in. It defaults to :class:`~feedinlib.models.Pvlib` which is currently the only implemented photovoltaic model. `model` is used as the `model` parameter for :class:`Base`. **attributes : PV system parameters. See `power_plant_parameters` parameter in respective model's :func:`feedin` method for further information on the model's required and optional plant parameters. As the :class:`~.models.Pvlib` model is currently the only implemented photovoltaic model see `power_plant_parameters` parameter :meth:`~.models.Pvlib.feedin` for further information. """
[docs] def __init__(self, model=Pvlib, **attributes): """ """ super().__init__(model=model, **attributes)
[docs] def feedin(self, weather, scaling=None, **kwargs): """ Calculates PV system feed-in in Watt. The feed-in can further be scaled by PV system area or peak power using the `scaling` parameter. This method delegates the actual computation to the model's :meth:`feedin` method while giving you the opportunity to override some of the inputs used to calculate the feed-in. As the :class:`~.models.Pvlib` model is currently the only implemented photovoltaic model see :meth:`~.models.Pvlib.feedin` for further information on feed-in calculation. If the respective model does calculate AC and DC feed-in, AC feed-in is returned by default. See the model's :meth:`feedin` method for information on how to overwrite this default behaviour. Parameters ---------- weather : Weather data to calculate feed-in. Check the `weather` parameter of the respective model's :meth:`feedin` method for required weather data parameters and format. scaling : str Specifies what feed-in is scaled by. Possible options are 'peak_power' and 'area'. Defaults to None in which case feed-in is not scaled. **kwargs Keyword arguments for respective model's feed-in calculation. Check the keyword arguments of the model's :meth:`feedin` method for further information. Returns ------- :pandas:`pandas.Series<series>` Series with PV system feed-in in Watt. """ # delegate feed-in calculation feedin = super().feedin(weather=weather, **kwargs) # scale feed-in if scaling: feedin_scaling = { "peak_power": lambda feedin: feedin / float(self.peak_power), "area": lambda feedin: feedin / float(self.area), } return feedin_scaling[scaling](feedin) return feedin
@property def area(self): """ Area of PV system in :math:`m^2`. See :attr:`pv_system_area` attribute of your chosen model for further information on how the area is calculated. """ return self.model.pv_system_area @property def peak_power(self): """ Peak power of PV system in Watt. See :attr:`pv_system_peak_power` attribute of your chosen model for further information and specifications on how the peak power is calculated. """ return self.model.pv_system_peak_power
[docs]class WindPowerPlant(Base): """ Class to define a standard set of wind power plant attributes. The WindPowerPlant class serves as a data container for wind power plant attributes. Actual calculation of feed-in provided by the wind power plant is done by the chosen wind power model. So far there are two wind power models, :class:`~.models.WindpowerlibTurbine` and :class:`~.models.WindpowerlibTurbineCluster`. The :class:`~.models.WindpowerlibTurbine` model should be used for single wind turbines, whereas the :class:`~.models.WindpowerlibTurbineCluster` model can be used for wind farm and wind turbine cluster calculations. Parameters ---------- model : A subclass or instance of subclass of \ :class:`feedinlib.models.WindpowerModelBase` The `model` parameter defines the feed-in model used to calculate the wind power plant feed-in. It defaults to :class:`~.models.WindpowerlibTurbine`. `model` is used as the `model` parameter for :class:`Base`. **attributes : Wind power plant parameters. See `power_plant_parameters` parameter in respective model's :meth:`feedin` method for further information on the model's required and optional plant parameters. """
[docs] def __init__(self, model=WindpowerlibTurbine, **attributes): """ """ super().__init__(model=model, **attributes)
[docs] def feedin(self, weather, scaling=None, **kwargs): """ Calculates wind power plant feed-in in Watt. The feed-in can further be scaled by the nominal power of the wind power plant using the `scaling` parameter. This method delegates the actual computation to the model's meth:`feedin` method while giving you the opportunity to override some of the inputs used to calculate the feed-in. See model's :meth:`feedin` method for further information on feed-in calculation. Parameters ---------- weather : Weather data to calculate feed-in. Check the `weather` parameter of the respective model's :meth:`feedin` method for required weather data parameters and format. scaling : str Specifies what feed-in is scaled by. Possible option is 'nominal_power'. Defaults to None in which case feed-in is not scaled. **kwargs Keyword arguments for respective model's feed-in calculation. Check the keyword arguments of the model's :meth:`feedin` method for further information. Returns ------- :pandas:`pandas.Series<series>` Series with wind power plant feed-in in Watt. """ # delegate feed-in calculation feedin = super().feedin(weather, **kwargs) # scale feed-in if scaling: feedin_scaling = { "nominal_power": lambda feedin: feedin / float(self.nominal_power) } return feedin_scaling[scaling](feedin) return feedin
@property def nominal_power(self): """ Nominal power of wind power plant in Watt. See :attr:`nominal_power` attribute of your chosen model for further information on how the nominal power is derived. """ return self.model.nominal_power_wind_power_plant