Skip to content

Commit

Permalink
Include remaining value for storage and DSM accordingly
Browse files Browse the repository at this point in the history
  • Loading branch information
jokochems committed Oct 13, 2023
1 parent ebd183a commit 15b721a
Show file tree
Hide file tree
Showing 2 changed files with 415 additions and 6 deletions.
142 changes: 139 additions & 3 deletions src/oemof/solph/components/_generic_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,21 @@ class GenericInvestmentStorageBlock(ScalarBlock):
&
\forall p \in \textrm{PERIODS}
In case, the remaining lifetime of a storage is greater than 0 and
attribute `use_remaining_value` of the energy system is True,
the difference in value for the investment period compared to the
last period of the optimization horizon is accounted for
as an adder to the investment costs:
.. math::
&
E_{invest}(p) \cdot (A(c_{invest,var}(p), l_{r}, ir) -
A(c_{invest,var}(|P|), l_{r}, ir)\\
& \cdot \frac {1}{ANF(l_{r}, ir)} \cdot DF^{-|P|}\\
&\\
&
\forall p \in \textrm{PERIODS}
* :attr:`nonconvex = True`
.. math::
Expand All @@ -913,6 +928,24 @@ class GenericInvestmentStorageBlock(ScalarBlock):
&
\forall p \in \textrm{PERIODS}
In case, the remaining lifetime of a storage is greater than 0 and
attribute `use_remaining_value` of the energy system is True,
the difference in value for the investment period compared to the
last period of the optimization horizon is accounted for
as an adder to the investment costs:
.. math::
&
(E_{invest}(p) \cdot (A(c_{invest,var}(p), l_{r}, ir) -
A(c_{invest,var}(|P|), l_{r}, ir)\\
& \cdot \frac {1}{ANF(l_{r}, ir)} \cdot DF^{-|P|}\\
&
+ (c_{invest,fix}(p) - c_{invest,fix}(|P|))
\cdot b_{invest}(p)) \cdot DF^{-p}\\
&\\
&
\forall p \in \textrm{PERIODS}
* :attr:`fixed_costs` not None for investments
.. math::
Expand All @@ -929,12 +962,14 @@ class GenericInvestmentStorageBlock(ScalarBlock):
\sum_{pp=0}^{limit_{exo}} E_{exist} \cdot c_{fixed}(pp)
\cdot DF^{-pp}
whereby:
* :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for
investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l`
and interest rate :math:`ir`.
* :math:`l_{r}` is the remaining lifetime at the end of the
optimization horizon (in case it is greater than 0 and
smaller than the actual lifetime).
* :math:`ANF(d, ir)` is the annuity factor for duration :math:`d`
and interest rate :math:`ir`.
* :math:`d=min\{year_{max} - year(p), l\}` defines the
Expand Down Expand Up @@ -1765,7 +1800,19 @@ def _objective_expression(self):
investment_costs_increment = (
self.invest[n, p] * annuity * present_value_factor
) * (1 + m.discount_rate) ** (-m.es.periods_years[p])
investment_costs += investment_costs_increment
remaining_value_difference = (
self._evaluate_remaining_value_difference(
m,
p,
n,
m.es.end_year_of_optimization,
lifetime,
interest,
)
)
investment_costs += (
investment_costs_increment + remaining_value_difference
)
period_investment_costs[p] += investment_costs_increment

for n in self.NON_CONVEX_INVESTSTORAGES:
Expand Down Expand Up @@ -1794,7 +1841,20 @@ def _objective_expression(self):
self.invest[n, p] * annuity * present_value_factor
+ self.invest_status[n, p] * n.investment.offset[p]
) * (1 + m.discount_rate) ** (-m.es.periods_years[p])
investment_costs += investment_costs_increment
remaining_value_difference = (
self._evaluate_remaining_value_difference(
m,
p,
n,
m.es.end_year_of_optimization,
lifetime,
interest,
nonconvex=True,
)
)
investment_costs += (
investment_costs_increment + remaining_value_difference
)
period_investment_costs[p] += investment_costs_increment

for n in self.INVESTSTORAGES:
Expand Down Expand Up @@ -1835,3 +1895,79 @@ def _objective_expression(self):
self.costs = Expression(expr=investment_costs + fixed_costs)

return self.costs

def _evaluate_remaining_value_difference(
self,
m,
p,
n,
end_year_of_optimization,
lifetime,
interest,
nonconvex=False,
):
"""Evaluate and return the remaining value difference of an investment
The remaining value difference in the net present values if the asset
was to be liquidated at the end of the optimization horizon and the
net present value using the original investment expenses.
Parameters
----------
m : oemof.solph.models.Model
Optimization model
p : int
Period in which investment occurs
n : oemof.solph.components.GenericStorage
storage unit
end_year_of_optimization : int
Last year of the optimization horizon
lifetime : int
lifetime of investment considered
interest : float
Demanded interest rate for investment
nonconvex : bool
Indicating whether considered flow is nonconvex.
"""
if m.es.use_remaining_value:
if end_year_of_optimization - m.es.periods_years[p] < lifetime:
remaining_lifetime = lifetime - (
end_year_of_optimization - m.es.periods_years[p]
)
remaining_annuity = economics.annuity(
capex=n.investment.ep_costs[-1],
n=remaining_lifetime,
wacc=interest,
)
original_annuity = economics.annuity(
capex=n.investment.ep_costs[p],
n=remaining_lifetime,
wacc=interest,
)
present_value_factor_remaining = 1 / economics.annuity(
capex=1, n=remaining_lifetime, wacc=interest
)
if nonconvex:
return (
self.invest[n, p]
* (remaining_annuity - original_annuity)
* present_value_factor_remaining
+ self.invest_status[n, p]
* (n.investment.offset[-1] - n.investment.offset[p])
) * (1 + m.discount_rate) ** (-end_year_of_optimization)
else:
return (
self.invest[n, p]
* (remaining_annuity - original_annuity)
* present_value_factor_remaining
) * (1 + m.discount_rate) ** (-end_year_of_optimization)
else:
return 0
else:
return 0

0 comments on commit 15b721a

Please sign in to comment.