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

Merge revision/include v0 5 fixes #1120

Merged
merged 15 commits into from
Aug 29, 2024
Merged
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
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
Loading