PL. 38 · ATTRACTORS / MAP / BEAM DYNAMICS
Gumowski–Mira Map
Igor Gumowski & Christian Mira, 1980
OPEN THE LIVE PLATE ▸DEFINITION
G(x) = μx + 2(1−μ)x²/(1+x²) xₙ₊₁ = yₙ + α·yₙ(1 − σ·yₙ²) + G(xₙ) yₙ₊₁ = −xₙ + G(xₙ₊₁)
NOTES
Gumowski and Mira were modelling the transverse oscillation of particle beams in CERN’s storage rings when they found this recurrence. Each starting point traces its own chain of islands, and their superposition looks unreasonably biological — moths, jellyfish, orchids — for a map built from a single rational function. The small α term is a whisper of dissipation that slowly sharpens the figure.
PROVENANCE
- Origin
- I. Gumowski & C. Mira, "Recurrences and Discrete Dynamic Systems", Lecture Notes in Mathematics 809, Springer, 1980
- Standing
- Public domain — an iterated map
- Constants
- σ = 0.05 as published; μ selects the figure, and nearly every value draws a different one
- Source
- doi:10.1007/BFb0089135
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. 38 · GUMOWSKI–MIRA MAP — Igor Gumowski & Christian Mira, 1980
// G(x) = μx + 2(1−μ)x²/(1+x²)
// xₙ₊₁ = yₙ + α·yₙ(1 − σ·yₙ²) + G(xₙ)
// yₙ₊₁ = −xₙ + G(xₙ₊₁)
// 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=mira
float p_m = -0.496 + chf('m_tweak'); // μ — nonlinearity · live -0.85 .. 0.35
float p_a = 0.008 + chf('a_tweak'); // α — dissipation · live 0 .. 0.02
float p_sigma = 0.05 + chf('sigma_tweak'); // σ — cubic term · live 0 .. 0.12
float p_run = 700 + chf('run_tweak'); // orbit length per seed · live 100 .. 3000
// 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)));
}
// Nearly conservative: each start owns its own island chain rather than
// falling onto one attractor, so the figure is many short orbits from
// scattered seeds superposed — which is what the published pictures are.
int forma_pts = 120000;
float x = 0.0, y = 0.0;
int run = int(p_run) + 1, si = 0; // force a seed on the first step
for (int i = 0; i < forma_pts; i++){
if (++run > int(p_run)){
run = 0;
// deterministic scattered restarts, mirroring the plate's seeded rng
float rad = 0.5 + 11.0 * random(si * 2);
float th = 6.28318530718 * random(si * 2 + 1);
x = rad * cos(th); y = rad * sin(th);
si++;
}
float gx = p_m * x + 2.0 * (1.0 - p_m) * x * x / (1.0 + x * x);
float nx = y + p_a * y * (1.0 - p_sigma * y * y) + gx;
float gn = p_m * nx + 2.0 * (1.0 - p_m) * nx * nx / (1.0 + nx * nx);
float ny = -x + gn; // the old x — the map reads it before it moves
x = nx; y = ny;
// canvas y runs down; negated so the figure sits as the plate shows it
int pt = addpoint(0, set(x, -y, 0.0));
float u = float(i) / float(forma_pts);
setpointattrib(0, "Cd", pt, forma_ramp(0.8 + 0.3 * u));
}