Skip to content

Oscillators

Oscillator realizations shared by the physics packages: phase and Stuart-Landau oscillators.

KuramotoCouplingInteraction(label, *, target, source=None, K=1.0, alpha=0.0, state='theta', reduce='sum', mode='edges', weights=None, include_self=False, delay=0.0, neighborhood=None, layer=None)

Bases: CouplingInteraction

Kuramoto coupling theta_i' += K sum_j sin(theta_j - theta_i - alpha) of the phases of a group.

The sum, or the mean, runs over the members j that the mode selects: the neighbours along the edges of a lattice or network, or within a neighbourhood such as RadiusNeighborhood(r), every other member of the group, every member of a separate source group, or the next member. With include_self it also runs over j = i, whose term -K sin(alpha) slows every phase. Over the whole group without weights or delay, the coupling reads the group sums of sin theta and cos theta once, so it costs time linear in the size of the group.

Parameters:

Name Type Description Default
label str

The label of the interaction, unique among the parts of its system.

required
target Annotated[str, RoleSpec()]

The path of the group of oscillators.

required
source Annotated[str | None, RoleSpec(optional=True)]

The path of the group of oscillators the target couples to in the mode 'group', or None for the target.

None
K Annotated[float, ParameterSpec()]

The coupling strength of one pair.

1.0
alpha Annotated[float, ParameterSpec()]

The phase lag.

0.0
state str

The name of the state that holds the phases.

'theta'
reduce str

'sum' or 'mean'.

'sum'
mode str

'edges', 'group', or 'next'.

'edges'
weights str | ArrayLike | sparray | None

The name of the state of the edge group in the mode 'edges', a matrix in the mode 'group', or None.

None
include_self bool

Whether the sum also runs over the member itself.

False
delay float

The delay of the phases of the other members, 0 for none.

0.0
neighborhood BaseNeighborhood | None

The neighbourhood of the mode 'edges', or None for the edges of the lattice or network.

None
layer str | None

The layer of the network whose edges the interaction runs on, or None for the graph of the network.

None

Examples:

>>> import numpy as np
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.core.system import System
>>> from skcomplex.engine.runtime import Simulation
>>> from skcomplex.models.physics.common.oscillators import (
...     KuramotoCouplingInteraction,
...     PhaseOscillatorElement,
... )
>>> phases = GroupElement('phases', element=PhaseOscillatorElement, size=4, values={'theta': [0, 1, 2, 3]})
>>> coupling = KuramotoCouplingInteraction('coupling', target='phases', K=2.0, mode='group', reduce='mean')
>>> system = System(elements=[phases], interactions=[coupling])
>>> theta = Simulation(system, dt=1.0).check().prepare().run(until=20.0).trajectory_.values('phases.theta')
>>> round(float(np.ptp(theta[-1])), 6)
0.0
Source code in src/skcomplex/models/physics/common/oscillators/_kuramoto_coupling.py
 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
def __init__(
    self,
    label: str,
    *,
    target: Annotated[str, RoleSpec()],
    source: Annotated[str | None, RoleSpec(optional=True)] = None,
    K: Annotated[float, ParameterSpec()] = 1.0,
    alpha: Annotated[float, ParameterSpec()] = 0.0,
    state: str = 'theta',
    reduce: str = 'sum',
    mode: str = 'edges',
    weights: str | npt.ArrayLike | scipy.sparse.sparray | None = None,
    include_self: bool = False,
    delay: float = 0.0,
    neighborhood: BaseNeighborhood | None = None,
    layer: str | None = None,
) -> None:
    super().__init__(
        label,
        target=target,
        source=source,
        read=state,
        write=state,
        function=self._sine,
        reduce=reduce,
        mode=mode,
        weights=weights,
        include_self=include_self,
        delay=delay,
        neighborhood=neighborhood,
        layer=layer,
    )
    self.K = K
    self.alpha = alpha
    self.state = state

PhaseOscillatorElement(label, visual=None, *, theta=0.0, omega=1.0)

Bases: Element

Phase oscillator, a phase theta that turns at its natural frequency, theta' = omega.

Couplings to other oscillators add to the rate of the phase.

Parameters:

Name Type Description Default
label str

The label of the oscillator or the group.

required
visual VisualSpec | None

How the oscillator is drawn, or None for default_visual_.

None
theta Annotated[float, StateSpec(role=phase)]

The initial phase.

0.0
omega Annotated[float, ParameterSpec()]

The natural frequency.

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.common.oscillators import PhaseOscillatorElement
>>> system = System(elements=[PhaseOscillatorElement('clock', omega=2.0)])
>>> float(Simulation(system, dt=0.5).check().prepare().run(until=1.0).trajectory_.values('clock.theta')[-1])
2.0
Source code in src/skcomplex/models/physics/common/oscillators/_phase_oscillator.py
45
46
47
48
49
50
51
52
53
54
55
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    theta: Annotated[float, StateSpec(role='phase')] = 0.0,
    omega: Annotated[float, ParameterSpec()] = 1.0,
) -> None:
    super().__init__(label, visual=visual)
    self.theta = theta
    self.omega = omega

SitedOscillatorElement(label, visual=None, *, theta=0.0, omega=1.0, x=0.0)

Bases: PhaseOscillatorElement

Phase oscillator with a place x in a continuous space, which couplings within a distance or swarming read.

The phase turns at the natural frequency, and the place changes only by the rates of interactions.

Parameters:

Name Type Description Default
label str

The label of the oscillator or the group.

required
visual VisualSpec | None

How the oscillator is drawn, or None for default_visual_.

None
theta float

The initial phase.

0.0
omega float

The natural frequency.

1.0
x Annotated[ArrayLike, StateSpec(vector=True, role=site)]

The initial place. A number applies to every component.

0.0

Attributes:

Name Type Description
default_visual_

The visual of the oscillator when it sets none.

Examples:

>>> from skcomplex.models.physics.common.oscillators import SitedOscillatorElement
>>> SitedOscillatorElement('unit', x=[0.0, 1.0]).x
[0.0, 1.0]
Source code in src/skcomplex/models/physics/common/oscillators/_sited_oscillator.py
45
46
47
48
49
50
51
52
53
54
55
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    theta: float = 0.0,
    omega: float = 1.0,
    x: Annotated[npt.ArrayLike, StateSpec(vector=True, role='site')] = 0.0,
) -> None:
    super().__init__(label, visual=visual, theta=theta, omega=omega)
    self.x = x

StuartLandauElement(label, visual=None, *, x=1.0, y=0.0, mu=1.0, omega=1.0, beta=0.0, kappa=1.0, tau=1.0)

Bases: Element

Stuart-Landau oscillator z' = tau ((mu + i omega) z - kappa (1 + i beta) |z|^2 z) of z = x + i y.

It is the normal form of a supercritical Hopf bifurcation. For mu > 0 the oscillator settles on the limit cycle of radius sqrt(mu / kappa), which it turns at the frequency tau (omega - beta mu), and for mu < 0 it decays to the fixed point 0. The twist beta makes the frequency depend on the amplitude, and the time scale tau speeds up or slows down the whole flow.

Parameters:

Name Type Description Default
label str

The label of the oscillator or the group.

required
visual VisualSpec | None

How the oscillator is drawn, or None for default_visual_.

None
x Annotated[float, StateSpec()]

The initial real part of z.

1.0
y Annotated[float, StateSpec()]

The initial imaginary part of z.

0.0
mu Annotated[float, ParameterSpec()]

The growth rate of the fixed point 0, the bifurcation parameter.

1.0
omega Annotated[float, ParameterSpec()]

The frequency of the linear rotation.

1.0
beta Annotated[float, ParameterSpec()]

The twist, the shear of the frequency with the amplitude.

0.0
kappa Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The strength of the cubic saturation.

1.0
tau Annotated[float, ParameterSpec(domain=open(0, oo))]

The time scale.

1.0

Attributes:

Name Type Description
default_visual_

The visual of the oscillator when it sets none.

Examples:

>>> import math
>>> from skcomplex.core.system import System
>>> from skcomplex.engine.runtime import Simulation
>>> from skcomplex.models.physics.common.oscillators import StuartLandauElement
>>> system = System(elements=[StuartLandauElement('oscillator', x=0.1, mu=4.0)])
>>> trajectory = Simulation(system, dt=0.5).check().prepare().run(until=10.0).trajectory_
>>> round(math.hypot(trajectory.values('oscillator.x')[-1], trajectory.values('oscillator.y')[-1]), 4)
2.0
Source code in src/skcomplex/models/physics/common/oscillators/_stuart_landau.py
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    x: Annotated[float, StateSpec()] = 1.0,
    y: Annotated[float, StateSpec()] = 0.0,
    mu: Annotated[float, ParameterSpec()] = 1.0,
    omega: Annotated[float, ParameterSpec()] = 1.0,
    beta: Annotated[float, ParameterSpec()] = 0.0,
    kappa: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    tau: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
) -> None:
    super().__init__(label, visual=visual)
    self.x = x
    self.y = y
    self.mu = mu
    self.omega = omega
    self.beta = beta
    self.kappa = kappa
    self.tau = tau