Skip to content

Takens-Bogdanov

The Takens-Bogdanov normal form x' = y, y' = β1 + β2 x + x² + s x y, where a saddle-node meets a Hopf.

  • Name: takens_bogdanov_form
  • Field: mathematics/dynamical_systems
  • Formalism: ordinary differential equations
  • References: Gros 2015; Dilão 2023

Factory

@register_model(
    field='mathematics/dynamical_systems',
    tags=('bifurcation', 'normal form', 'ode', 'codimension two'),
    references=('Gros 2015', 'Dilão 2023'),
    defaults={'until': 50.0, 'dt': 0.1},
)
def takens_bogdanov_form(
    x: float = 0.2,
    y: float = 0.0,
    *,
    beta1: float = 0.1,
    beta2: float = -1.0,
    sign: float = -1.0,
) -> System:
    """Return the Takens-Bogdanov normal form `x' = y`, `y' = β1 + β2 x + x² + s x y`, where a saddle-node meets a Hopf.

    Args:
        x:
            The initial position.

        y:
            The initial velocity.

        beta1:
            The first unfolding parameter.

        beta2:
            The second unfolding parameter.

        sign:
            The sign `s` of the mixed term, `-1` or `1`.

    Returns:
        system:
            The model, with the states `form.x` and `form.y`.

    Examples:
        >>> from skcomplex.models.mathematics.dynamical_systems import takens_bogdanov_form
        >>> takens_bogdanov_form(beta1=0.0).elements[0].beta1
        0.0
    """
    return System(elements=[TakensBogdanovElement('form', x=x, y=y, beta1=beta1, beta2=beta2, sign=sign)])

Components

class TakensBogdanovElement(Element):
    """Normal form `x' = y`, `y' = beta1 + beta2 x + x^2 + sign x y` of the Takens-Bogdanov bifurcation.

    Args:
        label:
            The label of the element.

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

        x:
            The initial first coordinate.

        y:
            The initial second coordinate.

        beta1:
            The first unfolding parameter.

        beta2:
            The second unfolding parameter.

        sign:
            The sign of the term `x y`, 1 or -1.

    Examples:
        >>> from skcomplex.models.mathematics.dynamical_systems import TakensBogdanovElement
        >>> TakensBogdanovElement('form', beta1=0.0).beta1
        0.0
    """

    def __init__(
        self,
        label: str,
        visual: VisualSpec | None = None,
        *,
        x: Annotated[object, StateSpec()] = 0.2,
        y: Annotated[object, StateSpec()] = 0.0,
        beta1: Annotated[object, ParameterSpec()] = 0.1,
        beta2: Annotated[object, ParameterSpec()] = -1.0,
        sign: Annotated[object, ParameterSpec()] = -1.0,
    ) -> None:
        super().__init__(label, visual=visual)
        self.x = x
        self.y = y
        self.beta1 = beta1
        self.beta2 = beta2
        self.sign = sign

    def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
        """Return the rates of the two coordinates.

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

        Returns:
            laws:
                The laws of the element.
        """
        return [RateLaw(s.x, s.y), RateLaw(s.y, s.beta1 + s.beta2 * s.x + s.x**2 + s.sign * s.x * s.y)]

Equations

form.x: diff(x_form(t), t) == y_form(t)
form.y: diff(y_form(t), t) == sign_form*x_form(t)*y_form(t) + beta2_form*x_form(t) + x_form(t)^2 + beta1_form