Nosé-Hoover oscillator
The Nosé-Hoover oscillator x' = y, y' = y z - x, z' = 1 - y², with tori next to a chaotic sea.
- Name:
nose_hoover - Field:
mathematics/dynamical_systems - Formalism: ordinary differential equations
- References: Hoover 1995; Datseris and Parlitz 2022
Select this system
from skcomplex.systems import create_simulation, create_system, describe
system = create_system('nose_hoover')
entry = describe('nose_hoover')
trajectory = create_simulation('nose_hoover').prepare().run().trajectory_
Factory
@register_system(
field='mathematics/dynamical_systems',
tags=('chaos', 'ode', 'conservative', 'thermostat', 'kam'),
references=('Hoover 1995', 'Datseris and Parlitz 2022'),
defaults={'until': 200.0, 'dt': 0.05},
)
def nose_hoover(x: float = 0.0, y: float = 0.1, z: float = 0.0) -> System:
"""Return the Nosé-Hoover oscillator `x' = y`, `y' = y z - x`, `z' = 1 - y²`, with tori next to a chaotic sea.
The flow conserves volume on average and its state space is mixed. From `(0, 1.549934227822898, 0)` the orbit is
periodic, from `(0, 1, 0)` it winds on a torus around that orbit, and from the default `(0, 0.1, 0)` it is chaotic
(Datseris and Parlitz 2022, Exercise 2.11). Since `z' = 1 - y²`, every bounded orbit has `<y²> = 1`.
Args:
x:
The initial position.
y:
The initial momentum.
z:
The initial friction of the thermostat.
Returns:
system:
The system, with the states `oscillator.x`, `oscillator.y`, and `oscillator.z`.
Examples:
>>> from skcomplex.systems.mathematics.dynamical_systems import nose_hoover
>>> nose_hoover(y=1.0).elements[0].y
1.0
"""
return System(elements=[NoseHooverElement('oscillator', x=x, y=y, z=z)])
Components
Elements:
NoseHooverElement, fromElement
class NoseHooverElement(Element):
"""Nosé-Hoover oscillator `x' = y`, `y' = y z - x`, `z' = 1 - y²`, a conservative flow with tori and chaos.
Args:
label:
The label of the element.
visual:
How the element is drawn, or `None` for `default_visual_`.
x:
The initial position.
y:
The initial momentum.
z:
The initial friction of the thermostat.
Examples:
>>> from skcomplex.systems.mathematics.dynamical_systems import NoseHooverElement
>>> NoseHooverElement('oscillator', y=1.0).y
1.0
"""
def __init__(
self,
label: str,
visual: VisualSpec | None = None,
*,
x: Annotated[object, StateSpec()] = 0.0,
y: Annotated[object, StateSpec()] = 0.1,
z: Annotated[object, StateSpec()] = 0.0,
) -> None:
super().__init__(label, visual=visual)
self.x = x
self.y = y
self.z = z
def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
"""Return the rates of the position, the momentum, and the friction.
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.y * s.z - s.x), RateLaw(s.z, 1 - s.y**2)]
Equations
oscillator.x: diff(x_oscillator(t), t) == y_oscillator(t)
oscillator.y: diff(y_oscillator(t), t) == y_oscillator(t)*z_oscillator(t) - x_oscillator(t)
oscillator.z: diff(z_oscillator(t), t) == -y_oscillator(t)^2 + 1