Gissinger geodynamo
Gissinger's geodynamo, whose dipole field reverses at irregular times.
- Name:
geodynamo - Field:
physics/climate - Formalism: ordinary differential equations
- References: Gissinger 2012; Datseris and Parlitz 2022
Factory
@register_model(
field='physics/climate',
tags=('chaos', 'ode', 'geomagnetism', 'reversals'),
references=('Gissinger 2012', 'Datseris and Parlitz 2022'),
defaults={'until': 500.0, 'dt': 0.5},
)
def geodynamo(
Q: float = 0.1,
D: float = 0.1,
V: float = 0.1,
*,
mu: float = 0.119,
nu: float = 0.1,
Gamma: float = 0.9,
) -> System:
"""Return Gissinger's geodynamo, whose dipole field reverses at irregular times.
The quadrupolar field `Q`, the dipolar field `D`, and the velocity `V` follow `dQ/dt = mu Q - V D`,
`dD/dt = -nu D + V Q`, and `dV/dt = Gamma - V + Q D`. The equations are symmetric under `(Q, D) -> (-Q, -D)`, so
the chaotic flow visits both polarities of the dipole.
Args:
Q:
The initial quadrupolar field.
D:
The initial dipolar field.
V:
The initial velocity.
mu:
The growth rate of the quadrupole.
nu:
The damping rate of the dipole.
Gamma:
The forcing of the flow.
Returns:
system:
The model, with the states `dynamo.Q`, `dynamo.D`, and `dynamo.V`.
Examples:
>>> from skcomplex.models.physics.climate import geodynamo
>>> geodynamo(mu=0.12).elements[0].mu
0.12
"""
return System(elements=[GeodynamoElement('dynamo', Q=Q, D=D, V=V, mu=mu, nu=nu, Gamma=Gamma)])
Components
class GeodynamoElement(Element):
"""Dynamo of Gissinger's geodynamo, its quadrupolar and dipolar fields and the velocity of the flow.
The quadrupolar field `Q`, the dipolar field `D`, and the velocity `V` follow `dQ/dt = mu Q - V D`,
`dD/dt = -nu D + V Q`, and `dV/dt = Gamma - V + Q D`.
Args:
label:
The label of the dynamo.
visual:
How the element is drawn, or `None` for `default_visual_`.
Q:
The initial quadrupolar field.
D:
The initial dipolar field.
V:
The initial velocity.
mu:
The growth rate of the quadrupole.
nu:
The damping rate of the dipole.
Gamma:
The forcing of the flow.
Examples:
>>> from skcomplex.models.physics.climate import GeodynamoElement
>>> GeodynamoElement('dynamo').Gamma
0.9
"""
def __init__(
self,
label: str,
visual: VisualSpec | None = None,
*,
Q: Annotated[float, StateSpec()] = 0.1,
D: Annotated[float, StateSpec()] = 0.1,
V: Annotated[float, StateSpec()] = 0.1,
mu: Annotated[float, ParameterSpec()] = 0.119,
nu: Annotated[float, ParameterSpec()] = 0.1,
Gamma: Annotated[float, ParameterSpec()] = 0.9,
) -> None:
super().__init__(label, visual=visual)
self.Q = Q
self.D = D
self.V = V
self.mu = mu
self.nu = nu
self.Gamma = Gamma
def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
"""Return the growth and damping of both fields and the forcing of the flow.
Args:
s:
The namespace of the symbols the laws can use.
Returns:
laws:
The rate laws of the quadrupolar field, the dipolar field, and the velocity.
"""
return [
RateLaw(s.Q, s.mu * s.Q - s.V * s.D),
RateLaw(s.D, -s.nu * s.D + s.V * s.Q),
RateLaw(s.V, s.Gamma - s.V + s.Q * s.D),
]
Equations
dynamo.Q: diff(Q_dynamo(t), t) == mu_dynamo*Q_dynamo(t) - D_dynamo(t)*V_dynamo(t)
dynamo.D: diff(D_dynamo(t), t) == -nu_dynamo*D_dynamo(t) + Q_dynamo(t)*V_dynamo(t)
dynamo.V: diff(V_dynamo(t), t) == D_dynamo(t)*Q_dynamo(t) + Gamma_dynamo - V_dynamo(t)