Skip to content

ENSO delay oscillator

The delayed oscillator of El Niño of Suarez and Schopf, dT/dt = T - T^3 - alpha T(t - delta).

  • Name: enso
  • Field: physics/climate
  • Formalism: ordinary differential equations
  • References: Suarez and Schopf 1988; Battisti and Hirst 1989; Ghil and Lucarini 2020

Factory

@register_model(
    field='physics/climate',
    tags=('delay', 'oscillation', 'El Niño', 'ENSO'),
    references=('Suarez and Schopf 1988', 'Battisti and Hirst 1989', 'Ghil and Lucarini 2020'),
    defaults={'until': 200.0, 'dt': 0.5},
)
def enso(T: float = 0.1, *, alpha: float = 0.75, delta: float = 6.0) -> System:
    """Return the delayed oscillator of El Niño of Suarez and Schopf, `dT/dt = T - T^3 - alpha T(t - delta)`.

    The sea surface temperature anomaly of the eastern Pacific grows by local feedback and is damped by the delayed
    return of oceanic waves reflected at the western boundary. For `alpha < 1` and a long enough delay the warm and cold
    states lose stability to an oscillation between El Niño and La Niña. The history before the start is the initial
    anomaly.

    Args:
        T:
            The initial temperature anomaly, also its history.

        alpha:
            The strength of the delayed negative feedback.

        delta:
            The delay of the wave transit.

    Returns:
        system:
            The model, with the anomaly `pacific.T`.

    Examples:
        >>> from skcomplex.models.physics.climate import enso
        >>> enso(delta=4.0).elements[0].delta
        4.0
    """
    return System(elements=[DelayedOscillatorElement('pacific', T=T, alpha=alpha, delta=delta)])

Components

class DelayedOscillatorElement(Element):
    """Eastern Pacific of the delayed oscillator of El Niño, its sea surface temperature anomaly.

    The anomaly follows `dT/dt = T - T^3 - alpha T(t - delta)`. It grows by local feedback and is damped by the
    delayed return of oceanic waves reflected at the western boundary.

    Args:
        label:
            The label of the ocean.

        visual:
            How the element is drawn, or `None` for `default_visual_`.

        T:
            The initial temperature anomaly, also its history.

        alpha:
            The strength of the delayed negative feedback.

        delta:
            The delay of the wave transit.

    Examples:
        >>> from skcomplex.models.physics.climate import DelayedOscillatorElement
        >>> DelayedOscillatorElement('pacific').delta
        6.0
    """

    def __init__(
        self,
        label: str,
        visual: VisualSpec | None = None,
        *,
        T: Annotated[float, StateSpec()] = 0.1,
        alpha: Annotated[float, ParameterSpec()] = 0.75,
        delta: Annotated[float, ParameterSpec()] = 6.0,
    ) -> None:
        super().__init__(label, visual=visual)
        self.T = T
        self.alpha = alpha
        self.delta = delta

    def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
        """Return the local growth and saturation of the anomaly and its delayed negative feedback.

        Args:
            s:
                The namespace of the symbols the laws can use.

        Returns:
            laws:
                The rate law of the anomaly.
        """
        return [RateLaw(s.T, s.T - s.T**3 - s.alpha * delayed(s.T, s.delta))]

Equations

pacific.T: diff(T_pacific(t), t) == -T_pacific(t)^3 - alpha_pacific*T_pacific(-delta_pacific + t) + T_pacific(t)