Skip to content

Commit

Permalink
Merge pull request #1090 from oemof/feature/storage_losses
Browse files Browse the repository at this point in the history
Introduce variable for storage losses
  • Loading branch information
p-snft authored Jul 10, 2024
2 parents 6dae8bc + 053b349 commit 9e06569
Show file tree
Hide file tree
Showing 19 changed files with 879 additions and 357 deletions.
2 changes: 1 addition & 1 deletion examples/storage_balanced_unbalanced/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def storage_example():

# create an energy system
idx = pd.date_range("1/1/2017", periods=len(timeseries), freq="h")
es = solph.EnergySystem(timeindex=idx)
es = solph.EnergySystem(timeindex=idx, infer_last_interval=True)

for data_set in DATA:
name = data_set["name"]
Expand Down
48 changes: 31 additions & 17 deletions src/oemof/solph/components/_generic_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,11 +358,14 @@ class GenericStorageBlock(ScalarBlock):
.. math::
E(t_{last}) = E(-1)
Storage balance :attr:`om.Storage.balance[n, t]`
.. math:: E(t) = &E(t-1) \cdot
(1 - \beta(t)) ^{\tau(t)/(t_u)} \\
Storage losses :attr:`om.Storage.losses[n, t]`
.. math:: E_{loss}(t) = &E(t-1) \cdot
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)}\\
&- \delta(t) \cdot {\tau(t)/(t_u)}
Storage balance :attr:`om.Storage.balance[n, t]`
.. math:: E(t) = &E(t-1) - E_{loss}(t)
&- \frac{\dot{E}_o(p, t)}{\eta_o(t)} \cdot \tau(t)
+ \dot{E}_i(p, t) \cdot \eta_i(t) \cdot \tau(t)
Expand Down Expand Up @@ -497,6 +500,8 @@ def _storage_content_bound_rule(block, n, t):
self.STORAGES, m.TIMEPOINTS, bounds=_storage_content_bound_rule
)

self.storage_losses = Var(self.STORAGES, m.TIMESTEPS)

# set the initial storage content
# ToDo: More elegant code possible?
for n in group:
Expand All @@ -508,30 +513,37 @@ def _storage_content_bound_rule(block, n, t):

# ************* Constraints ***************************

def _storage_balance_rule(block, n, t):
"""
Rule definition for the storage balance of every storage n and
every timestep.
"""
expr = 0
expr += block.storage_content[n, t + 1]
expr += (
-block.storage_content[n, t]
* (1 - n.loss_rate[t]) ** m.timeincrement[t]
def _storage_losses_rule(block, n, t):
expr = block.storage_content[n, t] * (
1 - (1 - n.loss_rate[t]) ** m.timeincrement[t]
)
expr += (
n.fixed_losses_relative[t]
* n.nominal_storage_capacity
* m.timeincrement[t]
)
expr += n.fixed_losses_absolute[t] * m.timeincrement[t]

return expr == block.storage_losses[n, t]

self.losses = Constraint(
self.STORAGES, m.TIMESTEPS, rule=_storage_losses_rule
)

def _storage_balance_rule(block, n, t):
"""
Rule definition for the storage balance of every storage n and
every timestep.
"""
expr = block.storage_content[n, t]
expr -= block.storage_losses[n, t]
expr += (
-m.flow[i[n], n, t] * n.inflow_conversion_factor[t]
m.flow[i[n], n, t] * n.inflow_conversion_factor[t]
) * m.timeincrement[t]
expr += (
expr -= (
m.flow[n, o[n], t] / n.outflow_conversion_factor[t]
) * m.timeincrement[t]
return expr == 0
return expr == block.storage_content[n, t + 1]

self.balance = Constraint(
self.STORAGES, m.TIMESTEPS, rule=_storage_balance_rule
Expand Down Expand Up @@ -1016,6 +1028,8 @@ class GenericInvestmentStorageBlock(ScalarBlock):
of the storage"
":math:`E(t)`", ":attr:`storage_content[n, t]`", "Current storage
content (current absolute stored energy)"
":math:`E_{loss}(t)`", ":attr:`storage_losses[n, t]`", "Current storage
losses (absolute losses per time step)"
":math:`E_{invest}(p)`", ":attr:`invest[n, p]`", "Invested (nominal)
capacity of the storage"
":math:`E_{old}(p)`", ":attr:`old[n, p]`", "
Expand Down
119 changes: 87 additions & 32 deletions tests/lp_files/nonequidistant_timeindex.lp
Original file line number Diff line number Diff line change
Expand Up @@ -149,59 +149,106 @@ c_e_ConverterBlock_relation(boiler_gas_heat_7)_:
-1 flow(boiler_heat_7)
= 0

c_e_GenericStorageBlock_losses(storage_0)_:
-1 GenericStorageBlock_storage_losses(storage_0)
= -30.0

c_e_GenericStorageBlock_losses(storage_1)_:
-1 GenericStorageBlock_storage_losses(storage_1)
+0.1 GenericStorageBlock_storage_content(storage_1)
= 0

c_e_GenericStorageBlock_losses(storage_2)_:
-1 GenericStorageBlock_storage_losses(storage_2)
+0.1 GenericStorageBlock_storage_content(storage_2)
= 0

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

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

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

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

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

c_e_GenericStorageBlock_balance(storage_0)_:
-1 flow(heat_storage_0)
+1 flow(storage_heat_0)
+1 GenericStorageBlock_storage_content(storage_1)
= 270.0
+1 flow(heat_storage_0)
-1 flow(storage_heat_0)
-1 GenericStorageBlock_storage_losses(storage_0)
-1 GenericStorageBlock_storage_content(storage_1)
= -300

c_e_GenericStorageBlock_balance(storage_1)_:
-1 flow(heat_storage_1)
+1 flow(storage_heat_1)
-0.9 GenericStorageBlock_storage_content(storage_1)
+1 GenericStorageBlock_storage_content(storage_2)
+1 flow(heat_storage_1)
-1 flow(storage_heat_1)
-1 GenericStorageBlock_storage_losses(storage_1)
+1 GenericStorageBlock_storage_content(storage_1)
-1 GenericStorageBlock_storage_content(storage_2)
= 0

c_e_GenericStorageBlock_balance(storage_2)_:
-1 flow(heat_storage_2)
+1 flow(storage_heat_2)
-0.9 GenericStorageBlock_storage_content(storage_2)
+1 GenericStorageBlock_storage_content(storage_3)
+1 flow(heat_storage_2)
-1 flow(storage_heat_2)
-1 GenericStorageBlock_storage_losses(storage_2)
+1 GenericStorageBlock_storage_content(storage_2)
-1 GenericStorageBlock_storage_content(storage_3)
= 0

c_e_GenericStorageBlock_balance(storage_3)_:
-2.0 flow(heat_storage_3)
+2.0 flow(storage_heat_3)
-0.81 GenericStorageBlock_storage_content(storage_3)
+1 GenericStorageBlock_storage_content(storage_4)
+2.0 flow(heat_storage_3)
-2.0 flow(storage_heat_3)
-1 GenericStorageBlock_storage_losses(storage_3)
+1 GenericStorageBlock_storage_content(storage_3)
-1 GenericStorageBlock_storage_content(storage_4)
= 0

c_e_GenericStorageBlock_balance(storage_4)_:
-2.0 flow(heat_storage_4)
+2.0 flow(storage_heat_4)
-0.81 GenericStorageBlock_storage_content(storage_4)
+1 GenericStorageBlock_storage_content(storage_5)
+2.0 flow(heat_storage_4)
-2.0 flow(storage_heat_4)
-1 GenericStorageBlock_storage_losses(storage_4)
+1 GenericStorageBlock_storage_content(storage_4)
-1 GenericStorageBlock_storage_content(storage_5)
= 0

c_e_GenericStorageBlock_balance(storage_5)_:
-0.5 flow(heat_storage_5)
+0.5 flow(storage_heat_5)
-0.9486832980505138 GenericStorageBlock_storage_content(storage_5)
+1 GenericStorageBlock_storage_content(storage_6)
+0.5 flow(heat_storage_5)
-0.5 flow(storage_heat_5)
-1 GenericStorageBlock_storage_losses(storage_5)
+1 GenericStorageBlock_storage_content(storage_5)
-1 GenericStorageBlock_storage_content(storage_6)
= 0

c_e_GenericStorageBlock_balance(storage_6)_:
-0.5 flow(heat_storage_6)
+0.5 flow(storage_heat_6)
-0.9486832980505138 GenericStorageBlock_storage_content(storage_6)
+1 GenericStorageBlock_storage_content(storage_7)
+0.5 flow(heat_storage_6)
-0.5 flow(storage_heat_6)
-1 GenericStorageBlock_storage_losses(storage_6)
+1 GenericStorageBlock_storage_content(storage_6)
-1 GenericStorageBlock_storage_content(storage_7)
= 0

c_e_GenericStorageBlock_balance(storage_7)_:
-0.5 flow(heat_storage_7)
+0.5 flow(storage_heat_7)
-0.9486832980505138 GenericStorageBlock_storage_content(storage_7)
+1 GenericStorageBlock_storage_content(storage_8)
+0.5 flow(heat_storage_7)
-0.5 flow(storage_heat_7)
-1 GenericStorageBlock_storage_losses(storage_7)
+1 GenericStorageBlock_storage_content(storage_7)
-1 GenericStorageBlock_storage_content(storage_8)
= 0

c_e_GenericStorageBlock_balanced_cstr(storage)_:
Expand Down Expand Up @@ -241,6 +288,14 @@ bounds
0 <= flow(storage_heat_5) <= 100
0 <= flow(storage_heat_6) <= 100
0 <= flow(storage_heat_7) <= 100
-inf <= GenericStorageBlock_storage_losses(storage_0) <= +inf
-inf <= GenericStorageBlock_storage_losses(storage_1) <= +inf
-inf <= GenericStorageBlock_storage_losses(storage_2) <= +inf
-inf <= GenericStorageBlock_storage_losses(storage_3) <= +inf
-inf <= GenericStorageBlock_storage_losses(storage_4) <= +inf
-inf <= GenericStorageBlock_storage_losses(storage_5) <= +inf
-inf <= GenericStorageBlock_storage_losses(storage_6) <= +inf
-inf <= GenericStorageBlock_storage_losses(storage_7) <= +inf
0 <= GenericStorageBlock_storage_content(storage_1) <= 300
0 <= GenericStorageBlock_storage_content(storage_2) <= 300
0 <= GenericStorageBlock_storage_content(storage_3) <= 300
Expand Down
Loading

0 comments on commit 9e06569

Please sign in to comment.