test_results_with_recent_dump()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 47
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 34
dl 0
loc 47
rs 9.064
c 0
b 0
f 0
cc 2
nop 0
1
# -*- coding: utf-8 -*-
2
3
"""
4
General description:
5
---------------------
6
7
The example models the following energy system:
8
9
                input/output  bgas     bel
10
                     |          |        |       |
11
                     |          |        |       |
12
 wind(FixedSource)   |------------------>|       |
13
                     |          |        |       |
14
 pv(FixedSource)     |------------------>|       |
15
                     |          |        |       |
16
 rgas(Commodity)     |--------->|        |       |
17
                     |          |        |       |
18
 demand(Sink)        |<------------------|       |
19
                     |          |        |       |
20
                     |          |        |       |
21
 pp_gas(Converter) |<---------|        |       |
22
                     |------------------>|       |
23
                     |          |        |       |
24
 storage(Storage)    |<------------------|       |
25
                     |------------------>|       |
26
27
28
29
This file is part of project oemof (github.com/oemof/oemof). It's copyrighted
30
by the contributors recorded in the version control history of the file,
31
available from its original location oemof/tests/test_scripts/test_solph/
32
test_storage_investment/test_storage_investment.py
33
34
SPDX-License-Identifier: MIT
35
"""
36
37
import logging
38
import os
39
40
import pandas as pd
41
import pytest
42
from oemof.tools import economics
43
44
from oemof import solph
45
from oemof.solph import processing
46
from oemof.solph import views
47
48
PP_GAS = None
49
50
51
def test_optimise_storage_size(
52
    filename="storage_investment.csv", solver="cbc"
53
):
54
    global PP_GAS
55
56
    logging.info("Initialize the energy system")
57
    date_time_index = pd.date_range("1/1/2012", periods=400, freq="h")
58
59
    es = solph.EnergySystem(
60
        timeindex=date_time_index,
61
        infer_last_interval=True,
62
    )
63
64
    full_filename = os.path.join(os.path.dirname(__file__), filename)
65
    data = pd.read_csv(full_filename, sep=",")
66
67
    # Buses
68
    bgas = solph.buses.Bus(label="natural_gas")
69
    bel = solph.buses.Bus(label="electricity")
70
    es.add(bgas, bel)
71
72
    # Sinks
73
    es.add(
74
        solph.components.Sink(
75
            label="excess_bel", inputs={bel: solph.flows.Flow()}
76
        )
77
    )
78
79
    es.add(
80
        solph.components.Sink(
81
            label="demand",
82
            inputs={
83
                bel: solph.flows.Flow(
84
                    fix=data["demand_el"], nominal_capacity=1
85
                )
86
            },
87
        )
88
    )
89
90
    # Sources
91
    es.add(
92
        solph.components.Source(
93
            label="rgas",
94
            outputs={
95
                bgas: solph.flows.Flow(
96
                    nominal_capacity=194397000 * 400 / 8760,
97
                    full_load_time_max=1,
98
                )
99
            },
100
        )
101
    )
102
103
    es.add(
104
        solph.components.Source(
105
            label="wind",
106
            outputs={
107
                bel: solph.flows.Flow(
108
                    fix=data["wind"], nominal_capacity=1000000
109
                )
110
            },
111
        )
112
    )
113
114
    es.add(
115
        solph.components.Source(
116
            label="pv",
117
            outputs={
118
                bel: solph.flows.Flow(fix=data["pv"], nominal_capacity=582000)
119
            },
120
        )
121
    )
122
123
    # Converter
124
    PP_GAS = solph.components.Converter(
125
        label="pp_gas",
126
        inputs={bgas: solph.flows.Flow()},
127
        outputs={
128
            bel: solph.flows.Flow(nominal_capacity=1e11, variable_costs=50)
129
        },
130
        conversion_factors={bel: 0.58},
131
    )
132
    es.add(PP_GAS)
133
134
    # Investment storage
135
    epc = economics.annuity(capex=1000, n=20, wacc=0.05)
136
    es.add(
137
        solph.components.GenericStorage(
138
            label="storage",
139
            inputs={
140
                bel: solph.flows.Flow(
141
                    variable_costs=10e10, nominal_capacity=solph.Investment()
142
                )
143
            },
144
            outputs={
145
                bel: solph.flows.Flow(
146
                    variable_costs=10e10, nominal_capacity=solph.Investment()
147
                )
148
            },
149
            loss_rate=0.00,
150
            initial_storage_level=0,
151
            invest_relation_input_capacity=1 / 6,
152
            invest_relation_output_capacity=1 / 6,
153
            inflow_conversion_factor=1,
154
            outflow_conversion_factor=0.8,
155
            nominal_capacity=solph.Investment(
156
                ep_costs=epc,
157
                existing=6851,
158
            ),
159
        )
160
    )
161
162
    # Solve model
163
    om = solph.Model(es)
164
    om.receive_duals()
165
    om.solve(solver=solver)
166
    es.results["main"] = processing.results(om)
167
    es.results["meta"] = processing.meta_results(om)
168
169
    # Check dump and restore
170
    es.dump(filename="./es_dump.oemof", consider_dpath=False)
171
172
173
def test_results_with_recent_dump():
174
    test_optimise_storage_size()
175
    energysystem = solph.EnergySystem()
176
    energysystem.restore(filename="./es_dump.oemof", consider_dpath=False)
177
178
    # Results
179
    results = energysystem.results["main"]
180
    meta = energysystem.results["meta"]
181
182
    electricity_bus = views.node(results, "electricity")
183
    my_results = electricity_bus["sequences"].sum(axis=0).to_dict()
184
    storage = energysystem.groups["storage"]
185
    my_results["storage_invest"] = results[(storage, None)]["scalars"][
186
        "invest"
187
    ]
188
189
    stor_invest_dict = {
190
        "storage_invest": 2040000,
191
        (("electricity", "None"), "duals"): 10800000000321,
192
        (("electricity", "demand"), "flow"): 105867395,
193
        (("electricity", "excess_bel"), "flow"): 211771291,
194
        (("electricity", "storage"), "flow"): 2350931,
195
        (("pp_gas", "electricity"), "flow"): 5148414,
196
        (("pv", "electricity"), "flow"): 7488607,
197
        (("storage", "electricity"), "flow"): 1880745,
198
        (("wind", "electricity"), "flow"): 305471851,
199
    }
200
201
    for key in stor_invest_dict.keys():
202
        assert my_results[key] == pytest.approx(stor_invest_dict[key])
203
204
    # Solver results
205
    assert str(meta["solver"]["Termination condition"]) == "optimal"
206
    assert meta["solver"]["Error rc"] == 0
207
    assert str(meta["solver"]["Status"]) == "ok"
208
209
    # Problem results
210
    assert meta["problem"]["Lower bound"] == 4.231675777e17
211
    assert meta["problem"]["Upper bound"], 4.231675777e17
212
    assert meta["problem"]["Number of variables"] == 2807
213
    assert meta["problem"]["Number of constraints"] == 2809
214
    assert meta["problem"]["Number of nonzeros"] == 1197
215
    assert meta["problem"]["Number of objectives"] == 1
216
    assert str(meta["problem"]["Sense"]) == "minimize"
217
218
    # Objective function
219
    assert meta["objective"] == pytest.approx(423167578261115584, abs=0.5)
220
221
222
def test_solph_converter_attributes_before_dump_and_after_restore():
223
    """dump/restore should preserve all attributes
224
    of `solph.components.Converter`"""
225
    test_optimise_storage_size()
226
    energysystem = solph.EnergySystem()
227
    energysystem.restore(filename="./es_dump.oemof", consider_dpath=False)
228
229
    trsf_attr_before_dump = sorted([x for x in dir(PP_GAS) if "__" not in x])
230
231
    trsf_attr_after_restore = sorted(
232
        [x for x in dir(energysystem.groups["pp_gas"]) if "__" not in x]
233
    )
234
235
    # Compare attributes before dump and after restore
236
    assert trsf_attr_before_dump == trsf_attr_after_restore
237