Skip to content

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)