Skip to content

Chua double and multiple scrolls

Chua's circuit, whose double-scroll or multiscroll attractor is chaotic.

  • Name: chua
  • Field: engineering/circuits
  • Formalism: ordinary differential equations
  • References: Chua, Komuro, and Matsumoto 1986; Tang et al. 2001; Trzaska 2023

The chua example

Example

Factory

@register_model(
    field='engineering/circuits',
    tags=('circuit', 'chaos', 'ode', 'attractor'),
    references=('Chua, Komuro, and Matsumoto 1986', 'Tang et al. 2001', 'Trzaska 2023'),
    defaults={'until': 100.0, 'dt': 0.05},
)
def chua(
    x: float | None = None,
    y: float | None = None,
    z: float = 0.0,
    *,
    nonlinearity: str = 'piecewise-linear',
    alpha: float | None = None,
    beta: float | None = None,
) -> System:
    """Return Chua's circuit, whose double-scroll or multiscroll attractor is chaotic.

    The voltages of the two capacitors and the current of the inductor, in dimensionless form, follow
    `x' = alpha (y - f(x))`, `y' = x - y + z`, and `z' = -β y`. The piecewise-linear diode has
    `f(x) = x + m1 x + (m0 - m1) (|x + 1| - |x - 1|) / 2`, which gives the double scroll. The sine diode has
    `f(x) = -b sin(π x / (2 a))`, continued linearly beyond `|x| = 2 a c`, which gives several scrolls side by side.

    Args:
        x:
            The initial voltage of the first capacitor, or `None` for 0.1 with the piecewise-linear diode and 1 with
            the sine diode.

        y:
            The initial voltage of the second capacitor, or `None` for 0 with the piecewise-linear diode and 1 with the
            sine diode.

        z:
            The initial current of the inductor.

        nonlinearity:
            The characteristic of the diode, `'piecewise-linear'` for the double scroll or `'sine'` for multiple
            scrolls.

        alpha:
            The ratio of the capacitances, or `None` for 15.6 with the piecewise-linear diode and 10.82 with the sine
            diode.

        beta:
            The ratio of the inductance to the second capacitance, or `None` for 28 with the piecewise-linear diode and
            14.286 with the sine diode.

    Returns:
        system:
            The model, with the states `circuit.x`, `circuit.y`, and `circuit.z`.

    Raises:
        ParameterError:
            The nonlinearity is neither `'piecewise-linear'` nor `'sine'`.

    Examples:
        >>> from skcomplex.models.engineering.circuits import chua
        >>> chua(nonlinearity='sine').elements[0].alpha
        10.82
    """
    if nonlinearity not in CHUA_NONLINEARITIES:
        error_msg = f"Unknown nonlinearity {nonlinearity!r}. Use 'piecewise-linear' or 'sine'."
        raise ParameterError(error_msg)
    element = ChuaCircuitElement if nonlinearity == 'piecewise-linear' else MultiscrollChuaCircuitElement
    initial = {'x': x, 'y': y, 'alpha': alpha, 'beta': beta}
    values: dict[str, float] = {name: value for name, value in initial.items() if value is not None}
    return System(elements=[element('circuit', z=z).set_params(**values)])

Components

class ChuaCircuitElement(Element):
    """Chua circuit with the piecewise-linear current of its diode."""

    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,
        alpha: Annotated[object, ParameterSpec(domain=RealSet.open(0, oo))] = 15.6,
        beta: Annotated[object, ParameterSpec(domain=RealSet.open(0, oo))] = 28.0,
        m0: Annotated[object, ParameterSpec()] = -8 / 7,
        m1: Annotated[object, ParameterSpec()] = -5 / 7,
    ) -> None:
        super().__init__(label, visual=visual)
        self.x = x
        self.y = y
        self.z = z
        self.alpha = alpha
        self.beta = beta
        self.m0 = m0
        self.m1 = m1

    def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
        """Return the rates of the states of the circuit."""
        return [
            RateLaw(s.x, s.alpha * (s.y - s.x - s.m1 * s.x - (s.m0 - s.m1) * (abs(s.x + 1) - abs(s.x - 1)) / 2)),
            RateLaw(s.y, s.x - s.y + s.z),
            RateLaw(s.z, -s.beta * s.y),
        ]

Equations

circuit.x: diff(x_circuit(t), t) == -1/2*((m0_circuit - m1_circuit)*(abs(x_circuit(t) + 1) - abs(x_circuit(t) - 1)) + 2*m1_circuit*x_circuit(t) + 2*x_circuit(t) - 2*y_circuit(t))*alpha_circuit
circuit.y: diff(y_circuit(t), t) == x_circuit(t) - y_circuit(t) + z_circuit(t)
circuit.z: diff(z_circuit(t), t) == -beta_circuit*y_circuit(t)