Skip to content

Commit

Permalink
Merge branch 'dev' into revision/include_v0-5_fixes
Browse files Browse the repository at this point in the history
# Conflicts:
#	docs/changelog.rst
#	src/oemof/solph/__init__.py
#	src/oemof/solph/components/_generic_storage.py
#	src/oemof/solph/flows/_non_convex_flow_block.py
  • Loading branch information
p-snft committed Aug 29, 2024
2 parents e9c0c56 + 50f4e4b commit 1234e0d
Show file tree
Hide file tree
Showing 182 changed files with 1,685 additions and 46,123 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tox_pytests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
run: tox

- name: Check test coverage
run: coverage report -m --fail-under=${{ matrix.vcs == 'bzr' && 89 || 90 }}
run: coverage report -m --fail-under=${{ matrix.vcs == 'bzr' && 84 || 85 }}

- name: Report to coveralls
run: coveralls
Expand Down
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ These are new features and improvements of note in each release
:backlinks: top


.. include:: whatsnew/v0-6-0.rst
.. include:: whatsnew/v0-5-5.rst
.. include:: whatsnew/v0-5-4.rst
.. include:: whatsnew/v0-5-3.rst
Expand Down
38 changes: 38 additions & 0 deletions docs/whatsnew/v0-6-0.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
v0.6.0
------

API changes
###########

* Costs for energy storage are now defined for N-1 points in time
(initial time step is neglected). This is because with a balanced
storage, content of the initial and the first time step (which is
effectively the same) had double weight before. Also, if the
initial storage level is defined, the costs just offset the
objective value without changing anything else.

New features
############


Documentation
#############

Bug fixes
#########


Other changes
#############


Known issues
############

* Incompatible to numpy >= 2.0.0. This is because of Pyomo, but we have to
enforce a lower version in our package.

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

* Patrik Schönfeldt
4 changes: 2 additions & 2 deletions src/oemof/solph/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.5.5"
__version__ = "0.6.0a2"

from . import buses
from . import components
Expand All @@ -8,8 +8,8 @@
from . import processing
from . import views
from ._energy_system import EnergySystem
from ._energy_system import create_time_index
from ._groupings import GROUPINGS
from ._helpers import create_time_index
from ._models import Model
from ._options import Investment
from ._options import NonConvex
Expand Down
50 changes: 33 additions & 17 deletions src/oemof/solph/_console_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from oemof import solph


def check_oemof_installation(silent=False):
def _check_oemof_installation(solvers):
logging.disable(logging.CRITICAL)

date_time_index = pd.date_range("1/1/2012", periods=6, freq="h")
Expand Down Expand Up @@ -48,22 +48,38 @@ def check_oemof_installation(silent=False):
om = solph.Model(energysystem)

# check solvers
solver = dict()
for s in ["cbc", "glpk", "gurobi", "cplex"]:
solver_status = dict()
for s in solvers:
try:
om.solve(solver=s)
solver[s] = "working"
solver_status[s] = True
except Exception:
solver[s] = "not working"

if not silent:
print()
print("*****************************")
print("Solver installed with oemof:")
print()
for s, t in solver.items():
print("{0}: {1}".format(s, t))
print()
print("*****************************")
print("oemof successfully installed.")
print("*****************************")
solver_status[s] = False

return solver_status


def check_oemof_installation():

solvers_to_test = ["cbc", "glpk", "gurobi", "cplex"]

solver_status = _check_oemof_installation(solvers_to_test)

print_text = (
"***********************************\n"
"Solver installed with oemof.solph:\n"
"\n"
)
for solver, works in solver_status.items():
if works:
print_text += f"{solver}: installed and working\n"
else:
print_text += f"{solver}: not installed/ not working\n"
print_text += (
"\n"
"***********************************\n"
"oemof.solph successfully installed.\n"
"***********************************\n"
)

print(print_text)
70 changes: 0 additions & 70 deletions src/oemof/solph/_energy_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
"""

import calendar
import datetime
import warnings

import numpy as np
Expand Down Expand Up @@ -244,71 +242,3 @@ def get_period_duration(self, period):
- self.periods[period].min().year
+ 1
)


def create_time_index(
year: int = None,
interval: float = 1,
number: int = None,
start: datetime.datetime or datetime.date = None,
):
"""
Create a datetime index for one year.
Notes
-----
To create 8760 hourly intervals for a non leap year a datetime index with
8761 time points need to be created. So the number of time steps is always
the number of intervals plus one.
Parameters
----------
year : int, datetime
The year of the index. If number and start is set the year parameter is
ignored.
interval : float
The time interval in hours e.g. 0.5 for 30min or 2 for a two hour
interval (default: 1).
number : int
The number of time intervals. By default number is calculated to create
an index of one year. For a shorter or longer period the number of
intervals can be set by the user.
start : datetime.datetime or datetime.date
Optional start time. If start is not set, 00:00 of the first day of
the given year is the start time.
Examples
--------
>>> len(create_time_index(2014))
8761
>>> len(create_time_index(2012)) # leap year
8785
>>> len(create_time_index(2014, interval=0.5))
17521
>>> len(create_time_index(2014, interval=0.5, number=10))
11
>>> len(create_time_index(2014, number=10))
11
>>> str(create_time_index(2014, interval=0.5, number=10)[-1])
'2014-01-01 05:00:00'
>>> str(create_time_index(2014, interval=2, number=10)[-1])
'2014-01-01 20:00:00'
"""
if number is None:
if calendar.isleap(year):
hoy = 8784
else:
hoy = 8760
number = round(hoy / interval)
if start is None:
start = f"1/1/{year}"
try:
time_index = pd.date_range(
start, periods=number + 1, freq=f"{interval}h"
)
except ValueError:
# Pandas <2.2 compatibility
time_index = pd.date_range(
start, periods=number + 1, freq=f"{interval}H"
)
return time_index
76 changes: 76 additions & 0 deletions src/oemof/solph/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
"""

import calendar
import datetime
from warnings import warn

import pandas as pd
from oemof.tools import debugging


Expand Down Expand Up @@ -45,3 +48,76 @@ def warn_if_missing_attribute(obj, attribute):
msg.format(attribute, obj.label, type(obj)),
debugging.SuspiciousUsageWarning,
)


def create_time_index(
year: int = None,
interval: float = 1,
number: int = None,
start: datetime.date = None,
):
"""
Create a datetime index for one year.
Notes
-----
To create 8760 hourly intervals for a non leap year a datetime index with
8761 time points need to be created. So the number of time steps is always
the number of intervals plus one.
Parameters
----------
year : int, datetime
The year of the index.
Used to automatically set start and number for the specific year.
interval : float
The time interval in hours e.g. 0.5 for 30min or 2 for a two hour
interval (default: 1).
number : int
The number of time intervals. By default number is calculated to create
an index of one year. For a shorter or longer period the number of
intervals can be set by the user.
start : datetime.datetime or datetime.date
Optional start time. If start is not set, 00:00 of the first day of
the given year is the start time.
Examples
--------
>>> len(create_time_index(2014))
8761
>>> len(create_time_index(2012)) # leap year
8785
>>> len(create_time_index(2014, interval=0.5))
17521
>>> len(create_time_index(2014, interval=0.5, number=10))
11
>>> len(create_time_index(2014, number=10))
11
>>> str(create_time_index(2014, interval=0.5, number=10)[-1])
'2014-01-01 05:00:00'
>>> str(create_time_index(2014, interval=2, number=10)[-1])
'2014-01-01 20:00:00'
"""
if number is None:
if calendar.isleap(year):
hours_in_year = 8784
else:
hours_in_year = 8760
number = round(hours_in_year / interval)
if start is not None:
if year is not None:
raise ValueError(
"Arguments 'start' and 'year' are mutually exclusive."
)
else:
start = f"1/1/{year}"
try:
time_index = pd.date_range(
start, periods=number + 1, freq=f"{interval}h"
)
except ValueError:
# Pandas <2.2 compatibility
time_index = pd.date_range(
start, periods=number + 1, freq=f"{interval}H"
)
return time_index
Loading

0 comments on commit 1234e0d

Please sign in to comment.