Passed
Pull Request — dev (#852)
by Uwe
07:13 queued 05:59
created

solph.constraints.set_idle_time.set_idle_time()   B

Complexity

Conditions 5

Size

Total Lines 61
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 32
dl 0
loc 61
rs 8.6453
c 0
b 0
f 0
cc 5
nop 5

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
# -*- coding: utf-8 -*-
2
3
"""Constraints to relate variables in an existing model.
4
5
SPDX-FileCopyrightText: Jann Launer
6
7
SPDX-License-Identifier: MIT
8
"""
9
from pyomo import environ as po
10
11
12
def set_idle_time(model, f1, f2, n, name_constraint="constraint_idle_time"):
13
    r"""
14
    Enforces f1 to be inactive for n timesteps before f2 can be active.
15
16
    For each timestep status of f2 can only be "on" if f1 has been off
17
    the previous n timesteps.
18
19
    **Constraint:**
20
21
    .. math:: X_2(t) \cdot \sum_{s=0}^t X_1(s) = 0 \forall t < n
22
    .. math:: X_2(t) \cdot \sum_{s=t-n}^t X_1(s) = 0 \forall t \le n
23
24
    """
25
    # make sure that idle time is not longer than number of timesteps
26
    n_timesteps = len(model.TIMESTEPS)
27
    assert n_timesteps > n, (
28
        f"Selected idle time {n}"
29
        f"is longer than total number of timesteps {n_timesteps}"
30
    )
31
32
    def _idle_rule(m):
33
        # In the first n steps, the status of f1 has to be inactive
34
        # for f2 to be active
35
        for ts in list(m.TIMESTEPS)[:n]:
36
            expr = (
37
                m.NonConvexFlowBlock.status[f2[0], f2[1], ts]
38
                * sum(
39
                    m.NonConvexFlowBlock.status[f1[0], f1[1], t]
40
                    for t in range(ts + 1)
41
                )
42
                == 0
43
            )
44
            if expr is not True:
45
                getattr(m, name_constraint).add(ts, expr)
46
47
        # for all following timesteps, f1 has to be inactive in the preceding
48
        # window of n timesteps for f2 to be active
49
        for ts in list(m.TIMESTEPS)[n:]:
50
            expr = (
51
                m.NonConvexFlowBlock.status[f2[0], f2[1], ts]
52
                * sum(
53
                    m.NonConvexFlowBlock.status[f1[0], f1[1], t]
54
                    for t in range(ts - n, ts + 1)
55
                )
56
                == 0
57
            )
58
            if expr is not True:
59
                getattr(m, name_constraint).add(ts, expr)
60
61
    setattr(
62
        model,
63
        name_constraint,
64
        po.Constraint(model.TIMESTEPS, noruleinit=True),
65
    )
66
    setattr(
67
        model,
68
        name_constraint + "_build",
69
        po.BuildAction(rule=_idle_rule),
70
    )
71
72
    return model
73