Passed
Pull Request — dev (#1193)
by Patrik
01:53
created

subnetwork_example.main()   B

Complexity

Conditions 3

Size

Total Lines 205
Code Lines 102

Duplication

Lines 205
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 102
dl 205
loc 205
rs 7
c 0
b 0
f 0
cc 3
nop 0

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
import logging
2
import os
3
4
import matplotlib.pyplot as plt
5
import pandas as pd
6
from oemof.tools import logger
7
from oemof.network import SubNetwork
8
9
from oemof.solph import EnergySystem
10
from oemof.solph import Model
11
from oemof.solph import buses
12
from oemof.solph import components
13
from oemof.solph import create_time_index
14
from oemof.solph import flows
15
from oemof.solph import helpers
16
from oemof.solph import Results
17
18
STORAGE_LABEL = "battery_storage"
19
20
21
def get_data_from_file_path(file_path: str) -> pd.DataFrame:
22
    file_dir = os.path.dirname(os.path.abspath(__file__))
23
    data = pd.read_csv(file_dir + "/" + file_path)
24
    return data
25
26
27 View Code Duplication
def plot_figures_for(element: dict) -> None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
28
    figure, axes = plt.subplots(figsize=(10, 5))
29
    element["sequences"].plot(ax=axes, kind="line", drawstyle="steps-post")
30
    plt.legend(
31
        loc="upper center",
32
        prop={"size": 8},
33
        bbox_to_anchor=(0.5, 1.25),
34
        ncol=2,
35
    )
36
    figure.subplots_adjust(top=0.8)
37
    plt.show()
38
39
40 View Code Duplication
def main():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
41
    # For models that need a long time to optimise, saving and loading the
42
    # EnergySystem might be advised. By default, we do not do this here. Feel
43
    # free to experiment with this once you understood the rest of the code.
44
45
    # *************************************************************************
46
    # ********** PART 1 - Define and optimise the energy system ***************
47
    # *************************************************************************
48
49
    # Read data file
50
    file_name = "subnetwork_example.csv"
51
    data = get_data_from_file_path(file_name)
52
53
    solver = "cbc"  # 'glpk', 'gurobi',....
54
    debug = False  # Set number_of_timesteps to 3 to get a readable lp-file.
55
    number_of_time_steps = len(data)
56
    solver_verbose = False  # show/hide solver output
57
58
    # initiate the logger (see the API docs for more information)
59
    logger.define_logging(
60
        logfile="oemof_example.log",
61
        screen_level=logging.INFO,
62
        file_level=logging.INFO,
63
    )
64
65
    logging.info("Initialize the energy system")
66
    date_time_index = create_time_index(2012, number=number_of_time_steps)
67
68
    # create the energysystem and assign the time index
69
    energysystem = EnergySystem(
70
        timeindex=date_time_index, infer_last_interval=False
71
    )
72
73
    ##########################################################################
74
    # Create oemof objects
75
    ##########################################################################
76
77
    logging.info("Create oemof objects")
78
79
    # The bus objects were assigned to variables which makes it easier to
80
    # connect components to these buses (see below).
81
82
    # create natural gas bus
83
    bus_gas = buses.Bus(label="natural_gas")
84
85
    # create electricity bus
86
    bus_electricity = buses.Bus(label="electricity")
87
88
    # adding the buses to the energy system
89
    energysystem.add(bus_gas, bus_electricity)
90
91
    # create excess component for the electricity bus to allow overproduction
92
    energysystem.add(
93
        components.Sink(
94
            label="excess_bus_electricity",
95
            inputs={bus_electricity: flows.Flow()},
96
        )
97
    )
98
99
    # create source object representing the gas commodity
100
    energysystem.add(
101
        components.Source(
102
            label="rgas",
103
            outputs={bus_gas: flows.Flow()},
104
        )
105
    )
106
107
    # *** SUB-NETWORK ***************************
108
    # Add a subnetwork for Renewable Energies.
109
    renewables = SubNetwork("renewables")
110
    re_bus = renewables.subnode(buses.Bus, "re_elec")
111
112
    # create fixed source object representing wind power plants
113
    renewables.subnode(
114
        components.Source,
115
        local_name="wind",
116
        outputs={re_bus: flows.Flow(fix=data["wind"], nominal_value=1000000)},
117
    )
118
    # create fixed source object representing pv power plants
119
    renewables.subnode(
120
        components.Source,
121
        local_name="pv",
122
        outputs={re_bus: flows.Flow(fix=data["pv"], nominal_value=582000)},
123
    )
124
    renewables.subnode(
125
        components.Converter,
126
        local_name="connection",
127
        outputs={bus_electricity: flows.Flow()},
128
        inputs={re_bus: flows.Flow()},
129
    )
130
    energysystem.add(renewables)  # Subnetwork to Energysystem
131
    # *************************************************************
132
133
    # create simple sink object representing the electrical demand
134
    # nominal_value is set to 1 because demand_el is not a normalised series
135
    energysystem.add(
136
        components.Sink(
137
            label="demand",
138
            inputs={
139
                bus_electricity: flows.Flow(
140
                    fix=data["demand_el"], nominal_value=1
141
                )
142
            },
143
        )
144
    )
145
146
    # create simple converter object representing a gas power plant
147
    energysystem.add(
148
        components.Converter(
149
            label="pp_gas",
150
            inputs={bus_gas: flows.Flow()},
151
            outputs={
152
                bus_electricity: flows.Flow(
153
                    nominal_capacity=10e10, variable_costs=50
154
                )
155
            },
156
            conversion_factors={bus_electricity: 0.58},
157
        )
158
    )
159
160
    # create storage object representing a battery
161
    nominal_capacity = 10077997
162
    nominal_value = nominal_capacity / 6
163
164
    battery_storage = components.GenericStorage(
165
        nominal_capacity=nominal_capacity,
166
        label=STORAGE_LABEL,
167
        inputs={bus_electricity: flows.Flow(nominal_value=nominal_value)},
168
        outputs={
169
            bus_electricity: flows.Flow(
170
                nominal_value=nominal_value, variable_costs=0.001
171
            )
172
        },
173
        loss_rate=0.00,
174
        initial_storage_level=None,
175
        inflow_conversion_factor=1,
176
        outflow_conversion_factor=0.8,
177
    )
178
179
    energysystem.add(battery_storage)
180
181
    ##########################################################################
182
    # Optimise the energy system and plot the results
183
    ##########################################################################
184
185
    logging.info("Optimise the energy system")
186
187
    # initialise the operational model
188
    energysystem_model = Model(energysystem)
189
190
    # This is for debugging only. It is not(!) necessary to solve the problem
191
    # and should be set to False to save time and disc space in normal use. For
192
    # debugging the timesteps should be set to 3, to increase the readability
193
    # of the lp-file.
194
    if debug:
195
        file_path = os.path.join(
196
            helpers.extend_basic_path("lp_files"), "basic_example.lp"
197
        )
198
        logging.info(f"Store lp-file in {file_path}.")
199
        io_option = {"symbolic_solver_labels": True}
200
        energysystem_model.write(file_path, io_options=io_option)
201
202
    # if tee_switch is true solver messages will be displayed
203
    logging.info("Solve the optimization problem")
204
    energysystem_model.solve(
205
        solver=solver, solve_kwargs={"tee": solver_verbose}
206
    )
207
208
    results = Results(energysystem_model)
209
210
    # ToDO Implement a filter methode for the Result object to exclude
211
    #  subcomponents of a facade/sub-network
212
    # The following lines are meant to show how the result should look like
213
    # in case the subcomponents should be exclude. There should not be a
214
    # postprocessing it is better to filter the nodes directly
215
216
    # Filter columns that are internal only
217
    keep_columns = [
218
        c
219
        for c in results.flow.columns
220
        if getattr(c[1].label, "parent", None)
221
        != getattr(c[0].label, "parent", None)
222
        or (
223
            getattr(c[0].label, "parent", True) is True
224
            and getattr(c[1].label, "parent", True) is True
225
        )
226
    ]
227
    flow_results_filtered = results.flow[keep_columns].copy()
228
229
    # Replace subcomponent with facade object
230
    for level in [0, 1]:
231
        flow_results_filtered.rename(
232
            columns={
233
                c[level]: getattr(c[level].label, "parent", c[level])
234
                for c in flow_results_filtered.columns
235
            },
236
            level=level,
237
            inplace=True,
238
        )
239
240
    print("**** All results ****")
241
    print(results.flow.sum())
242
243
    print("**** Filtered results ****")
244
    print(flow_results_filtered.sum())
245
246
247
if __name__ == "__main__":
248
    main()
249