Source code for oemof.solph.flows._non_convex_flow_block
# -*- coding: utf-8 -*-
"""Creating sets, variables, constraints and parts of the objective function
for Flow objects with nonconvex but without investment options.
SPDX-FileCopyrightText: Uwe Krien <krien@uni-bremen.de>
SPDX-FileCopyrightText: Simon Hilpert
SPDX-FileCopyrightText: Cord Kaldemeyer
SPDX-FileCopyrightText: Patrik Schönfeldt
SPDX-FileCopyrightText: Birgit Schachler
SPDX-FileCopyrightText: jnnr
SPDX-FileCopyrightText: jmloenneberga
SPDX-FileCopyrightText: Johannes Kochems
SPDX-License-Identifier: MIT
"""
from pyomo.core import Binary
from pyomo.core import Constraint
from pyomo.core import Expression
from pyomo.core import NonNegativeReals
from pyomo.core import Set
from pyomo.core import Var
from pyomo.core.base.block import ScalarBlock
from . import _shared
[docs]
class NonConvexFlowBlock(ScalarBlock):
r"""
.. automethod:: _create_constraints
.. automethod:: _create_variables
.. automethod:: _create_sets
.. automethod:: _objective_expression
Parameters are defined in :class:`Flow`.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def _create(self, group=None):
"""Creates set, variables, constraints for all flow object with
an attribute flow of type class:`.NonConvexFlowBlock`.
Parameters
----------
group : list
List of oemof.solph.NonConvexFlowBlock objects for which
the constraints are build.
"""
if group is None:
return None
self._create_sets(group)
self._create_variables()
self._create_constraints()
[docs]
def _create_sets(self, group):
r"""
**The following sets are created:** (-> see basic sets at
:class:`.Model` )
FIXED_CAPACITY_NONCONVEX_FLOWS
A set of flows with the attribute `nonconvex` of type
:class:`.options.NonConvex`.
Also creates everything listed in `_sets_for_non_convex_flows`.
"""
self.FIXED_CAPACITY_NONCONVEX_FLOWS = Set(
initialize=[(g[0], g[1]) for g in group]
)
_shared.sets_for_non_convex_flows(self, group)
[docs]
def _create_variables(self):
r"""
:math:`Y_{status}` (binary) `om.NonConvexFlowBlock.status`:
Variable indicating if flow is >= 0
:math:`P_{max,status}` Status_nominal (continuous)
Variable indicating if flow is >= 0
Also creates :py:func:`_variables_for_non_convex_flows`.
"""
m = self.parent_block()
self.status = Var(
self.FIXED_CAPACITY_NONCONVEX_FLOWS, m.TIMESTEPS, within=Binary
)
for o, i in self.FIXED_CAPACITY_NONCONVEX_FLOWS:
if m.flows[o, i].nonconvex.initial_status is not None:
for t in range(
0, m.flows[o, i].nonconvex.first_flexible_timestep
):
self.status[o, i, t] = m.flows[
o, i
].nonconvex.initial_status
self.status[o, i, t].fix()
# `status_nominal` is a parameter which represents the
# multiplication of a binary variable (`status`)
# and a continuous variable (`invest` or `nominal_capacity`)
self.status_nominal = Var(
self.FIXED_CAPACITY_NONCONVEX_FLOWS,
m.TIMESTEPS,
within=NonNegativeReals,
)
_shared.variables_for_non_convex_flows(self)
[docs]
def _create_constraints(self):
"""
The following constraints are created:
.. automethod:: _status_nominal_constraint
Also creates: :py:func:`_minimum_flow_constraint`,
:py:func:`_maximum_flow_constraint`, and
:py:func:`_shared_constraints_for_non_convex_flows`.
"""
self.status_nominal_constraint = self._status_nominal_constraint()
self.min = _shared.minimum_flow_constraint(self)
self.max = _shared.maximum_flow_constraint(self)
_shared.shared_constraints_for_non_convex_flows(self)
[docs]
def _objective_expression(self):
r"""
The following terms are to the cost function:
* :py:func:`_startup_costs`
* :py:func:`_shutdown_costs`
* :py:func:`_activity_costs`
* :py:func:`_inactivity_costs`
"""
if not hasattr(self, "FIXED_CAPACITY_NONCONVEX_FLOWS"):
return 0
startup_costs = _shared.startup_costs(self)
shutdown_costs = _shared.shutdown_costs(self)
activity_costs = _shared.activity_costs(self)
inactivity_costs = _shared.inactivity_costs(self)
self.activity_costs = Expression(expr=activity_costs)
self.inactivity_costs = Expression(expr=inactivity_costs)
self.startup_costs = Expression(expr=startup_costs)
self.shutdown_costs = Expression(expr=shutdown_costs)
self.costs = Expression(
expr=(
startup_costs
+ shutdown_costs
+ activity_costs
+ inactivity_costs
)
)
return self.costs
[docs]
def _status_nominal_constraint(self):
r"""
.. math::
P_{max,status}(t) = Y_{status}(t) \cdot P_{nom}, \\
\forall t \in \textrm{TIMESTEPS}.
"""
m = self.parent_block()
def _status_nominal_rule(_, i, o, t):
"""Rule definition for status_nominal"""
expr = (
self.status_nominal[i, o, t]
== self.status[i, o, t] * m.flows[i, o].nominal_capacity
)
return expr
return Constraint(
self.FIXED_CAPACITY_NONCONVEX_FLOWS,
m.TIMESTEPS,
rule=_status_nominal_rule,
)