Passed
Pull Request — dev (#850)
by Uwe
01:35
created

add_constraints   A

Complexity

Total Complexity 5

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 5
eloc 68
dl 0
loc 149
rs 10
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
B run_add_constraints_example() 0 102 5
1
# -*- coding: utf-8 -*-
2
3
"""
4
General description
5
-------------------
6
This script shows how to add an individual constraint to the oemof solph
7
OperationalModel.
8
The constraint we add forces a flow to be greater or equal a certain share
9
of all inflows of its target bus. Moreover we will set an emission constraint.
10
11
Installation requirements
12
-------------------------
13
This example requires oemof.solph (v0.5.x), install by:
14
15
    pip install oemof.solph[examples]
16
17
To draw the graph pygraphviz is required, installed by:
18
19
    pip install pygraphviz
20
21
License
22
-------
23
Simon Hilpert - 31.10.2016 - [email protected]
24
25
`MIT license <https://github.com/oemof/oemof-solph/blob/dev/LICENSE>`_
26
"""
27
28
__copyright__ = "oemof developer group"
29
__license__ = "GPLv3"
30
31
import logging
32
33
import pandas as pd
34
import pyomo.environ as po
35
36
from oemof.solph import Bus
37
from oemof.solph import EnergySystem
38
from oemof.solph import Flow
39
from oemof.solph import Model
40
from oemof.solph import components as cmp
41
42
43
def run_add_constraints_example(solver="cbc", nologg=False):
44
    if not nologg:
45
        logging.basicConfig(level=logging.INFO)
46
    # ##### creating an oemof solph optimization model, nothing special here ##
47
    # create an energy system object for the oemof solph nodes
48
    es = EnergySystem(
49
        timeindex=pd.date_range("1/1/2017", periods=5, freq="H"),
50
        infer_last_interval=False,
51
    )
52
    # add some nodes
53
54
    boil = Bus(label="oil", balanced=False)
55
    blig = Bus(label="lignite", balanced=False)
56
    b_el = Bus(label="b_el")
57
58
    es.add(boil, blig, b_el)
59
60
    sink = cmp.Sink(
61
        label="Sink",
62
        inputs={b_el: Flow(nominal_value=40, fix=[0.5, 0.4, 0.3, 1])},
63
    )
64
    pp_oil = cmp.Transformer(
65
        label="pp_oil",
66
        inputs={boil: Flow()},
67
        outputs={b_el: Flow(nominal_value=50, variable_costs=25)},
68
        conversion_factors={b_el: 0.39},
69
    )
70
    pp_lig = cmp.Transformer(
71
        label="pp_lig",
72
        inputs={blig: Flow()},
73
        outputs={b_el: Flow(nominal_value=50, variable_costs=10)},
74
        conversion_factors={b_el: 0.41},
75
    )
76
77
    es.add(sink, pp_oil, pp_lig)
78
79
    # create the model
80
    om = Model(energysystem=es)
81
82
    # add specific emission values to flow objects if source is a commodity bus
83
    for s, t in om.flows.keys():
84
        if s is boil:
85
            om.flows[s, t].emission_factor = 0.27  # t/MWh
86
        if s is blig:
87
            om.flows[s, t].emission_factor = 0.39  # t/MWh
88
    emission_limit = 60e3
89
90
    # add the outflow share
91
    om.flows[(boil, pp_oil)].outflow_share = [1, 0.5, 0, 0.3]
92
93
    # Now we are going to add a 'sub-model' and add a user specific constraint
94
    # first we add a pyomo Block() instance that we can use to add our
95
    # constraints. Then, we add this Block to our previous defined
96
    # Model instance and add the constraints.
97
    myblock = po.Block()
98
99
    # create a pyomo set with the flows (i.e. list of tuples),
100
    # there will of course be only one flow inside this set, the one we used to
101
    # add outflow_share
102
    myblock.MYFLOWS = po.Set(
103
        initialize=[
104
            k for (k, v) in om.flows.items() if hasattr(v, "outflow_share")
105
        ]
106
    )
107
108
    # pyomo does not need a po.Set, we can use a simple list as well
109
    myblock.COMMODITYFLOWS = [
110
        k for (k, v) in om.flows.items() if hasattr(v, "emission_factor")
111
    ]
112
113
    # add the sub-model to the oemof Model instance
114
    om.add_component("MyBlock", myblock)
115
116
    def _inflow_share_rule(m, s, e, t):
117
        """pyomo rule definition: Here we can use all objects from the block or
118
        the om object, in this case we don't need anything from the block
119
        except the newly defined set MYFLOWS.
120
        """
121
        expr = om.flow[s, e, t] >= om.flows[s, e].outflow_share[t] * sum(
122
            om.flow[i, o, t] for (i, o) in om.FLOWS if o == e
123
        )
124
        return expr
125
126
    myblock.inflow_share = po.Constraint(
127
        myblock.MYFLOWS, om.TIMESTEPS, rule=_inflow_share_rule
128
    )
129
    # add emission constraint
130
    myblock.emission_constr = po.Constraint(
131
        expr=(
132
            sum(
133
                om.flow[i, o, t]
134
                for (i, o) in myblock.COMMODITYFLOWS
135
                for t in om.TIMESTEPS
136
            )
137
            <= emission_limit
138
        )
139
    )
140
141
    # solve and write results to dictionary
142
    # you may print the model with om.pprint()
143
    om.solve(solver=solver)
144
    logging.info("Successfully finished.")
145
146
147
if __name__ == "__main__":
148
    run_add_constraints_example()
149