|
1
|
|
|
# -*- coding: utf-8 -*- |
|
2
|
|
|
|
|
3
|
|
|
""" |
|
4
|
|
|
General description |
|
5
|
|
|
------------------- |
|
6
|
|
|
|
|
7
|
|
|
A minimal example to show how time steps work. |
|
8
|
|
|
|
|
9
|
|
|
* Flows are defined in time intervals, storage content at points in time. |
|
10
|
|
|
Thus, there is one more value for storage contents then for the |
|
11
|
|
|
flow values. |
|
12
|
|
|
* Time intervals are named by the time at the beginning of that interval. |
|
13
|
|
|
The quantity changes to the given value at the given point in time. |
|
14
|
|
|
* The initial_storage_level of a GenericStorage is given |
|
15
|
|
|
at the first time step. If the storage is balanced, |
|
16
|
|
|
this is the same storage level as in the last time step. |
|
17
|
|
|
* The nominal_value in Flows has to be interpreted in means of power: |
|
18
|
|
|
We have nominal_value=0.5, but the maximum change of the storage content |
|
19
|
|
|
of an ideal storage is 0.125. |
|
20
|
|
|
|
|
21
|
|
|
Installation requirements |
|
22
|
|
|
------------------------- |
|
23
|
|
|
This example requires oemof.solph (v0.5.x), install by: |
|
24
|
|
|
|
|
25
|
|
|
pip install oemof.solph[examples] |
|
26
|
|
|
|
|
27
|
|
|
|
|
28
|
|
|
License |
|
29
|
|
|
------- |
|
30
|
|
|
`MIT license <https://github.com/oemof/oemof-solph/blob/dev/LICENSE>`_ |
|
31
|
|
|
""" |
|
32
|
|
|
import matplotlib.pyplot as plt |
|
33
|
|
|
|
|
34
|
|
|
from oemof import solph |
|
35
|
|
|
|
|
36
|
|
|
|
|
37
|
|
View Code Duplication |
def main(): |
|
|
|
|
|
|
38
|
|
|
|
|
39
|
|
|
solver = "cbc" # 'glpk', 'gurobi',... |
|
40
|
|
|
solver_verbose = False # show/hide solver output |
|
41
|
|
|
|
|
42
|
|
|
date_time_index = solph.create_time_index(2000, interval=0.25, number=8) |
|
43
|
|
|
|
|
44
|
|
|
energy_system = solph.EnergySystem( |
|
45
|
|
|
timeindex=date_time_index, infer_last_interval=False |
|
46
|
|
|
) |
|
47
|
|
|
|
|
48
|
|
|
bus = solph.buses.Bus(label="bus") |
|
49
|
|
|
source = solph.components.Source( |
|
50
|
|
|
label="source", |
|
51
|
|
|
outputs={ |
|
52
|
|
|
bus: solph.flows.Flow( |
|
53
|
|
|
nominal_value=2, |
|
54
|
|
|
variable_costs=0.2, |
|
55
|
|
|
max=[0, 0, 0, 0, 1, 0.25, 0.75, 1], |
|
56
|
|
|
) |
|
57
|
|
|
}, |
|
58
|
|
|
) |
|
59
|
|
|
storage = solph.components.GenericStorage( |
|
60
|
|
|
label="storage", |
|
61
|
|
|
inputs={bus: solph.flows.Flow()}, |
|
62
|
|
|
outputs={bus: solph.flows.Flow()}, |
|
63
|
|
|
nominal_storage_capacity=4, |
|
64
|
|
|
initial_storage_level=0.5, |
|
65
|
|
|
) |
|
66
|
|
|
sink = solph.components.Sink( |
|
67
|
|
|
label="sink", |
|
68
|
|
|
inputs={ |
|
69
|
|
|
bus: solph.flows.Flow( |
|
70
|
|
|
nominal_value=2, |
|
71
|
|
|
variable_costs=0.1, |
|
72
|
|
|
fix=[1, 1, 0.5, 0.5, 0, 0, 0, 0], |
|
73
|
|
|
) |
|
74
|
|
|
}, |
|
75
|
|
|
) |
|
76
|
|
|
|
|
77
|
|
|
energy_system.add(bus, source, sink, storage) |
|
78
|
|
|
model = solph.Model(energy_system) |
|
79
|
|
|
model.solve(solver=solver, solve_kwargs={"tee": solver_verbose}) |
|
80
|
|
|
|
|
81
|
|
|
results = solph.processing.results(model) |
|
82
|
|
|
|
|
83
|
|
|
results_df = results[(storage, None)]["sequences"].copy() |
|
84
|
|
|
results_df["storage_inflow"] = results[(bus, storage)]["sequences"]["flow"] |
|
85
|
|
|
results_df["storage_outflow"] = results[(storage, bus)]["sequences"]["flow"] |
|
86
|
|
|
|
|
87
|
|
|
print(results_df) |
|
88
|
|
|
|
|
89
|
|
|
if plt is not None: |
|
90
|
|
|
plt.plot( |
|
91
|
|
|
results[(bus, storage)]["sequences"], |
|
92
|
|
|
drawstyle="steps-post", |
|
93
|
|
|
label="Storage inflow", |
|
94
|
|
|
) |
|
95
|
|
|
plt.plot(results[(storage, None)]["sequences"], label="Storage content") |
|
96
|
|
|
plt.plot( |
|
97
|
|
|
results[(storage, bus)]["sequences"], |
|
98
|
|
|
drawstyle="steps-post", |
|
99
|
|
|
label="Storage outflow", |
|
100
|
|
|
) |
|
101
|
|
|
|
|
102
|
|
|
plt.legend(loc="lower left") |
|
103
|
|
|
plt.show() |
|
104
|
|
|
|
|
105
|
|
|
|
|
106
|
|
|
if __name__ == "__main__": |
|
107
|
|
|
main() |
|
108
|
|
|
|