PL. 77 · ATTRACTORS / CIRCUIT / DOUBLE SCROLL
Chua’s Circuit
Leon O. Chua, 1983 · simulated by Takashi Matsumoto
OPEN THE LIVE PLATE ▸DEFINITION
ẋ = α(y − x − f(x)) ẏ = x − y + z ż = −β·y f(x) = m₁x + ½(m₀ − m₁)(|x+1| − |x−1|)
NOTES
The first chaotic system built deliberately rather than stumbled upon. Chua wanted a circuit that provably had to be chaotic, and the trick is one nonlinear component — a resistor whose current-voltage curve bends the wrong way, in three straight segments. Two unstable equilibria, one on each outer segment, and the trajectory winds out around one until it falls into the basin of the other: the double scroll. Matsumoto ran the simulation that first showed it, on Chua’s instructions, days before Chua went into surgery.
PROVENANCE
- Origin
- L. O. Chua, 1983, devised while visiting Waseda University; the chaotic behaviour was first exhibited in T. Matsumoto’s numerical simulation the same year. The double scroll is the canonical attractor of the dimensionless system above
- Standing
- Public domain — a system of differential equations. This plate implements only those; whether any physical realisation of the circuit was ever patented is a separate question and not one this plate depends on
- Constants
- α = 15.6, β = 28 with diode slopes m₀ = −1.143, m₁ = −0.714 is the classic double-scroll set. The slopes are LOCKED from regenerate: they set the sign structure of the nonlinearity, and jitter across a segment boundary yields a fixed point rather than an attractor
- Source
- doi:10.1109/TCS.1984.1085459
HOUDINI · VEX
The same published mathematics as a Detail Wrangle body. Paste it into a Wrangle with Run Over set to Detail; every constant is the published value plus a tweak channel, so Create Spare Parameters gives a slider that starts where the paper does.
// FORMA — PL. 77 · CHUA’S CIRCUIT — Leon O. Chua, 1983 · simulated by Takashi Matsumoto
// ẋ = α(y − x − f(x))
// ẏ = x − y + z
// ż = −β·y
// f(x) = m₁x + ½(m₀ − m₁)(|x+1| − |x−1|)
// Paste into a Detail Wrangle (Run Over: Detail), no inputs needed.
// Written from the published mathematics, not adapted from any code.
// Constants arrive at their published values. Press the node's Create
// Spare Parameters button and every tweak becomes a slider — starting
// at 0, the published figure, and moving in the constant's own units.
// https://forma-gen.com/#plate=chua
float p_alpha = 15.6 + chf('alpha_tweak'); // α — C₂/C₁ · live 8.5 .. 18
float p_beta = 28 + chf('beta_tweak'); // β — inductance · live 20 .. 36
float p_m0 = -1.143 + chf('m0_tweak'); // m₀ — inner slope · live -1.35 .. -0.95
float p_m1 = -0.714 + chf('m1_tweak'); // m₁ — outer slope · live -0.85 .. -0.58
// The plate's own colour: FORMA's ATTRACTORS accent as a cosine ramp,
// brightest near t = 0 and t = 1, near-black around t = 0.5.
vector forma_ramp(float t){
return set(
0.0956 + 0.1039 * cos(6.28318530718 * (t + 0)),
0.4041 + 0.4392 * cos(6.28318530718 * (t + 0.05)),
0.46 + 0.5 * cos(6.28318530718 * (t + 0.1)));
}
// Euler integration matching the plate: dt = 0.0025, 30000 steps from
// (0.7, 0, 0), the first 3000 discarded as transient. Axes are the published
// state unchanged — note the plate scales y sixfold for display, because y
// runs an order thinner than x and z; scale to taste.
int forma_steps = 30000;
int forma_skip = 3000;
float forma_dt = 0.0025;
float x = 0.7, y = 0.0, z = 0.0;
int prim = addprim(0, "polyline");
for (int i = 0; i < forma_steps; i++){
// Chua's diode: three straight segments, and the middle one is the
// negative resistance that makes the whole thing go
float fx = p_m1 * x + 0.5 * (p_m0 - p_m1) * (abs(x + 1.0) - abs(x - 1.0));
float dx = p_alpha * (y - x - fx);
float dy = x - y + z;
float dz = -p_beta * y;
x += dx * forma_dt; y += dy * forma_dt; z += dz * forma_dt;
if (!isfinite(x) || !isfinite(z)) break;
if (i <= forma_skip) continue;
int pt = addpoint(0, set(x, y, z));
// colour sweeps the bright lobe of the ramp along the path
float u = float(i - forma_skip) / float(forma_steps - forma_skip);
setpointattrib(0, "Cd", pt, forma_ramp(0.8 + 0.3 * u));
addvertex(0, prim, pt);
}
AFTER EFFECTS · EXPRESSION
The same published mathematics as a Shape Layer path expression. Paste it onto a Path property; every constant is the published value plus a Slider Control named
// FORMA — PL. 77 · CHUA’S CIRCUIT — Leon O. Chua, 1983 · simulated by Takashi Matsumoto
// ẋ = α(y − x − f(x))
// ẏ = x − y + z
// ż = −β·y
// f(x) = m₁x + ½(m₀ − m₁)(|x+1| − |x−1|)
// After Effects port — paste onto a Shape Layer's Path property
// (Contents › Shape › Path). Written from the published mathematics, not
// adapted from any code. Constants arrive at their published values; add a
// Slider Control (Effect › Expression Controls) named <k>_tweak and that
// constant moves in its own units, starting at 0 — the published figure.
// The plate's comet and its reveal are Trim Paths; the stroke colour is
// FORMA's ATTRACTORS accent, #35E0FF. Animation runs on time.
// https://forma-gen.com/#plate=chua
// A missing slider reads 0, so a bare paste already draws the figure.
function forma_tweak(n){ try { return effect(n)("Slider"); } catch (e){ return 0; } }
var p_alpha = 15.6 + forma_tweak("alpha_tweak"); // α — C₂/C₁ · live 8.5 .. 18
var p_beta = 28 + forma_tweak("beta_tweak"); // β — inductance · live 20 .. 36
var p_m0 = -1.143 + forma_tweak("m0_tweak"); // m₀ — inner slope · live -1.35 .. -0.95
var p_m1 = -0.714 + forma_tweak("m1_tweak"); // m₁ — outer slope · live -0.85 .. -0.58
// The frame: the plate's W × H canvas is this comp, with the origin at the
// layer's anchor; canvas y already runs down, as After Effects' does.
var forma_W = thisComp.width, forma_H = thisComp.height, forma_t = time;
var forma_phase = 0.4315276483539492; // this plate's own fixed phase, as the page has it
function forma_pt(x, y){ return [x - forma_W / 2, y - forma_H / 2]; }
// Euler integration of Chua's circuit, the plate's own 30,000 steps of
// dt = 0.0025 from (0.7, 0, 0), the first 3,000 discarded. The diode is three
// straight segments — f(x) = m₁x + ½(m₀ − m₁)(|x + 1| − |x − 1|) — and the
// middle one is the negative resistance that makes the whole thing go. y is
// an order thinner than x and z, so it is stretched ×6 as the page does. The
// page's view: the x–y plane turns at 0.11 rad/s, z is the screen vertical,
// 1/11 of the shorter side. Every second point is emitted.
var x = 0.7, y = 0, z = 0, dt = 0.0025;
var rot = forma_t * 0.11, co = Math.cos(rot), si = Math.sin(rot);
var s = Math.min(forma_W, forma_H) / 11, cx = forma_W / 2, cy = forma_H / 2;
var pts = [];
for (var i = 0; i < 30000; i++){
var fx = p_m1 * x + 0.5 * (p_m0 - p_m1) * (Math.abs(x + 1) - Math.abs(x - 1));
var dx = p_alpha * (y - x - fx);
var dy = x - y + z;
var dz = -p_beta * y;
x += dx * dt; y += dy * dt; z += dz * dt;
if (!isFinite(x) || !isFinite(z)) break;
if (i > 3000 && (i & 1) === 0){
var yy = y * 6;
pts.push(forma_pt(cx + (x * co + yy * si) * s, cy - z * s));
}
}
createPath(pts, [], [], false);