Passed
Pull Request — dev (#1208)
by Patrik
04:04 queued 02:13
created

home_pv_4   A

Complexity

Total Complexity 0

Size/Duplication

Total Lines 211
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 0
eloc 130
dl 0
loc 211
rs 10
c 0
b 0
f 0
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
# %%[energy_system]
29
30
# parse_dates does not set the freq attribute.
31
# However, we want to use it for the EnergySystem.
32
input_data.index.freq = pd.infer_freq(input_data.index)
33
34
energy_system = solph.EnergySystem(
35
    timeindex=input_data.index,
36
    infer_last_interval=True,
37
)
38
39
# %%[dispatch_model]
40
41
el_bus = solph.Bus(label="electricity")
42
43
demand = solph.components.Sink(
44
    label="demand",
45
    inputs={
46
        el_bus: solph.Flow(
47
            nominal_capacity=1,
48
            fix=input_data["electricity demand (kW)"],
49
        )
50
    },
51
)
52
53
energy_system.add(el_bus, demand)
54
55
grid = solph.Bus(
56
    label="grid",
57
    inputs={el_bus: solph.Flow(variable_costs=-0.06)},
58
    outputs={el_bus: solph.Flow(variable_costs=0.3)},
59
    balanced=False,
60
)
61
62
energy_system.add(grid)
63
64
pv_specific_costs = 1500  # €/kW
65
pv_lifetime = 20  # years
66
pv_epc = pv_specific_costs / pv_lifetime
67
68
pv_system = solph.components.Source(
69
    label="PV",
70
    outputs={
71
        el_bus: solph.Flow(
72
            nominal_capacity=solph.Investment(ep_costs=pv_epc, maximum=10),
73
            max=input_data["pv yield (kW/kW)"],
74
        )
75
    },
76
)
77
78
energy_system.add(pv_system)
79
80
# %%[battery]
81
82
battery_specific_costs = 1000  # €/kW
83
battery_lifetime = 10  # years
84
battery_epc = battery_specific_costs / battery_lifetime
85
battery_size = 10  # kWh
86
87
battery = solph.components.GenericStorage(
88
    label="Battery",
89
    nominal_capacity=battery_size,
90
    inputs={el_bus: solph.Flow()},
91
    outputs={el_bus: solph.Flow()},
92
    inflow_conversion_factor=0.9,
93
    loss_rate=0.01,
94
)
95
96
energy_system.add(battery)
97
98
# %%[graph_plotting]
99
plt.figure()
100
graph = create_nx_graph(energy_system)
101
nx.drawing.nx_pydot.write_dot(graph, "home_pv_graph_4.dot")
102
nx.draw(graph, with_labels=True, font_size=8)
103
# %%[model_optimisation]
104
model = solph.Model(energy_system)
105
106
model.solve(solver="cbc", solve_kwargs={"tee": True})
107
results = solph.processing.results(model)
108
meta_results = solph.processing.meta_results(model)
109
110
# %%[results]
111
112
pv_size = results[(pv_system, el_bus)]["scalars"]["invest"]
113
114
battery_annuity = battery_epc * battery_size
115
pv_annuity = pv_epc * results[(pv_system, el_bus)]["scalars"]["invest"]
116
annual_grid_supply = results[(grid, el_bus)]["sequences"]["flow"].sum()
117
el_costs = 0.3 * annual_grid_supply
118
el_revenue = 0.1 * results[(el_bus, grid)]["sequences"]["flow"].sum()
119
120
tce = meta_results["objective"] + battery_annuity
121
122
print(f"The optimal PV size is {pv_size:.2f} kW.")
123
124
print(f"The annual costs for grid electricity are {el_costs:.2f} €.")
125
print(f"The annual revenue from feed-in is {el_revenue:.2f} €.")
126
print(f"The annuity for the PV system is {pv_annuity:.2f} €.")
127
print(f"The annuity for the battery is {battery_annuity:.2f} €.")
128
print(f"The total annual costs are {tce:.2f} €.")
129
130
annual_demand = input_data["electricity demand (kW)"].sum()
131
132
print(
133
    f"Autarky is 1 - {annual_grid_supply:.2f} kWh / {annual_demand:.2f} kWh"
134
    + f" = {100 - 100 * annual_grid_supply / annual_demand:.2f} %."
135
)
136
137
electricity_fows = solph.views.node(results, "electricity")["sequences"]
138
139
baseline = np.zeros(len(electricity_fows))
140
141
plt.figure()
142
143
mode = "light"
144
# mode = "dark"
145
if mode == "dark":
146
    plt.style.use("dark_background")
147
148
plt.fill_between(
149
    electricity_fows.index,
150
    baseline,
151
    baseline + electricity_fows[(("grid", "electricity"), "flow")],
152
    step="pre",
153
    label="Grid supply",
154
)
155
156
baseline += electricity_fows[(("grid", "electricity"), "flow")]
157
158
plt.fill_between(
159
    electricity_fows.index,
160
    baseline,
161
    baseline + electricity_fows[(("PV", "electricity"), "flow")],
162
    step="pre",
163
    label="PV supply",
164
)
165
166
baseline += electricity_fows[(("PV", "electricity"), "flow")]
167
168
plt.fill_between(
169
    electricity_fows.index,
170
    baseline,
171
    baseline + electricity_fows[(("Battery", "electricity"), "flow")],
172
    step="pre",
173
    label="Battery supply",
174
)
175
176
plt.step(
177
    electricity_fows.index,
178
    electricity_fows[(("electricity", "demand"), "flow")],
179
    "-",
180
    color="darkgrey",
181
    label="Electricity demand",
182
)
183
184
plt.step(
185
    electricity_fows.index,
186
    electricity_fows[(("electricity", "demand"), "flow")]
187
    + electricity_fows[(("electricity", "Battery"), "flow")],
188
    "--",
189
    color="darkgrey",
190
    label="Battery charging",
191
)
192
193
plt.step(
194
    electricity_fows.index,
195
    electricity_fows[(("electricity", "demand"), "flow")]
196
    + electricity_fows[(("electricity", "Battery"), "flow")]
197
    + electricity_fows[(("electricity", "grid"), "flow")],
198
    ":",
199
    color="darkgrey",
200
    label="Feed-In",
201
)
202
203
plt.legend()
204
plt.ylabel("Power (kW)")
205
plt.xlim(pd.Timestamp("2020-02-21 00:00"), pd.Timestamp("2020-02-28 00:00"))
206
plt.gcf().autofmt_xdate()
207
208
plt.savefig(f"home_pv_result-4_{mode}.svg")
209
210
plt.show()
211