PL. 75 · ATTRACTORS / FORCED OSCILLATOR / SECTION
Ueda Attractor
Yoshisuke Ueda, 1961
OPEN THE LIVE PLATE ▸DEFINITION
ẍ + k·ẋ + x³ = B·cos t the Poincaré section: (x, ẋ) sampled once per drive period k = 0.05, B = 7.5 is Ueda’s own set
NOTES
The oldest recorded strange attractor, and nobody was allowed to say so. On 27 November 1961 Ueda — a third-year graduate student at Kyoto — was running a forced Duffing oscillator on an analog computer and got a trace that never settled. He called it a randomly transitional phenomenon. His supervisor Chihiro Hayashi told him it was a transient still taking its time, the way a real resonance circuit lingers, and did not let him publish; the work did not appear until 1970. What the plate draws is the section rather than the trajectory, because the fractal is only visible once per drive period — the shredded, layered sheet that convinced Ueda he was not looking at noise.
PROVENANCE
- Origin
- Y. Ueda, Kyoto University, 27 November 1961, in Chihiro Hayashi’s laboratory; publication was withheld until 1970. Recounted in Ueda’s "The Road to Chaos". The system is the forced Duffing oscillator; the attractor is often called the Japanese attractor
- Standing
- Public domain — a differential equation and its Poincaré section
- Constants
- Both ranges are measured, not declared: k lives in 0.015–0.08 and B in 6.9–8.1 around Ueda’s own pair, and outside those the section collapses to a few periodic points — a true picture of a different system and an empty plate of this one. Even inside them about one jittered pair in eight is periodic, so both are LOCKED. The window is measured too: the union of the section’s extent across the whole live band. x and ẋ carry different units, so there is no natural aspect and the figure is scaled to fill the frame, as published sections of it are
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. 75 · UEDA ATTRACTOR — Yoshisuke Ueda, 1961
// ẍ + k·ẋ + x³ = B·cos t
// the Poincaré section: (x, ẋ) sampled once per drive period
// k = 0.05, B = 7.5 is Ueda’s own set
// 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=ueda
float p_k = 0.05 + chf('k_tweak'); // k — damping · live 0.02 .. 0.078
float p_B = 7.5 + chf('B_tweak'); // B — drive · live 6.95 .. 8.05
// 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)));
}
// The Poincaré section of the driven Duffing oscillator: integrate one drive
// period of 2π, keep one point, repeat. RK4 rather than Euler — the cubic
// restoring term is stiff enough near the turning points that a first-order
// step drifts off the sheet and draws a band fatter than the system has.
// 32 substeps a period and 200 settle periods, as the plate measured.
int forma_sec = 30000; // section points
int forma_settle = 200; // drive periods of transient to discard
int forma_sub = 32; // RK4 substeps per period
vector2 forma_f(float tt, xx, yy, k, B){
return set(yy, -k * yy - xx * xx * xx + B * cos(tt));
}
float x = 0.1, y = 0.1;
float dt = 6.28318530718 / float(forma_sub);
for (int n = 0; n < forma_sec + forma_settle; n++){
// VEX floats are 32-bit: a running clock loses the drive phase by the
// thousandth period, smearing the section. The drive is 2π-periodic, so
// the phase restarts at zero each period — exact by construction.
float tt = 0.0;
for (int i = 0; i < forma_sub; i++){
vector2 a = forma_f(tt, x, y, p_k, p_B);
vector2 b = forma_f(tt + dt / 2.0, x + a.x * dt / 2.0, y + a.y * dt / 2.0, p_k, p_B);
vector2 c = forma_f(tt + dt / 2.0, x + b.x * dt / 2.0, y + b.y * dt / 2.0, p_k, p_B);
vector2 d = forma_f(tt + dt, x + c.x * dt, y + c.y * dt, p_k, p_B);
x += dt / 6.0 * (a.x + 2.0 * b.x + 2.0 * c.x + d.x);
y += dt / 6.0 * (a.y + 2.0 * b.y + 2.0 * c.y + d.y);
tt += dt;
}
// the walk onto the attractor is not the attractor
if (n < forma_settle) continue;
// canvas y runs down; negated so the section sits as the plate shows it
int pt = addpoint(0, set(x, -y, 0.0));
float u = float(n - forma_settle) / float(forma_sec);
setpointattrib(0, "Cd", pt, forma_ramp(0.8 + 0.3 * u));
}