1
|
|
|
# -*- coding: utf-8 -*- |
2
|
|
|
|
3
|
|
|
""" |
4
|
|
|
SPDX-FileCopyrightText: Patrik Schönfeldt |
5
|
|
|
SPDX-FileCopyrightText: Daniel Niederhöfer |
6
|
|
|
SPDX-FileCopyrightText: DLR e.V. |
7
|
|
|
|
8
|
|
|
SPDX-License-Identifier: MIT |
9
|
|
|
""" |
10
|
|
|
# %%[imports] |
11
|
|
|
import os |
12
|
|
|
import matplotlib.pyplot as plt |
13
|
|
|
import networkx as nx |
14
|
|
|
import numpy as np |
15
|
|
|
from oemof.network.graph import create_nx_graph |
16
|
|
|
import pandas as pd |
17
|
|
|
|
18
|
|
|
from oemof import solph |
19
|
|
|
|
20
|
|
|
# %%[input_data] |
21
|
|
|
|
22
|
|
|
file_path = os.path.dirname(__file__) |
23
|
|
|
filename = os.path.join(file_path, "pv_example_data.csv") |
24
|
|
|
input_data = pd.read_csv( |
25
|
|
|
filename, index_col="timestep", parse_dates=["timestep"] |
26
|
|
|
) |
27
|
|
|
|
28
|
|
|
input_data.plot(drawstyle="steps") |
29
|
|
|
plt.xlim(pd.Timestamp("2020-03-01 00:00"), pd.Timestamp("2020-03-07 00:00")) |
30
|
|
|
plt.show() |
31
|
|
|
|
32
|
|
|
# %%[energy_system] |
33
|
|
|
|
34
|
|
|
# parse_dates does not set the freq attribute. |
35
|
|
|
# However, we want to use it for the EnergySystem. |
36
|
|
|
input_data.index.freq = pd.infer_freq(input_data.index) |
37
|
|
|
|
38
|
|
|
energy_system = solph.EnergySystem( |
39
|
|
|
timeindex=input_data.index, |
40
|
|
|
infer_last_interval=True, |
41
|
|
|
) |
42
|
|
|
|
43
|
|
|
# %%[dispatch_model] |
44
|
|
|
|
45
|
|
|
el_bus = solph.Bus(label="electricity") |
46
|
|
|
|
47
|
|
|
demand = solph.components.Sink( |
48
|
|
|
label="demand", |
49
|
|
|
inputs={ |
50
|
|
|
el_bus: solph.Flow( |
51
|
|
|
nominal_capacity=1, |
52
|
|
|
fix=input_data["electricity demand (kW)"], |
53
|
|
|
) |
54
|
|
|
}, |
55
|
|
|
) |
56
|
|
|
|
57
|
|
|
energy_system.add(el_bus, demand) |
58
|
|
|
|
59
|
|
|
grid = solph.Bus( |
60
|
|
|
label="grid", |
61
|
|
|
outputs={el_bus: solph.Flow(variable_costs=0.3)}, |
62
|
|
|
balanced=False, |
63
|
|
|
) |
64
|
|
|
|
65
|
|
|
energy_system.add(grid) |
66
|
|
|
# %%[graph_plotting] |
67
|
|
|
plt.figure() |
68
|
|
|
graph = create_nx_graph(energy_system) |
69
|
|
|
nx.drawing.nx_pydot.write_dot(graph, "home_pv_graph_1.dot") |
70
|
|
|
nx.draw(graph, with_labels=True, font_size=8) |
71
|
|
|
plt.show() |
72
|
|
|
# %%[model_optimisation] |
73
|
|
|
model = solph.Model(energy_system) |
74
|
|
|
|
75
|
|
|
model.solve(solver="cbc", solve_kwargs={"tee": True}) |
76
|
|
|
results = solph.processing.results(model) |
77
|
|
|
meta_results = solph.processing.meta_results(model) |
78
|
|
|
|
79
|
|
|
# %%[results] |
80
|
|
|
|
81
|
|
|
tce = meta_results["objective"] |
82
|
|
|
print(f"The total annual costs are {tce:.2f} €.") |
83
|
|
|
el_costs = 0.3 * results[(grid, el_bus)]["sequences"]["flow"].sum() |
84
|
|
|
print(f"The annual costs for grid electricity are {el_costs:.2f} €.") |
85
|
|
|
|
86
|
|
|
electricity_flows = solph.views.node(results, "electricity")["sequences"] |
87
|
|
|
|
88
|
|
|
baseline = np.zeros(len(electricity_flows)) |
89
|
|
|
|
90
|
|
|
mode = "light" |
91
|
|
|
# mode = "dark" |
92
|
|
|
if mode == "dark": |
93
|
|
|
plt.style.use("dark_background") |
94
|
|
|
|
95
|
|
|
plt.fill_between( |
96
|
|
|
electricity_flows.index, |
97
|
|
|
baseline, |
98
|
|
|
electricity_flows[(("grid", "electricity"), "flow")], |
99
|
|
|
step="pre", |
100
|
|
|
label="Grid supply", |
101
|
|
|
) |
102
|
|
|
|
103
|
|
|
plt.step( |
104
|
|
|
electricity_flows.index, |
105
|
|
|
electricity_flows[(("electricity", "demand"), "flow")], |
106
|
|
|
"-", |
107
|
|
|
color="darkgrey", |
108
|
|
|
label="Electricity demand", |
109
|
|
|
) |
110
|
|
|
plt.legend() |
111
|
|
|
plt.ylabel("Power (kW)") |
112
|
|
|
plt.xlim(pd.Timestamp("2020-01-01 00:00"), pd.Timestamp("2020-01-07 00:00")) |
113
|
|
|
plt.gcf().autofmt_xdate() |
114
|
|
|
|
115
|
|
|
plt.savefig(f"home_pv_result-1_{mode}.svg") |
116
|
|
|
|
117
|
|
|
plt.show() |
118
|
|
|
|