Passed
Pull Request — dev (#1174)
by
unknown
01:56
created

example_generic_invest_offset.main()   B

Complexity

Conditions 3

Size

Total Lines 188
Code Lines 119

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 119
dl 0
loc 188
rs 7
c 0
b 0
f 0
cc 3
nop 1

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
r"""
3
General description
4
-------------------
5
Example that shows how to use "Generic Investment Limit With Offset".
6
7
There are two supply chains. The energy systems looks like that:
8
9
.. code-block:: text
10
11
                  bus_a_0          bus_a_1
12
                   |                 |
13
    source_a_0 --->|---> trafo_a --->|--->demand_a
14
                                     |
15
                       source_a_1--->|
16
                                     |
17
18
                  bus_b_0          bus_b_1
19
                   |                 |
20
    source_b_0 --->|---> trafo_b --->|--->demand_b
21
                                     |
22
                       source_b_1--->|
23
                                     |
24
                                     v
25
                              generic_storage_b
26
                               /            \
27
                              |              |
28
                              v              v
29
                            bus_b_1        bus_b_1
30
31
32
Everything is identical - the costs for the sources, the demand, the efficiency
33
of the Converter. And both Converter have an investment at the output.
34
The source '\*_1' is in both cases very expensive, so that
35
a investment is probably done in the converter. The demand and the
36
maximum investment in Converter b1 is so set, that an investment in a generic
37
storage is beneficial to not use source b0.
38
Now, all investments share a third resource, which is called "space" in this
39
example. (This could be anything, and you could use as many additional
40
resources as you want.) And this resource is limited. In this case, every
41
converter and storage capacity unit, which might be installed, needs 2 space
42
for each installed capacity as well as an offset.
43
See what happens, have fun ;)
44
45
Code
46
----
47
Download source code: :download:`example_generic_invest.py </../examples/generic_invest_limit/example_generic_invest_offset.py>`
48
49
.. dropdown:: Click to display code
50
51
    .. literalinclude:: /../examples/generic_invest_limit/example_generic_invest_offset.py
52
        :language: python
53
        :lines: 62-
54
55
Installation requirements
56
-------------------------
57
This example requires oemof.solph (v0.5.x), install by:
58
59
.. code:: bash
60
61
    pip install oemof.solph[examples]
62
63
License
64
-------
65
Maximilian Hillen <[email protected]>
66
67
`MIT license <https://github.com/oemof/oemof-solph/blob/dev/LICENSE>`_
68
"""
69
70
import logging
71
import os
72
73
from PIL.ImageChops import offset
74
75
try:
76
    import matplotlib.pyplot as plt
77
except ModuleNotFoundError:
78
    plt = None
79
80
from oemof import solph
81
82
83
def main(optimize=True):
84
85
    data = [2, 2, 12, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
86
    # create an energy system
87
    idx = solph.create_time_index(2020, number=len(data))
88
    es = solph.EnergySystem(timeindex=idx, infer_last_interval=False)
89
90
    # Parameter: costs for the sources
91
    c_0 = 10
92
    c_1 = 100
93
94
    epc_invest = 50
95
96
    # commodity a
97
    bus_a_0 = solph.Bus(label="bus_a_0")
98
    bus_a_1 = solph.Bus(label="bus_a_1")
99
    es.add(bus_a_0, bus_a_1)
100
101
    es.add(
102
        solph.components.Source(
103
            label="source_a_0",
104
            outputs={bus_a_0: solph.Flow(variable_costs=c_0)},
105
        )
106
    )
107
108
    es.add(
109
        solph.components.Source(
110
            label="source_a_1",
111
            outputs={bus_a_1: solph.Flow(variable_costs=c_1 * 10000)},
112
        )
113
    )
114
115
    es.add(
116
        solph.components.Sink(
117
            label="demand_a",
118
            inputs={bus_a_1: solph.Flow(fix=data, nominal_capacity=1)},
119
        )
120
    )
121
122
    # commodity b
123
    bus_b_0 = solph.Bus(label="bus_b_0")
124
    bus_b_1 = solph.Bus(label="bus_b_1")
125
    es.add(bus_b_0, bus_b_1)
126
    es.add(
127
        solph.components.Source(
128
            label="source_b_0",
129
            outputs={bus_b_0: solph.Flow(variable_costs=c_0)},
130
        )
131
    )
132
133
    es.add(
134
        solph.components.Source(
135
            label="source_b_1",
136
            outputs={bus_b_1: solph.Flow(variable_costs=c_1 * 10000)},
137
        )
138
    )
139
140
    es.add(
141
        solph.components.Sink(
142
            label="demand_b",
143
            inputs={bus_b_1: solph.Flow(fix=data, nominal_capacity=1)},
144
        )
145
    )
146
147
    # Converter a
148
    es.add(
149
        solph.components.Converter(
150
            label="trafo_a",
151
            inputs={bus_a_0: solph.Flow()},
152
            outputs={
153
                bus_a_1: solph.Flow(
154
                    nominal_capacity=solph.Investment(
155
                        ep_costs=epc_invest,
156
                        custom_attributes={"space": {"cost": 1, "offset": 20}},
157
                        nonconvex=True,
158
                        maximum=20,
159
                    ),
160
                    custom_attributes={"space": 0.1},
161
                )
162
            },
163
            conversion_factors={bus_a_1: 1},
164
        )
165
    )
166
167
    # Converter b
168
    es.add(
169
        solph.components.Converter(
170
            label="trafo_b",
171
            inputs={bus_b_0: solph.Flow()},
172
            outputs={
173
                bus_b_1: solph.Flow(
174
                    nominal_capacity=solph.Investment(
175
                        ep_costs=epc_invest,
176
                        custom_attributes={"space": {"cost": 1}},
177
                        nonconvex=True,
178
                        maximum=10,
179
                    ),
180
                    custom_attributes={"space": 0.1},
181
                )
182
            },
183
        )
184
    )
185
    # Generic Storage b_0
186
    generic_storage_b_0 = solph.components.GenericStorage(
187
        label="generic_storage_b_0",
188
        inputs={bus_b_1: solph.Flow()},
189
        outputs={bus_b_1: solph.Flow()},
190
        inflow_conversion_factor=1,
191
        nominal_capacity = solph.Investment(
192
            ep_costs=epc_invest ,
193
            nonconvex=True,
194
            maximum=1,
195
            custom_attributes={"space": {"cost": 0.5, "offset":1 }},
196
        ),
197
        invest_relation_input_capacity = 0.5,
198
        invest_relation_output_capacity = 0.5,
199
    )
200
201
    es.add(generic_storage_b_0)
202
203
    # Generic Storage b_1
204
    generic_storage_b_1 = solph.components.GenericStorage(
205
            label="generic_storage_b_1",
206
            inputs={bus_b_1: solph.Flow()},
207
            outputs={bus_b_1: solph.Flow()},
208
            inflow_conversion_factor=1,
209
            nominal_capacity = solph.Investment(
210
                ep_costs=epc_invest *100,
211
                nonconvex=True,
212
                maximum=2,
213
                custom_attributes={"space": {"cost": 1, "offset":5 }},
214
                )
215
            ,
216
        )
217
218
    es.add(generic_storage_b_1)
219
    if optimize is False:
220
        return es
221
222
    # create an optimization problem and solve it
223
    om = solph.Model(es)
224
225
    # add constraint for generic investment limit
226
    om = solph.constraints.additional_total_limit(om, "space", limit=100)
227
    # export lp file
228
    filename = os.path.join(
229
        solph.helpers.extend_basic_path("lp_files"), "GenericInvest.lp"
230
    )
231
    logging.info("Store lp-file in {0}.".format(filename))
232
    om.write(filename, io_options={"symbolic_solver_labels": True})
233
234
    # solve model
235
    om.solve(solver="gurobi", solve_kwargs={"tee": True})
236
237
    # create result object
238
    results = solph.processing.results(om)
239
240
    bus1 = solph.views.node(results, "bus_a_1")["sequences"]
241
    bus2 = solph.views.node(results, "bus_b_1")["sequences"]
242
243
    # plot the time series (sequences) of a specific component/bus
244
    if plt is not None:
245
        bus1.plot(kind="line", drawstyle="steps-mid")
246
        plt.legend()
247
        plt.show()
248
        bus2.plot(kind="line", drawstyle="steps-mid")
249
        plt.legend()
250
        plt.show()
251
252
    space_used = om.total_limit_space()
253
    print("Space value: ", space_used)
254
    print(
255
        "Investment trafo_a: ",
256
        solph.views.node(results, "trafo_a")["scalars"][0],
257
    )
258
    print(
259
        "Investment trafo_b: ",
260
        solph.views.node(results, "trafo_b")["scalars"][0],
261
    )
262
263
    print(
264
        "Investment generic_storage_b_0: ",
265
        results[generic_storage_b_0, None]["scalars"]["total"],
266
    )
267
268
    print(
269
        "Investment generic_storage_b_1: ",
270
        results[generic_storage_b_1, None]["scalars"]["total"],
271
    )
272
273
if __name__ == "__main__":
274
    main()
275