Passed
Pull Request — dev (#1220)
by Patrik
01:48
created

NonConvexFlowBlock._create_sets()   A

Complexity

Conditions 1

Size

Total Lines 16
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 16
rs 10
c 0
b 0
f 0
cc 1
nop 2
1
# -*- coding: utf-8 -*-
2
3
"""Creating sets, variables, constraints and parts of the objective function
4
for Flow objects with nonconvex but without investment options.
5
6
SPDX-FileCopyrightText: Uwe Krien <[email protected]>
7
SPDX-FileCopyrightText: Simon Hilpert
8
SPDX-FileCopyrightText: Cord Kaldemeyer
9
SPDX-FileCopyrightText: Patrik Schönfeldt
10
SPDX-FileCopyrightText: Birgit Schachler
11
SPDX-FileCopyrightText: jnnr
12
SPDX-FileCopyrightText: jmloenneberga
13
SPDX-FileCopyrightText: Johannes Kochems
14
15
SPDX-License-Identifier: MIT
16
17
"""
18
19
from pyomo.core import Binary
20
from pyomo.core import Constraint
21
from pyomo.core import Expression
22
from pyomo.core import NonNegativeReals
23
from pyomo.core import Set
24
from pyomo.core import Var
25
from pyomo.core.base.block import ScalarBlock
26
27
from ._shared import activity_costs
28
from ._shared import inactivity_costs
29
from ._shared import maximum_flow_constraint
30
from ._shared import minimum_flow_constraint
31
from ._shared import sets_for_non_convex_flows
32
from ._shared import shared_constraints_for_non_convex_flows
33
from ._shared import shutdown_costs
34
from ._shared import startup_costs
35
from ._shared import variables_for_non_convex_flows
36
37
38
class NonConvexFlowBlock(ScalarBlock):
39
    r"""
40
    .. automethod:: _create_constraints
41
    .. automethod:: _create_variables
42
    .. automethod:: _create_sets
43
44
    .. automethod:: _objective_expression
45
46
    Parameters are defined in :class:`Flow`.
47
    """
48
49
    def __init__(self, *args, **kwargs):
50
        super().__init__(*args, **kwargs)
51
52
    def _create(self, group=None):
53
        """Creates set, variables, constraints for all flow object with
54
        an attribute flow of type class:`.NonConvexFlowBlock`.
55
56
        Parameters
57
        ----------
58
        group : list
59
            List of oemof.solph.NonConvexFlowBlock objects for which
60
            the constraints are build.
61
        """
62
        if group is None:
63
            return None
64
65
        self._create_sets(group)
66
        self._create_variables()
67
        self._create_constraints()
68
69
    def _create_sets(self, group):
70
        r"""
71
        **The following sets are created:** (-> see basic sets at
72
        :class:`.Model` )
73
74
        FIXED_CAPACITY_NONCONVEX_FLOWS
75
            A set of flows with the attribute `nonconvex` of type
76
            :class:`.options.NonConvex`.
77
78
        Also creates everything listed in `_sets_for_non_convex_flows`.
79
        """
80
        self.FIXED_CAPACITY_NONCONVEX_FLOWS = Set(
81
            initialize=[(g[0], g[1]) for g in group]
82
        )
83
84
        sets_for_non_convex_flows(self, group)
85
86
    def _create_variables(self):
87
        r"""
88
        :math:`Y_{status}` (binary) `om.NonConvexFlowBlock.status`:
89
            Variable indicating if flow is >= 0
90
91
        :math:`P_{max,status}` Status_nominal (continuous)
92
            Variable indicating if flow is >= 0
93
94
        Also creates :py:func:`_variables_for_non_convex_flows`.
95
        """
96
        m = self.parent_block()
97
        self.status = Var(
98
            self.FIXED_CAPACITY_NONCONVEX_FLOWS, m.TIMESTEPS, within=Binary
99
        )
100
        for o, i in self.FIXED_CAPACITY_NONCONVEX_FLOWS:
101
            if m.flows[o, i].nonconvex.initial_status is not None:
102
                for t in range(
103
                    0, m.flows[o, i].nonconvex.first_flexible_timestep
104
                ):
105
                    self.status[o, i, t] = m.flows[
106
                        o, i
107
                    ].nonconvex.initial_status
108
                    self.status[o, i, t].fix()
109
110
        # `status_nominal` is a parameter which represents the
111
        # multiplication of a binary variable (`status`)
112
        # and a continuous variable (`invest` or `nominal_capacity`)
113
        self.status_nominal = Var(
114
            self.FIXED_CAPACITY_NONCONVEX_FLOWS,
115
            m.TIMESTEPS,
116
            within=NonNegativeReals,
117
        )
118
119
        variables_for_non_convex_flows(self)
120
121
    def _create_constraints(self):
122
        """
123
        The following constraints are created:
124
125
        .. automethod:: _status_nominal_constraint
126
127
        Also creates: :py:func:`_minimum_flow_constraint`,
128
        :py:func:`_maximum_flow_constraint`, and
129
        :py:func:`_shared_constraints_for_non_convex_flows`.
130
131
        """
132
133
        self.status_nominal_constraint = self._status_nominal_constraint()
134
        self.min = minimum_flow_constraint(self)
135
        self.max = maximum_flow_constraint(self)
136
137
        shared_constraints_for_non_convex_flows(self)
138
139
    def _objective_expression(self):
140
        r"""
141
        The following terms are to the cost function:
142
143
        * :py:func:`_startup_costs`
144
        * :py:func:`_shutdown_costs`
145
        * :py:func:`_activity_costs`
146
        * :py:func:`_inactivity_costs`
147
        """
148
        if not hasattr(self, "FIXED_CAPACITY_NONCONVEX_FLOWS"):
149
            return 0
150
151
        startup_costs = startup_costs(self)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable startup_costs does not seem to be defined.
Loading history...
152
        shutdown_costs = shutdown_costs(self)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable shutdown_costs does not seem to be defined.
Loading history...
153
        activity_costs = activity_costs(self)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable activity_costs does not seem to be defined.
Loading history...
154
        inactivity_costs = inactivity_costs(self)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable inactivity_costs does not seem to be defined.
Loading history...
155
156
        self.activity_costs = Expression(expr=activity_costs)
157
        self.inactivity_costs = Expression(expr=inactivity_costs)
158
        self.startup_costs = Expression(expr=startup_costs)
159
        self.shutdown_costs = Expression(expr=shutdown_costs)
160
161
        self.costs = Expression(
162
            expr=(
163
                startup_costs
164
                + shutdown_costs
165
                + activity_costs
166
                + inactivity_costs
167
            )
168
        )
169
170
        return self.costs
171
172
    def _status_nominal_constraint(self):
173
        r"""
174
        .. math::
175
            P_{max,status}(t) =  Y_{status}(t) \cdot P_{nom}, \\
176
            \forall t \in \textrm{TIMESTEPS}.
177
        """
178
        m = self.parent_block()
179
180
        def _status_nominal_rule(_, i, o, t):
181
            """Rule definition for status_nominal"""
182
            expr = (
183
                self.status_nominal[i, o, t]
184
                == self.status[i, o, t] * m.flows[i, o].nominal_capacity
185
            )
186
            return expr
187
188
        return Constraint(
189
            self.FIXED_CAPACITY_NONCONVEX_FLOWS,
190
            m.TIMESTEPS,
191
            rule=_status_nominal_rule,
192
        )
193