Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove internal discounting functionality #1111

Draft
wants to merge 5 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1325,13 +1325,6 @@ Besides the `invest` variable, new variables are introduced as well. These are:

.. note::

* You can specify a `discount_rate` for the model. If you do not do so, 0.02 will be used as a default, corresponding
to sort of a social discount rate. If you work with costs in real terms, discounting is obsolete, so define
`discount_rate = 0` in that case.
* You can specify an `interest_rate` for every investment object. If you do not do so, it will be chosen the same
as the model's `discount_rate`. You could use this default to model a perfect competition administered by some sort of
social planner, but even in a social planner setting, you might want to deviate from the `discount_rate`
value and/or discriminate among technologies with different risk profiles and hence different interest requirements.
* For storage units, the `initial_content` is not allowed combined with multi-period investments.
The storage inflow and outflow are forced to zero until the storage unit is invested into.
* You can specify periods of different lengths, but the frequency of your timeindex needs to be consistent. Also,
Expand Down
2 changes: 2 additions & 0 deletions src/oemof/solph/_energy_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ def __init__(
self._extract_periods_matrix()
self._extract_end_year_of_optimization()
self.use_remaining_value = use_remaining_value
else:
self.end_year_of_optimization = 1

def _extract_periods_years(self):
"""Map years in optimization to respective period based on time indices
Expand Down
20 changes: 2 additions & 18 deletions src/oemof/solph/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ class Model(po.ConcreteModel):
Solph looks for these groups in the given energy system and uses them
to create the constraints of the optimization problem.
Defaults to `Model.CONSTRAINT_GROUPS`
discount_rate : float or None
The rate used for discounting in a multi-period model.
A 2% discount rate needs to be defined as 0.02.
objective_weighting : array like (optional)
Weights used for temporal objective function
expressions. If nothing is passed, `timeincrement` will be used which
Expand Down Expand Up @@ -84,17 +81,6 @@ class Model(po.ConcreteModel):
rc : `pyomo.core.base.suffix.Suffix` or None
Store the reduced costs of the model if pyomo suffix is set to IMPORT

Note
----

* The discount rate is only applicable for a multi-period model.
* If you want to work with costs data in nominal terms,
you should specify a discount rate.
* By default, there is a discount rate of 2% in a multi-period model.
* If you want to provide your costs data in real terms,
just specify `discount_rate = 0`, i.e. effectively there will be
no discounting.


**The following basic sets are created**:

Expand Down Expand Up @@ -134,7 +120,7 @@ class Model(po.ConcreteModel):
InvestNonConvexFlowBlock,
]

def __init__(self, energysystem, discount_rate=None, **kwargs):
def __init__(self, energysystem, **kwargs):
super().__init__()

# Check root logger. Due to a problem with pyomo the building of the
Expand Down Expand Up @@ -190,9 +176,7 @@ def __init__(self, energysystem, discount_rate=None, **kwargs):
self.dual = None
self.rc = None

if discount_rate is not None:
self.discount_rate = discount_rate
elif energysystem.periods is not None:
if energysystem.periods is not None:
self._set_discount_rate_with_warning()
else:
pass
Expand Down
57 changes: 17 additions & 40 deletions src/oemof/solph/components/_generic_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,26 +420,18 @@ class GenericStorageBlock(ScalarBlock):

**The following parts of the objective function are created:**

*Standard model*

* :attr: `storage_costs` not 0

.. math::
\sum_{t \in \textrm{TIMEPOINTS} > 0} c_{storage}(t) \cdot E(t)


*Multi-period model*

* :attr:`fixed_costs` not None
* :attr:`fixed_costs` not 0

.. math::
\displaystyle \sum_{pp=0}^{year_{max}} E_{nom}
\cdot c_{fixed}(pp) \cdot DF^{-pp}
\cdot c_{fixed}(pp)

where:

* :math:`DF=(1+dr)` is the discount factor with discount rate :math:`dr`.
* :math:`year_{max}` denotes the last year of the optimization
where :math:`year_{max}` denotes the last year of the optimization
horizon, i.e. at the end of the last period.

""" # noqa: E501
Expand Down Expand Up @@ -591,26 +583,19 @@ def _objective_expression(self):
r"""
Objective expression for storages with no investment.

Note
----
* For standard models, this adds nothing as variable costs are
already added in the Block :py:class:`~.SimpleFlowBlock`.
* For multi-period models, fixed costs may be introduced
and added here.
* Fixed costs (will not have an impact on the actual optimisation).
* Variable costs for storage content.
"""
m = self.parent_block()

fixed_costs = 0

if m.es.periods is not None:
for n in self.STORAGES:
if valid_sequence(n.fixed_costs, len(m.PERIODS)):
fixed_costs += sum(
n.nominal_storage_capacity
* n.fixed_costs[pp]
* (1 + m.discount_rate) ** (-pp)
for pp in range(m.es.end_year_of_optimization)
)
for n in self.STORAGES:
if valid_sequence(n.fixed_costs, len(m.PERIODS)):
fixed_costs += sum(
n.nominal_storage_capacity * n.fixed_costs[pp]
for pp in range(m.es.end_year_of_optimization)
)
self.fixed_costs = Expression(expr=fixed_costs)

storage_costs = 0
Expand Down Expand Up @@ -1813,7 +1798,7 @@ def _objective_expression(self):
)
investment_costs_increment = (
self.invest[n, p] * annuity * present_value_factor
) * (1 + m.discount_rate) ** (-m.es.periods_years[p])
)
remaining_value_difference = (
self._evaluate_remaining_value_difference(
m,
Expand Down Expand Up @@ -1854,7 +1839,7 @@ def _objective_expression(self):
investment_costs_increment = (
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])
)
remaining_value_difference = (
self._evaluate_remaining_value_difference(
m,
Expand All @@ -1880,9 +1865,7 @@ def _objective_expression(self):
m.es.periods_years[p] + lifetime,
)
fixed_costs += sum(
self.invest[n, p]
* n.investment.fixed_costs[pp]
* (1 + m.discount_rate) ** (-pp)
self.invest[n, p] * n.investment.fixed_costs[pp]
for pp in range(
m.es.periods_years[p],
range_limit,
Expand All @@ -1897,9 +1880,7 @@ def _objective_expression(self):
m.es.end_year_of_optimization, lifetime - age
)
fixed_costs += sum(
n.investment.existing
* n.investment.fixed_costs[pp]
* (1 + m.discount_rate) ** (-pp)
n.investment.existing * n.investment.fixed_costs[pp]
for pp in range(range_limit)
)

Expand Down Expand Up @@ -1971,15 +1952,11 @@ def _evaluate_remaining_value_difference(
self.invest[n, p]
* (remaining_annuity - original_annuity)
* present_value_factor_remaining
) * (1 + m.discount_rate) ** (-end_year_of_optimization)
)
if nonconvex:
return convex_investment_costs + self.invest_status[
n, p
] * (n.investment.offset[-1] - n.investment.offset[p]) * (
1 + m.discount_rate
) ** (
-end_year_of_optimization
)
] * (n.investment.offset[-1] - n.investment.offset[p])
else:
return convex_investment_costs
else:
Expand Down
Loading
Loading