Saddle-node
The saddle-node normal form x' = μ - x², whose two equilibria ±√μ meet and vanish at μ = 0.
- Name:
saddle_node_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'),
references=('Gros 2015', 'Dilão 2023'),
defaults={'until': 10.0, 'dt': 0.05},
)
def saddle_node_form(x: float = 0.0, *, mu: float = 1.0) -> System:
"""Return the saddle-node normal form `x' = μ - x²`, whose two equilibria `±√μ` meet and vanish at μ = 0.
Args:
x:
The initial value.
mu:
The bifurcation parameter.
Returns:
system:
The model, with the state `form.x`.
Examples:
>>> from skcomplex.models.mathematics.dynamical_systems import saddle_node_form
>>> saddle_node_form(mu=0.5).elements[0].mu
0.5
"""
return System(elements=[SaddleNodeElement('form', x=x, mu=mu)])
Components
class SaddleNodeElement(Element):
"""Normal form `x' = mu - x^2` of the saddle-node bifurcation.
Args:
label:
The label of the element.
visual:
How the element is drawn, or `None` for `default_visual_`.
x:
The initial value.
mu:
The bifurcation parameter.
Examples:
>>> from skcomplex.models.mathematics.dynamical_systems import SaddleNodeElement
>>> SaddleNodeElement('form', mu=-1.0).mu
-1.0
"""
def __init__(
self,
label: str,
visual: VisualSpec | None = None,
*,
x: Annotated[object, StateSpec()] = 0.0,
mu: Annotated[object, ParameterSpec()] = 1.0,
) -> None:
super().__init__(label, visual=visual)
self.x = x
self.mu = mu
def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
"""Return the rate of the value.
Args:
s:
The namespace of the symbols the laws can use.
Returns:
laws:
The laws of the element.
"""
return [RateLaw(s.x, s.mu - s.x**2)]
Equations
form.x: diff(x_form(t), t) == -x_form(t)^2 + mu_form