Nonlinear oscillators
Nonlinear oscillators: Duffing, Van der Pol, Stuart-Landau, Adler, billiards, and Hamiltonian chaos.
AdlerPhaseElement(label, visual=None, *, phi=0.0, detuning=0.5, epsilon=1.0)
Bases: Element
Phase difference of a forced oscillator, phi' = detuning + epsilon sin(phi), the Adler equation.
The phase locks at a fixed point when |detuning| <= epsilon, and slips with the period
2 pi / sqrt(detuning^2 - epsilon^2) otherwise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the phase difference. |
required |
visual
|
VisualSpec | None
|
How the phase difference is drawn, or |
None
|
phi
|
Annotated[float, StateSpec()]
|
The initial phase difference. |
0.0
|
detuning
|
Annotated[float, ParameterSpec()]
|
The detuning of the natural frequency from the forcing. |
0.5
|
epsilon
|
Annotated[float, ParameterSpec()]
|
The strength of the forcing. |
1.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
default_visual_ |
The visual of the phase difference when it sets none. |
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import AdlerPhaseElement
>>> AdlerPhaseElement('difference').detuning
0.5
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_adler_phase.py
48 49 50 51 52 53 54 55 56 57 58 59 60 | |
DuffingElement(label, visual=None, *, x=1.0, x_d1=0.0, delta=0.3, alpha=-1.0, beta=1.0, gamma=0.5, omega=1.2)
Bases: Element
Displacement and parameters of the forced Duffing oscillator, whose acceleration a RateInteraction sets.
The acceleration is x'' = -delta x' - alpha x - beta x^3 + gamma cos(omega t).
For alpha < 0 < beta the potential has two wells, and a strong enough forcing drives the oscillator chaotically
between them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the oscillator. |
required |
visual
|
VisualSpec | None
|
How the oscillator is drawn, or |
None
|
x
|
Annotated[float, StateSpec(order=2)]
|
The initial displacement. |
1.0
|
x_d1
|
float
|
The initial velocity. |
0.0
|
delta
|
Annotated[float, ParameterSpec()]
|
The damping. |
0.3
|
alpha
|
Annotated[float, ParameterSpec()]
|
The linear stiffness. |
-1.0
|
beta
|
Annotated[float, ParameterSpec()]
|
The cubic stiffness. |
1.0
|
gamma
|
Annotated[float, ParameterSpec()]
|
The amplitude of the forcing. |
0.5
|
omega
|
Annotated[float, ParameterSpec()]
|
The frequency of the forcing. |
1.2
|
Attributes:
| Name | Type | Description |
|---|---|---|
default_visual_ |
The visual of the oscillator when it sets none. |
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import DuffingElement
>>> DuffingElement('duffing').alpha
-1.0
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_duffing.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
HenonHeilesElement(label, visual=VisualSpec('bodies', {'positions': ('x', 'y'), 'trail': None}), *, x=0.0, y=0.1, px=0.35, py=0.0)
Bases: Element
Star in the Hénon-Heiles potential V = (x^2 + y^2) / 2 + x^2 y - y^3 / 3, with the canonical momenta px, py.
The coordinates and the momenta are states of order 1, which a Hamiltonian interaction moves. Below the escape
energy 1 / 6 the motion is regular for small energies and mostly chaotic near the escape energy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the star. |
required |
visual
|
VisualSpec | None
|
How the star is drawn. |
VisualSpec('bodies', {'positions': ('x', 'y'), 'trail': None})
|
x
|
Annotated[float, StateSpec()]
|
The initial first coordinate. |
0.0
|
y
|
Annotated[float, StateSpec()]
|
The initial second coordinate. |
0.1
|
px
|
Annotated[float, StateSpec()]
|
The initial first momentum. |
0.35
|
py
|
Annotated[float, StateSpec()]
|
The initial second momentum. |
0.0
|
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import HenonHeilesElement
>>> HenonHeilesElement('star').px
0.35
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_henon_heiles.py
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | |
MushroomBilliardElement(label, visual=None, *, x=0.1, y=0.6, vx=0.6, vy=0.8, radius=1.0, width=0.4, height=1.0)
Bases: Element
Free particle in a mushroom table: a half disc cap of radius radius on a stem of half width width.
The particle flies straight, and reflects specularly off the cap, the floor of the cap beside the stem, the walls of
the stem, and its floor at depth height. Its phase space mixes regular orbits that stay in the cap with chaotic
orbits that enter the stem.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the particle. |
required |
visual
|
VisualSpec | None
|
How the particle is drawn, or |
None
|
x
|
Annotated[float, StateSpec()]
|
The initial first coordinate. |
0.1
|
y
|
Annotated[float, StateSpec()]
|
The initial second coordinate. |
0.6
|
vx
|
Annotated[float, StateSpec()]
|
The initial first velocity. |
0.6
|
vy
|
Annotated[float, StateSpec()]
|
The initial second velocity. |
0.8
|
radius
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The radius of the cap. |
1.0
|
width
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The half width of the stem. |
0.4
|
height
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The height of the stem. |
1.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
default_visual_ |
The visual of the particle when it sets none. |
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import MushroomBilliardElement
>>> MushroomBilliardElement('ball').width
0.4
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_mushroom_billiard.py
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
SinaiBilliardElement(label, visual=VisualSpec('bodies', {'positions': ('x', 'y'), 'trail': None, 'outline': _sinai_walls}), *, x=0.1, y=0.6, vx=0.6, vy=0.8, size=1.0, radius=0.4)
Bases: Element
Free particle in a square table of half side size with a central disc of radius radius, the Sinai billiard.
The particle flies straight, and its specular reflections off the four walls and the disc make its motion ergodic and chaotic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the particle. |
required |
visual
|
VisualSpec | None
|
How the particle is drawn. |
VisualSpec('bodies', {'positions': ('x', 'y'), 'trail': None, 'outline': _sinai_walls})
|
x
|
Annotated[float, StateSpec()]
|
The initial first coordinate. |
0.1
|
y
|
Annotated[float, StateSpec()]
|
The initial second coordinate. |
0.6
|
vx
|
Annotated[float, StateSpec()]
|
The initial first velocity. |
0.6
|
vy
|
Annotated[float, StateSpec()]
|
The initial second velocity. |
0.8
|
size
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The half side of the square. |
1.0
|
radius
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The radius of the disc. |
0.4
|
Attributes:
| Name | Type | Description |
|---|---|---|
default_visual_ |
The visual of the particle when it sets none. |
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import SinaiBilliardElement
>>> SinaiBilliardElement('ball').radius
0.4
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_sinai_billiard.py
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
VanDerPolElement(label, visual=None, *, x=2.0, x_d1=0.0, mu=1.0, A=0.0, omega=1.0)
Bases: Element
Van der Pol oscillator x'' = mu (1 - x^2) x' - x + A cos(omega t), with an optional periodic forcing.
The damping is negative for small amplitudes and positive for large ones, so the unforced oscillator, A = 0,
settles on a limit cycle of amplitude near 2. A forcing of amplitude A and frequency omega locks it or drives it
quasiperiodically or chaotically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the oscillator. |
required |
visual
|
VisualSpec | None
|
How the oscillator is drawn, or |
None
|
x
|
Annotated[float, StateSpec(order=2)]
|
The initial displacement. |
2.0
|
x_d1
|
float
|
The initial velocity. |
0.0
|
mu
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The strength of the nonlinear damping. |
1.0
|
A
|
Annotated[float, ParameterSpec()]
|
The amplitude of the forcing. |
0.0
|
omega
|
Annotated[float, ParameterSpec()]
|
The frequency of the forcing. |
1.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
default_visual_ |
The visual of the oscillator when it sets none. |
Examples:
>>> from skcomplex.core.system import System
>>> from skcomplex.engine.runtime import Simulation
>>> from skcomplex.models.physics.nonlinear_oscillators import VanDerPolElement
>>> system = System(elements=[VanDerPolElement('oscillator', x=0.1)])
>>> trajectory = Simulation(system, dt=0.1).check().prepare().run(until=50.0).trajectory_
>>> round(float(abs(trajectory.values('oscillator.x')[-300:]).max()), 1)
2.0
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_van_der_pol.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
adler_equation(phi=0.0, *, detuning=0.5, epsilon=1.0)
Return the Adler equation Δφ' = Δω + ε sin Δφ for the phase difference of an oscillator and its drive.
The phase difference locks at a fixed point when |Δω| < ε, inside the Arnold tongue. Outside it, the phase slips
by 2π every 2π / sqrt(Δω² - ε²).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
phi
|
float
|
The initial phase difference. |
0.0
|
detuning
|
float
|
The frequency difference |
0.5
|
epsilon
|
float
|
The strength of the coupling. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the phase difference |
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import adler_equation
>>> adler_equation(detuning=2.0).elements[0].detuning
2.0
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_oscillators.py
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | |
billiards(shape='sinai', x=0.1, y=0.6, vx=0.6, vy=0.8, *, size=1.0, disc_radius=0.4, cap_radius=1.0, width=0.4, height=1.0)
Return a particle moving freely on a billiard table and reflecting specularly off its walls.
The Sinai table is the square [-size, size]² with a disc of radius disc_radius at its center, and its motion is
chaotic. The mushroom table is the upper half of a disc of radius cap_radius on a stem of half width width and
height height, and its phase space mixes regular orbits that stay in the cap with chaotic orbits that enter the
stem. Every bounce is an event, and the speed is conserved.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shape
|
str
|
|
'sinai'
|
x
|
float
|
The initial horizontal position. |
0.1
|
y
|
float
|
The initial vertical position. |
0.6
|
vx
|
float
|
The initial horizontal velocity. |
0.6
|
vy
|
float
|
The initial vertical velocity. |
0.8
|
size
|
float
|
The half side of the Sinai table. |
1.0
|
disc_radius
|
float
|
The radius of the disc of the Sinai table. |
0.4
|
cap_radius
|
float
|
The radius of the cap of the mushroom. |
1.0
|
width
|
float
|
The half width of the stem of the mushroom. |
0.4
|
height
|
float
|
The height of the stem of the mushroom. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the position |
Raises:
| Type | Description |
|---|---|
ValidationError
|
The shape is unknown. |
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import billiards
>>> type(billiards('mushroom').elements[0]).__name__
'MushroomBilliardElement'
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_billiards.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | |
duffing(x=1.0, v=0.0, *, delta=0.3, alpha=-1.0, beta=1.0, gamma=0.5, omega=1.2)
Return the forced Duffing oscillator x'' = -delta x' - alpha x - beta x^3 + gamma cos(omega t), chaotic here.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
The initial displacement. |
1.0
|
v
|
float
|
The initial velocity. |
0.0
|
delta
|
float
|
The damping. |
0.3
|
alpha
|
float
|
The linear stiffness, negative for a double well. |
-1.0
|
beta
|
float
|
The cubic stiffness. |
1.0
|
gamma
|
float
|
The amplitude of the forcing. |
0.5
|
omega
|
float
|
The angular frequency of the forcing. |
1.2
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the displacement |
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import duffing
>>> duffing(gamma=0.3).elements[0].gamma
0.3
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_oscillators.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | |
forced_van_der_pol(x=2.0, v=0.0, *, mu=1.0, A=1.0, omega=1.0)
Return the Van der Pol oscillator driven by a periodic force, x'' = μ (1 - x²) x' - x + A cos(ω t).
A strong enough force entrains the limit cycle, so the oscillator locks to the driving frequency inside Arnold tongues, and the motion can be quasiperiodic or chaotic outside them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
The initial displacement. |
2.0
|
v
|
float
|
The initial velocity. |
0.0
|
mu
|
float
|
The strength of the nonlinear damping. |
1.0
|
A
|
float
|
The amplitude of the force. |
1.0
|
omega
|
float
|
The angular frequency of the force. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the displacement |
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import forced_van_der_pol
>>> forced_van_der_pol(A=0.5).elements[0].A
0.5
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_oscillators.py
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | |
henon_heiles(x=0.0, y=0.1, px=0.35, py=0.0)
Return the Hénon-Heiles model of a star in a galactic potential, whose motion is chaotic at higher energies.
The star moves under the Hamiltonian H = (px² + py²) / 2 + (x² + y²) / 2 + x² y - y³ / 3, which is conserved.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
The initial first coordinate. |
0.0
|
y
|
float
|
The initial second coordinate. |
0.1
|
px
|
float
|
The initial first momentum. |
0.35
|
py
|
float
|
The initial second momentum. |
0.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the coordinates |
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import henon_heiles
>>> henon_heiles(px=0.3).elements[0].px
0.3
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_oscillators.py
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | |
stuart_landau(x=0.1, y=0.0, *, mu=1.0, omega=1.0, beta=0.0)
Return the Stuart-Landau oscillator z' = (μ + i ω) z - (1 + i β) |z|² z, the normal form of a Hopf bifurcation.
The complex amplitude z = x + i y is written as two real states. For μ > 0 every orbit except the origin
settles on the circle of radius sqrt(μ), turning at the frequency ω - β μ.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
The initial real part of the amplitude. |
0.1
|
y
|
float
|
The initial imaginary part of the amplitude. |
0.0
|
mu
|
float
|
The distance from the Hopf bifurcation. |
1.0
|
omega
|
float
|
The linear frequency. |
1.0
|
beta
|
float
|
The nonlinear frequency shift. |
0.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the real part |
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import stuart_landau
>>> stuart_landau(mu=0.5).elements[0].mu
0.5
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_oscillators.py
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | |
van_der_pol(x=2.0, v=0.0, *, mu=1.0)
Return the Van der Pol oscillator x'' = μ (1 - x²) x' - x, which settles on a limit cycle for μ > 0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
The initial displacement. |
2.0
|
v
|
float
|
The initial velocity. |
0.0
|
mu
|
float
|
The strength of the nonlinear damping. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the displacement |
Examples:
>>> from skcomplex.models.physics.nonlinear_oscillators import van_der_pol
>>> van_der_pol(mu=3.0).elements[0].mu
3.0
Source code in src/skcomplex/models/physics/nonlinear_oscillators/_oscillators.py
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | |