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

test_simple_invest   A

Complexity

Total Complexity 2

Size/Duplication

Total Lines 215
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 2
eloc 126
dl 0
loc 215
rs 10
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
B test_dispatch_example() 0 181 2
1
# -*- coding: utf-8 -*-
2
3
"""This example shows how to create an energysystem with oemof objects and
4
solve it with the solph module.
5
6
Data: example_data.csv
7
8
This file is part of project oemof (github.com/oemof/oemof). It's copyrighted
9
by the contributors recorded in the version control history of the file,
10
available from its original location
11
oemof/tests/test_scripts/test_solph/test_simple_dispatch/test_simple_dispatch.py
12
13
SPDX-License-Identifier: MIT
14
"""
15
16
import os
17
18
import pandas as pd
19
import pytest
20
from oemof.tools import economics
21
22
from oemof.solph import EnergySystem
23
from oemof.solph import Investment
24
from oemof.solph import Model
25
from oemof.solph import processing
26
from oemof.solph import views
27
from oemof.solph.buses import Bus
28
from oemof.solph.components import Converter
29
from oemof.solph.components import Sink
30
from oemof.solph.components import Source
31
from oemof.solph.flows import Flow
32
33
34
def test_dispatch_example(solver="cbc", periods=24 * 5):
35
    """Create an energy system and optimize the dispatch at least costs."""
36
37
    filename = os.path.join(os.path.dirname(__file__), "input_data.csv")
38
    data = pd.read_csv(filename, sep=",")
39
40
    # ######################### create energysystem components ################
41
42
    # resource buses
43
    bcoal = Bus(label="coal", balanced=False)
44
    bgas = Bus(label="gas", balanced=False)
45
    boil = Bus(label="oil", balanced=False)
46
    blig = Bus(label="lignite", balanced=False)
47
48
    # electricity and heat
49
    bel = Bus(label="b_el")
50
    bth = Bus(label="b_th")
51
52
    # an excess and a shortage variable can help to avoid infeasible problems
53
    excess_el = Sink(label="excess_el", inputs={bel: Flow()})
54
    # shortage_el = Source(label='shortage_el',
55
    #                      outputs={bel: Flow(variable_costs=200)})
56
57
    # sources
58
    ep_wind = economics.annuity(capex=1000, n=20, wacc=0.05)
59
    wind = Source(
60
        label="wind",
61
        outputs={
62
            bel: Flow(
63
                fix=data["wind"],
64
                nominal_capacity=Investment(ep_costs=ep_wind, existing=100),
65
            )
66
        },
67
    )
68
69
    ep_pv = economics.annuity(capex=1500, n=20, wacc=0.05)
70
    pv = Source(
71
        label="pv",
72
        outputs={
73
            bel: Flow(
74
                fix=data["pv"],
75
                nominal_capacity=Investment(ep_costs=ep_pv, existing=80),
76
            )
77
        },
78
    )
79
80
    # demands (electricity/heat)
81
    demand_el = Sink(
82
        label="demand_elec",
83
        inputs={bel: Flow(nominal_capacity=85, fix=data["demand_el"])},
84
    )
85
86
    demand_th = Sink(
87
        label="demand_therm",
88
        inputs={bth: Flow(nominal_capacity=40, fix=data["demand_th"])},
89
    )
90
91
    # power plants
92
    pp_coal = Converter(
93
        label="pp_coal",
94
        inputs={bcoal: Flow()},
95
        outputs={bel: Flow(nominal_capacity=20.2, variable_costs=25)},
96
        conversion_factors={bel: 0.39},
97
    )
98
99
    pp_lig = Converter(
100
        label="pp_lig",
101
        inputs={blig: Flow()},
102
        outputs={bel: Flow(nominal_capacity=11.8, variable_costs=19)},
103
        conversion_factors={bel: 0.41},
104
    )
105
106
    pp_gas = Converter(
107
        label="pp_gas",
108
        inputs={bgas: Flow()},
109
        outputs={bel: Flow(nominal_capacity=41, variable_costs=40)},
110
        conversion_factors={bel: 0.50},
111
    )
112
113
    pp_oil = Converter(
114
        label="pp_oil",
115
        inputs={boil: Flow()},
116
        outputs={bel: Flow(nominal_capacity=5, variable_costs=50)},
117
        conversion_factors={bel: 0.28},
118
    )
119
120
    # combined heat and power plant (chp)
121
    pp_chp = Converter(
122
        label="pp_chp",
123
        inputs={bgas: Flow()},
124
        outputs={
125
            bel: Flow(nominal_capacity=30, variable_costs=42),
126
            bth: Flow(nominal_capacity=40),
127
        },
128
        conversion_factors={bel: 0.3, bth: 0.4},
129
    )
130
131
    # heatpump with a coefficient of performance (COP) of 3
132
    b_heat_source = Bus(label="b_heat_source")
133
134
    heat_source = Source(label="heat_source", outputs={b_heat_source: Flow()})
135
136
    cop = 3
137
    heat_pump = Converter(
138
        label="el_heat_pump",
139
        inputs={bel: Flow(), b_heat_source: Flow()},
140
        outputs={bth: Flow(nominal_capacity=10)},
141
        conversion_factors={bel: 1 / 3, b_heat_source: (cop - 1) / cop},
142
    )
143
144
    datetimeindex = pd.date_range("1/1/2012", periods=periods, freq="h")
145
    energysystem = EnergySystem(
146
        timeindex=datetimeindex, infer_last_interval=True
147
    )
148
    energysystem.add(
149
        bcoal,
150
        bgas,
151
        boil,
152
        bel,
153
        bth,
154
        blig,
155
        excess_el,
156
        wind,
157
        pv,
158
        demand_el,
159
        demand_th,
160
        pp_coal,
161
        pp_lig,
162
        pp_oil,
163
        pp_gas,
164
        pp_chp,
165
        b_heat_source,
166
        heat_source,
167
        heat_pump,
168
    )
169
170
    # ################################ optimization ###########################
171
172
    # create optimization model based on energy_system
173
    optimization_model = Model(energysystem=energysystem)
174
175
    # solve problem
176
    optimization_model.solve(solver=solver)
177
178
    # write back results from optimization object to energysystem
179
    optimization_model.results()
180
181
    # ################################ results ################################
182
183
    # generic result object
184
    results = processing.results(model=optimization_model)
185
186
    # subset of results that includes all flows into and from electrical bus
187
    # sequences are stored within a pandas.DataFrames and scalars e.g.
188
    # investment values within a pandas.Series object.
189
    # in this case the entry data['scalars'] does not exist since no investment
190
    # variables are used
191
    data = views.node(results, "b_el")
192
193
    # generate results to be evaluated in tests
194
    comp_results = data["sequences"].sum(axis=0).to_dict()
195
    comp_results["pv_capacity"] = results[(pv, bel)]["scalars"].invest
196
    comp_results["wind_capacity"] = results[(wind, bel)]["scalars"].invest
197
198
    test_results = {
199
        (("wind", "b_el"), "flow"): 9239,
200
        (("pv", "b_el"), "flow"): 1147,
201
        (("b_el", "demand_elec"), "flow"): 7440,
202
        (("b_el", "excess_el"), "flow"): 6261,
203
        (("pp_chp", "b_el"), "flow"): 477,
204
        (("pp_lig", "b_el"), "flow"): 850,
205
        (("pp_gas", "b_el"), "flow"): 934,
206
        (("pp_coal", "b_el"), "flow"): 1256,
207
        (("pp_oil", "b_el"), "flow"): 0,
208
        (("b_el", "el_heat_pump"), "flow"): 202,
209
        "pv_capacity": 44,
210
        "wind_capacity": 246,
211
    }
212
213
    for key in test_results.keys():
214
        assert comp_results[key] == pytest.approx(test_results[key], abs=0.5)
215