Module nemo.storage

Storage classes.

Storage objects are usually shared between a load and a generator (for example, a pumped hydro system having a pump, a turbine and a storage system.

Expand source code
# Copyright (C) 2023 Ben Elliston
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.

"""
Storage classes.

Storage objects are usually shared between a load and a generator (for
example, a pumped hydro system having a pump, a turbine and a storage
system.
"""


class GenericStorage():
    """A simple electrical storage system.

    The storage has unity efficiency. It is up to the load and
    generator to handle the round trip efficiency of the relevant
    technologies.
    """

    def __init__(self, maxstorage, label=None):
        """Construct a storage object.

        The storage capacity (in MWh) is specified by maxstorage.
        """
        self.label = label
        # initialise to silence pylint
        self.storage = 0
        self.set_storage(maxstorage)

    def set_storage(self, maxstorage):
        """
        Change the storage capacity.

        >>> r = GenericStorage(1000)
        >>> r.set_storage(1200)
        >>> r.maxstorage
        1200
        >>> r.storage
        600.0
        """
        self.storage = maxstorage / 2
        self.maxstorage = maxstorage

    def reset(self):
        """
        Reset storage to 50% SOC.

        >>> r = GenericStorage(1000)
        >>> r.storage = 200
        >>> r.reset()
        >>> r.storage
        500.0
        """
        self.storage = self.maxstorage / 2

    def soc(self):
        """Return the storage SOC (state of charge).

        >>> r = GenericStorage(1000)
        >>> r.soc()
        0.5
        """
        return self.storage / self.maxstorage

    def empty_p(self):
        """Return True if the storage is empty.

        >>> r = GenericStorage(1000)
        >>> r.storage = 0
        >>> r.empty_p(), r.full_p()
        (True, False)
        """
        return self.storage == 0

    def full_p(self):
        """Return True if the storage is full.

        >>> r = GenericStorage(1000)
        >>> r.storage = 1000
        >>> r.full_p(), r.empty_p()
        (True, False)
        """
        return self.maxstorage == self.storage

    def charge(self, amt):
        """
        Charge the storage by amt.

        >>> stg = GenericStorage(1000, 'test')
        >>> stg.charge(600), stg.full_p()
        (500.0, True)
        """
        assert amt >= 0
        delta = min(self.maxstorage - self.storage, amt)
        self.storage = min(self.maxstorage, self.storage + amt)
        assert 0 <= self.storage <= self.maxstorage
        return delta

    def discharge(self, amt):
        """
        Discharge the storage by 'amt'.

        >>> stg = GenericStorage(1000, 'test')
        >>> stg.discharge(600), stg.empty_p()
        (500.0, True)
        """
        assert amt >= 0
        delta = min(self.storage, amt)
        self.storage = max(0, self.storage - amt)
        assert 0 <= self.storage <= self.maxstorage
        return delta


class BatteryStorage(GenericStorage):
    """Battery storage."""


class HydrogenStorage(GenericStorage):
    """Hydrogen storage."""


class PumpedHydroStorage(GenericStorage):
    """A pair of reservoirs for pumped storage."""

    def __init__(self, maxstorage, label=None):
        """Construct a pumped hydro storage reservoir pair.

        The storage capacity (in MWh) is specified by maxstorage.
        """
        GenericStorage.__init__(self, maxstorage, label)

        # Communicate between pump and turbine here to prevent both
        # generators running in the same hour.
        self.last_gen = None
        self.last_pump = None

    def reset(self):
        """Reset the storage."""
        GenericStorage.reset(self)
        self.last_gen = None
        self.last_pump = None

Classes

class BatteryStorage (maxstorage, label=None)

Battery storage.

Construct a storage object.

The storage capacity (in MWh) is specified by maxstorage.

Expand source code
class BatteryStorage(GenericStorage):
    """Battery storage."""

Ancestors

Inherited members

class GenericStorage (maxstorage, label=None)

A simple electrical storage system.

The storage has unity efficiency. It is up to the load and generator to handle the round trip efficiency of the relevant technologies.

Construct a storage object.

The storage capacity (in MWh) is specified by maxstorage.

Expand source code
class GenericStorage():
    """A simple electrical storage system.

    The storage has unity efficiency. It is up to the load and
    generator to handle the round trip efficiency of the relevant
    technologies.
    """

    def __init__(self, maxstorage, label=None):
        """Construct a storage object.

        The storage capacity (in MWh) is specified by maxstorage.
        """
        self.label = label
        # initialise to silence pylint
        self.storage = 0
        self.set_storage(maxstorage)

    def set_storage(self, maxstorage):
        """
        Change the storage capacity.

        >>> r = GenericStorage(1000)
        >>> r.set_storage(1200)
        >>> r.maxstorage
        1200
        >>> r.storage
        600.0
        """
        self.storage = maxstorage / 2
        self.maxstorage = maxstorage

    def reset(self):
        """
        Reset storage to 50% SOC.

        >>> r = GenericStorage(1000)
        >>> r.storage = 200
        >>> r.reset()
        >>> r.storage
        500.0
        """
        self.storage = self.maxstorage / 2

    def soc(self):
        """Return the storage SOC (state of charge).

        >>> r = GenericStorage(1000)
        >>> r.soc()
        0.5
        """
        return self.storage / self.maxstorage

    def empty_p(self):
        """Return True if the storage is empty.

        >>> r = GenericStorage(1000)
        >>> r.storage = 0
        >>> r.empty_p(), r.full_p()
        (True, False)
        """
        return self.storage == 0

    def full_p(self):
        """Return True if the storage is full.

        >>> r = GenericStorage(1000)
        >>> r.storage = 1000
        >>> r.full_p(), r.empty_p()
        (True, False)
        """
        return self.maxstorage == self.storage

    def charge(self, amt):
        """
        Charge the storage by amt.

        >>> stg = GenericStorage(1000, 'test')
        >>> stg.charge(600), stg.full_p()
        (500.0, True)
        """
        assert amt >= 0
        delta = min(self.maxstorage - self.storage, amt)
        self.storage = min(self.maxstorage, self.storage + amt)
        assert 0 <= self.storage <= self.maxstorage
        return delta

    def discharge(self, amt):
        """
        Discharge the storage by 'amt'.

        >>> stg = GenericStorage(1000, 'test')
        >>> stg.discharge(600), stg.empty_p()
        (500.0, True)
        """
        assert amt >= 0
        delta = min(self.storage, amt)
        self.storage = max(0, self.storage - amt)
        assert 0 <= self.storage <= self.maxstorage
        return delta

Subclasses

Methods

def charge(self, amt)

Charge the storage by amt.

>>> stg = GenericStorage(1000, 'test')
>>> stg.charge(600), stg.full_p()
(500.0, True)
Expand source code
def charge(self, amt):
    """
    Charge the storage by amt.

    >>> stg = GenericStorage(1000, 'test')
    >>> stg.charge(600), stg.full_p()
    (500.0, True)
    """
    assert amt >= 0
    delta = min(self.maxstorage - self.storage, amt)
    self.storage = min(self.maxstorage, self.storage + amt)
    assert 0 <= self.storage <= self.maxstorage
    return delta
def discharge(self, amt)

Discharge the storage by 'amt'.

>>> stg = GenericStorage(1000, 'test')
>>> stg.discharge(600), stg.empty_p()
(500.0, True)
Expand source code
def discharge(self, amt):
    """
    Discharge the storage by 'amt'.

    >>> stg = GenericStorage(1000, 'test')
    >>> stg.discharge(600), stg.empty_p()
    (500.0, True)
    """
    assert amt >= 0
    delta = min(self.storage, amt)
    self.storage = max(0, self.storage - amt)
    assert 0 <= self.storage <= self.maxstorage
    return delta
def empty_p(self)

Return True if the storage is empty.

>>> r = GenericStorage(1000)
>>> r.storage = 0
>>> r.empty_p(), r.full_p()
(True, False)
Expand source code
def empty_p(self):
    """Return True if the storage is empty.

    >>> r = GenericStorage(1000)
    >>> r.storage = 0
    >>> r.empty_p(), r.full_p()
    (True, False)
    """
    return self.storage == 0
def full_p(self)

Return True if the storage is full.

>>> r = GenericStorage(1000)
>>> r.storage = 1000
>>> r.full_p(), r.empty_p()
(True, False)
Expand source code
def full_p(self):
    """Return True if the storage is full.

    >>> r = GenericStorage(1000)
    >>> r.storage = 1000
    >>> r.full_p(), r.empty_p()
    (True, False)
    """
    return self.maxstorage == self.storage
def reset(self)

Reset storage to 50% SOC.

>>> r = GenericStorage(1000)
>>> r.storage = 200
>>> r.reset()
>>> r.storage
500.0
Expand source code
def reset(self):
    """
    Reset storage to 50% SOC.

    >>> r = GenericStorage(1000)
    >>> r.storage = 200
    >>> r.reset()
    >>> r.storage
    500.0
    """
    self.storage = self.maxstorage / 2
def set_storage(self, maxstorage)

Change the storage capacity.

>>> r = GenericStorage(1000)
>>> r.set_storage(1200)
>>> r.maxstorage
1200
>>> r.storage
600.0
Expand source code
def set_storage(self, maxstorage):
    """
    Change the storage capacity.

    >>> r = GenericStorage(1000)
    >>> r.set_storage(1200)
    >>> r.maxstorage
    1200
    >>> r.storage
    600.0
    """
    self.storage = maxstorage / 2
    self.maxstorage = maxstorage
def soc(self)

Return the storage SOC (state of charge).

>>> r = GenericStorage(1000)
>>> r.soc()
0.5
Expand source code
def soc(self):
    """Return the storage SOC (state of charge).

    >>> r = GenericStorage(1000)
    >>> r.soc()
    0.5
    """
    return self.storage / self.maxstorage
class HydrogenStorage (maxstorage, label=None)

Hydrogen storage.

Construct a storage object.

The storage capacity (in MWh) is specified by maxstorage.

Expand source code
class HydrogenStorage(GenericStorage):
    """Hydrogen storage."""

Ancestors

Inherited members

class PumpedHydroStorage (maxstorage, label=None)

A pair of reservoirs for pumped storage.

Construct a pumped hydro storage reservoir pair.

The storage capacity (in MWh) is specified by maxstorage.

Expand source code
class PumpedHydroStorage(GenericStorage):
    """A pair of reservoirs for pumped storage."""

    def __init__(self, maxstorage, label=None):
        """Construct a pumped hydro storage reservoir pair.

        The storage capacity (in MWh) is specified by maxstorage.
        """
        GenericStorage.__init__(self, maxstorage, label)

        # Communicate between pump and turbine here to prevent both
        # generators running in the same hour.
        self.last_gen = None
        self.last_pump = None

    def reset(self):
        """Reset the storage."""
        GenericStorage.reset(self)
        self.last_gen = None
        self.last_pump = None

Ancestors

Methods

def reset(self)

Reset the storage.

Expand source code
def reset(self):
    """Reset the storage."""
    GenericStorage.reset(self)
    self.last_gen = None
    self.last_pump = None

Inherited members