Completed
Push — dev ( 68ddc7...49e927 )
by Patrik
58s queued 48s
created

test_storage_tsam_vs_original   A

Complexity

Total Complexity 3

Size/Duplication

Total Lines 188
Duplicated Lines 23.4 %

Importance

Changes 0
Metric Value
wmc 3
eloc 103
dl 44
loc 188
rs 10
c 0
b 0
f 0

3 Functions

Rating   Name   Duplication   Size   Complexity  
A test_soc() 33 33 1
A test_storage_output() 0 9 1
A test_storage_input() 11 11 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
# -*- coding: utf-8 -*-
2
3
"""
4
General description:
5
---------------------
6
7
The example models the same setup as in test_storage_tsam_integration,
8
but instead of aggregating timeseries, timeseries are left untouched.
9
Nevertheless, storage input/output and SOC should equal TSAM example.
10
11
This file is part of project oemof (github.com/oemof/oemof). It's copyrighted
12
by the contributors recorded in the version control history of the file,
13
available from its original location oemof/tests/test_scripts/test_solph/
14
test_storage_investment/test_storage_investment.py
15
16
SPDX-License-Identifier: MIT
17
"""
18
19
import logging
20
21
import pandas as pd
22
import pytest
23
from oemof.tools import logger
24
25
from oemof import solph
26
27
##########################################################################
28
# Initialize the energy system and read/calculate necessary parameters
29
##########################################################################
30
31
logger.define_logging()
32
logging.info("Initialize the energy system")
33
34
tindex = pd.date_range("2022-01-01", periods=8, freq="H")
35
36
energysystem = solph.EnergySystem(
37
    timeindex=tindex,
38
    infer_last_interval=True,
39
)
40
41
##########################################################################
42
# Create oemof objects
43
##########################################################################
44
45
logging.info("Create oemof objects")
46
47
# create electricity bus
48
bel = solph.Bus(label="electricity")
49
energysystem.add(bel)
50
51
# create fixed source object representing wind power plants
52
wind = solph.components.Source(
53
    label="wind",
54
    outputs={
55
        bel: solph.Flow(fix=[1000, 0, 0, 50, 0, 50, 1000, 0], nominal_value=1)
56
    },
57
)
58
59
# create simple sink object representing the electrical demand
60
demand = solph.components.Sink(
61
    label="demand",
62
    inputs={
63
        bel: solph.Flow(
64
            fix=[100] * 8,
65
            nominal_value=1,
66
        )
67
    },
68
)
69
70
# Solving equations from above, needed initial SOC is as follows:
71
first_input = (
72
    (100 * 1 / 0.8) / (1 - 0.01)
73
    + (100 * 1 / 0.8) / (1 - 0.01) ** 2
74
    + (50 * 1 / 0.8) / (1 - 0.01) ** 3
75
    + (100 * 1 / 0.8) / (1 - 0.01) ** 4
76
    + (50 * 1 / 0.8) / (1 - 0.01) ** 5
77
)
78
last_output = (100 * 1 / 0.8) / 0.99
79
init_soc = (first_input - last_output) / (1 / 0.99 + 0.99)
80
81
# create storage object representing a battery
82
storage = solph.components.GenericStorage(
83
    label="storage",
84
    nominal_storage_capacity=2000,
85
    initial_storage_level=init_soc / 2000,
86
    inputs={bel: solph.Flow()},
87
    outputs={bel: solph.Flow()},
88
    loss_rate=0.01,
89
    inflow_conversion_factor=0.9,
90
    outflow_conversion_factor=0.8,
91
)
92
93
excess = solph.components.Sink(
94
    label="excess",
95
    inputs={bel: solph.Flow()},
96
)
97
98
energysystem.add(wind, demand, storage, excess)
99
100
##########################################################################
101
# Optimise the energy system
102
##########################################################################
103
104
logging.info("Optimise the energy system")
105
106
# initialise the operational model
107
om = solph.Model(energysystem)
108
109
# if tee_switch is true solver messages will be displayed
110
logging.info("Solve the optimization problem")
111
om.solve(solver="cbc", solve_kwargs={"tee": True})
112
113
##########################################################################
114
# Check and plot the results
115
##########################################################################
116
117
# check if the new result object is working for custom components
118
results = solph.processing.results(om)
119
120
# Concatenate flows:
121
flows = pd.concat([flow["sequences"] for flow in results.values()], axis=1)
122
flows = flows.drop(
123
    "storage_losses", axis=1
124
)  # todo: why are storage losses not return of results.keys()?
125
126
flows.columns = [
127
    f"{oemof_tuple[0]}-{oemof_tuple[1]}" for oemof_tuple in results.keys()
128
]
129
130
131 View Code Duplication
def test_storage_input():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
132
    assert flows["electricity-storage"][0] == pytest.approx(
133
        (first_input - 0.99 * init_soc) / 0.9
134
    )
135
    assert flows["electricity-storage"][1] == 0
136
    assert flows["electricity-storage"][2] == 0
137
    assert flows["electricity-storage"][3] == 0
138
    assert flows["electricity-storage"][4] == 0
139
    assert flows["electricity-storage"][5] == 0
140
    assert flows["electricity-storage"][6] == flows["electricity-storage"][0]
141
    assert flows["electricity-storage"][7] == 0
142
143
144
def test_storage_output():
145
    assert flows["storage-electricity"][0] == 0
146
    assert flows["storage-electricity"][1] == 100
147
    assert flows["storage-electricity"][2] == 100
148
    assert flows["storage-electricity"][3] == 50
149
    assert flows["storage-electricity"][4] == 100
150
    assert flows["storage-electricity"][5] == 50
151
    assert flows["storage-electricity"][6] == 0
152
    assert flows["storage-electricity"][7] == 100
153
154
155 View Code Duplication
def test_soc():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
156
    assert flows["storage-None"][0] == pytest.approx(init_soc)
157
    assert flows["storage-None"][1] == pytest.approx(
158
        (100 * 1 / 0.8) / (1 - 0.01)
159
        + (100 * 1 / 0.8) / (1 - 0.01) ** 2
160
        + (50 * 1 / 0.8) / (1 - 0.01) ** 3
161
        + (100 * 1 / 0.8) / (1 - 0.01) ** 4
162
        + (50 * 1 / 0.8) / (1 - 0.01) ** 5,
163
        abs=1e-2,
164
    )
165
    assert flows["storage-None"][2] == pytest.approx(
166
        (100 * 1 / 0.8) / (1 - 0.01)
167
        + (50 * 1 / 0.8) / (1 - 0.01) ** 2
168
        + (100 * 1 / 0.8) / (1 - 0.01) ** 3
169
        + (50 * 1 / 0.8) / (1 - 0.01) ** 4,
170
        abs=1e-2,
171
    )
172
    assert flows["storage-None"][3] == pytest.approx(
173
        (50 * 1 / 0.8) / (1 - 0.01)
174
        + (100 * 1 / 0.8) / (1 - 0.01) ** 2
175
        + (50 * 1 / 0.8) / (1 - 0.01) ** 3,
176
        abs=1e-2,
177
    )
178
    assert flows["storage-None"][4] == pytest.approx(
179
        (100 * 1 / 0.8) / (1 - 0.01) + (50 * 1 / 0.8) / (1 - 0.01) ** 2,
180
        abs=1e-2,
181
    )
182
    assert flows["storage-None"][5] == pytest.approx(
183
        (50 * 1 / 0.8) / (1 - 0.01), abs=1e-2
184
    )
185
    assert flows["storage-None"][6] == pytest.approx(0, abs=1e-2)
186
    assert flows["storage-None"][7] == pytest.approx(
187
        (init_soc + (100 * 1 / 0.8)) / 0.99
188
    )
189