|
1
|
|
|
# %%[imports_start] |
|
2
|
|
|
|
|
3
|
|
|
import matplotlib.pyplot as plt |
|
4
|
|
|
import networkx as nx |
|
5
|
|
|
import numpy as np |
|
6
|
|
|
from oemof.network.graph import create_nx_graph |
|
7
|
|
|
import pandas as pd |
|
8
|
|
|
from helpers import plot_results |
|
9
|
|
|
|
|
10
|
|
|
# %%[imports_end] |
|
11
|
|
|
# %%[create_time_index_set_up_energysystem_start] |
|
12
|
|
|
import oemof.solph as solph |
|
13
|
|
|
|
|
14
|
|
|
time_index = pd.date_range( |
|
15
|
|
|
start="2025-01-01", |
|
16
|
|
|
end="2025-01-02", |
|
17
|
|
|
freq="5min", |
|
18
|
|
|
inclusive="both", |
|
19
|
|
|
) |
|
20
|
|
|
|
|
21
|
|
|
ev_energy_system = solph.EnergySystem( |
|
22
|
|
|
timeindex=time_index, |
|
23
|
|
|
infer_last_interval=False, |
|
24
|
|
|
) |
|
25
|
|
|
# %%[create_time_index_set_up_energysystem_end] |
|
26
|
|
|
# %%[trip_data_start] |
|
27
|
|
|
ev_demand = pd.Series(0, index=time_index[:-1]) |
|
28
|
|
|
|
|
29
|
|
|
driving_start_morning = pd.Timestamp("2025-01-01 07:10") |
|
30
|
|
|
driving_end_morning = pd.Timestamp("2025-01-01 08:10") |
|
31
|
|
|
ev_demand.loc[driving_start_morning:driving_end_morning] = 10 # kW |
|
32
|
|
|
|
|
33
|
|
|
|
|
34
|
|
|
driving_start_evening = pd.Timestamp("2025-01-01 16:13:37") |
|
35
|
|
|
driving_end_evening = pd.Timestamp("2025-01-01 17:45:11") |
|
36
|
|
|
ev_demand.loc[driving_start_evening:driving_end_evening] = 9 # kW |
|
37
|
|
|
# %%[trip_data_end] |
|
38
|
|
|
## %%[plot_trip_data_start] |
|
39
|
|
|
plt.figure() |
|
40
|
|
|
# plt.style.use("dark_background") |
|
41
|
|
|
plt.title("Driving pattern") |
|
42
|
|
|
plt.plot(ev_demand) |
|
43
|
|
|
plt.ylabel("Power (kW)") |
|
44
|
|
|
plt.gcf().autofmt_xdate() |
|
45
|
|
|
## %%[plot_trip_data_end] |
|
46
|
|
|
# %%[energysystem_and_bus_start] |
|
47
|
|
|
bus_car = solph.Bus(label="Car Electricity") |
|
48
|
|
|
|
|
49
|
|
|
ev_energy_system.add(bus_car) |
|
50
|
|
|
# %%[energysystem_and_bus_end] |
|
51
|
|
|
# %%[car_start] |
|
52
|
|
|
demand_driving = solph.components.Sink( |
|
53
|
|
|
label="Driving Demand", |
|
54
|
|
|
inputs={bus_car: solph.Flow(nominal_capacity=1, fix=ev_demand)}, |
|
55
|
|
|
) |
|
56
|
|
|
|
|
57
|
|
|
ev_energy_system.add(demand_driving) |
|
58
|
|
|
|
|
59
|
|
|
storage_revenue = np.zeros(len(time_index) - 1) |
|
60
|
|
|
storage_revenue[-1] = -0.6 # 60 ct/kWh in the last time step |
|
61
|
|
|
|
|
62
|
|
|
car_battery = solph.components.GenericStorage( |
|
63
|
|
|
label="Car Battery", |
|
64
|
|
|
nominal_capacity=50, # kWh |
|
65
|
|
|
inputs={bus_car: solph.Flow()}, |
|
66
|
|
|
outputs={bus_car: solph.Flow()}, |
|
67
|
|
|
initial_storage_level=1, # full in the beginning |
|
68
|
|
|
loss_rate=0.001, # 0.1 % / hr |
|
69
|
|
|
inflow_conversion_factor=0.9, # 90 % charging efficiency |
|
70
|
|
|
balanced=False, # True: content at beginning and end need to be equal |
|
71
|
|
|
storage_costs=storage_revenue, # Only has an effect on charging. |
|
72
|
|
|
) |
|
73
|
|
|
|
|
74
|
|
|
ev_energy_system.add(car_battery) |
|
75
|
|
|
# %%[car_end] |
|
76
|
|
|
|
|
77
|
|
|
|
|
78
|
|
|
# %%[AC_30ct_charging_start] |
|
79
|
|
|
|
|
80
|
|
|
car_at_home = pd.Series(1, index=time_index[:-1]) |
|
81
|
|
|
car_at_home.loc[driving_start_morning:driving_end_evening] = 0 |
|
82
|
|
|
|
|
83
|
|
|
# To be able to load the battery a electric source e.g. electric grid is |
|
84
|
|
|
# necessary. We set the maximum use to 1 if the car is present, while it |
|
85
|
|
|
# is 0 between the morning start and the evening arrival back home. |
|
86
|
|
|
# While the car itself can potentially charge with at a higher power, |
|
87
|
|
|
# we just add an AC source with 16 A at 230 V. |
|
88
|
|
|
charger230V = solph.components.Source( |
|
89
|
|
|
label="230V AC", |
|
90
|
|
|
outputs={ |
|
91
|
|
|
bus_car: solph.Flow( |
|
92
|
|
|
nominal_capacity=3.68, # 230 V * 16 A = 3.68 kW |
|
93
|
|
|
variable_costs=0.3, # 30 ct/kWh |
|
94
|
|
|
max=car_at_home, |
|
95
|
|
|
) |
|
96
|
|
|
}, |
|
97
|
|
|
) |
|
98
|
|
|
|
|
99
|
|
|
ev_energy_system.add(charger230V) |
|
100
|
|
|
|
|
101
|
|
|
# %%[AC_30ct_charging_end] |
|
102
|
|
|
# %%[DC_charging_start] |
|
103
|
|
|
car_at_work = pd.Series(0, index=time_index[:-1]) |
|
104
|
|
|
car_at_work.loc[driving_end_morning:driving_start_evening] = 1 |
|
105
|
|
|
|
|
106
|
|
|
# variable_costs in the Flow default to 0, so it's free |
|
107
|
|
|
charger11kW = solph.components.Source( |
|
108
|
|
|
label="11kW", |
|
109
|
|
|
outputs={ |
|
110
|
|
|
bus_car: solph.Flow( |
|
111
|
|
|
nominal_capacity=11, # 11 kW |
|
112
|
|
|
max=car_at_work, |
|
113
|
|
|
) |
|
114
|
|
|
}, |
|
115
|
|
|
) |
|
116
|
|
|
|
|
117
|
|
|
ev_energy_system.add(charger11kW) |
|
118
|
|
|
# %%[DC_charging_end] |
|
119
|
|
|
# %%[graph_start] |
|
120
|
|
|
plt.figure() |
|
121
|
|
|
graph = create_nx_graph(ev_energy_system) |
|
122
|
|
|
nx.drawing.nx_pydot.write_dot(graph, "ev_carging_graph_3.dot") |
|
123
|
|
|
nx.draw(graph, with_labels=True, font_size=8) |
|
124
|
|
|
# %%[graph_end] |
|
125
|
|
|
# %%[solve_start] |
|
126
|
|
|
# %%[solve_start] |
|
127
|
|
|
model = solph.Model(ev_energy_system) |
|
128
|
|
|
model.solve(solver="cbc", solve_kwargs={"tee": True}) |
|
129
|
|
|
results = solph.processing.results(model) |
|
130
|
|
|
# %%[solve_end] |
|
131
|
|
|
# %%[plot_results_start] |
|
132
|
|
|
plot_results( |
|
133
|
|
|
results=results, |
|
134
|
|
|
plot_title="Home and work charging", |
|
135
|
|
|
dark_mode=False, |
|
136
|
|
|
) |
|
137
|
|
|
plt.show() |
|
138
|
|
|
# %%[plot_results_end] |
|
139
|
|
|
|