Source code for pybamm.experiment.step.step_termination

from warnings import warn

import pybamm


[docs] class BaseTermination: """ Base class for a termination event for an experiment step. To create a custom termination, a class must implement `get_event` to return a :class:`pybamm.Event` corresponding to the desired termination. In most cases the class :class:`pybamm.step.CustomTermination` can be used to assist with this. Parameters ---------- value : float The value at which the event is triggered """ def __init__(self, value, operator=None): self.value = value if operator not in ["<", ">", None]: raise ValueError(f"Invalid operator: {operator}") self.operator = operator
[docs] def get_event(self, variables, step): """ Return a :class:`pybamm.Event` object corresponding to the termination event Parameters ---------- variables : dict Dictionary of model variables, to be used for selecting the variable(s) that determine the event step : :class:`pybamm.step.BaseStep` Step for which this is a termination event, to be used in some cases to determine the sign of the event. """ raise NotImplementedError
def __eq__(self, other): # objects are equal if they have the same type and value if isinstance(other, self.__class__): return self.value == other.value else: return False
[docs] class CRateTermination(BaseTermination): """ Termination based on C-rate, created when a string termination of the C-rate type (e.g. "C/10") is provided """
[docs] def get_event(self, variables, step): """ See :meth:`BaseTermination.get_event` """ event = pybamm.Event( "C-rate cut-off [experiment]", abs(variables["C-rate"]) - self.value, ) return event
class CrateTermination(CRateTermination): """ Termination based on C-rate, created when a string termination of the C-rate type (e.g. "C/10") is provided """ def __init__(self, value, operator=None): super().__init__(value, operator) warning = DeprecationWarning( "CrateTermination is deprecated and will be removed in a future release. Use CRateTermination instead." ) warn(warning, stacklevel=2)
[docs] class CurrentTermination(BaseTermination): """ Termination based on current, created when a string termination of the current type (e.g. "1A") is provided """
[docs] def get_event(self, variables, step): """ See :meth:`BaseTermination.get_event` """ operator = self.operator if operator == ">": expr = self.value - variables["Current [A]"] event_string = f"Current [A] > {self.value} [A] [experiment]" elif operator == "<": expr = variables["Current [A]"] - self.value event_string = f"Current [A] < {self.value} [A] [experiment]" else: expr = abs(variables["Current [A]"]) - self.value event_string = f"abs(Current [A]) < {self.value} [A] [experiment]" event = pybamm.Event( event_string, expr, ) return event
[docs] class VoltageTermination(BaseTermination): """ Termination based on voltage, created when a string termination of the voltage type (e.g. "4.2V") is provided """
[docs] def get_event(self, variables, step): """ See :meth:`BaseTermination.get_event` """ # The voltage event should be positive at the start of charge/ # discharge. We use the sign of the current or power input to # figure out whether the voltage event is greater than the starting # voltage (charge) or less (discharge) and set the sign of the # event accordingly operator = self.operator if operator is None: direction = step.direction if direction == "charge": operator = ">" elif direction == "discharge": operator = "<" else: # No event for rest steps return None if operator == ">": sign = -1 else: # operator can only be "<" or ">" sign = 1 # Event should be positive at initial conditions for both # charge and discharge event = pybamm.Event( f"Voltage {operator} {self.value} [V] [experiment]", sign * (variables["Battery voltage [V]"] - self.value), ) return event
class Voltage: def __gt__(self, value): return VoltageTermination(value, operator=">") def __lt__(self, value): return VoltageTermination(value, operator="<") class Current: def __gt__(self, value): return CurrentTermination(value, operator=">") def __lt__(self, value): return CurrentTermination(value, operator="<")
[docs] class CustomTermination(BaseTermination): """ Define a custom termination event using a function. This can be used to create an event based on any variable in the model. Parameters ---------- name : str Name of the event event_function : callable A function that takes in a dictionary of variables and evaluates the event value. Must be positive before the event is triggered and zero when the event is triggered. Example ------- Add a cut-off based on negative electrode stoichiometry. The event will trigger when the negative electrode stoichiometry reaches 10%. >>> def neg_stoich_cutoff(variables): ... return variables["Negative electrode stoichiometry"] - 0.1 >>> neg_stoich_termination = pybamm.step.CustomTermination( ... name="Negative stoichiometry cut-off", event_function=neg_stoich_cutoff ... ) """ def __init__(self, name, event_function): if not name.endswith(" [experiment]"): name += " [experiment]" self.name = name self.event_function = event_function
[docs] def get_event(self, variables, step): """ See :meth:`BaseTermination.get_event` """ return pybamm.Event(self.name, self.event_function(variables))
def _read_termination(termination, operator=None): if isinstance(termination, tuple): op, typ, value = termination else: return termination termination_class = { "current": CurrentTermination, "voltage": VoltageTermination, "C-rate": CRateTermination, }[typ] return termination_class(value, operator=op)