Source code for VeraGridEngine.Devices.Injections.battery

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0


from typing import Tuple

from VeraGridEngine.Devices.Parents.editable_device import DeviceType, GCProp
from VeraGridEngine.enumerations import PrpCat, GeneratorControlMode
from VeraGridEngine.Devices.Injections.generator import Generator, BuildStatus


[docs] class Battery(Generator): """ Battery """ __slots__ = ( 'device_type', '_charge_efficiency', '_discharge_efficiency', '_max_soc', '_min_soc', 'min_soc_charge', 'charge_per_cycle', '_discharge_per_cycle', '_Enom', '_soc_0', 'soc', 'min_energy', 'energy', ) LOCAL_PROPERTY_DECLARATIONS: Tuple[GCProp, ...] = ( GCProp( prop_name='Enom', units='MWh', tpe=float, definition='Nominal energy capacity.', cat=[PrpCat.OPF], ), GCProp( prop_name='max_soc', units='p.u.', tpe=float, definition='Minimum state of charge.', cat=[PrpCat.OPF], ), GCProp( prop_name='min_soc', units='p.u.', tpe=float, definition='Maximum state of charge.', cat=[PrpCat.OPF], ), GCProp( prop_name='soc_0', units='p.u.', tpe=float, definition='Initial state of charge.', cat=[PrpCat.OPF], ), GCProp( prop_name='charge_efficiency', units='p.u.', tpe=float, definition='Charging efficiency.', cat=[PrpCat.OPF], ), GCProp( prop_name='discharge_efficiency', units='p.u.', tpe=float, definition='Discharge efficiency.', cat=[PrpCat.OPF], ), GCProp( prop_name='discharge_per_cycle', units='p.u.', tpe=float, definition='', cat=[PrpCat.OPF], ), ) def __init__(self, name='batt', idtag=None, code="", P=0.0, Pmin=-9999, Pmax=9999, Q=0.0, Qmin=-9999, Qmax=9999, power_factor=0.8, vset=1.0, control_mode: GeneratorControlMode = GeneratorControlMode.V, Snom=9999, Enom=9999, Cost=1.0, active=True, Sbase=100, enabled_dispatch=True, mttf=0.0, mttr=0.0, charge_efficiency=0.9, discharge_efficiency=0.9, max_soc=0.99, min_soc=0.3, soc=0.8, charge_per_cycle=0.1, discharge_per_cycle=0.1, r1=1e-20, x1=1e-20, r0=1e-20, x0=1e-20, r2=1e-20, x2=1e-20, capex=0, opex=0, srap_enabled: bool = True, build_status: BuildStatus = BuildStatus.Commissioned): """ :ref:`Battery<battery>` (voltage controlled and dispatchable). :param name: Name of the battery :param idtag: :param P: Active power in MW :param power_factor: Power factor :param vset: Voltage setpoint in per unit :param control_mode: Generator control mode :param Qmin: Minimum reactive power in MVAr :param Qmax: Maximum reactive power in MVAr :param Snom: Nominal apparent power in MVA :param Enom: Nominal energy capacity in MWh :param Pmin: Minimum dispatchable power in MW :param Pmax: Maximum dispatchable power in MW :param Cost: Operational cost in Eur (or other e) per MW :param active: Is the battery active? :param Sbase: Base apparent power in MVA :param enabled_dispatch: Is the battery enabled for OPF? :param mttf: Mean time to failure in hours :param mttr: Mean time to recovery in hours :param charge_efficiency: Efficiency when charging :param discharge_efficiency: Efficiency when discharging :param max_soc: Maximum state of charge :param min_soc: Minimum state of charge :param soc: Current state of charge :param charge_per_cycle: Per unit of power to take per cycle when charging :param discharge_per_cycle: Per unit of power to deliver per cycle when discharging :param r1: :param x1: :param r0: :param x0: :param r2: :param x2: :param capex: :param opex: :param build_status: """ Generator.__init__(self, name=name, idtag=idtag, code=code, P=P, Pmin=Pmin, Pmax=Pmax, Q=Q, Qmin=Qmin, Qmax=Qmax, Snom=Snom, power_factor=power_factor, vset=vset, control_mode=control_mode, active=active, Cost=Cost, Sbase=Sbase, enabled_dispatch=enabled_dispatch, mttf=mttf, mttr=mttr, r1=r1, x1=x1, r0=r0, x0=x0, r2=r2, x2=x2, capex=capex, opex=opex, srap_enabled=srap_enabled, build_status=build_status) # type of this device self.device_type = DeviceType.BatteryDevice self.charge_efficiency = float(charge_efficiency) self.discharge_efficiency = float(discharge_efficiency) self.max_soc = float(max_soc) self.min_soc = float(min_soc) self.min_soc_charge = (self.max_soc + self.min_soc) / 2 # SoC state to force the battery charge self.charge_per_cycle = float(charge_per_cycle) # charge 10% per cycle self.discharge_per_cycle = float(discharge_per_cycle) self.Enom = float(Enom) self.soc_0 = float(soc) self.soc = float(soc) self.min_energy = self.Enom * self.min_soc self.energy = self.Enom * self.soc def __iadd__(self, other: "Battery"): """ Add another generator here :param other: Generator to add """ super().__iadd__(other) self.Enom += other.Enom # Scalar property accessors coerce assignments to the declared schema types. @property def Enom(self) -> float: """ Get ``Enom``. :return: float """ return self._Enom @Enom.setter def Enom(self, val: float) -> None: """ Set ``Enom``. :param val: Value to assign. :return: None """ self._Enom = float(val) @property def max_soc(self) -> float: """ Get ``max_soc``. :return: float """ return self._max_soc @max_soc.setter def max_soc(self, val: float) -> None: """ Set ``max_soc``. :param val: Value to assign. :return: None """ self._max_soc = float(val) @property def min_soc(self) -> float: """ Get ``min_soc``. :return: float """ return self._min_soc @min_soc.setter def min_soc(self, val: float) -> None: """ Set ``min_soc``. :param val: Value to assign. :return: None """ self._min_soc = float(val) @property def soc_0(self) -> float: """ Get ``soc_0``. :return: float """ return self._soc_0 @soc_0.setter def soc_0(self, val: float) -> None: """ Set ``soc_0``. :param val: Value to assign. :return: None """ self._soc_0 = float(val) @property def charge_efficiency(self) -> float: """ Get ``charge_efficiency``. :return: float """ return self._charge_efficiency @charge_efficiency.setter def charge_efficiency(self, val: float) -> None: """ Set ``charge_efficiency``. :param val: Value to assign. :return: None """ self._charge_efficiency = float(val) @property def discharge_efficiency(self) -> float: """ Get ``discharge_efficiency``. :return: float """ return self._discharge_efficiency @discharge_efficiency.setter def discharge_efficiency(self, val: float) -> None: """ Set ``discharge_efficiency``. :param val: Value to assign. :return: None """ self._discharge_efficiency = float(val) @property def discharge_per_cycle(self) -> float: """ Get ``discharge_per_cycle``. :return: float """ return self._discharge_per_cycle @discharge_per_cycle.setter def discharge_per_cycle(self, val: float) -> None: """ Set ``discharge_per_cycle``. :param val: Value to assign. :return: None """ self._discharge_per_cycle = float(val)