Esempio n. 1
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.from_bus = kwargs.get('from_bus')

        self.to_bus = kwargs.get('to_bus')

        self.reactance = sequence(kwargs.get('reactance', 0.00001))

        self.capacity = kwargs.get('capacity')

        self.capacity_cost = kwargs.get('capacity_cost')

        # oemof related attribute setting of 'Flow-object'
        self.input = self.from_bus

        self.output = self.to_bus

        self.bidirectional = True

        self.nominal_value = self.capacity

        self.min = sequence(-1)

        self.investment = self._investment()
Esempio n. 2
0
    def __init__(self, energysystem, **kwargs):
        super().__init__()

        # ########################  Arguments #################################

        self.name = kwargs.get('name', type(self).__name__)

        self.es = energysystem

        try:
            self.timeincrement = sequence(self.es.timeindex.freq.nanos / 3.6e12)
        except AttributeError:
            logging.warning(
                'Could not get timeincrement from pd.DateTimeIndex! ' +
                'To avoid this warning, make sure the `freq` attribute of ' +
                'your timeindex is not None. Setting timeincrement to 1...')
            self.timeincrement = sequence(1)



        self.objective_weighting = kwargs.get('objective_weighting',
                                              self.timeincrement)

        self._constraint_groups = (type(self).CONSTRAINT_GROUPS +
                                   kwargs.get('constraint_groups', []))

        self._constraint_groups += [i for i in self.es.groups
                                    if hasattr(i, 'CONSTRAINT_GROUP') and
                                    i not in self._constraint_groups]

        self.flows = self.es.flows()

        if kwargs.get("auto_construct", True):
            self._construct()
Esempio n. 3
0
    def build_solph_components(self):
        """
        """

        if self.expandable:
            raise NotImplementedError(
                "Investment for solar thermal collector facade has not been implemented yet."
            )

        inflow = Source(
            label=self.label + "-inflow",
            outputs={
                self:
                Flow(nominal_value=self.aperture_area,
                     max=self.collectors_heat)
            },
        )

        self.conversion_factors.update({
            self.electricity_in_bus:
            sequence(self.electrical_consumption *
                     (1 - self.peripheral_losses)),
            self.heat_out_bus:
            sequence(1 - self.peripheral_losses),
            inflow:
            sequence(1)
        })

        self.inputs.update({self.electricity_in_bus: Flow()})
        self.outputs.update({self.heat_out_bus: Flow()})

        self.subnodes = (inflow, )
Esempio n. 4
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args,
                         **kwargs,
                         _facade_requires_=['from_bus', 'to_bus'])

        self.capacity = kwargs.get('capacity')

        self.efficiency = kwargs.get('efficiency', 1)

        self.marginal_cost = kwargs.get('marginal_cost', 0)

        self.capacity_cost = kwargs.get('capacity_cost')

        self.input_edge_parameters = kwargs.get('input_edge_parameters', {})

        self.output_edge_parameters = kwargs.get('output_edge_parameters', {})

        self.conversion_factors.update({
            self.from_bus: sequence(1),
            self.to_bus: sequence(self.efficiency)
        })

        self.inputs.update({self.from_bus: Flow(**self.input_edge_parameters)})

        self.outputs.update({
            self.to_bus:
            Flow(nominal_value=self.capacity,
                 variable_costs=self.marginal_cost,
                 investment=self._investment(),
                 **self.output_edge_parameters)
        })
Esempio n. 5
0
    def __init__(self, energysystem, **kwargs):
        super().__init__()

        # ########################  Arguments #################################

        self.name = kwargs.get('name', type(self).__name__)
        self.es = energysystem
        self.timeincrement = sequence(kwargs.get('timeincrement', None))

        if self.timeincrement[0] is None:
            try:
                self.timeincrement = sequence(self.es.timeindex.freq.nanos /
                                              3.6e12)
            except AttributeError:
                msg = ("No valid time increment found. Please pass a valid "
                       "timeincremet parameter or pass an EnergySystem with "
                       "a valid time index. Please note that a valid time"
                       "index need to have a 'freq' attribute.")
                raise AttributeError(msg)

        self.objective_weighting = kwargs.get('objective_weighting',
                                              self.timeincrement)

        self._constraint_groups = (type(self).CONSTRAINT_GROUPS +
                                   kwargs.get('constraint_groups', []))

        self._constraint_groups += [
            i for i in self.es.groups if hasattr(i, 'CONSTRAINT_GROUP')
            and i not in self._constraint_groups
        ]

        self.flows = self.es.flows()

        if kwargs.get("auto_construct", True):
            self._construct()
Esempio n. 6
0
    def build_solph_components(self):
        """
        """
        self.conversion_factors.update({
            self.fuel_bus:
            sequence(1),
            self.electricity_bus:
            sequence(self.electric_efficiency),
            self.heat_bus:
            sequence(self.thermal_efficiency),
        })

        self.inputs.update({
            self.fuel_bus:
            Flow(variable_costs=self.carrier_cost, **self.input_parameters)
        })

        self.outputs.update({
            self.electricity_bus:
            Flow(
                nominal_value=self._nominal_value(),
                investment=self._investment(),
            ),
            self.heat_bus:
            Flow(),
        })
Esempio n. 7
0
    def build_solph_components(self):
        """
        """

        if self.expandable:
            raise NotImplementedError(
                "Investment for reservoir class is not implemented.")

        inflow = Source(
            label=self.label + "-inflow",
            outputs={
                self:
                Flow(nominal_value=self.aperture_area,
                     max=self.collectors_heat)
            },
        )

        self.conversion_factors.update({
            self.electrical_bus:
            sequence(self.electrical_consumption *
                     (1 - self.additional_losses)),
            self.heat_bus:
            sequence(1 - self.additional_losses),
            inflow:
            sequence(1)
        })

        self.inputs.update({self.electrical_bus: Flow()})
        self.outputs.update({self.heat_bus: Flow()})

        self.subnodes = (inflow, )
Esempio n. 8
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args,
                         **kwargs,
                         _facade_requires_=['from_bus', 'to_bus'])

        self.capacity = kwargs.get('capacity')

        self.loss = kwargs.get('loss', 0)

        self.capacity_cost = kwargs.get('capacity_cost')

        investment = self._investment()

        self.inputs.update({self.from_bus: Flow(), self.to_bus: Flow()})

        self.outputs.update({
            self.from_bus:
            Flow(nominal_value=self.capacity, investment=investment),
            self.to_bus:
            Flow(nominal_value=self.capacity, investment=investment)
        })

        self.conversion_factors.update({
            (self.from_bus, self.to_bus):
            sequence((1 - self.loss)),
            (self.to_bus, self.from_bus):
            sequence((1 - self.loss))
        })
Esempio n. 9
0
    def __init__(self, **kwargs):
        # TODO: Check if we can inherit from pyomo.core.base.var _VarData
        # then we need to create the var object with
        # pyomo.core.base.IndexedVarWithDomain before any Flow is created.
        # E.g. create the variable in the energy system and populate with
        # information afterwards when creating objects.

        super().__init__()

        scalars = [
            'nominal_value', 'summed_max', 'summed_min', 'investment',
            'nonconvex', 'integer', 'fixed'
        ]
        sequences = ['actual_value', 'variable_costs', 'min', 'max']
        dictionaries = ['positive_gradient', 'negative_gradient']
        defaults = {
            'fixed': False,
            'min': 0,
            'max': 1,
            'variable_costs': 0,
            'positive_gradient': {
                'ub': None,
                'costs': 0
            },
            'negative_gradient': {
                'ub': None,
                'costs': 0
            },
        }
        keys = [k for k in kwargs if k != 'label']

        for attribute in set(scalars + sequences + dictionaries + keys):
            value = kwargs.get(attribute, defaults.get(attribute))
            if attribute in dictionaries:
                setattr(self, attribute, {
                    'ub': sequence(value['ub']),
                    'costs': value['costs']
                })
            elif 'fixed_costs' in attribute:
                raise AttributeError(
                    "The `fixed_costs` attribute has been removed"
                    " with v0.2!")
            else:
                setattr(self, attribute,
                        sequence(value) if attribute in sequences else value)

        # Checking for impossible attribute combinations
        if self.fixed and self.actual_value[0] is None:
            raise ValueError("Cannot fix flow value to None.\n Please "
                             "set the actual_value attribute of the flow")
        if self.investment and self.nominal_value is not None:
            raise ValueError("Using the investment object the nominal_value"
                             " has to be set to None.")
        if self.investment and self.nonconvex:
            raise ValueError("Investment flows cannot be combined with " +
                             "nonconvex flows!")
Esempio n. 10
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.conversion_factors = {
            k: sequence(v)
            for k, v in kwargs.get('conversion_factors', {}).items()
        }

        missing_conversion_factor_keys = (
            (set(self.outputs) | set(self.inputs)) -
            set(self.conversion_factors))

        for cf in missing_conversion_factor_keys:
            self.conversion_factors[cf] = sequence(1)
Esempio n. 11
0
    def __init__(self, *args, **kwargs):
        super().__init__(conversion_factor_full_condensation={},
                         *args,
                         **kwargs,
                         _facade_requires_=[
                             'carrier', 'electricity_bus', 'heat_bus',
                             'thermal_efficiency', 'electric_efficiency',
                             'condensing_efficiency'
                         ])

        self.carrier = kwargs.get('carrier')

        self.carrier_cost = kwargs.get('carrier_cost', 0)

        self.capacity = kwargs.get('capacity')

        self.condensing_efficiency = sequence(self.condensing_efficiency)

        self.marginal_cost = kwargs.get('marginal_cost', 0)

        self.capacity_cost = kwargs.get('capacity_cost')

        self.electricity_bus = kwargs.get('electricity_bus')

        self.heat_bus = kwargs.get('heat_bus')

        self.conversion_factors.update({
            self.carrier:
            sequence(1),
            self.electricity_bus:
            sequence(self.electric_efficiency),
            self.heat_bus:
            sequence(self.thermal_efficiency)
        })

        self.inputs.update(
            {self.carrier: Flow(variable_cost=self.carrier_cost)})

        self.outputs.update({
            self.electricity_bus:
            Flow(nominal_value=self.capacity,
                 variable_costs=self.marginal_cost,
                 investment=self._investment()),
            self.heat_bus:
            Flow()
        })

        self.conversion_factor_full_condensation.update(
            {self.electricity_bus: self.condensing_efficiency})
Esempio n. 12
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.heat_loss_factor = sequence(kwargs.get('heat_loss_factor', 0))
        self.heat_loss_factor_fix = sequence(
            kwargs.get('heat_loss_factor_fix', 0))

        self._invest_group = False
        self._nonconvex_group = False
        self._demand_group = False

        if len(self.inputs) > 1 or len(self.outputs) > 2:
            if len(self.outputs) == 2:
                self._demand_group = True
            else:
                raise ValueError("Heatpipe must not have more than"
                                 " one input and two outputs!")

        for f in self.inputs.values():
            if f.nonconvex is not None:
                raise ValueError(
                    "Inputflow must not be of type NonConvexFlow!")

        for f in self.outputs.values():
            if f.nonconvex is not None:
                self._nonconvex_group = True

        self._check_flows_invest()

        if (self._nonconvex_group is True) and (self._invest_group is True):
            raise ValueError(
                "Either an investment OR a switchable heatloss can be set"
                " (NonConvexFlow)."
                " Remove the NonConvexFlow or drop "
                "the Investment attribute.")

        if self._invest_group is True:
            self._set_flows()
            o = list(self.outputs.keys())[0]
            if (self.heat_loss_factor_fix[0] > 0) \
                    and (self.outputs[o].investment.nonconvex is False):
                warnings.warn(
                    "Be careful! In case of a convex Investment "
                    "(Investment.nonconvex is False), the "
                    "'heat_loss_factor_fix' is considered, even though the "
                    "investment might be zero! => A simple sink could be "
                    "the results. Hopefully, you know what you are doing.")
        else:
            self._set_nominal_value()
Esempio n. 13
0
def calculate_timeincrement(timeindex, fill_value=None):
    """
    Calculates timeincrement for `timeindex`

    Parameters
    ----------
    timeindex: pd.DatetimeIndex
        timeindex of energysystem
    fill_value: numerical
        timeincrement for first timestep in hours
    """
    if isinstance(timeindex, pd.DatetimeIndex) and \
        (fill_value and isinstance(fill_value, pd.Timedelta) or
         fill_value is None):
        if len(set(timeindex)) != len(timeindex):
            raise IndexError("No equal DatetimeIndex allowed!")
        timeindex = timeindex.to_series()
        timeindex_sorted = timeindex.sort_values()
        if fill_value:
            timeincrement = timeindex_sorted.diff().fillna(value=fill_value)
        else:
            timeincrement = timeindex_sorted.diff().fillna(method='bfill')
        timeincrement_sec = timeincrement.map(dt.timedelta.total_seconds)
        timeincrement_hourly = list(timeincrement_sec.map(lambda x: x / 3600))
        timeincrement = sequence(timeincrement_hourly)
        return timeincrement
    else:
        raise AttributeError(
            "'timeindex' must be of type 'DatetimeIndex' and " +
            "'fill_value' of type 'Timedelta'.")
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.length = kwargs.get('length')
        self.heat_loss_factor = sequence(kwargs.get('heat_loss_factor'))

        self._invest_group = False

        if len(self.inputs) > 1 or len(self.outputs) > 1:
            raise ValueError("Heatpipe must not have more than \
                             one input and one output!")

        for f in self.inputs.values():
            if f.nonconvex is not None:
                raise ValueError(
                    "Attribute `nonconvex` of component `HeatPipeline`" +
                    "has not been tested yet.")

        for f in self.outputs.values():
            if f.nonconvex is not None:
                raise ValueError(
                    "Attribute `nonconvex` of component `HeatPipeline`" +
                    "has not been tested yet.")

        self._check_flows()
Esempio n. 15
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.reactance = sequence(kwargs.get('reactance', 0.00001))

        if len(self.inputs) > 1 or len(self.outputs) > 1:
            raise ValueError("Component ElectricLine must not have more than \
                             one input and one output!")

        self.input = self._input()
        self.output = self._output()

        # set input / output flow values to -1 by default if not set by user
        for f in self.inputs.values():
            if f.nonconvex is not None:
                raise ValueError("Attribute `nonconvex` must be None for" +
                                 " inflows of component `ElectricalLine`!")
            if f.min is None:
                f.min = -1
            # to be used in grouping for all bidi flows
            f.bidirectional = True

        for f in self.outputs.values():
            if f.nonconvex is not None:
                raise ValueError("Attribute `nonconvex` must be None for" +
                                 " outflows of component `ElectricalLine`!")
            if f.min is None:
                f.min = -1
            # to be used in grouping for all bidi flows
            f.bidirectional = True
Esempio n. 16
0
    def build_solph_components(self):
        """
        """
        self.nominal_storage_capacity = self.storage_capacity

        self.inflow_conversion_factor = sequence(self.efficiency)

        self.outflow_conversion_factor = sequence(self.efficiency)

        # make it investment but don't set costs (set below for flow (power))
        self.investment = self._investment()

        if self.investment:
            self.invest_relation_input_output = 1

            for attr in ["invest_relation_input_output"]:
                if getattr(self, attr) is None:
                    raise AttributeError(
                        ("You need to set attr "
                         "`{}` "
                         "for component {}").format(attr, self.label))

            # set capacity costs at one of the flows
            fi = Flow(investment=Investment(
                ep_costs=self.capacity_cost,
                maximum=self.capacity_potential,
                existing=self.capacity,
            ),
                      **self.input_parameters)
            # set investment, but no costs (as relation input / output = 1)
            fo = Flow(investment=Investment(),
                      variable_costs=self.marginal_cost,
                      **self.output_parameters)
            # required for correct grouping in oemof.solph.components
            self._invest_group = True
        else:
            fi = Flow(nominal_value=self._nominal_value(),
                      **self.input_parameters)
            fo = Flow(nominal_value=self._nominal_value(),
                      variable_costs=self.marginal_cost,
                      **self.output_parameters)

        self.inputs.update({self.bus: fi})

        self.outputs.update({self.bus: fo})

        self._set_flows()
Esempio n. 17
0
    def build_solph_components(self):
        """
        """
        self.conversion_factors.update({
            self.from_bus: sequence(1),
            self.to_bus: sequence(self.efficiency),
        })

        self.inputs.update({self.from_bus: Flow(**self.input_parameters)})

        self.outputs.update({
            self.to_bus:
            Flow(nominal_value=self._nominal_value(),
                 variable_costs=self.marginal_cost,
                 investment=self._investment(),
                 **self.output_parameters)
        })
Esempio n. 18
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if len(self.inputs) > 2 or len(self.outputs) > 2:
            raise ValueError("Component `Link` must not have more than \
                             2 inputs and 2 outputs!")

        self.conversion_factors = {
            k: sequence(v)
            for k, v in kwargs.get('conversion_factors', {}).items()}
Esempio n. 19
0
    def __init__(self, **kwargs):
        scalars = ['minimum_uptime', 'minimum_downtime', 'initial_status']
        sequences = ['startup_costs', 'shutdown_costs']
        defaults = {'initial_status': 0}

        for attribute in set(scalars + sequences + list(kwargs)):
            value = kwargs.get(attribute, defaults.get(attribute))
            setattr(self, attribute,
                    sequence(value) if attribute in sequences else value)

        self._max_up_down = None
Esempio n. 20
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if not self.inputs:
            msg = "`Transformer` '{0}' constructed without `inputs`."
            warn(msg.format(self), debugging.SuspiciousUsageWarning)
        if not self.outputs:
            msg = "`Transformer` '{0}' constructed without `outputs`."
            warn(msg.format(self), debugging.SuspiciousUsageWarning)

        self.conversion_factors = {
            k: sequence(v)
            for k, v in kwargs.get('conversion_factors', {}).items()
        }

        missing_conversion_factor_keys = (
            (set(self.outputs) | set(self.inputs)) -
            set(self.conversion_factors))

        for cf in missing_conversion_factor_keys:
            self.conversion_factors[cf] = sequence(1)
Esempio n. 21
0
def constraint_optimization_against_two_values(om: solph.Model,
                                               limit: float) -> solph.Model:
    """
        Function for optimization against two parameters
        (e.g. monetary, emissions)

        :param om: oemof solph model to which the constraints will be \
                   added
        :type om: oemof.solph.Model
        :param limit: maximum value for the second parameter for the \
                      whole energysystem
        :type limit: int
        :return: - **om** (oemof.solph.Model) - oemof solph Model within \
                                                the constraints
    """
    import pyomo.environ as po
    from oemof.solph.plumbing import sequence
    invest_flows = {}
    for (i, o) in om.flows:
        if hasattr(om.flows[i, o].investment, "periodical_constraint_costs"):
            invest_flows[(i, o)] = om.flows[i, o].investment

    limit_name = "invest_limit_" + "space"

    setattr(om, limit_name, po.Expression(
        expr=sum(om.InvestmentFlow.invest[inflow, outflow] *
                 getattr(invest_flows[inflow, outflow],
                         "periodical_constraint_costs")
                 for (inflow, outflow) in invest_flows
                 )))

    ############
    flows = {}
    for (i, o) in om.flows:
        if hasattr(om.flows[i, o], "emission_factor"):
            flows[(i, o)] = om.flows[i, o]

    limit_name1 = "integral_limit_" + "emission_factor"

    setattr(om, limit_name1, po.Expression(
        expr=sum(om.flow[inflow, outflow, t]
                 * om.timeincrement[t]
                 * sequence(getattr(flows[inflow, outflow],
                                    "emission_factor"))[t]
                 for (inflow, outflow) in flows
                 for t in om.TIMESTEPS)))

    setattr(om, limit_name + "_constraint", po.Constraint(
        expr=((getattr(om, limit_name) + getattr(om, limit_name1)) <= limit)))

    return om
Esempio n. 22
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.reactance = sequence(kwargs.get('reactance', 0.00001))

        # set input / output flow values to -1 by default if not set by user
        if self.nonconvex is not None:
            raise ValueError(
                ("Attribute `nonconvex` must be None for " +
                 "component `ElectricalLine` from {} to {}!").format(
                     self.input, self.output))
        if self.min is None:
            self.min = -1
        # to be used in grouping for all bidi flows
        self.bidirectional = True
Esempio n. 23
0
    def build_solph_components(self):
        """
        """
        investment = self._investment()

        self.inputs.update({self.from_bus: Flow(), self.to_bus: Flow()})

        self.outputs.update({
            self.from_bus:
            Flow(
                variable_costs=self.marginal_cost,
                nominal_value=self._nominal_value(),
                investment=investment,
            ),
            self.to_bus:
            Flow(nominal_value=self._nominal_value(), investment=investment),
        })

        self.conversion_factors.update({
            (self.from_bus, self.to_bus):
            sequence((1 - self.loss)),
            (self.to_bus, self.from_bus):
            sequence((1 - self.loss)),
        })
Esempio n. 24
0
    def __init__(self, *args, **kwargs):
        kwargs.update({"_facade_requires_": ["bus", "carrier", "tech"]})
        super().__init__(*args, **kwargs)

        self.profile = kwargs.get("profile", sequence(1))

        self.capacity = kwargs.get("capacity")

        self.capacity_potential = kwargs.get("capacity_potential")

        self.marginal_cost = kwargs.get("marginal_cost", 0)

        self.capacity_cost = kwargs.get("capacity_cost")

        self.expandable = bool(kwargs.get("expandable", False))

        self.output_parameters = kwargs.get("output_parameters", {})

        self.build_solph_components()
Esempio n. 25
0
    def __init__(self, *args, **kwargs):
        kwargs.update({
            "_facade_requires_": [
                "fuel_bus",
                "carrier",
                "tech",
                "electricity_bus",
                "heat_bus",
                "thermal_efficiency",
                "electric_efficiency",
                "condensing_efficiency",
            ]
        })
        super().__init__(conversion_factor_full_condensation={},
                         *args,
                         **kwargs)

        self.fuel_bus = kwargs.get("fuel_bus")

        self.electricity_bus = kwargs.get("electricity_bus")

        self.heat_bus = kwargs.get("heat_bus")

        self.carrier = kwargs.get("carrier")

        self.carrier_cost = kwargs.get("carrier_cost", 0)

        self.capacity = kwargs.get("capacity")

        self.condensing_efficiency = sequence(self.condensing_efficiency)

        self.marginal_cost = kwargs.get("marginal_cost", 0)

        self.capacity_cost = kwargs.get("capacity_cost")

        self.expandable = bool(kwargs.get("expandable", False))

        self.input_parameters = kwargs.get("input_parameters", {})

        self.build_solph_components()
Esempio n. 26
0
    def __init__(self, energysystem, **kwargs):
        super().__init__()

        # ########################  Arguments #################################

        self.name = kwargs.get('name', type(self).__name__)

        self.es = energysystem

        self.timeincrement = sequence(self.es.timeindex.freq.nanos / 3.6e12)

        self._constraint_groups = (type(self).CONSTRAINT_GROUPS +
                                   kwargs.get('constraint_groups', []))

        self._constraint_groups += [
            i for i in self.es.groups if hasattr(i, 'CONSTRAINT_GROUP')
            and i not in self._constraint_groups
        ]

        self.flows = self.es.flows()

        if kwargs.get("auto_construct", True):
            self._construct()
Esempio n. 27
0
    def build_solph_components(self):
        """
        """
        self.nominal_storage_capacity = self.storage_capacity

        self.outflow_conversion_factor = sequence(self.efficiency)

        if self.expandable:
            raise NotImplementedError(
                "Investment for reservoir class is not implemented.")

        inflow = Source(
            label=self.label + "-inflow",
            outputs={
                self: Flow(nominal_value=1, max=self.profile, fixed=False)
            },
        )

        self.outputs.update({
            self.bus:
            Flow(nominal_value=self.capacity, **self.output_parameters)
        })

        self.subnodes = (inflow, )
Esempio n. 28
0
    def build_solph_components(self):
        """
        """
        self.inflow_conversion_factor = sequence(self.efficiency)

        self.outflow_conversion_factor = sequence(self.efficiency)

        self.loss_rate = sequence(self.loss_rate)

        self.fixed_losses_relative = sequence(self.fixed_losses_relative)

        self.fixed_losses_absolute = sequence(self.fixed_losses_absolute)

        # make it investment but don't set costs (set below for flow (power))
        self.investment = self._investment()

        if self.investment:
            self.invest_relation_input_output = 1

            for attr in ["invest_relation_input_output"]:
                if getattr(self, attr) is None:
                    raise AttributeError(
                        ("You need to set attr "
                         "`{}` "
                         "for component {}").format(attr, self.label))

            # set capacity costs at one of the flows
            fi = Flow(investment=Investment(
                ep_costs=self.capacity_cost,
                maximum=self.capacity_potential,
                existing=self.capacity,
            ),
                      **self.input_parameters)
            # set investment, but no costs (as relation input / output = 1)
            fo = Flow(investment=Investment(),
                      variable_costs=self.marginal_cost,
                      **self.output_parameters)
            # required for correct grouping in oemof.solph.components
            self._invest_group = True
        else:
            self.volume = calculate_storage_dimensions(self.height,
                                                       self.diameter)[0]

            self.nominal_storage_capacity = calculate_capacities(
                self.volume, self.temp_h, self.temp_c, **{
                    key: value
                    for key, value in self.water_properties.items()
                    if value is not None
                })

            fi = Flow(nominal_value=self._nominal_value(),
                      **self.input_parameters)
            fo = Flow(nominal_value=self._nominal_value(),
                      variable_costs=self.marginal_cost,
                      **self.output_parameters)

        self.inputs.update({self.bus: fi})

        self.outputs.update({self.bus: fo})

        self._set_flows()
Esempio n. 29
0
def generic_integral_limit(om, keyword, flows=None, limit=None):
    """Set a global limit for flows weighted by attribute called keyword.
    The attribute named by keyword has to be added
    to every flow you want to take into account.

    Total value of keyword attributes after optimization can be retrieved
    calling the :attr:`om.oemof.solph.Model.integral_limit_${keyword}()`.

    Parameters
    ----------
    om : oemof.solph.Model
        Model to which constraints are added.
    flows : dict
        Dictionary holding the flows that should be considered in constraint.
        Keys are (source, target) objects of the Flow. If no dictionary is
        given all flows containing the keyword attribute will be
        used.
    keyword : attribute to consider
    limit : numeric
        Absolute limit of keyword attribute for the energy system.

    Note
    ----
    Flow objects required an attribute named like keyword!

    **Constraint:**

    .. math:: \sum_{i \in F_E} \sum_{t \in T} P_i(t) \cdot w_i(t)
               \cdot \tau(t) \leq M


    With `F_I` being the set of flows considered for the integral limit and
    `T` being the set of time steps.

    The symbols used are defined as follows
    (with Variables (V) and Parameters (P)):

    ================ ==== =====================================================
    math. symbol     type explanation
    ================ ==== =====================================================
    :math:`P_n(t)`   V    power flow :math:`n` at time step :math:`t`
    :math:`w_N(t)`   P    weight given to Flow named according to `keyword`
    :math:`\tau(t)`  P    width of time step :math:`t`
    :math:`L`        P    global limit given by keyword `limit`

    """
    if flows is None:
        flows = {}
        for (i, o) in om.flows:
            if hasattr(om.flows[i, o], keyword):
                flows[(i, o)] = om.flows[i, o]

    else:
        for (i, o) in flows:
            if not hasattr(flows[i, o], keyword):
                raise AttributeError(
                    ('Flow with source: {0} and target: {1} '
                     'has no attribute {2}.').format(i.label, o.label,
                                                     keyword))

    limit_name = "integral_limit_" + keyword

    setattr(
        om, limit_name,
        po.Expression(expr=sum(
            om.flow[inflow, outflow, t] * om.timeincrement[t] *
            sequence(getattr(flows[inflow, outflow], keyword))[t]
            for (inflow, outflow) in flows for t in om.TIMESTEPS)))

    setattr(om, limit_name + "_constraint",
            po.Constraint(expr=(getattr(om, limit_name) <= limit)))

    return om
Esempio n. 30
0
    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs, _facade_requires_=['bus'])

        self.storage_capacity = kwargs.get('storage_capacity')

        self.capacity = kwargs.get('capacity')

        self.nominal_capacity = self.storage_capacity

        self.capacity_cost = kwargs.get('capacity_cost')

        self.loss = sequence(kwargs.get('loss', 0))

        self.inflow_conversion_factor = sequence(kwargs.get('efficiency', 1))

        self.outflow_conversion_factor = sequence(kwargs.get('efficiency', 1))

        # make it investment but don't set costs (set below for flow (power))
        self.investment = self._investment()

        self.input_edge_parameters = kwargs.get('input_edge_parameters', {})

        self.output_edge_parameters = kwargs.get('output_edge_parameters', {})

        if self.investment:
            if kwargs.get('capacity_ratio') is None:
                raise AttributeError(
                    ("You need to set attr `capacity_ratio` for "
                     "component {}").format(self.label))
            else:
                self.invest_relation_input_capacity = kwargs.get(
                    'capacity_ratio')
                self.invest_relation_output_capacity = kwargs.get(
                    'capacity_ratio')
                self.invest_relation_input_output = 1

            # set capacity costs at one of the flows
            fi = Flow(investment=Investment(ep_costs=self.capacity_cost,
                                            maximum=getattr(
                                                self, 'capacity_potential',
                                                float('+inf'))),
                      **self.input_edge_parameters)
            # set investment, but no costs (as relation input / output = 1)
            fo = Flow(investment=Investment(), **self.output_edge_parameters)
            # required for correct grouping in oemof.solph.components
            self._invest_group = True
        else:
            investment = None

            fi = Flow(nominal_value=self.capacity,
                      **self.input_edge_parameters)
            fo = Flow(nominal_value=self.capacity,
                      **self.output_edge_parameters)

        self.inputs.update({self.bus: fi})

        self.outputs.update({self.bus: fo})

        # annoying oemof stuff, that requires _set_flows() to provide a
        # drepreciated warning
        self._set_flows('Ignore this warning...')