district_heating_supply_4   A
last analyzed

Complexity

Total Complexity 0

Size/Duplication

Total Lines 231
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 0
eloc 152
dl 0
loc 231
rs 10
c 0
b 0
f 0
1
import pandas as pd
2
from helpers import LCOH
3
from helpers import epc
4
5
import oemof.solph as solph
6
7
8
data = pd.read_csv("input_data.csv", sep=";", index_col=0, parse_dates=True)
9
10
district_heating_system = solph.EnergySystem(
11
    timeindex=data.index, infer_last_interval=False
12
)
13
14
heat_bus = solph.Bus(label="heat network")
15
gas_bus = solph.Bus(label="gas network")
16
waste_heat_bus = solph.Bus(label="waste heat network")
17
electricity_bus = solph.Bus(label="electricity network")
18
19
district_heating_system.add(heat_bus, gas_bus, waste_heat_bus, electricity_bus)
20
21
gas_source = solph.components.Source(
22
    label="gas source",
23
    outputs={gas_bus: solph.flows.Flow(variable_costs=data["gas price"])},
24
)
25
26
electricity_source = solph.components.Source(
27
    label="electricity source",
28
    outputs={
29
        electricity_bus: solph.flows.Flow(variable_costs=data["el_spot_price"])
30
    },
31
)
32
33
heat_sink = solph.components.Sink(
34
    label="heat sink",
35
    inputs={
36
        heat_bus: solph.flows.Flow(
37
            nominal_value=data["heat demand"].max(),
38
            fix=data["heat demand"] / data["heat demand"].max(),
39
        )
40
    },
41
)
42
43
district_heating_system.add(gas_source, electricity_source, heat_sink)
44
45
# %%[sec_1_start]
46
waste_heat_source = solph.components.Source(
47
    label="waste heat source",
48
    outputs={waste_heat_bus: solph.flows.Flow(nominal_value=1, fix=2.5)},
49
)
50
51
district_heating_system.add(waste_heat_source)
52
# %%[sec_1_end]
53
54
spec_inv_gas_boiler = 60000
55
var_cost_gas_boiler = 1.10
56
57
gas_boiler = solph.components.Converter(
58
    label="gas boiler",
59
    inputs={gas_bus: solph.flows.Flow()},
60
    outputs={
61
        heat_bus: solph.flows.Flow(
62
            nominal_value=solph.Investment(
63
                ep_costs=epc(spec_inv_gas_boiler), maximum=50
64
            ),
65
            variable_costs=var_cost_gas_boiler,
66
        )
67
    },
68
    conversion_factors={gas_bus: 0.95},
69
)
70
71
district_heating_system.add(gas_boiler)
72
73
spec_inv_storage = 1060
74
var_cost_storage = 0.1
75
76
heat_storage = solph.components.GenericStorage(
77
    label="heat storage",
78
    nominal_capacity=solph.Investment(ep_costs=epc(spec_inv_storage)),
79
    inputs={heat_bus: solph.flows.Flow(variable_costs=var_cost_storage)},
80
    outputs={heat_bus: solph.flows.Flow(variable_costs=var_cost_storage)},
81
    invest_relation_input_capacity=1 / 24,
82
    invest_relation_output_capacity=1 / 24,
83
    balanced=True,
84
    loss_rate=0.001,
85
)
86
87
district_heating_system.add(heat_storage)
88
89
cop = 3.5
90
spec_inv_heat_pump = 500000
91
var_cost_heat_pump = 1.2
92
93
94
heat_pump = solph.components.Converter(
95
    label="heat pump",
96
    inputs={
97
        electricity_bus: solph.flows.Flow(),
98
        waste_heat_bus: solph.flows.Flow(),
99
    },
100
    outputs={
101
        heat_bus: solph.flows.Flow(
102
            nominal_value=solph.Investment(
103
                ep_costs=epc(spec_inv_heat_pump), maximum=999
104
            ),
105
            variable_costs=1.2,
106
            min=0.5,
107
            nonconvex=solph.NonConvex(),
108
        )
109
    },
110
    conversion_factors={
111
        electricity_bus: 1 / cop,
112
        waste_heat_bus: (cop - 1) / cop,
113
    },
114
)
115
district_heating_system.add(heat_pump)
116
117
# solve model
118
model = solph.Model(district_heating_system)
119
model.solve(
120
    solver="cbc",
121
    solve_kwargs={"tee": True},
122
    cmdline_options={"ratio": 0.01},
123
    allow_nonoptimal=True,
124
)
125
126
# results
127
results = solph.processing.results(model)
128
129
data_gas_bus = solph.views.node(results, "gas network")["sequences"]
130
data_heat_bus = solph.views.node(results, "heat network")["sequences"]
131
data_el_bus = solph.views.node(results, "electricity network")["sequences"]
132
data_caps = solph.views.node(results, "heat network")["scalars"]
133
134
cap_gas_boiler = data_caps[("gas boiler", "heat network"), "invest"]
135
cap_heat_pump = data_caps[("heat pump", "heat network"), "invest"]
136
cap_storage = solph.views.node(results, "heat storage")["scalars"][
137
    (("heat storage", "None"), "invest")
138
]
139
cap_storage_out = data_caps[("heat storage", "heat network"), "invest"]
140
141
print(f"capacity gas boiler: {cap_gas_boiler:.1f} MW")
142
print(f"capacity heat pump: {cap_heat_pump:.1f} MW")
143
print(f"capacity heat storage: {cap_storage:.1f} MWh")
144
print(f"capacity heat storage (out): {cap_storage_out:.1f} MW")
145
146
invest_cost = (
147
    spec_inv_gas_boiler * cap_gas_boiler
148
    + spec_inv_storage * cap_storage
149
    + spec_inv_heat_pump * cap_heat_pump
150
)
151
operation_cost = (
152
    var_cost_gas_boiler
153
    * data_heat_bus[(("gas boiler", "heat network"), "flow")].sum()
154
    + (
155
        data["gas price"]
156
        * data_gas_bus[(("gas network", "gas boiler"), "flow")]
157
    ).sum()
158
    + var_cost_heat_pump
159
    * data_heat_bus[(("heat pump", "heat network"), "flow")].sum()
160
    + (
161
        data["el_spot_price"]
162
        * data_el_bus[(("electricity network", "heat pump"), "flow")]
163
    ).sum()
164
    + var_cost_storage
165
    * data_heat_bus[(("heat storage", "heat network"), "flow")].sum()
166
    + var_cost_storage
167
    * data_heat_bus[(("heat network", "heat storage"), "flow")].sum()
168
)
169
heat_produced = data_heat_bus[(("heat network", "heat sink"), "flow")].sum()
170
171
lcoh = LCOH(invest_cost, operation_cost, heat_produced)
172
print(f"LCOH: {lcoh:.2f} €/MWh")
173
174
import matplotlib.pyplot as plt
175
176
# plt.style.use('dark_background')
177
178
unit_colors = {
179
    "gas boiler": "#EC6707",
180
    "heat pump": "#B54036",
181
    "heat storage (discharge)": "#BFBFBF",
182
    "heat storage (charge)": "#696969",
183
}
184
185
fig, ax = plt.subplots(figsize=[10, 6])
186
187
bottom = 0
188
for unit in ["heat pump", "gas boiler", "heat storage"]:
189
    unit_label = f"{unit} (discharge)" if "storage" in unit else unit
190
    ax.bar(
191
        data_heat_bus.index,
192
        data_heat_bus[((unit, "heat network"), "flow")],
193
        label=unit_label,
194
        color=unit_colors[unit_label],
195
        bottom=bottom,
196
    )
197
    bottom += data_heat_bus[((unit, "heat network"), "flow")]
198
199
unit_label = "heat storage (charge)"
200
ax.bar(
201
    data_heat_bus.index,
202
    -1 * data_heat_bus[(("heat network", "heat storage"), "flow")],
203
    label=unit_label,
204
    color=unit_colors[unit_label],
205
)
206
207
ax.legend(loc="upper center", ncol=2)
208
ax.grid(axis="y")
209
ax.set_ylabel("Hourly heat production in MWh")
210
211
# plt.tight_layout()
212
# plt.savefig('intro_tut_dhs_4_hourly_heat_production.svg')
213
214
215
fig, ax = plt.subplots(figsize=[10, 6])
216
217
data_heat_storage = solph.views.node(results, "heat storage")["sequences"]
218
219
ax.plot(
220
    data_heat_storage[(("heat storage", "None"), "storage_content")],
221
    color="#00395B",
222
)
223
224
ax.grid(axis="y")
225
ax.set_ylabel("Hourly heat storage content in MWh")
226
227
# plt.tight_layout()
228
# plt.savefig('intro_tut_dhs_4_hourly_storage_content.svg')
229
230
plt.show()
231