Skip to content

Commit

Permalink
Merge pull request #1120 from oemof/revision/include_v0-5_fixes
Browse files Browse the repository at this point in the history
Merge revision/include v0 5 fixes
  • Loading branch information
p-snft authored Aug 29, 2024
2 parents 50f4e4b + 1234e0d commit 37cb747
Show file tree
Hide file tree
Showing 20 changed files with 169 additions and 56 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ name: "CodeQL"

on:
push:
branches: [ "dev", "master" ]
branches:
- dev
- master
- 'release/**'
pull_request:
branches: [ "dev" ]
schedule:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- master
- dev
- 'release/**'
pull_request:

jobs:
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/packaging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ name: packaging
on:
# Make sure packaging process is not broken
push:
branches: [master, dev]
branches:
- master
- dev
- 'release/**'
pull_request:
# Make a package for release
release:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/tox_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
branches:
- master
- dev
- 'release/**'
pull_request:

workflow_dispatch:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/tox_pytests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- master
- dev
- 'release/**'
pull_request:

workflow_dispatch:
Expand Down
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ These are new features and improvements of note in each release


.. include:: whatsnew/v0-6-0.rst
.. include:: whatsnew/v0-5-5.rst
.. include:: whatsnew/v0-5-4.rst
.. include:: whatsnew/v0-5-3.rst
.. include:: whatsnew/v0-5-2.rst
Expand Down
12 changes: 12 additions & 0 deletions docs/whatsnew/v0-5-5.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
v0.5.5 (August 29th, 2024)
--------------------------

Bug fixes
#########

* Fix iterating over _FakeSequence objects

Contributors
############

* Patrik Schönfeldt
43 changes: 40 additions & 3 deletions src/oemof/solph/_plumbing.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
SPDX-License-Identifier: MIT
"""

import warnings
from collections import abc
from itertools import repeat

Expand All @@ -19,8 +19,8 @@

def sequence(iterable_or_scalar):
"""Checks if an object is iterable (except string) or scalar and returns
the original sequence if object is an iterable and an 'emulated'
sequence object of class _Sequence if object is a scalar or string.
the an numpy array of the sequence if object is an iterable or an
'emulated' sequence object of class _FakeSequence if object is a scalar.
Parameters
----------
Expand Down Expand Up @@ -56,6 +56,43 @@ def sequence(iterable_or_scalar):
return _FakeSequence(value=iterable_or_scalar)


def valid_sequence(sequence, length: int) -> bool:
"""Checks if an object is a numpy array of at least the given length
or an 'emulated' sequence object of class _FakeSequence.
If unset, the latter is set to the required lenght.
"""
if sequence[0] is None:
return False

if isinstance(sequence, _FakeSequence):
if sequence.size is None:
sequence.size = length

if sequence.size == length:
return True
else:
return False

if isinstance(sequence, np.ndarray):
if sequence.size == length:
return True
# --- BEGIN: To be removed for versions >= v0.6 ---
elif sequence.size > length:
warnings.warn(
"Sequence longer than needed"
f" ({sequence.size} items instead of {length})."
" This will be trated as an error in the future.",
FutureWarning,
)
return True
# --- END ---
else:
raise ValueError(f"Lentgh of {sequence} should be {length}.")

return False


class _FakeSequence:
"""Emulates a list whose length is not known in advance.
Expand Down
6 changes: 3 additions & 3 deletions src/oemof/solph/components/_extraction_turbine_chp.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
from pyomo.environ import BuildAction
from pyomo.environ import Constraint

from oemof.solph._plumbing import sequence as solph_sequence
from oemof.solph.components._converter import Converter
from oemof.solph._plumbing import sequence
from oemof.solph.components import Converter


class ExtractionTurbineCHP(Converter):
Expand Down Expand Up @@ -87,7 +87,7 @@ def __init__(
custom_attributes=custom_attributes,
)
self.conversion_factor_full_condensation = {
k: solph_sequence(v)
k: sequence(v)
for k, v in conversion_factor_full_condensation.items()
}

Expand Down
39 changes: 18 additions & 21 deletions src/oemof/solph/components/_generic_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@

from oemof.solph._helpers import check_node_object_for_missing_attribute
from oemof.solph._options import Investment
from oemof.solph._plumbing import sequence as solph_sequence
from oemof.solph._plumbing import sequence
from oemof.solph._plumbing import valid_sequence


class GenericStorage(Node):
Expand Down Expand Up @@ -225,26 +226,22 @@ def __init__(

self.initial_storage_level = initial_storage_level
self.balanced = balanced
self.loss_rate = solph_sequence(loss_rate)
self.fixed_losses_relative = solph_sequence(fixed_losses_relative)
self.fixed_losses_absolute = solph_sequence(fixed_losses_absolute)
self.inflow_conversion_factor = solph_sequence(
inflow_conversion_factor
)
self.outflow_conversion_factor = solph_sequence(
outflow_conversion_factor
)
self.max_storage_level = solph_sequence(max_storage_level)
self.min_storage_level = solph_sequence(min_storage_level)
self.fixed_costs = solph_sequence(fixed_costs)
self.storage_costs = solph_sequence(storage_costs)
self.invest_relation_input_output = solph_sequence(
self.loss_rate = sequence(loss_rate)
self.fixed_losses_relative = sequence(fixed_losses_relative)
self.fixed_losses_absolute = sequence(fixed_losses_absolute)
self.inflow_conversion_factor = sequence(inflow_conversion_factor)
self.outflow_conversion_factor = sequence(outflow_conversion_factor)
self.max_storage_level = sequence(max_storage_level)
self.min_storage_level = sequence(min_storage_level)
self.fixed_costs = sequence(fixed_costs)
self.storage_costs = sequence(storage_costs)
self.invest_relation_input_output = sequence(
invest_relation_input_output
)
self.invest_relation_input_capacity = solph_sequence(
self.invest_relation_input_capacity = sequence(
invest_relation_input_capacity
)
self.invest_relation_output_capacity = solph_sequence(
self.invest_relation_output_capacity = sequence(
invest_relation_output_capacity
)
self.lifetime_inflow = lifetime_inflow
Expand Down Expand Up @@ -607,7 +604,7 @@ def _objective_expression(self):

if m.es.periods is not None:
for n in self.STORAGES:
if n.fixed_costs[0] is not None:
if valid_sequence(n.fixed_costs, len(m.PERIODS)):
fixed_costs += sum(
n.nominal_storage_capacity
* n.fixed_costs[pp]
Expand All @@ -619,7 +616,7 @@ def _objective_expression(self):
storage_costs = 0

for n in self.STORAGES:
if n.storage_costs[0] is not None:
if valid_sequence(n.storage_costs, len(m.TIMESTEPS)):
# We actually want to iterate over all TIMEPOINTS except the
# 0th. As integers are used for the index, this is equicalent
# to iterating over the TIMESTEPS with one offset.
Expand Down Expand Up @@ -1875,7 +1872,7 @@ def _objective_expression(self):
period_investment_costs[p] += investment_costs_increment

for n in self.INVESTSTORAGES:
if n.investment.fixed_costs[0] is not None:
if valid_sequence(n.investment.fixed_costs, len(m.PERIODS)):
lifetime = n.investment.lifetime
for p in m.PERIODS:
range_limit = min(
Expand All @@ -1893,7 +1890,7 @@ def _objective_expression(self):
)

for n in self.EXISTING_INVESTSTORAGES:
if n.investment.fixed_costs[0] is not None:
if valid_sequence(n.investment.fixed_costs, len(m.PERIODS)):
lifetime = n.investment.lifetime
age = n.investment.age
range_limit = min(
Expand Down
19 changes: 10 additions & 9 deletions src/oemof/solph/components/experimental/_sink_dsm.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

from oemof.solph._options import Investment
from oemof.solph._plumbing import sequence
from oemof.solph._plumbing import valid_sequence
from oemof.solph.components._sink import Sink


Expand Down Expand Up @@ -703,7 +704,7 @@ def _objective_expression(self):
* (1 + m.discount_rate) ** (-m.es.periods_years[p])
)

if g.fixed_costs[0] is not None:
if valid_sequence(g.fixed_costs, len(m.PERIODS)):
fixed_costs += sum(
max(g.max_capacity_up, g.max_capacity_down)
* g.fixed_costs[pp]
Expand Down Expand Up @@ -1434,7 +1435,7 @@ def _objective_expression(self):
* (1 + m.discount_rate) ** (-m.es.periods_years[p])
)

if g.investment.fixed_costs[0] is not None:
if valid_sequence(g.investment.fixed_costs, len(m.PERIODS)):
lifetime = g.investment.lifetime
for p in m.PERIODS:
range_limit = min(
Expand All @@ -1452,7 +1453,7 @@ def _objective_expression(self):
)

for g in self.EXISTING_INVESTDSM:
if g.investment.fixed_costs[0] is not None:
if valid_sequence(g.investment.fixed_costs, len(m.PERIODS)):
lifetime = g.investment.lifetime
age = g.investment.age
range_limit = min(
Expand Down Expand Up @@ -2198,7 +2199,7 @@ def _objective_expression(self):
* (1 + m.discount_rate) ** (-m.es.periods_years[p])
)

if g.fixed_costs[0] is not None:
if valid_sequence(g.fixed_costs, len(m.PERIODS)):
fixed_costs += sum(
max(g.max_capacity_up, g.max_capacity_down)
* g.fixed_costs[pp]
Expand Down Expand Up @@ -3290,7 +3291,7 @@ def _objective_expression(self):
* (1 + m.discount_rate) ** (-m.es.periods_years[p])
)

if g.investment.fixed_costs[0] is not None:
if valid_sequence(g.investment.fixed_costs, len(m.PERIODS)):
lifetime = g.investment.lifetime
for p in m.PERIODS:
range_limit = min(
Expand All @@ -3308,7 +3309,7 @@ def _objective_expression(self):
)

for g in self.EXISTING_INVESTDSM:
if g.investment.fixed_costs[0] is not None:
if valid_sequence(g.investment.fixed_costs, len(m.PERIODS)):
lifetime = g.investment.lifetime
age = g.investment.age
range_limit = min(
Expand Down Expand Up @@ -4391,7 +4392,7 @@ def _objective_expression(self):
* (1 + m.discount_rate) ** (-m.es.periods_years[p])
)

if g.fixed_costs[0] is not None:
if valid_sequence(g.fixed_costs, len(m.PERIODS)):
fixed_costs += sum(
max(g.max_capacity_up, g.max_capacity_down)
* g.fixed_costs[pp]
Expand Down Expand Up @@ -5791,7 +5792,7 @@ def _objective_expression(self):
* (1 + m.discount_rate) ** (-m.es.periods_years[p])
)

if g.investment.fixed_costs[0] is not None:
if valid_sequence(g.investment.fixed_costs, len(m.PERIODS)):
lifetime = g.investment.lifetime
for p in m.PERIODS:
range_limit = min(
Expand All @@ -5809,7 +5810,7 @@ def _objective_expression(self):
)

for g in self.EXISTING_INVESTDSM:
if g.investment.fixed_costs[0] is not None:
if valid_sequence(g.investment.fixed_costs, len(m.PERIODS)):
lifetime = g.investment.lifetime
age = g.investment.age
range_limit = min(
Expand Down
10 changes: 8 additions & 2 deletions src/oemof/solph/flows/_investment_flow_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
from pyomo.core import Var
from pyomo.core.base.block import ScalarBlock

from oemof.solph._plumbing import valid_sequence


class InvestmentFlowBlock(ScalarBlock):
r"""Block for all flows with :attr:`Investment` being not None.
Expand Down Expand Up @@ -1007,7 +1009,9 @@ def _objective_expression(self):
period_investment_costs[p] += investment_costs_increment

for i, o in self.INVESTFLOWS:
if m.flows[i, o].investment.fixed_costs[0] is not None:
if valid_sequence(
m.flows[i, o].investment.fixed_costs, len(m.PERIODS)
):
lifetime = m.flows[i, o].investment.lifetime
for p in m.PERIODS:
range_limit = min(
Expand All @@ -1022,7 +1026,9 @@ def _objective_expression(self):
)

for i, o in self.EXISTING_INVESTFLOWS:
if m.flows[i, o].investment.fixed_costs[0] is not None:
if valid_sequence(
m.flows[i, o].investment.fixed_costs, len(m.PERIODS)
):
lifetime = m.flows[i, o].investment.lifetime
age = m.flows[i, o].investment.age
range_limit = min(
Expand Down
Loading

0 comments on commit 37cb747

Please sign in to comment.