Passed
Pull Request — dev (#799)
by Uwe
01:54
created

ExtractionTurbineCHPBlock.__init__()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nop 3
1
# -*- coding: utf-8 -
2
3
"""
4
ExtractionTurbineCHP and associated individual constraints (blocks)
5
and groupings.
6
7
SPDX-FileCopyrightText: Uwe Krien <[email protected]>
8
SPDX-FileCopyrightText: Simon Hilpert
9
SPDX-FileCopyrightText: Cord Kaldemeyer
10
SPDX-FileCopyrightText: Patrik Schönfeldt
11
SPDX-FileCopyrightText: FranziPl
12
SPDX-FileCopyrightText: jnnr
13
SPDX-FileCopyrightText: Stephan Günther
14
SPDX-FileCopyrightText: FabianTU
15
SPDX-FileCopyrightText: Johannes Röder
16
17
SPDX-License-Identifier: MIT
18
19
"""
20
21
from pyomo.core.base.block import ScalarBlock
22
from pyomo.environ import BuildAction
23
from pyomo.environ import Constraint
24
25
from oemof.solph._plumbing import sequence as solph_sequence
26
from oemof.solph.components._transformer import Transformer
27
28
29
class ExtractionTurbineCHP(Transformer):
30
    r"""
31
    A CHP with an extraction turbine in a linear model. For more options see
32
    the :class:`~oemof.solph.components.GenericCHP` class.
33
34
    One main output flow has to be defined and is tapped by the remaining flow.
35
    The conversion factors have to be defined for the maximum tapped flow (
36
    full CHP mode) and for no tapped flow (full condensing mode). Even though
37
    it is possible to limit the variability of the tapped flow, so that the
38
    full condensing mode will never be reached.
39
40
    Parameters
41
    ----------
42
    conversion_factors : dict
43
        Dictionary containing conversion factors for conversion of inflow
44
        to specified outflow. Keys are output bus objects.
45
        The dictionary values can either be a scalar or a sequence with length
46
        of time horizon for simulation.
47
    conversion_factor_full_condensation : dict
48
        The efficiency of the main flow if there is no tapped flow. Only one
49
        key is allowed. Use one of the keys of the conversion factors. The key
50
        indicates the main flow. The other output flow is the tapped flow.
51
52
    Notes
53
    -----
54
    The following sets, variables, constraints and objective parts are created
55
     * :py:class:`~oemof.solph.components.extraction_turbine_chp.ExtractionTurbineCHPBlock`
56
57
    Examples
58
    --------
59
    >>> from oemof import solph
60
    >>> bel = solph.buses.Bus(label='electricityBus')
61
    >>> bth = solph.buses.Bus(label='heatBus')
62
    >>> bgas = solph.buses.Bus(label='commodityBus')
63
    >>> et_chp = solph.components.ExtractionTurbineCHP(
64
    ...    label='variable_chp_gas',
65
    ...    inputs={bgas: solph.flows.Flow(nominal_value=10e10)},
66
    ...    outputs={bel: solph.flows.Flow(), bth: solph.flows.Flow()},
67
    ...    conversion_factors={bel: 0.3, bth: 0.5},
68
    ...    conversion_factor_full_condensation={bel: 0.5})
69
    """  # noqa: E501
70
71
    def __init__(self, conversion_factor_full_condensation, *args, **kwargs):
72
        super().__init__(*args, **kwargs)
73
        self.conversion_factor_full_condensation = {
74
            k: solph_sequence(v)
75
            for k, v in conversion_factor_full_condensation.items()
76
        }
77
78
    def constraint_group(self):
79
        return ExtractionTurbineCHPBlock
80
81
82
class ExtractionTurbineCHPBlock(ScalarBlock):
83
    r"""Block for the linear relation of nodes with type
84
    :class:`~oemof.solph.components.ExtractionTurbineCHP`
85
86
    **The following two constraints are created:**
87
88
    .. _ETCHP-equations:
89
90
        .. math::
91
            &
92
            (1)\dot H_{Fuel}(t) =
93
               \frac{P_{el}(t) + \dot Q_{th}(t) \cdot \beta(t)}
94
                 {\eta_{el,woExtr}(t)} \\
95
            &
96
            (2)P_{el}(t) \geq \dot Q_{th}(t) \cdot C_b =
97
               \dot Q_{th}(t) \cdot
98
               \frac{\eta_{el,maxExtr}(t)}
99
                 {\eta_{th,maxExtr}(t)}
100
101
    where :math:`\beta` is defined as:
102
103
         .. math::
104
            \beta(t) = \frac{\eta_{el,woExtr}(t) -
105
            \eta_{el,maxExtr}(t)}{\eta_{th,maxExtr}(t)}
106
107
    where the first equation is the result of the relation between the input
108
    flow and the two output flows, the second equation stems from how the two
109
    output flows relate to each other, and the symbols used are defined as
110
    follows (with Variables (V) and Parameters (P)):
111
112
    ========================= ============================================ ==== =========
113
    symbol                    attribute                                    type explanation
114
    ========================= ============================================ ==== =========
115
    :math:`\dot H_{Fuel}`     `flow[i, n, t]`                              V    fuel input flow
116
117
    :math:`P_{el}`            `flow[n, main_output, t]`                    V    electric power
118
119
    :math:`\dot Q_{th}`       `flow[n, tapped_output, t]`                  V    thermal output
120
121
    :math:`\beta`             `main_flow_loss_index[n, t]`                 P    power loss index
122
123
    :math:`\eta_{el,woExtr}`  `conversion_factor_full_condensation[n, t]`  P    electric efficiency
124
                                                                                        without heat extraction
125
    :math:`\eta_{el,maxExtr}` `conversion_factors[main_output][n, t]`      P    electric efficiency
126
                                                                                        with max heat extraction
127
    :math:`\eta_{th,maxExtr}` `conversion_factors[tapped_output][n, t]`    P    thermal efficiency with
128
                                                                                        maximal heat extraction
129
    ========================= ============================================ ==== =========
130
131
    """  # noqa: E501
132
133
    CONSTRAINT_GROUP = True
134
135
    def __init__(self, *args, **kwargs):
136
        super().__init__(*args, **kwargs)
137
138
    def _create(self, group=None):
139
        """Creates the linear constraint for the
140
        :class:`oemof.solph.components.TransformerBlock` block.
141
142
        Parameters
143
        ----------
144
        group : list
145
            List of :class:`oemof.solph.components.ExtractionTurbineCHP`
146
            (trsf) objects for which the linear relation of inputs and outputs
147
            is created e.g. group = [trsf1, trsf2, trsf3, ...]. Note that the
148
            relation is created for all existing relations of the inputs and
149
            all outputs of the transformer. The components inside the list need
150
            to hold all needed attributes.
151
        """
152
        if group is None:
153
            return None
154
155
        m = self.parent_block()
156
157
        for n in group:
158
            n.inflow = list(n.inputs)[0]
159
            n.main_flow = [
160
                k for k, v in n.conversion_factor_full_condensation.items()
161
            ][0]
162
            n.main_output = [o for o in n.outputs if n.main_flow == o][0]
163
            n.tapped_output = [o for o in n.outputs if n.main_flow != o][0]
164
            n.conversion_factor_full_condensation_sq = (
165
                n.conversion_factor_full_condensation[n.main_output]
166
            )
167
            n.flow_relation_index = [
168
                n.conversion_factors[n.main_output][t]
169
                / n.conversion_factors[n.tapped_output][t]
170
                for t in m.TIMESTEPS
171
            ]
172
            n.main_flow_loss_index = [
173
                (
174
                    n.conversion_factor_full_condensation_sq[t]
175
                    - n.conversion_factors[n.main_output][t]
176
                )
177
                / n.conversion_factors[n.tapped_output][t]
178
                for t in m.TIMESTEPS
179
            ]
180
181
        def _input_output_relation_rule(block):
182
            """Connection between input, main output and tapped output."""
183
            for t in m.TIMESTEPS:
0 ignored issues
show
introduced by
The variable m does not seem to be defined for all execution paths.
Loading history...
184
                for g in group:
185
                    lhs = m.flow[g.inflow, g, t]
186
                    rhs = (
187
                        m.flow[g, g.main_output, t]
188
                        + m.flow[g, g.tapped_output, t]
189
                        * g.main_flow_loss_index[t]
190
                    ) / g.conversion_factor_full_condensation_sq[t]
191
                    block.input_output_relation.add((g, t), (lhs == rhs))
192
193
        self.input_output_relation = Constraint(
194
            group, m.TIMESTEPS, noruleinit=True
195
        )
196
        self.input_output_relation_build = BuildAction(
197
            rule=_input_output_relation_rule
198
        )
199
200
        def _out_flow_relation_rule(block):
201
            """Relation between main and tapped output in full chp mode."""
202
            for t in m.TIMESTEPS:
0 ignored issues
show
introduced by
The variable m does not seem to be defined for all execution paths.
Loading history...
203
                for g in group:
204
                    lhs = m.flow[g, g.main_output, t]
205
                    rhs = (
206
                        m.flow[g, g.tapped_output, t]
207
                        * g.flow_relation_index[t]
208
                    )
209
                    block.out_flow_relation.add((g, t), (lhs >= rhs))
210
211
        self.out_flow_relation = Constraint(
212
            group, m.TIMESTEPS, noruleinit=True
213
        )
214
        self.out_flow_relation_build = BuildAction(
215
            rule=_out_flow_relation_rule
216
        )
217