Completed
Push — dev ( 49e927...0219a0 )
by Patrik
20s queued 12s
created

economics_results_with_invest.main()   C

Complexity

Conditions 8

Size

Total Lines 264
Code Lines 134

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 134
dl 0
loc 264
rs 5.1333
c 0
b 0
f 0
cc 8
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
3
"""
4
General description
5
-------------------
6
7
A basic example to show how to model a simple energy system with oemof.solph.
8
and use the Results class to calculate the variable costs as well as the
9
investment costs.
10
11
The following energy system is modeled:
12
13
.. code-block:: text
14
15
                     input/output  bgas     bel
16
                         |          |        |
17
                         |          |        |
18
     wind(FixedSource)   |------------------>|
19
                         |          |        |
20
     pv(FixedSource)     |------------------>|
21
                         |          |        |
22
     rgas(Commodity)     |--------->|        |
23
                         |          |        |
24
     demand(Sink)        |<------------------|
25
                         |          |        |
26
                         |          |        |
27
     pp_gas(Converter)   |<---------|        |
28
                         |------------------>|
29
                         |          |        |
30
     storage(Storage)    |<------------------|
31
                         |------------------>|
32
33
Code
34
----
35
Download source code: :download:`economic_results.py </../examples/economic_results/economics_results_with_invest.py>`
36
37
.. dropdown:: Click to display code
38
39
    .. literalinclude:: /../examples/economic_results/economics_results_with_invest.py
40
        :language: python
41
        :lines: 61-
42
43
Data
44
----
45
Download data: :download:`time_series.csv </../examples/economic_results/time_series.csv>`
46
47
Installation requirements
48
-------------------------
49
This example requires oemof.solph (v0.6.x), install by:
50
51
.. code:: bash
52
53
    pip install oemof.solph[examples]
54
55
License
56
-------
57
`MIT license <https://github.com/oemof/oemof-solph/blob/dev/LICENSE>`_
58
"""
59
###########################################################################
60
# imports
61
###########################################################################
62
63
import logging
64
import os
65
66
import matplotlib.pyplot as plt
67
import pandas as pd
68
from oemof.tools import logger
69
70
from oemof.solph import EnergySystem
71
from oemof.solph import Investment
72
from oemof.solph import Model
73
from oemof.solph import Results
74
from oemof.solph import buses
75
from oemof.solph import components
76
from oemof.solph import create_time_index
77
from oemof.solph import flows
78
79
80
def get_data_from_file_path(file_path: str) -> pd.DataFrame:
81
    try:
82
        data = pd.read_csv(file_path)
83
    except FileNotFoundError:
84
        dir = os.path.dirname(os.path.abspath(__file__))
85
        data = pd.read_csv(dir + "/" + file_path)
86
    return data
87
88
89
def main(optimize=True):
90
91
    # *************************************************************************
92
    # ********** PART 1 - Define and optimise the energy system ***************
93
    # *************************************************************************
94
95
    # Read data file
96
    file_name = "time_series.csv"
97
    data = get_data_from_file_path(file_name)
98
99
    solver = "cbc"  # 'glpk', 'gurobi',....
100
    number_of_time_steps = len(data)
101
    solver_verbose = False  # show/hide solver output
102
103
    # initiate the logger (see the API docs for more information)
104
    logger.define_logging(
105
        logfile="oemof_example.log",
106
        screen_level=logging.INFO,
107
        file_level=logging.INFO,
108
    )
109
110
    logging.info("Initialize the energy system")
111
    date_time_index = create_time_index(2012, number=number_of_time_steps)
112
113
    # create the energysystem and assign the time index
114
    energysystem = EnergySystem(
115
        timeindex=date_time_index, infer_last_interval=False
116
    )
117
118
    ##########################################################################
119
    # Create oemof objects
120
    ##########################################################################
121
122
    logging.info("Create oemof objects")
123
124
    # The bus objects were assigned to variables which makes it easier to
125
    # connect components to these buses (see below).
126
127
    # create natural gas bus
128
    bus_gas = buses.Bus(label="natural_gas")
129
130
    # create electricity bus
131
    bus_electricity = buses.Bus(label="electricity")
132
133
    # adding the buses to the energy system
134
    energysystem.add(bus_gas, bus_electricity)
135
136
    # create excess component for the electricity bus to allow overproduction
137
    energysystem.add(
138
        components.Sink(
139
            label="excess_bus_electricity",
140
            inputs={bus_electricity: flows.Flow()},
141
        )
142
    )
143
144
    # create source object representing the gas commodity
145
    energysystem.add(
146
        components.Source(
147
            label="rgas",
148
            outputs={bus_gas: flows.Flow()},
149
        )
150
    )
151
152
    # create fixed source object representing wind power plants
153
    energysystem.add(
154
        components.Source(
155
            label="wind",
156
            outputs={
157
                bus_electricity: flows.Flow(
158
                    fix=data["wind"], nominal_capacity=1000000
159
                )
160
            },
161
        )
162
    )
163
164
    # create fixed source object representing pv power plants
165
    energysystem.add(
166
        components.Source(
167
            label="pv",
168
            outputs={
169
                bus_electricity: flows.Flow(
170
                    fix=data["pv"], nominal_capacity=582000
171
                )
172
            },
173
        )
174
    )
175
176
    # create simple sink object representing the electrical demand
177
    # nominal_capacity is set to 1 because demand_el is not a normalised series
178
    energysystem.add(
179
        components.Sink(
180
            label="demand",
181
            inputs={
182
                bus_electricity: flows.Flow(
183
                    fix=data["demand_el"], nominal_capacity=1
184
                )
185
            },
186
        )
187
    )
188
189
    # create simple converter object representing a gas power plant
190
    energysystem.add(
191
        components.Converter(
192
            label="pp_gas",
193
            inputs={bus_gas: flows.Flow()},
194
            outputs={
195
                bus_electricity: flows.Flow(
196
                    nominal_capacity=Investment(
197
                        ep_costs=300, nonconvex=True, offset=400, maximum=10e10
198
                    ),
199
                    variable_costs=50,
200
                )
201
            },
202
            conversion_factors={bus_electricity: 0.58},
203
        )
204
    )
205
206
    # create storage object representing a battery
207
    nominal_capacity = 10077997
208
    nominal_capacity = Investment(ep_costs=80, maximum=nominal_capacity / 6)
209
210
    battery_storage = components.GenericStorage(
211
        nominal_capacity=nominal_capacity,
212
        label="battery_storage",
213
        inputs={bus_electricity: flows.Flow(nominal_capacity=10077997 / 6)},
214
        outputs={
215
            bus_electricity: flows.Flow(
216
                nominal_capacity=10077997 / 6, variable_costs=10
217
            )
218
        },
219
        loss_rate=0.00,
220
        initial_storage_level=None,
221
        inflow_conversion_factor=1,
222
        outflow_conversion_factor=0.8,
223
    )
224
225
    energysystem.add(battery_storage)
226
227
    ##########################################################################
228
    # Optimise the energy system and plot the results
229
    ##########################################################################
230
231
    if optimize is False:
232
        return energysystem
233
234
    logging.info("Optimise the energy system")
235
236
    # initialise the operational model
237
    energysystem_model = Model(energysystem)
238
239
    # if tee_switch is true solver messages will be displayed
240
    logging.info("Solve the optimization problem")
241
    energysystem_model.solve(
242
        solver=solver, solve_kwargs={"tee": solver_verbose}
243
    )
244
245
    logging.info("Store the energy system with the results.")
246
247
    # The processing module of the outputlib can be used to extract the results
248
    # from the model transfer them into a homogeneous structured dictionary.
249
250
    results = Results(energysystem_model)
251
252
    # *************************************************************************
253
    # ********** PART 2 - Processing the results ******************************
254
    # *************************************************************************
255
256
    # These are the keys to access information from the Results()
257
    keys = results.keys()
258
    print("\n********* Keys to access information from Results() *********")
259
    for key in keys:
260
        print("Key: {}".format(key))
261
262
    # Evaluating the economics of the solution
263
264
    print("\n********* Evaluating economics *********")
265
266
    # -------------- variable costs ---------------------------
267
    variable_costs = results.to_df("variable_costs")
268
    values = results.to_df("flow")
269
270
    var_costs_dict = {}
271
    for i, o in energysystem_model.FLOWS:
272
        var_costs_dict["({}, {})".format(i, o)] = energysystem_model.flows[
273
            i, o
274
        ].variable_costs
275
276
    df_var_costs = pd.DataFrame.from_dict(var_costs_dict)
277
    df_var_costs.index = create_time_index(
278
        2012, number=number_of_time_steps - 1
279
    )
280
281
    start_date = "2012-04-07 00:00:00"
282
    end_date = "2012-04-21 23:00:00"
283
284
    # Create figure and subplots
285
    fig, axs = plt.subplots(3, 1, figsize=(10, 10), sharex=True)
286
287
    # First subplot for flow values
288
    values.loc[start_date:end_date, :].plot(ax=axs[0])
289
    axs[0].set_title("Flow Values")
290
    axs[0].set_ylabel("Power in kW")
291
292
    # Second subplot for variable costs
293
    df_var_costs.loc[start_date:end_date, :].plot(ax=axs[1])
294
    axs[1].set_title("Variable costs")
295
    axs[1].set_ylabel("specific variable costs in €/kWh")
296
297
    # Third subplot for variable opex
298
    variable_costs.loc[start_date:end_date, :].plot(ax=axs[2])
299
    axs[2].set_title("Variable OPEX")
300
    axs[2].set_ylabel("variable costs in €")
301
302
    # plt.show()
303
304
    # -------------- Investment Costs ---------------------------
305
306
    invest = results.to_df("invest")
307
    print(invest)
308
309
    investment_costs = results.to_df("investment_costs")
310
311
    annual_costs_dict = {}
312
    for i, o in energysystem_model.FLOWS:
313
        if hasattr(energysystem_model.flows[i, o].investment, "ep_costs"):
314
            annual_costs_dict["({}, {})".format(i, o)] = {
315
                "ep_costs": (
316
                    energysystem_model.flows[i, o].investment.ep_costs[0]
317
                ),
318
                "offset": (
319
                    energysystem_model.flows[i, o].investment.offset[0]
320
                ),
321
            }
322
    for node in energysystem_model.nodes:
323
        if isinstance(
324
            node,
325
            components._generic_storage.GenericStorage,
326
        ):
327
            annual_costs_dict[node.label] = {
328
                "ep_costs": (node.investment.ep_costs[0]),
329
                "offset": (node.investment.offset[0]),
330
            }
331
332
    df_annual_costs = pd.DataFrame.from_dict(annual_costs_dict)
333
334
    # Create figure and subplots
335
    fig2, axs2 = plt.subplots(1, 3, figsize=(10, 6))
336
337
    # First subplot for invest decisions
338
    results.to_df("invest").plot(ax=axs2[0], kind="bar")
339
    axs2[0].set_title("Yearly Investment Installation")
340
    axs2[0].set_ylabel("installed capacity in kW")
341
342
    # Second subplot for ep_costs and offset
343
    df_annual_costs.plot(ax=axs2[1], kind="bar")
344
    axs2[1].set_title("ep_costs and offset")
345
    axs2[1].set_ylabel("specific investment costs in €/kWh and €")
346
347
    # Third subplot for yearly investment costs
348
    investment_costs.plot(ax=axs2[2], kind="bar")
349
    axs2[2].set_title("Yearly Investment Costs")
350
    axs2[2].set_ylabel("investment costs in €")
351
352
    plt.show()
353
354
355
if __name__ == "__main__":
356
    main()
357