|
1
|
|
|
from emobpy import DataBase |
|
2
|
|
|
import pandas as pd |
|
3
|
|
|
import os |
|
4
|
|
|
import numpy as np |
|
5
|
|
|
from reegis import config as cfg |
|
6
|
|
|
from matplotlib import pyplot as plt |
|
7
|
|
|
|
|
8
|
|
|
def get_charging_profiles_from_database(path): |
|
9
|
|
|
""" |
|
10
|
|
|
This function can be used to process results obtained with the library emobpy by DIW Berlin. |
|
11
|
|
|
It takes a path to data as input and returns the summed charging power. |
|
12
|
|
|
|
|
13
|
|
|
Parameters |
|
14
|
|
|
---------- |
|
15
|
|
|
path: String |
|
16
|
|
|
Path to a folder with stored driving, availability and charging profiles |
|
17
|
|
|
|
|
18
|
|
|
Returns: DataFrame |
|
19
|
|
|
Summed charging power for 4 different charging strategies |
|
20
|
|
|
------- |
|
21
|
|
|
""" |
|
22
|
|
|
|
|
23
|
|
|
# Load profiles from Files |
|
24
|
|
|
manager = DataBase(path) |
|
25
|
|
|
manager.update() |
|
26
|
|
|
|
|
27
|
|
|
# Liste mit Availability Profilen |
|
28
|
|
|
keys_driving = [k for k, v in manager.db.items() if v['kind'] == 'driving'] |
|
29
|
|
|
keys_availability = [k for k, v in manager.db.items() if v['kind'] == 'availability'] |
|
30
|
|
|
keys_charging = [k for k, v in manager.db.items() if v['kind'] == 'charging'] |
|
31
|
|
|
keys_immediate = [k for k, v in manager.db.items() if v['kind'] == 'charging' and v['option'] == 'immediate' ] |
|
32
|
|
|
keys_balanced = [k for k, v in manager.db.items() if v['kind'] == 'charging' and v['option'] == 'balanced' ] |
|
33
|
|
|
keys_23to8 = [k for k, v in manager.db.items() if v['kind'] == 'charging' and v['option'] == 'from_23_to_8_at_home'] |
|
34
|
|
|
keys_0to24 = [k for k, v in manager.db.items() if v['kind'] == 'charging' and v['option'] == 'from_0_to_24_at_home'] |
|
35
|
|
|
|
|
36
|
|
|
# Summenprofil für Fahrleistung in kmd |
|
37
|
|
|
driving_profiles = pd.DataFrame() |
|
38
|
|
|
for k in keys_driving: |
|
39
|
|
|
test = manager.db[k]["timeseries"]["consumption"] |
|
40
|
|
|
driving_profiles = pd.concat([driving_profiles, test], axis=1) |
|
41
|
|
|
|
|
42
|
|
|
#cum_profile = driving_profiles.sum(axis=1) |
|
43
|
|
|
|
|
44
|
|
|
|
|
45
|
|
|
# Summenprofil für Ladeleistung (immediate) |
|
46
|
|
|
ch_profiles_immediate = pd.DataFrame() |
|
47
|
|
|
for k in keys_immediate: |
|
48
|
|
|
tmp = manager.db[k]["timeseries"]["charge_grid"] |
|
49
|
|
|
ch_profiles_immediate = pd.concat([ch_profiles_immediate, tmp], axis=1) |
|
50
|
|
|
|
|
51
|
|
|
P_immediate = ch_profiles_immediate.sum(axis=1) |
|
52
|
|
|
|
|
53
|
|
|
|
|
54
|
|
|
# Summenprofil für Ladeleistung (balanced) |
|
55
|
|
|
ch_profiles_balanced = pd.DataFrame() |
|
56
|
|
|
for k in keys_balanced: |
|
57
|
|
|
tmp = manager.db[k]["timeseries"]["charge_grid"] |
|
58
|
|
|
ch_profiles_balanced = pd.concat([ch_profiles_balanced, tmp], axis=1) |
|
59
|
|
|
|
|
60
|
|
|
P_balanced = ch_profiles_balanced.sum(axis=1) |
|
61
|
|
|
|
|
62
|
|
|
|
|
63
|
|
|
# Summenprofil für Ladeleistung (23 to 8) |
|
64
|
|
|
ch_profiles_23to8 = pd.DataFrame() |
|
65
|
|
|
for k in keys_23to8: |
|
66
|
|
|
tmp = manager.db[k]["timeseries"]["charge_grid"] |
|
67
|
|
|
ch_profiles_23to8 = pd.concat([ch_profiles_23to8, tmp], axis=1) |
|
68
|
|
|
|
|
69
|
|
|
P_23to8 = ch_profiles_23to8.sum(axis=1) |
|
70
|
|
|
|
|
71
|
|
|
|
|
72
|
|
|
# Summenprofil für Ladeleistung (0 to 24) |
|
73
|
|
|
ch_profiles_0to24 = pd.DataFrame() |
|
74
|
|
|
for k in keys_0to24: |
|
75
|
|
|
tmp = manager.db[k]["timeseries"]["charge_grid"] |
|
76
|
|
|
ch_profiles_0to24 = pd.concat([ch_profiles_0to24, tmp], axis=1) |
|
77
|
|
|
|
|
78
|
|
|
P_0to24 = ch_profiles_0to24.sum(axis=1) |
|
79
|
|
|
|
|
80
|
|
|
P_sum = pd.concat([P_immediate, P_balanced, P_23to8, P_0to24], axis=1) |
|
81
|
|
|
P_sum.columns = ['immediate', 'balanced', '23to8', '0to24'] |
|
82
|
|
|
|
|
83
|
|
|
return P_sum |
|
84
|
|
|
|
|
85
|
|
|
|
|
86
|
|
|
def return_normalized_charging_series(df): |
|
87
|
|
|
""" |
|
88
|
|
|
This function normalizes profiles so that the sum of the timeseries is 1. The profiles can then be scaled to |
|
89
|
|
|
a user defined energy consumption of BEV charging. |
|
90
|
|
|
|
|
91
|
|
|
Parameters |
|
92
|
|
|
---------- |
|
93
|
|
|
df: DataFrame |
|
94
|
|
|
Dataframe with 4 charging timereries |
|
95
|
|
|
|
|
96
|
|
|
Returns: DataFrame |
|
97
|
|
|
Normalized charging series |
|
98
|
|
|
------- |
|
99
|
|
|
""" |
|
100
|
|
|
|
|
101
|
|
|
# Cut off initial charging |
|
102
|
|
|
df.iloc[0:48] = df.iloc[48:96].values |
|
103
|
|
|
# Cut off end charging to initial SoC |
|
104
|
|
|
df.iloc[len(df)-48:len(df)] = df.iloc[len(df)-96:len(df)-48].values |
|
|
|
|
|
|
105
|
|
|
idx = pd.DatetimeIndex(df.index, freq='30min') |
|
106
|
|
|
df.set_index(idx, inplace=True) |
|
107
|
|
|
p_immediate = df['immediate'] |
|
108
|
|
|
p_balanced = df['balanced'] |
|
109
|
|
|
p_23to8 = df['23to8'] |
|
110
|
|
|
p_0to24 = df['0to24'] |
|
111
|
|
|
|
|
112
|
|
|
# Resample to hourly values |
|
113
|
|
|
immediate_hourly = p_immediate.resample('H').sum() |
|
114
|
|
|
balanced_hourly = p_balanced.resample('H').sum() |
|
115
|
|
|
hourly_23to8 = p_23to8.resample('H').sum() |
|
116
|
|
|
hourly_0to24 = p_0to24.resample('H').sum() |
|
117
|
|
|
|
|
118
|
|
|
# Normalize Yearly energy use to 1 |
|
119
|
|
|
immediate_norm = immediate_hourly * (1 / immediate_hourly.sum()) |
|
120
|
|
|
balanced_norm = balanced_hourly * (1 / balanced_hourly.sum()) |
|
121
|
|
|
norm_23to8 = hourly_23to8 * (1 / hourly_23to8 .sum()) |
|
122
|
|
|
norm_0to24 = hourly_0to24 * (1 / hourly_0to24.sum()) |
|
123
|
|
|
|
|
124
|
|
|
P_sum_norm = pd.concat([immediate_norm, balanced_norm, norm_23to8, norm_0to24], axis=1) |
|
125
|
|
|
smaller_zero = P_sum_norm < 0 |
|
126
|
|
|
P_sum_norm[smaller_zero] = 0 |
|
127
|
|
|
|
|
128
|
|
|
for n in ['immediate', 'balanced', '23to8', '0to24']: |
|
129
|
|
|
inc_fac = 1 / P_sum_norm[n].sum() |
|
130
|
|
|
P_sum_norm[n] = P_sum_norm[n].multiply(inc_fac) |
|
131
|
|
|
|
|
132
|
|
|
return P_sum_norm |
|
133
|
|
|
|
|
134
|
|
|
|
|
135
|
|
|
def return_sum_charging_power(path=None): |
|
136
|
|
|
""" |
|
137
|
|
|
This function returns a DataFrame with summed charging power series. Prerequisite is the calculation of profiles |
|
138
|
|
|
with the library emobpy by DIW Berlin. If the function is run for the first time a path to data must be provided. |
|
139
|
|
|
|
|
140
|
|
|
Parameters |
|
141
|
|
|
---------- |
|
142
|
|
|
path: String |
|
143
|
|
|
Path to a directory containing at least one folder with charging power series files. |
|
144
|
|
|
|
|
145
|
|
|
Returns: DataFrame |
|
146
|
|
|
Summed charging profiles |
|
147
|
|
|
------- |
|
148
|
|
|
""" |
|
149
|
|
|
fn = os.path.join(cfg.get("paths", "scenario_data"), 'sum_charging_power.csv') |
|
150
|
|
|
|
|
151
|
|
|
if not os.path.isfile(fn): |
|
152
|
|
|
os.chdir(path) |
|
153
|
|
|
dirs = os.listdir(os.getcwd()) |
|
154
|
|
|
result_dict = dict.fromkeys(dirs) |
|
155
|
|
|
|
|
156
|
|
|
for dir in result_dict.keys(): |
|
157
|
|
|
path = os.path.join(os.getcwd(), dir) |
|
158
|
|
|
result_dict[dir] = get_charging_profiles_from_database(path) |
|
159
|
|
|
|
|
160
|
|
|
charging_types = result_dict[dir].columns |
|
|
|
|
|
|
161
|
|
|
idx = result_dict[dir].index |
|
162
|
|
|
P_sum = pd.DataFrame(index=idx, columns=charging_types) |
|
163
|
|
|
len_series = len(result_dict[list(result_dict.keys())[0]]['immediate']) |
|
164
|
|
|
|
|
165
|
|
|
for ch_type in charging_types: |
|
166
|
|
|
sum_temp = pd.Series(np.zeros(shape=len_series), index=idx) |
|
167
|
|
|
|
|
168
|
|
|
for key in result_dict.keys(): |
|
169
|
|
|
P_tmp = result_dict[key][ch_type] |
|
170
|
|
|
sum_temp = sum_temp.add(P_tmp, fill_value=0) |
|
171
|
|
|
|
|
172
|
|
|
P_sum[ch_type] = sum_temp |
|
173
|
|
|
|
|
174
|
|
|
P_sum.to_csv(fn) |
|
175
|
|
|
|
|
176
|
|
|
else: |
|
177
|
|
|
P_sum = pd.read_csv(fn) |
|
178
|
|
|
P_sum.set_index('Unnamed: 0', drop=True, inplace=True) |
|
179
|
|
|
|
|
180
|
|
|
return P_sum |
|
181
|
|
|
|
|
182
|
|
|
|
|
183
|
|
|
def return_averaged_charging_series(weight_im=0.4, weight_bal=0.4, weight_night=0.2): |
|
184
|
|
|
cs = return_sum_charging_power() |
|
185
|
|
|
cs_norm = return_normalized_charging_series(cs) |
|
186
|
|
|
|
|
187
|
|
|
im = cs_norm["immediate"] |
|
188
|
|
|
bal = cs_norm["balanced"] |
|
189
|
|
|
night = cs_norm["23to8"] |
|
190
|
|
|
|
|
191
|
|
|
P_charge = weight_im * im + weight_bal * bal + weight_night * night |
|
192
|
|
|
|
|
193
|
|
|
return P_charge |
|
194
|
|
|
|
|
195
|
|
|
|
|
196
|
|
|
def plot_charging_series_comparison(df, df_mean): |
|
197
|
|
|
fig, axs = plt.subplots(5) |
|
198
|
|
|
fig.suptitle('Charging strategy comparison') |
|
199
|
|
|
axs[0].plot(df["immediate"]), axs[0].set_title('Immediate') |
|
200
|
|
|
axs[1].plot(df["balanced"]), axs[1].set_title('balanced') |
|
201
|
|
|
axs[2].plot(df["0to24"]), axs[2].set_title('0to24') |
|
202
|
|
|
axs[3].plot(df["23to8"]), axs[3].set_title('23to8') |
|
203
|
|
|
axs[4].plot(df_mean), axs[4].set_title('Averaged series') |
|
204
|
|
|
|