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

solph.constraints.set_idle_time   A

Complexity

Total Complexity 5

Size/Duplication

Total Lines 73
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 5
eloc 34
dl 0
loc 73
rs 10
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
B set_idle_time() 0 61 5
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