|
1
|
|
|
""" |
|
2
|
|
|
SPDX-FileCopyrightText: Patrik Schönfeldt |
|
3
|
|
|
SPDX-FileCopyrightText: DLR e.V. |
|
4
|
|
|
|
|
5
|
|
|
SPDX-License-Identifier: MIT |
|
6
|
|
|
""" |
|
7
|
|
|
|
|
8
|
|
|
from pathlib import Path |
|
9
|
|
|
|
|
10
|
|
|
import demandlib |
|
11
|
|
|
import matplotlib.pyplot as plt |
|
12
|
|
|
import pandas as pd |
|
13
|
|
|
import numpy as np |
|
14
|
|
|
from urllib.request import urlretrieve |
|
15
|
|
|
from workalendar.europe import Germany |
|
16
|
|
|
|
|
17
|
|
|
|
|
18
|
|
|
def prepare_input_data(plot_resampling=False): |
|
19
|
|
|
url_temperature = ( |
|
20
|
|
|
"https://oemof.org/wp-content/uploads/2025/12/temperature.csv" |
|
21
|
|
|
) |
|
22
|
|
|
url_energy = "https://oemof.org/wp-content/uploads/2025/12/energy.csv" |
|
23
|
|
|
|
|
24
|
|
|
print( |
|
25
|
|
|
"Data is licensed from M. Schlemminger, T. Ohrdes, E. Schneider," |
|
26
|
|
|
" and M. Knoop. Under Creative Commons Attribution 4.0 International" |
|
27
|
|
|
" License. It is also available at doi: 10.5281/zenodo.5642902." |
|
28
|
|
|
" (We use single family home 26 plus the south-facing PV" |
|
29
|
|
|
" from that dataset.)" |
|
30
|
|
|
) |
|
31
|
|
|
|
|
32
|
|
|
file_path = Path(__file__).parent |
|
33
|
|
|
|
|
34
|
|
|
temperature_file = Path(file_path, "temperature.csv") |
|
35
|
|
|
if not temperature_file.exists(): |
|
36
|
|
|
urlretrieve(url_temperature, temperature_file) |
|
37
|
|
|
df_temperature = pd.read_csv( |
|
38
|
|
|
temperature_file, |
|
39
|
|
|
index_col="Unix Epoch", |
|
40
|
|
|
) |
|
41
|
|
|
timedelta = np.empty(len(df_temperature)) |
|
42
|
|
|
timedelta[:-1] = ( |
|
43
|
|
|
df_temperature.index[1:] - df_temperature.index[:-1] |
|
44
|
|
|
) / 3600 |
|
45
|
|
|
timedelta[-1] = np.nan |
|
46
|
|
|
|
|
47
|
|
|
df_temperature.index = pd.to_datetime( |
|
48
|
|
|
df_temperature.index, |
|
49
|
|
|
unit="s", |
|
50
|
|
|
utc=True, |
|
51
|
|
|
) |
|
52
|
|
|
|
|
53
|
|
|
building_area = 120 # m² (from publication) |
|
54
|
|
|
specific_heat_demand = 60 # kWh/m²/a (educated guess) |
|
55
|
|
|
holidays = dict(Germany().holidays(2019)) |
|
56
|
|
|
|
|
57
|
|
|
# We estimate the heat demand from the ambient temperature using demandlib. |
|
58
|
|
|
# This returns energy per time step in units of kWh. |
|
59
|
|
|
df_temperature["heat demand (kWh)"] = demandlib.bdew.HeatBuilding( |
|
60
|
|
|
df_temperature.index, |
|
61
|
|
|
holidays=holidays, |
|
62
|
|
|
temperature=df_temperature["Air Temperature (°C)"], |
|
63
|
|
|
shlp_type="EFH", |
|
64
|
|
|
building_class=1, |
|
65
|
|
|
wind_class=1, |
|
66
|
|
|
annual_heat_demand=building_area * specific_heat_demand, |
|
67
|
|
|
name="EFH", |
|
68
|
|
|
).get_bdew_profile() |
|
69
|
|
|
|
|
70
|
|
|
df_temperature["heat demand (W)"] = ( |
|
71
|
|
|
df_temperature["heat demand (kWh)"] * 1e3 / timedelta |
|
72
|
|
|
) |
|
73
|
|
|
|
|
74
|
|
|
energy_file = Path(file_path, "energy.csv") |
|
75
|
|
|
if not energy_file.exists(): |
|
76
|
|
|
urlretrieve(url_energy, energy_file) |
|
77
|
|
|
df_energy = pd.read_csv( |
|
78
|
|
|
energy_file, |
|
79
|
|
|
index_col=0, |
|
80
|
|
|
) |
|
81
|
|
|
df_energy.index = pd.to_datetime( |
|
82
|
|
|
df_energy.index, |
|
83
|
|
|
unit="s", |
|
84
|
|
|
utc=True, |
|
85
|
|
|
) |
|
86
|
|
|
|
|
87
|
|
|
if plot_resampling: |
|
88
|
|
|
p_pv = {} |
|
89
|
|
|
resolutions = [ |
|
90
|
|
|
"1 min", |
|
91
|
|
|
"5 min", |
|
92
|
|
|
"10 min", |
|
93
|
|
|
"15 min", |
|
94
|
|
|
"30 min", |
|
95
|
|
|
"1 h", |
|
96
|
|
|
"2 h", |
|
97
|
|
|
"3 h", |
|
98
|
|
|
"6 h", |
|
99
|
|
|
] |
|
100
|
|
|
|
|
101
|
|
|
for resolution in resolutions: |
|
102
|
|
|
p_pv[resolution] = df_energy["PV (W)"].resample(resolution).mean() |
|
103
|
|
|
plt.plot( |
|
104
|
|
|
np.linspace(0, 8760, len(p_pv[resolution])), |
|
105
|
|
|
sorted(p_pv[resolution]/1e3)[::-1], |
|
106
|
|
|
label=resolution, |
|
107
|
|
|
) |
|
108
|
|
|
|
|
109
|
|
|
plt.xlim(-10, 510) |
|
110
|
|
|
plt.ylim(7, 16) |
|
111
|
|
|
plt.legend() |
|
112
|
|
|
plt.show() |
|
113
|
|
|
|
|
114
|
|
|
|
|
115
|
|
|
if __name__ == "__main__": |
|
116
|
|
|
prepare_input_data(plot_resampling=True) |
|
117
|
|
|
|