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

NonConvexFlowBlock._create_variables()   A

Complexity

Conditions 4

Size

Total Lines 34
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 34
rs 9.55
c 0
b 0
f 0
cc 4
nop 1
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
79
        .. automethod:: _sets_for_non_convex_flows
80
        """
81
        self.FIXED_CAPACITY_NONCONVEX_FLOWS = Set(
82
            initialize=[(g[0], g[1]) for g in group]
83
        )
84
85
        _sets_for_non_convex_flows(self, group)
86
87
    def _create_variables(self):
88
        r"""
89
        :math:`Y_{status}` (binary) `om.NonConvexFlowBlock.status`:
90
            Variable indicating if flow is >= 0
91
92
        :math:`P_{max,status}` Status_nominal (continuous)
93
            Variable indicating if flow is >= 0
94
95
        .. automethod:: _variables_for_non_convex_flows
96
        """
97
        m = self.parent_block()
98
        self.status = Var(
99
            self.FIXED_CAPACITY_NONCONVEX_FLOWS, m.TIMESTEPS, within=Binary
100
        )
101
        for o, i in self.FIXED_CAPACITY_NONCONVEX_FLOWS:
102
            if m.flows[o, i].nonconvex.initial_status is not None:
103
                for t in range(
104
                    0, m.flows[o, i].nonconvex.first_flexible_timestep
105
                ):
106
                    self.status[o, i, t] = m.flows[
107
                        o, i
108
                    ].nonconvex.initial_status
109
                    self.status[o, i, t].fix()
110
111
        # `status_nominal` is a parameter which represents the
112
        # multiplication of a binary variable (`status`)
113
        # and a continuous variable (`invest` or `nominal_capacity`)
114
        self.status_nominal = Var(
115
            self.FIXED_CAPACITY_NONCONVEX_FLOWS,
116
            m.TIMESTEPS,
117
            within=NonNegativeReals,
118
        )
119
120
        _variables_for_non_convex_flows(self)
121
122
    def _create_constraints(self):
123
        """
124
        The following constraints are created:
125
126
        .. automethod:: _status_nominal_constraint
127
        .. automethod:: _minimum_flow_constraint
128
        .. automethod:: _maximum_flow_constraint
129
        .. automethod:: _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
        .. automethod:: _startup_costs
144
        .. automethod:: _shutdown_costs
145
        .. automethod:: _activity_costs
146
        .. automethod:: _inactivity_costs
147
        """
148
        if not hasattr(self, "FIXED_CAPACITY_NONCONVEX_FLOWS"):
149
            return 0
150
151
        startup_costs = _startup_costs(self)
152
        shutdown_costs = _shutdown_costs(self)
153
        activity_costs = _activity_costs(self)
154
        inactivity_costs = _inactivity_costs(self)
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