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)