Skip to content

Commit

Permalink
Fix loss calculation for non-hourly time steps
Browse files Browse the repository at this point in the history
This one first slipped through due to too many irrelevant changes
in the LP files. I now added a unit test that is independent of lp files.

Note that the formula is more complicated but it just changes a value
in the lp file, so it will not significantly increase computational time.
  • Loading branch information
p-snft committed Jul 9, 2024
1 parent a44eda1 commit f849db9
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/oemof/solph/components/_generic_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ class GenericStorageBlock(ScalarBlock):
Storage losses :attr:`om.Storage.losses[n, t]`
.. math:: E_{loss}(t) = &E(t-1) \cdot
\beta(t)^{\tau(t)/(t_u)} \\
1 - (1 - \beta(t))^{\tau(t)/(t_u)} \\
&- \gamma(t)\cdot E_{nom} \cdot {\tau(t)/(t_u)}\\
&- \delta(t) \cdot {\tau(t)/(t_u)}
Expand Down Expand Up @@ -515,7 +515,7 @@ def _storage_content_bound_rule(block, n, t):

def _storage_losses_rule(block, n, t):
expr = block.storage_content[n, t] * (
n.loss_rate[t] ** m.timeincrement[t]
1 - (1 - n.loss_rate[t]) ** m.timeincrement[t]
)
expr += (
n.fixed_losses_relative[t]
Expand Down
10 changes: 5 additions & 5 deletions tests/lp_files/nonequidistant_timeindex.lp
Original file line number Diff line number Diff line change
Expand Up @@ -165,27 +165,27 @@ c_e_GenericStorageBlock_losses(storage_2)_:

c_e_GenericStorageBlock_losses(storage_3)_:
-1 GenericStorageBlock_storage_losses(storage_3)
+0.010000000000000002 GenericStorageBlock_storage_content(storage_3)
+0.19 GenericStorageBlock_storage_content(storage_3)
= 0

c_e_GenericStorageBlock_losses(storage_4)_:
-1 GenericStorageBlock_storage_losses(storage_4)
+0.010000000000000002 GenericStorageBlock_storage_content(storage_4)
+0.19 GenericStorageBlock_storage_content(storage_4)
= 0

c_e_GenericStorageBlock_losses(storage_5)_:
-1 GenericStorageBlock_storage_losses(storage_5)
+0.31622776601683794 GenericStorageBlock_storage_content(storage_5)
+0.05131670194948623 GenericStorageBlock_storage_content(storage_5)
= 0

c_e_GenericStorageBlock_losses(storage_6)_:
-1 GenericStorageBlock_storage_losses(storage_6)
+0.31622776601683794 GenericStorageBlock_storage_content(storage_6)
+0.05131670194948623 GenericStorageBlock_storage_content(storage_6)
= 0

c_e_GenericStorageBlock_losses(storage_7)_:
-1 GenericStorageBlock_storage_losses(storage_7)
+0.31622776601683794 GenericStorageBlock_storage_content(storage_7)
+0.05131670194948623 GenericStorageBlock_storage_content(storage_7)
= 0

c_e_GenericStorageBlock_balance(storage_0)_:
Expand Down
50 changes: 50 additions & 0 deletions tests/test_components/test_storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-

import pytest
import numpy as np

from oemof import solph


def test_relative_losses():
cases = [
{"number": 500, "interval": 2},
{"number": 1000, "interval": 1},
{"number": 2000, "interval": 0.5},
]

for case in cases:
es = solph.EnergySystem(
timeindex=solph.create_time_index(
year=2023, number=case["number"], interval=case["interval"]
),
infer_last_interval=True,
)

bus = solph.Bus("slack_bus", balanced=False)
es.add(bus)

storage = solph.components.GenericStorage(
"storage",
inputs={bus: solph.Flow(variable_costs=1)},
outputs={bus: solph.Flow(variable_costs=1)},
nominal_storage_capacity=10,
initial_storage_level=1,
loss_rate=0.004125876075, # half life of one week
)
es.add(storage)

model = solph.Model(es)
model.solve("cbc")

result = solph.processing.results(model)[(storage, None)]["sequences"][
"storage_content"
]
case["result"] = np.array(result)

for i in range(500):
assert (
cases[0]["result"][i]
== pytest.approx(cases[1]["result"][2 * i])
== pytest.approx(cases[2]["result"][4 * i])
)

0 comments on commit f849db9

Please sign in to comment.