PL. 07 · ATTRACTORS / FLOW / DIFFERENTIAL
Lorenz Attractor
Edward Lorenz, 1963
OPEN THE LIVE PLATE ▸DEFINITION
ẋ = σ(y − x) ẏ = x(ρ − z) − y ż = xy − βz
NOTES
Lorenz was running a truncated weather model, restarted it from a rounded printout, and got a completely different forecast. The butterfly shape is the set the trajectory settles onto — bounded, never repeating, never crossing itself. This is the origin of the phrase "sensitive dependence on initial conditions".
PROVENANCE
- Origin
- E. N. Lorenz, "Deterministic Nonperiodic Flow", J. Atmos. Sci. 20, 1963
- Standing
- Public domain — a system of differential equations
- Constants
- σ=10, ρ=28, β=8/3 is the classic parameter set
- Source
- doi:10.1175/1520-0469(1963)020<0130:DNF>2.0.CO;2
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. 07 · LORENZ ATTRACTOR — Edward Lorenz, 1963
// ẋ = σ(y − x)
// ẏ = x(ρ − z) − y
// ż = xy − βz
// 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=lorenz
float p_sigma = 10 + chf('sigma_tweak'); // σ — Prandtl · live 4 .. 20
float p_rho = 28 + chf('rho_tweak'); // ρ — Rayleigh · live 14 .. 60
float p_beta = 2.667 + chf('beta_tweak'); // β — geometry · live 0.5 .. 5
// 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)));
}
// waived: view — the azimuth the finished attractor is viewed from, and Houdini has a camera of its own
// Euler integration matching the plate: dt = 0.005, 18000 steps, the first
// 400 discarded — the walk toward the attractor is not the attractor.
int forma_steps = 18000;
int forma_skip = 400;
float forma_dt = 0.005;
// Lorenz's z is conventionally the vertical; mapped onto Houdini's y-up.
float x = 0.1, y = 0.0, z = 0.0;
int prim = addprim(0, "polyline");
for (int i = 0; i < forma_steps; i++){
float dx = p_sigma * (y - x);
float dy = x * (p_rho - z) - y;
float dz = x * y - p_beta * z;
x += dx * forma_dt; y += dy * forma_dt; z += dz * forma_dt;
if (i <= forma_skip) continue;
int pt = addpoint(0, set(x, z, y));
// 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. 07 · LORENZ ATTRACTOR — Edward Lorenz, 1963
// ẋ = σ(y − x)
// ẏ = x(ρ − z) − y
// ż = xy − βz
// 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=lorenz
// 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_sigma = 10 + forma_tweak("sigma_tweak"); // σ — Prandtl · live 4 .. 20
var p_rho = 28 + forma_tweak("rho_tweak"); // ρ — Rayleigh · live 14 .. 60
var p_beta = 2.667 + forma_tweak("beta_tweak"); // β — geometry · live 0.5 .. 5
var p_view = 0 + forma_tweak("view_tweak"); // view azimuth ° · live -180 .. 180
// 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.05998828588053584; // 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 the Lorenz system, the plate's own 18,000 steps of
// dt = 0.005 from (0.1, 0, 0), the first 400 discarded — the walk toward the
// attractor is not the attractor. The z axis is lowered by 0.72ρ so the wings
// sit centred. Then the page's view: the x–y plane turns at 0.13 rad/s and z
// is the screen vertical, scaled by 1/56 of the shorter side. Every second
// point is emitted — 8,800 vertices is what one After Effects path carries
// comfortably; the integration itself is untouched.
var x = 0.1, y = 0, z = 0, dt = 0.005;
var DEG = Math.PI / 180;
var rot = forma_t * 0.13 + p_view * DEG, co = Math.cos(rot), si = Math.sin(rot);
var s = Math.min(forma_W, forma_H) / 56, cx = forma_W / 2, cy = forma_H / 2;
var pts = [];
for (var i = 0; i < 18000; i++){
var dx = p_sigma * (y - x);
var dy = x * (p_rho - z) - y;
var dz = x * y - p_beta * z;
x += dx * dt; y += dy * dt; z += dz * dt;
if (i > 400 && (i & 1) === 0){
var zz = z - p_rho * 0.72;
pts.push(forma_pt(cx + (x * co + y * si) * s, cy - zz * s));
}
}
createPath(pts, [], [], false);