|
1
|
|
|
# -*- coding: utf-8 -*- |
|
2
|
|
|
|
|
3
|
|
|
""" |
|
4
|
|
|
This example gives a simplified idea how SubNetworks |
|
5
|
|
|
might be used to work with discretised temperatures. |
|
6
|
|
|
|
|
7
|
|
|
SPDX-FileCopyrightText: Patrik Schönfeldt <[email protected]> |
|
8
|
|
|
SPDX-FileCopyrightText: Deutsches Zentrum für Luft- und Raumfahrt (DLR) |
|
9
|
|
|
|
|
10
|
|
|
SPDX-License-Identifier: MIT |
|
11
|
|
|
""" |
|
12
|
|
|
|
|
13
|
|
|
import numpy as np |
|
14
|
|
|
|
|
15
|
|
|
from oemof.network import SubNetwork |
|
16
|
|
|
|
|
17
|
|
|
from oemof import solph |
|
18
|
|
|
|
|
19
|
|
|
|
|
20
|
|
|
class HeatPump(SubNetwork): |
|
21
|
|
|
|
|
22
|
|
|
def __init__( |
|
23
|
|
|
self, |
|
24
|
|
|
label: str, |
|
25
|
|
|
el_supply: solph.Bus, |
|
26
|
|
|
heat_demand: dict[solph.Bus, float], |
|
27
|
|
|
source_temperature: float | list[float], |
|
28
|
|
|
cpf: float = 0.5, |
|
29
|
|
|
el_power_limit: float = None, |
|
30
|
|
|
parent_node=None, |
|
31
|
|
|
): |
|
32
|
|
|
self.el_supply_bus = el_supply |
|
33
|
|
|
self.heat_demand_buses = heat_demand |
|
34
|
|
|
self.temperature = np.array(source_temperature) |
|
35
|
|
|
|
|
36
|
|
|
self.cpf = cpf |
|
37
|
|
|
self.el_power_limit = el_power_limit |
|
38
|
|
|
|
|
39
|
|
|
super().__init__(label=label, parent_node=parent_node) |
|
40
|
|
|
|
|
41
|
|
|
el_bus = self.subnode( |
|
42
|
|
|
solph.Bus, |
|
43
|
|
|
local_name="el", |
|
44
|
|
|
inputs={ |
|
45
|
|
|
self.el_supply_bus: solph.Flow( |
|
46
|
|
|
nominal_capacity=self.el_power_limit, |
|
47
|
|
|
), |
|
48
|
|
|
}, |
|
49
|
|
|
) |
|
50
|
|
|
|
|
51
|
|
|
for target, temperature in self.heat_demand_buses.items(): |
|
52
|
|
|
cop = self.cpf * temperature / (temperature - self.temperature) |
|
53
|
|
|
|
|
54
|
|
|
self.subnode( |
|
55
|
|
|
solph.components.Converter, |
|
56
|
|
|
local_name=f"hp_{temperature}", |
|
57
|
|
|
inputs={el_bus: solph.Flow()}, |
|
58
|
|
|
outputs={target: solph.Flow()}, |
|
59
|
|
|
conversion_factors={el_bus: cop}, |
|
60
|
|
|
) |
|
61
|
|
|
|
|
62
|
|
|
|
|
63
|
|
|
def main(): |
|
64
|
|
|
|
|
65
|
|
|
date_time_index = solph.create_time_index(2025, number=2) |
|
66
|
|
|
|
|
67
|
|
|
# create the energysystem and assign the time index |
|
68
|
|
|
es = solph.EnergySystem( |
|
69
|
|
|
timeindex=date_time_index, infer_last_interval=False |
|
70
|
|
|
) |
|
71
|
|
|
|
|
72
|
|
|
house = SubNetwork("house") |
|
73
|
|
|
|
|
74
|
|
|
el_bus = house.subnode( |
|
75
|
|
|
solph.Bus, |
|
76
|
|
|
local_name="el", |
|
77
|
|
|
) |
|
78
|
|
|
el_source = solph.components.Source( |
|
79
|
|
|
label="el_grid", |
|
80
|
|
|
outputs={el_bus: solph.Flow(variable_costs=0.3)}, |
|
81
|
|
|
) |
|
82
|
|
|
es.add(house, el_bus, el_source) |
|
83
|
|
|
|
|
84
|
|
|
heat_demands = house.subnode( |
|
85
|
|
|
SubNetwork, |
|
86
|
|
|
local_name="heat demand", |
|
87
|
|
|
) |
|
88
|
|
|
demand_bus_dhw = heat_demands.subnode(solph.Bus, "b_dhw") |
|
89
|
|
|
demand_bus_sh = heat_demands.subnode(solph.Bus, "b_sh") |
|
90
|
|
|
|
|
91
|
|
|
heat_demands.subnode( |
|
92
|
|
|
solph.components.Sink, |
|
93
|
|
|
local_name="d_dhw", |
|
94
|
|
|
inputs={demand_bus_dhw: solph.Flow(nominal_capacity=1, fix=[0, 0.2])}, |
|
95
|
|
|
) |
|
96
|
|
|
heat_demands.subnode( |
|
97
|
|
|
solph.components.Sink, |
|
98
|
|
|
local_name="d_sh", |
|
99
|
|
|
inputs={demand_bus_sh: solph.Flow(nominal_capacity=1, fix=[0.4, 2.1])}, |
|
100
|
|
|
) |
|
101
|
|
|
es.add(heat_demands) |
|
102
|
|
|
hp = house.subnode( |
|
103
|
|
|
HeatPump, |
|
104
|
|
|
local_name="hp", |
|
105
|
|
|
el_supply=el_bus, |
|
106
|
|
|
heat_demand={demand_bus_dhw: 60.0, demand_bus_sh: 30}, |
|
107
|
|
|
source_temperature=[3, 0], |
|
108
|
|
|
cpf=0.45, |
|
109
|
|
|
el_power_limit=3, |
|
110
|
|
|
) |
|
111
|
|
|
es.add(hp) |
|
112
|
|
|
|
|
113
|
|
|
model = solph.Model(es) |
|
114
|
|
|
model.solve() |
|
115
|
|
|
|
|
116
|
|
|
results = solph.Results(model) |
|
117
|
|
|
|
|
118
|
|
|
print(results.flow) |
|
119
|
|
|
|
|
120
|
|
|
|
|
121
|
|
|
if __name__ == "__main__": |
|
122
|
|
|
main() |
|
123
|
|
|
|