tests.test_components   A
last analyzed

Complexity

Total Complexity 37

Size/Duplication

Total Lines 357
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 37
eloc 227
dl 0
loc 357
rs 9.44
c 0
b 0
f 0

19 Functions

Rating   Name   Duplication   Size   Complexity  
A test_generic_storage_relations_overdetermined() 0 20 2
A test_generic_storage_input_output_relation_without_investment_flow_out() 0 14 2
A test_offsetconverter_without_nonconvex() 0 15 2
A test_offsetconverter_multiple_nonconvex() 0 14 2
A test_generic_storage_with_non_convex_investment() 0 14 2
A test_generic_storage_input_capacity_relation_without_investment_flow() 0 14 2
A test_generic_storage_output_capacity_relation_without_investment_flow() 0 14 2
A test_generic_storage_with_convex_invest_offset() 0 13 2
A test_generic_chp_without_warning() 0 25 1
A test_generic_storage_too_many_inputs() 0 9 2
A test_generic_storage_initial_storage_level() 0 22 2
A test_generic_storage_input_capacity_relation_without_storage_investment() 0 14 2
A test_generic_storage_output_capacity_relation_without_storage_investment() 0 14 2
A test_generic_storage_too_many_outputs() 0 9 2
A test_generic_storage_without_inputs() 0 3 2
A test_generic_storage_input_output_relation_without_investment_flow_in() 0 14 2
A test_generic_storage_with_invest_and_fixed_losses_absolute() 0 18 2
A test_offsetconverter_investment_not_on_nonconvex() 0 14 2
A test_generic_storage_with_non_convex_invest_maximum() 0 13 2
1
# -*- coding: utf-8 -
2
3
"""Tests of the component module.
4
5
This file is part of project oemof (github.com/oemof/oemof). It's copyrighted
6
by the contributors recorded in the version control history of the file,
7
available from its original location oemof/tests/test_components.py
8
9
SPDX-License-Identifier: MIT
10
"""
11
12
import warnings
13
14
import pytest
15
from oemof.tools.debugging import SuspiciousUsageWarning
16
17
from oemof.solph import Investment
18
from oemof.solph import NonConvex
19
from oemof.solph import components
20
from oemof.solph.buses import Bus
21
from oemof.solph.flows import Flow
22
23
# ********* GenericStorage *********
24
25
26
def test_generic_storage_relations_overdetermined():
27
    """Duplicate definition inflow."""
28
    bel = Bus()
29
    with pytest.raises(AttributeError, match="Overdetermined."):
30
        components.GenericStorage(
31
            label="storage",
32
            inputs={
33
                bel: Flow(variable_costs=10e10, nominal_capacity=Investment())
34
            },
35
            outputs={
36
                bel: Flow(variable_costs=10e10, nominal_capacity=Investment())
37
            },
38
            loss_rate=0.00,
39
            initial_storage_level=0,
40
            invest_relation_input_output=1,
41
            invest_relation_output_capacity=1,
42
            invest_relation_input_capacity=1,
43
            nominal_capacity=Investment(),
44
            inflow_conversion_factor=1,
45
            outflow_conversion_factor=0.8,
46
        )
47
48
49
def test_generic_storage_input_capacity_relation_without_investment_flow():
50
    """invest_relation_input_capacity set without passing an Investment object
51
    to the input flow"""
52
    bel = Bus()
53
    with pytest.raises(
54
        AttributeError,
55
        match="The input flow needs to have an Investment object",
56
    ):
57
        components.GenericStorage(
58
            label="storage",
59
            inputs={bel: Flow()},
60
            outputs={bel: Flow()},
61
            invest_relation_input_capacity=1,
62
            nominal_capacity=Investment(),
63
        )
64
65
66
def test_generic_storage_input_capacity_relation_without_storage_investment():
67
    """invest_relation_input_capacity set without passing an Investment object
68
    to the storage"""
69
    bel = Bus()
70
    with pytest.raises(
71
        AttributeError,
72
        match="`nominal_capacity` needs to be an Investment",
73
    ):
74
        components.GenericStorage(
75
            label="storage",
76
            inputs={bel: Flow(nominal_capacity=Investment())},
77
            outputs={bel: Flow()},
78
            invest_relation_input_capacity=1,
79
            nominal_capacity=45,
80
        )
81
82
83
def test_generic_storage_output_capacity_relation_without_investment_flow():
84
    """invest_relation_output_capacity set without passing an Investment
85
    object to the output flow"""
86
    bel = Bus()
87
    with pytest.raises(
88
        AttributeError,
89
        match="The output flow needs to have an Investment object",
90
    ):
91
        components.GenericStorage(
92
            label="storage",
93
            inputs={bel: Flow()},
94
            outputs={bel: Flow()},
95
            invest_relation_output_capacity=1,
96
            nominal_capacity=Investment(),
97
        )
98
99
100
def test_generic_storage_output_capacity_relation_without_storage_investment():
101
    """invest_relation_output_capacity set without passing an Investment object
102
    to the storage"""
103
    bel = Bus()
104
    with pytest.raises(
105
        AttributeError,
106
        match="`nominal_capacity` needs to be an Investment",
107
    ):
108
        components.GenericStorage(
109
            label="storage",
110
            inputs={bel: Flow()},
111
            outputs={bel: Flow(nominal_capacity=Investment())},
112
            invest_relation_output_capacity=1,
113
            nominal_capacity=45,
114
        )
115
116
117
def test_generic_storage_input_output_relation_without_investment_flow_in():
118
    """invest_relation_input_output set without passing an Investment
119
    object to the input flow"""
120
    bel = Bus()
121
    with pytest.raises(
122
        AttributeError,
123
        match="The input flow needs to have an Investment object",
124
    ):
125
        components.GenericStorage(
126
            label="storage",
127
            inputs={bel: Flow()},
128
            outputs={bel: Flow(nominal_capacity=Investment())},
129
            invest_relation_input_output=1,
130
            nominal_capacity=45,
131
        )
132
133
134
def test_generic_storage_input_output_relation_without_investment_flow_out():
135
    """invest_relation_input_output set without passing an Investment
136
    object to the output flow"""
137
    bel = Bus()
138
    with pytest.raises(
139
        AttributeError,
140
        match="The output flow needs to have an Investment object",
141
    ):
142
        components.GenericStorage(
143
            label="storage",
144
            inputs={bel: Flow(nominal_capacity=Investment())},
145
            outputs={bel: Flow()},
146
            invest_relation_input_output=1,
147
            nominal_capacity=45,
148
        )
149
150
151
def test_generic_storage_initial_storage_level():
152
    """Infeasible parameter combination for initial_storage_level"""
153
    bel = Bus()
154
    with pytest.raises(
155
        ValueError, match="initial_storage_level must be greater"
156
    ):
157
        components.GenericStorage(
158
            label="storage",
159
            nominal_capacity=Investment(),
160
            inputs={
161
                bel: Flow(variable_costs=10e10, nominal_capacity=Investment())
162
            },
163
            outputs={
164
                bel: Flow(variable_costs=10e10, nominal_capacity=Investment())
165
            },
166
            loss_rate=0.00,
167
            initial_storage_level=0,
168
            min_storage_level=0.1,
169
            invest_relation_input_capacity=1 / 6,
170
            invest_relation_output_capacity=1 / 6,
171
            inflow_conversion_factor=1,
172
            outflow_conversion_factor=0.8,
173
        )
174
175
176
def test_generic_storage_with_non_convex_investment():
177
    """Tests error if `offset` and `existing` attribute are given."""
178
    with pytest.raises(
179
        AttributeError, match=r"Values for 'offset' and 'existing' are given"
180
    ):
181
        bel = Bus()
182
        components.GenericStorage(
183
            label="storage4",
184
            inputs={bel: Flow()},
185
            outputs={bel: Flow()},
186
            invest_relation_input_capacity=1 / 6,
187
            invest_relation_output_capacity=1 / 6,
188
            nominal_capacity=Investment(
189
                nonconvex=True, existing=5, maximum=25
190
            ),
191
        )
192
193
194
def test_generic_storage_with_non_convex_invest_maximum():
195
    """No investment maximum at nonconvex investment."""
196
    with pytest.raises(
197
        AttributeError, match=r"Please provide a maximum investment value"
198
    ):
199
        bel = Bus()
200
        components.GenericStorage(
201
            label="storage6",
202
            inputs={bel: Flow()},
203
            outputs={bel: Flow()},
204
            invest_relation_input_capacity=1 / 6,
205
            invest_relation_output_capacity=1 / 6,
206
            nominal_capacity=Investment(nonconvex=True),
207
        )
208
209
210
def test_generic_storage_with_convex_invest_offset():
211
    """Offset value is given and nonconvex is False."""
212
    with pytest.raises(
213
        AttributeError, match=r"If `nonconvex` is `False`, the `offset`"
214
    ):
215
        bel = Bus()
216
        components.GenericStorage(
217
            label="storage6",
218
            inputs={bel: Flow()},
219
            outputs={bel: Flow()},
220
            invest_relation_input_capacity=1 / 6,
221
            invest_relation_output_capacity=1 / 6,
222
            nominal_capacity=Investment(offset=10),
223
        )
224
225
226
def test_generic_storage_with_invest_and_fixed_losses_absolute():
227
    """
228
    Storage with fixed losses in the investment mode but no minimum or existing
229
    value is set an AttributeError is raised because this may result in storage
230
    with zero capacity but fixed losses.
231
    """
232
    msg = (
233
        r"With fixed_losses_absolute > 0, either investment.existing or"
234
        " investment.minimum has to be non-zero."
235
    )
236
    with pytest.raises(AttributeError, match=msg):
237
        bel = Bus()
238
        components.GenericStorage(
239
            label="storage4",
240
            inputs={bel: Flow()},
241
            outputs={bel: Flow()},
242
            nominal_capacity=Investment(ep_costs=23, minimum=0, existing=0),
243
            fixed_losses_absolute=[0, 0, 4],
244
        )
245
246
247
def test_generic_storage_without_inputs():
248
    with pytest.warns(SuspiciousUsageWarning):
249
        components.GenericStorage(label="storage5")
250
251
252
def test_generic_storage_too_many_inputs():
253
    msg = r"Only one input flow allowed in the GenericStorage storage6"
254
    bel1 = Bus()
255
    bel2 = Bus()
256
    with pytest.raises(AttributeError, match=msg):
257
        components.GenericStorage(
258
            label="storage6",
259
            inputs={bel1: Flow(), bel2: Flow()},
260
            outputs={bel2: Flow()},
261
        )
262
263
264
def test_generic_storage_too_many_outputs():
265
    msg = r"Only one output flow allowed in the GenericStorage storage7"
266
    bel1 = Bus()
267
    bel2 = Bus()
268
    with pytest.raises(AttributeError, match=msg):
269
        components.GenericStorage(
270
            label="storage7",
271
            inputs={bel1: Flow()},
272
            outputs={bel1: Flow(), bel2: Flow()},
273
        )
274
275
276
# ********* OffsetConverter *********
277
278
279
def test_offsetconverter_without_nonconvex():
280
    """No NonConvex attribute is defined for any of the attached flows."""
281
    with pytest.raises(
282
        ValueError,
283
        match=(
284
            "Exactly one flow of the `OffsetConverter` must have the "
285
            "`NonConvex` attribute."
286
        ),
287
    ):
288
        b_diesel = Bus(label="bus_diesel")
289
        b_el = Bus(label="bus_electricity")
290
        components.OffsetConverter(
291
            label="diesel_genset",
292
            inputs={b_diesel: Flow()},
293
            outputs={b_el: Flow()},
294
        )
295
296
297
def test_offsetconverter_multiple_nonconvex():
298
    """NonConvex attribute is defined for more than one flow."""
299
    with pytest.raises(
300
        ValueError,
301
        match=(
302
            "Exactly one flow of the `OffsetConverter` must have the "
303
            "`NonConvex` attribute."
304
        ),
305
    ):
306
        b_diesel = Bus(label="bus_diesel")
307
        b_heat = Bus(label="bus_heat")
308
        components.OffsetConverter(
309
            inputs={b_diesel: Flow(nonconvex=NonConvex())},
310
            outputs={b_heat: Flow(nonconvex=NonConvex())},
311
        )
312
313
314
def test_offsetconverter_investment_not_on_nonconvex():
315
    """Investment attribute is defined for a not NonConvex flow."""
316
    with pytest.raises(
317
        TypeError,
318
        match=(
319
            "`Investment` attribute must be "
320
            "defined only for the NonConvex flow!"
321
        ),
322
    ):
323
        b_diesel = Bus(label="bus_diesel")
324
        b_heat = Bus(label="bus_heat")
325
        components.OffsetConverter(
326
            inputs={b_diesel: Flow(nominal_capacity=Investment(maximum=1))},
327
            outputs={b_heat: Flow(nonconvex=NonConvex())},
328
        )
329
330
331
# ********* GenericCHP *********
332
def test_generic_chp_without_warning():
333
    warnings.filterwarnings("error", category=SuspiciousUsageWarning)
334
    bel = Bus(label="electricityBus")
335
    bth = Bus(label="heatBus")
336
    bgas = Bus(label="commodityBus")
337
    components.GenericCHP(
338
        label="combined_cycle_extraction_turbine",
339
        fuel_input={
340
            bgas: Flow(custom_attributes={"H_L_FG_share_max": [0.183]})
341
        },
342
        electrical_output={
343
            bel: Flow(
344
                custom_attributes={
345
                    "P_max_woDH": [155.946],
346
                    "P_min_woDH": [68.787],
347
                    "Eta_el_max_woDH": [0.525],
348
                    "Eta_el_min_woDH": [0.444],
349
                }
350
            )
351
        },
352
        heat_output={bth: Flow(custom_attributes={"Q_CW_min": [10.552]})},
353
        beta=[0.122],
354
        back_pressure=False,
355
    )
356
    warnings.filterwarnings("always", category=SuspiciousUsageWarning)
357