Thomas cyclically symmetric attractor
The Thomas flow x' = -a x + sin y with its cyclic permutations, chaotic for a = 0.18.
- Name:
thomas - Field:
mathematics/dynamical_systems - Formalism: ordinary differential equations
- References: Thomas 1999; Dilão 2023
Select this system
from skcomplex.systems import create_simulation, create_system, describe
system = create_system('thomas')
entry = describe('thomas')
trajectory = create_simulation('thomas').prepare().run().trajectory_
Factory
@register_system(
field='mathematics/dynamical_systems',
tags=('chaos', 'ode', 'cyclic symmetry', 'strange attractor'),
references=('Thomas 1999', 'Dilão 2023'),
defaults={'until': 500.0, 'dt': 0.1},
)
def thomas(x: float = 0.1, y: float = 0.0, z: float = 0.0, *, a: float = 0.18) -> System:
"""Return the Thomas flow `x' = -a x + sin y` with its cyclic permutations, chaotic for `a = 0.18`.
The flow is symmetric under the cyclic permutation of its coordinates. As the damping `a` falls the fixed points
give way to limit cycles and then to chaos, and at `a = 0` the orbits wander through a lattice of cells, Thomas's
labyrinth chaos (Dilão 2023, Exercise 3.23).
Args:
x:
The initial first coordinate.
y:
The initial second coordinate.
z:
The initial third coordinate.
a:
The damping of every coordinate.
Returns:
system:
The system, with the states `thomas.x`, `thomas.y`, and `thomas.z`.
Examples:
>>> from skcomplex.systems.mathematics.dynamical_systems import thomas
>>> thomas(a=0.2).elements[0].a
0.2
"""
return System(elements=[ThomasElement('thomas', x=x, y=y, z=z, a=a)])
Components
Elements:
ThomasElement, fromElement
class ThomasElement(Element):
"""Thomas flow `x' = -a x + sin y`, `y' = -a y + sin z`, `z' = -a z + sin x`, cyclically symmetric and damped.
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.
z:
The initial third coordinate.
a:
The damping of every coordinate.
Examples:
>>> from skcomplex.systems.mathematics.dynamical_systems import ThomasElement
>>> ThomasElement('thomas', a=0.2).a
0.2
"""
def __init__(
self,
label: str,
visual: VisualSpec | None = None,
*,
x: Annotated[object, StateSpec()] = 0.1,
y: Annotated[object, StateSpec()] = 0.0,
z: Annotated[object, StateSpec()] = 0.0,
a: Annotated[object, ParameterSpec()] = 0.18,
) -> None:
super().__init__(label, visual=visual)
self.x = x
self.y = y
self.z = z
self.a = a
def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
"""Return the rates of the three coordinates.
Args:
s:
The namespace of the symbols the laws can use.
Returns:
laws:
The laws of the element.
"""
return [
RateLaw(s.x, -s.a * s.x + sin(s.y)),
RateLaw(s.y, -s.a * s.y + sin(s.z)),
RateLaw(s.z, -s.a * s.z + sin(s.x)),
]
Equations
thomas.x: diff(x_thomas(t), t) == -a_thomas*x_thomas(t) + sin(y_thomas(t))
thomas.y: diff(y_thomas(t), t) == -a_thomas*y_thomas(t) + sin(z_thomas(t))
thomas.z: diff(z_thomas(t), t) == -a_thomas*z_thomas(t) + sin(x_thomas(t))