Passed
Pull Request — dev (#821)
by Uwe
02:17
created

solph.components._offset_transformer   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 162
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 12
eloc 47
dl 0
loc 162
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A OffsetTransformerBlock.__init__() 0 2 1
A OffsetTransformerBlock._create() 0 34 2
A OffsetTransformer.constraint_group() 0 2 1
B OffsetTransformer.__init__() 0 23 8
1
# -*- coding: utf-8 -
2
3
"""
4
OffsetTransformer and associated individual constraints (blocks) and groupings.
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: FranziPl
11
SPDX-FileCopyrightText: jnnr
12
SPDX-FileCopyrightText: Stephan Günther
13
SPDX-FileCopyrightText: FabianTU
14
SPDX-FileCopyrightText: Johannes Röder
15
16
SPDX-License-Identifier: MIT
17
18
"""
19
20
from oemof.network import network
21
from pyomo.core.base.block import ScalarBlock
22
from pyomo.environ import Constraint
23
from pyomo.environ import Set
24
25
from oemof.solph._plumbing import sequence as solph_sequence
26
27
28
class OffsetTransformer(network.Transformer):
29
    """An object with one input and one output.
30
31
    Parameters
32
    ----------
33
34
    coefficients : tuple
35
        Tuple containing the first two polynomial coefficients
36
        i.e. the y-intersection and slope of a linear equation.
37
        The tuple values can either be a scalar or a sequence with length
38
        of time horizon for simulation.
39
40
    Notes
41
    -----
42
    The sets, variables, constraints and objective parts are created
43
     * :py:class:`~oemof.solph.components._offset_transformer.OffsetTransformerBlock`
44
45
    Examples
46
    --------
47
48
    >>> from oemof import solph
49
50
    >>> bel = solph.buses.Bus(label='bel')
51
    >>> bth = solph.buses.Bus(label='bth')
52
53
    >>> ostf = solph.components.OffsetTransformer(
54
    ...    label='ostf',
55
    ...    inputs={bel: solph.flows.Flow(
56
    ...        nominal_value=60, min=0.5, max=1.0,
57
    ...        nonconvex=solph.NonConvex())},
58
    ...    outputs={bth: solph.flows.Flow()},
59
    ...    coefficients=(20, 0.5))
60
61
    >>> type(ostf)
62
    <class 'oemof.solph.components._offset_transformer.OffsetTransformer'>
63
    """  # noqa: E501
64
65
    def __init__(self, *args, **kwargs):
66
        super().__init__(*args, **kwargs)
67
68
        if kwargs.get("coefficients") is not None:
69
            self.coefficients = tuple(
70
                [solph_sequence(i) for i in kwargs.get("coefficients")]
71
            )
72
            if len(self.coefficients) != 2:
73
                raise ValueError(
74
                    "Two coefficients or coefficient series have to be given."
75
                )
76
77
        if len(self.inputs) == 1:
78
            for k, v in self.inputs.items():
79
                if not v.nonconvex:
80
                    raise TypeError(
81
                        "Input flows must be of type NonConvexFlow!"
82
                    )
83
84
        if len(self.inputs) > 1 or len(self.outputs) > 1:
85
            raise ValueError(
86
                "Component `OffsetTransformer` must not have "
87
                + "more than 1 input and 1 output!"
88
            )
89
90
    def constraint_group(self):
91
        return OffsetTransformerBlock
92
93
94
class OffsetTransformerBlock(ScalarBlock):
95
    r"""Block for the relation of nodes with type
96
    :class:`~oemof.solph.components._offset_transformer.OffsetTransformer`
97
98
    **The following constraints are created:**
99
100
    .. _OffsetTransformer-equations:
101
102
    .. math::
103
        &
104
        P_{out}(t) = C_1(t) \cdot P_{in}(t) + C_0(t) \cdot Y(t) \\
105
106
107
    .. csv-table:: Variables (V) and Parameters (P)
108
        :header: "symbol", "attribute", "type", "explanation"
109
        :widths: 1, 1, 1, 1
110
111
        ":math:`P_{out}(t)`", "`flow[n, o, t]`", "V", "Power of output"
112
        ":math:`P_{in}(t)`", "`flow[i, n, t]`", "V","Power of input"
113
        ":math:`Y(t)`", "`status[i, n, t]`", "V","binary
114
        status variable of nonconvex input flow "
115
        ":math:`C_1(t)`", "`coefficients[1][n, t]`", "P", "linear
116
        coefficient 1 (slope)"
117
        ":math:`C_0(t)`", "`coefficients[0][n, t]`", "P", "linear
118
        coefficient 0 (y-intersection)"
119
120
121
    """
122
123
    CONSTRAINT_GROUP = True
124
125
    def __init__(self, *args, **kwargs):
126
        super().__init__(*args, **kwargs)
127
128
    def _create(self, group=None):
129
        """Creates the relation for the class:`OffsetTransformer`.
130
131
        Parameters
132
        ----------
133
        group : list
134
            List of oemof.solph.experimental.OffsetTransformer objects for
135
            which the relation of inputs and outputs is created
136
            e.g. group = [ostf1, ostf2, ostf3, ...]. The components inside
137
            the list need to hold an attribute `coefficients` of type dict
138
            containing the conversion factors for all inputs to outputs.
139
        """
140
        if group is None:
141
            return None
142
143
        m = self.parent_block()
144
145
        self.OFFSETTRANSFORMERS = Set(initialize=[n for n in group])
146
147
        def _relation_rule(block, n, t):
148
            """Link binary input and output flow to component outflow."""
149
            expr = 0
150
            expr += -m.flow[n, list(n.outputs.keys())[0], t]
0 ignored issues
show
introduced by
The variable m does not seem to be defined for all execution paths.
Loading history...
151
            expr += (
152
                m.flow[list(n.inputs.keys())[0], n, t] * n.coefficients[1][t]
153
            )
154
            expr += (
155
                m.NonConvexFlowBlock.status[list(n.inputs.keys())[0], n, t]
156
                * n.coefficients[0][t]
157
            )
158
            return expr == 0
159
160
        self.relation = Constraint(
161
            self.OFFSETTRANSFORMERS, m.TIMESTEPS, rule=_relation_rule
162
        )
163