# Oscillation ## Microsim ### Live player <div class="microsim-player"> <iframe src="https://editor.p5js.org/sciencenibber/full/Q21EyK7NF" width="100%" height="620" frameborder="0" sandbox="allow-scripts allow-same-origin"></iframe> </div> <div class="microsim-fallback"> <img src="Microsims/thumbs/Oscillation.png" alt="Oscillation microsim poster" style="width:100%;border:1px solid #4445;border-radius:6px;"> <p><em>Live microsim (desktop) · <a href="https://editor.p5js.org/sciencenibber/sketches/Q21EyK7NF">open sketch in the p5.js editor</a></em></p> </div> **Editor URL:** https://editor.p5js.org/sciencenibber/sketches/Q21EyK7NF **Description (100 words):** Three single-degree-of-freedom oscillator archetypes integrated side-by-side under a common time step: a linear damped harmonic oscillator (`x'' + 2 zeta omega x' + omega^2 x = 0`), a real pendulum with full sine restoring (`theta'' + (g/L) sin(theta) = 0`), and a Van der Pol self-sustained oscillator (`x'' - mu (1 - x^2) x' + x = 0`). Each row pairs a time-domain scope with a phase portrait. Three sliders (`zeta`, `theta_max`, `mu`) and pause/reset buttons let the reader watch isochronism in linear motion, period growth with amplitude in the pendulum, and the limit-cycle [[Attractor|attractor]] of Van der Pol emerge from any non-trivial start. ```js // ===================================================================== // Wikitube microsim - Oscillation // Slug: Oscillation // URL: en.wikitube.io/wiki/Oscillation // Pattern: A reskin - Classical mechanics constructions (Energy room) // // What it shows // Three single-degree-of-freedom oscillator archetypes integrated // side-by-side under a common time step so the reader can compare // their characters at a glance: // // 1. Linear x'' + 2 zeta omega x' + omega^2 x = 0 // sinusoidal, isochronous (period independent of // amplitude), elliptical phase portrait. // 2. Nonlinear theta'' + (g/L) sin(theta) = 0 (real pendulum) // anharmonic; period stretches with amplitude; // phase portrait curves into the pendulum "eye". // 3. Self- x'' - mu (1 - x^2) x' + x = 0 (Van der Pol) // sustained energy fed in for small x, dissipated for large // x, so the trajectory falls onto a limit cycle // from any non-trivial initial condition. // // Each oscillator gets its own row: a time-domain scope on the left // and a phase portrait on the right. A run/pause and reset button, // plus three sliders that drive the meaningful parameter of each // row, sit in a dedicated bottom band that does not collide with // the readouts (cf. pitfalls.md, slider-thumb-vs-readout entry). // // Live readouts (bottom-left, above the slider band) // row 1 (linear): omega, zeta, T = 2 pi / omega_d // row 2 (pendulum): theta_max, T_pendulum, T0 / T0 (period growth) // row 3 (Van der Pol): mu, period_estimate from zero crossings // // Pattern A reskin (Energy room) // Each "body" is rendered as a labelled point. The rig sketches are // suppressed (the room already has Vibration, Harmonic_oscillator, // Pendulum, Pendulum_(mechanics) microsims that show rigs); here the // point is the universal common shape across regimes, which lives in // the phase portraits. Conservation visibly drifts on the linear and // pendulum traces under nonzero damping; the Van der Pol trajectory // pumps itself onto its limit cycle. // // Pitfall guards (Skills/P5js Microsim Standards/pitfalls.md) // - p5.disableFriendlyErrors = true (no FES noise) // - all canvas-side strings ASCII; Unicode lives only in comments // (so "omega", "zeta", "theta", "mu", "pi" not the Greek letters) // - sliders sit in a dedicated bottom band so the slider thumb // does not float over readout text // - ring buffers capped so memory does not grow unbounded // - velocity-Verlet for the conservative oscillators; explicit-Euler // is fine for the dissipative Van der Pol since it is bounded by // its own attractor // ===================================================================== const ARTICLE = "Oscillation"; p5.disableFriendlyErrors = true; // ---------- Energy palette (Articles/P5_JS_EDITOR.md, section 4) ----- const BG = 18; const FG = 240; const HOT = [220, 110, 60]; // pendulum trace const COLD = [ 60, 130, 220]; // linear trace const STRUCT = [120, 130, 150]; // axes, structural lines const TRAJ = [240, 220, 80]; // current-state dot const GAUGE = [120, 220, 140]; // Van der Pol trace // ---------- Controls (created in setup) ------------------------------ let zetaSlider, thetaSlider, muSlider; let runBtn, resetBtn; let isRunning = true; // ---------- State ---------------------------------------------------- // Linear oscillator (x1, v1) // Nonlinear pendulum (theta, omegaP) theta in radians // Van der Pol (x3, v3) let x1 = 1.0, v1 = 0.0; let theta = 0.6, omegaP = 0.0; let x3 = 0.1, v3 = 0.0; let t = 0; // Ring buffers of {t, x, v} for each oscillator const N_BUF = 600; const buf1 = []; const buf2 = []; const buf3 = []; // Period estimation for Van der Pol: track zero crossings of x3. let lastZeroT = -1; let lastPeriod = 0; let prevX3 = x3; let prevTh0 = 0.6; // last seen pendulum-amplitude slider value // Pendulum "small-amplitude" reference period. const G_OVER_L = 4.0; // omega0^2 = g/L; omega0 = 2 rad/s function setup() { createCanvas(windowWidth, windowHeight); pixelDensity(2); // --- Bottom slider band (below the readout band) ------------------- zetaSlider = createSlider(0.0, 0.6, 0.05, 0.01).position(180, height - 90).size(180); thetaSlider = createSlider(0.05, 3.0, 0.6, 0.05).position(180, height - 60).size(180); muSlider = createSlider(0.0, 4.0, 1.5, 0.05).position(180, height - 30).size(180); runBtn = createButton("pause").position(420, height - 30); runBtn.mousePressed(() => { isRunning = !isRunning; runBtn.html(isRunning ? "pause" : "run"); }); resetBtn = createButton("reset").position(490, height - 30); resetBtn.mousePressed(() => { x1 = 1.0; v1 = 0.0; theta = thetaSlider.value(); omegaP = 0.0; x3 = 0.1; v3 = 0.0; t = 0; buf1.length = 0; buf2.length = 0; buf3.length = 0; lastZeroT = -1; lastPeriod = 0; prevX3 = x3; }); } function draw() { background(BG); // ---- read parameters once at top of draw (Energy room convention) - const zeta = zetaSlider.value(); const th0 = thetaSlider.value(); // current pendulum amplitude target const mu = muSlider.value(); const dt = isRunning ? min(deltaTime / 1000, 0.05) : 0; // If the user moved the amplitude slider, re-seed the pendulum from // rest at the new amplitude so the "period grows with amplitude" // lesson is one slider drag away. We watch th0 itself rather than // the live pendulum state, so a swinging pendulum reaching its // (mirrored) apex does not retrigger this and freeze the motion. if (abs(th0 - prevTh0) > 1e-3) { theta = th0; omegaP = 0.0; buf2.length = 0; prevTh0 = th0; } // ---- integrate --------------------------------------------------- // Run several substeps per frame so the oscillator periods (a few // seconds of simulation time each) finish in one or two seconds of // wall-clock time. Without this the trace looks suspiciously flat // even though the math is correct. const SUBSTEPS = 6; const dts = dt / SUBSTEPS; // Speed multiplier: 1 wall-clock second ~ SPEEDUP simulation seconds. const SPEEDUP = 8.0; if (dt > 0) { for (let s = 0; s < SUBSTEPS; s++) { const h = dts * SPEEDUP; // Linear: m=1, omega=1, damping zeta. Velocity-Verlet. const a1 = -x1 - 2 * zeta * v1; v1 += a1 * h * 0.5; x1 += v1 * h; const a1b = -x1 - 2 * zeta * v1; v1 += a1b * h * 0.5; // Pendulum: full sine restoring, light velocity damping. const aT = -G_OVER_L * sin(theta) - 2 * zeta * omegaP; omegaP += aT * h * 0.5; theta += omegaP * h; const aTb = -G_OVER_L * sin(theta) - 2 * zeta * omegaP; omegaP += aTb * h * 0.5; // Van der Pol: x'' = mu(1 - x^2) x' - x. Symplectic-ish midpoint. const a3 = mu * (1 - x3 * x3) * v3 - x3; v3 += a3 * h; x3 += v3 * h; t += h; // zero-crossing period estimate for Van der Pol if (prevX3 < 0 && x3 >= 0) { if (lastZeroT > 0) lastPeriod = 2 * (t - lastZeroT); lastZeroT = t; } prevX3 = x3; // Sample to buffers AT EACH SUBSTEP, not just once per frame. // If the iframe gets throttled to a lower frame rate the // per-frame sampling aliases the oscillation into a slow decay. buf1.push({ t, x: x1, v: v1 }); if (buf1.length > N_BUF) buf1.shift(); buf2.push({ t, x: theta, v: omegaP }); if (buf2.length > N_BUF) buf2.shift(); buf3.push({ t, x: x3, v: v3 }); if (buf3.length > N_BUF) buf3.shift(); } } // ---- layout ------------------------------------------------------- const padTop = 60; // leave room for HUD title block const padBot = 130; // leave room for readouts + sliders const rowH = (height - padTop - padBot) / 3; const scopeW = (width - 60) * 0.55; const phaseW = (width - 60) * 0.45 - 40; for (let r = 0; r < 3; r++) { const y0 = padTop + r * rowH + 10; const buf = [buf1, buf2, buf3][r]; const col = [COLD, HOT, GAUGE][r]; const xLim = [2.0, 3.4, 2.5][r]; const vLim = [2.0, 3.4, 4.0][r]; const label = ["linear x(t)", "pendulum theta(t)", "Van der Pol x(t)"][r]; const phaseLabel = ["phase (x, v)", "phase (theta, omega)", "phase (x, v)"][r]; drawScope(20, y0, scopeW, rowH - 20, buf, col, xLim, label); drawPhase(40 + scopeW, y0, phaseW, rowH - 20, buf, col, xLim, vLim, phaseLabel); } // ---- readouts and HUD -------------------------------------------- drawReadouts(zeta, mu); drawSliderLabels(); drawHud(); drawEquationFooter(); } function drawScope(x0, y0, w, h, buf, col, xLim, label) { push(); translate(x0, y0); stroke(STRUCT[0], STRUCT[1], STRUCT[2], 80); strokeWeight(1); noFill(); rect(0, 0, w, h); line(0, h / 2, w, h / 2); if (buf.length >= 2) { const tMin = buf[0].t, tMax = buf[buf.length - 1].t; stroke(col[0], col[1], col[2]); strokeWeight(2); noFill(); beginShape(); for (const s of buf) { vertex(map(s.t, tMin, tMax, 0, w), map(s.x, -xLim, xLim, h, 0)); } endShape(); } noStroke(); fill(STRUCT[0], STRUCT[1], STRUCT[2]); textSize(11); textAlign(LEFT, TOP); text(label, 8, 6); pop(); } function drawPhase(x0, y0, w, h, buf, col, xLim, vLim, label) { push(); translate(x0, y0); stroke(STRUCT[0], STRUCT[1], STRUCT[2], 80); strokeWeight(1); noFill(); rect(0, 0, w, h); line(0, h / 2, w, h / 2); line(w / 2, 0, w / 2, h); if (buf.length >= 2) { stroke(col[0], col[1], col[2]); strokeWeight(1.4); noFill(); beginShape(); for (const s of buf) { vertex(map(s.x, -xLim, xLim, 0, w), map(s.v, -vLim, vLim, h, 0)); } endShape(); // current-state dot const last = buf[buf.length - 1]; noStroke(); fill(TRAJ[0], TRAJ[1], TRAJ[2]); circle(map(last.x, -xLim, xLim, 0, w), map(last.v, -vLim, vLim, h, 0), 7); } noStroke(); fill(STRUCT[0], STRUCT[1], STRUCT[2]); textSize(11); textAlign(LEFT, TOP); text(label, 8, 6); pop(); } function drawReadouts(zeta, mu) { // canonical-symbol readouts in a band just above the slider band. // omega for linear is fixed = 1 rad/s by construction. const omega = 1.0; const T_lin = (2 * PI) / omega; // pendulum period estimate from current theta apex (small amplitude // reference T0 = 2 pi / sqrt(g/L)). Use the elliptic-K-free first // correction T = T0 * (1 + theta_max^2 / 16). const omega0 = sqrt(G_OVER_L); const T0 = (2 * PI) / omega0; const thMax = max(abs(theta), 1e-6); const T_pend = T0 * (1 + (thMax * thMax) / 16); const stretch = T_pend / T0; push(); noStroke(); fill(STRUCT[0], STRUCT[1], STRUCT[2]); textSize(12); textAlign(LEFT, BOTTOM); text("linear: omega = " + nf(omega, 1, 2) + " zeta = " + nf(zeta, 1, 2) + " T = " + nf(T_lin, 1, 2) + " s", 16, height - 110); text("pendulum: theta_max = " + nf(thMax, 1, 2) + " rad T0 = " + nf(T0, 1, 2) + " T/T0 = " + nf(stretch, 1, 3), 16, height - 96); text("Van der Pol: mu = " + nf(mu, 1, 2) + " period ~ " + nf(lastPeriod, 1, 2) + " s", 16, height - 82); pop(); } function drawSliderLabels() { // labels sit just left of each slider, right-aligned push(); noStroke(); fill(STRUCT[0], STRUCT[1], STRUCT[2]); textSize(12); textAlign(RIGHT, CENTER); text("zeta (damping)", 170, height - 80); text("theta_max (pend amp)", 170, height - 50); text("mu (Van der Pol)", 170, height - 20); pop(); } function drawHud() { push(); // top-left: title + wikitube URL line. The Energy palette sets // BG = 18 (near-black) so the title needs a light fill, not the // near-black fill(20) the standards spec assumes for a light bg. noStroke(); fill(FG); textSize(20); textAlign(LEFT, TOP); text("Oscillation", 20, 16); fill(170); textSize(12); text("Wikitube microsim - en.wikitube.io/wiki/" + ARTICLE, 20, 40); // top-right: control hints fill(150); textSize(11); textAlign(RIGHT, TOP); text("sliders: zeta, theta_max, mu (per row)", width - 20, 16); text("buttons: pause / reset; rows: linear, pendulum, Van der Pol", width - 20, 32); pop(); } function drawEquationFooter() { push(); noStroke(); fill(160); textSize(11); textAlign(RIGHT, BOTTOM); text("x'' + 2 zeta omega x' + omega^2 x = 0 | theta'' + (g/L) sin(theta) = 0 | x'' - mu (1 - x^2) x' + x = 0", width - 20, height - 110); pop(); } function windowResized() { resizeCanvas(windowWidth, windowHeight); // re-pin the controls after a resize zetaSlider.position(180, height - 90); thetaSlider.position(180, height - 60); muSlider.position(180, height - 30); runBtn.position(420, height - 30); resetBtn.position(490, height - 30); } ``` ## Links (Wikipedia order) <!-- injected from _registry/childlinks/Oscillation.json (2026-07-30T02:09:12Z) --> `Aerodynamics` · `Aircraft` · [[Alternating_current]] · `Angle_of_attack` · `Anisotropy` · `Anti-vibration_compound` · `Antiresonance` · `Armstrong_oscillator` · `Arnold_tongue` · `Asteroseismology` · `Astronomy` · `Atlantic_multidecadal_oscillation` · `BIBO_stability` · `Beat_(acoustics)` · `Belousov–Zhabotinsky_reaction` · `Blocking_oscillator` · `Bray–Liebhafsky_reaction` · `Briggs–Rauscher_reaction` · `Business_cycle` · `Butler_oscillator` · `Cepheid_variable` · `Chandler_wobble` · [[Christiaan_Huygens]] · `Circadian_rhythm` · `Clapp_oscillator` · `Classical_limit` · `Colpitts_oscillator` · `Continuum_mechanics` · [[Control_theory]] · `Critical_speed` · `Crystal_oscillator` · `Cycle_(music)` · `Degrees_of_freedom_(physics_and_chemistry)` · `Delay-line_oscillator` · `Double_pendulum` · [[Dynamical_system]] · [[Dynamics_(mechanics)]] · [[Earthquake_engineering]] · [[Ecology]] · `Economics` · `Electromagnetic_field` · `Electronic_circuit` · `Electronic_oscillator` · `Exponential_decay` · `Extended_interaction_oscillator` · [[Feedback]] · `Fluid` · [[Force]] · `Foucault_pendulum` · `Fourier_transform` · `Frequency` · `Friction` · `Function_(mathematics)` · `Generation_gap` · `Geology` · `Geyser` · `Gravity` · `Guitar` · `Harmonic_oscillator` · `Hartley_oscillator` · `Helioseismology` · `Helmholtz_resonance` · `Hooke's_law` · `Hunting_oscillation` · `Infinity` · `Injection_locking` · `Interval_(mathematics)` · `Isotropy` · `Kepler_orbit` · `Kinetic_energy` · `Laser` · [[Least-squares_spectral_analysis]] · `Lennard-Jones_potential` · `Lever_escapement` · `Local_oscillator` · `Madden–Julian_oscillation` · `Mechanical_equilibrium` · `Mercury_beating_heart` · `Momentum` · `Neural_oscillation` · `Neutral_particle_oscillation` · `Neutrino_oscillation` · `Normal_mode` · `Open_set` · `Oscillating_gene` · `Oscillation_(mathematics)` · `Oscillator_(cellular_automaton)` · `Oscillator_(disambiguation)` · `Oscillator_phase_noise` · `Oscillistor` · `Pacific_decadal_oscillation` · [[Pendulum]] · `Periodic_function` · `Phase-shift_oscillator` · `Phase_noise` · `Phugoid` · `Pierce_oscillator` · `Pilot-induced_oscillation` · `Potential_energy` · `Puberty` · `Quantum_harmonic_oscillator` · `Quantum_optics` · `Quasi-biennial_oscillation` · `Quasiperiodic_function` · `Quasiperiodicity` · `RLC_circuit` · `Real_number` · `Reciprocating_motion` · `Relaxation_oscillator` · `Resonance` · `Resonator` · `Rhythm` · `Route_flapping` · `Royer_oscillator` · `Seasonality` · `Self-oscillation` · `Self-pulsation` · [[Sequence]] · `Signal_generator` · [[Simple_harmonic_motion]] · [[Sine_wave]] · `Sliding_mode_control` · `Spring_(device)` · `Squegging` · `Stability_theory` · `Statics` · `Stiffness` · `String_instrument` · `Structural_stability` · `Swing_(seat)` · `Tension_(physics)` · `Time` · `Torsional_vibration` · `Tuned_mass_damper` · `Tuning_fork` · `Valve` · `Vibrate_(disambiguation)` · `Vibration` · `Vibrations_(disambiguation)` · `Vibrator_(mechanical)` · `Water` · [[Wave]] · [[Wayback_Machine]] · `Weight` · `Wien_bridge_oscillator` · `Wilberforce_pendulum` · `Wing` ## Media (PD/CC) <!-- MEDIA-DEPLOY:Oscillation/Animated-mass-spring.gif --> !Gif Library/Oscillation/Animated-mass-spring.gif *Animated-mass-spring.gif · Svjo · CC BY-SA 3.0 · [source](https://commons.wikimedia.org/wiki/File:Animated-mass-spring.gif)* <!-- /MEDIA-DEPLOY --> <!-- SIGN-SYSTEMS:START --> **Semiotic universals** (the notations and alphabet letters this article speaks — each opens its canonical card): oscillation · energy · amplitude · cycle · damping. Index: the glyph gallery · SEMIOTICS PORTAL. <!-- SIGN-SYSTEMS:END --> > **Room:** [[Energy]] · **Status:** ✅ shipped ## Overview Oscillation is the repetitive variation of a quantity about a central value, the most universal idiom in [[Physics|physics]]: anywhere a [[System|system]] has a restoring tendency and a way to store energy, it oscillates. The mathematical skeleton is one second-order [[Ordinary_differential_equation|ordinary differential equation]] in time, x'' = f(x, x'), whose qualitative behaviour falls into three families that dominate the room. Linear oscillation, where the restoring [[Force|force]] is strictly proportional to displacement (x'' + omega^2 x = 0), produces sinusoids whose frequency is independent of amplitude: the regime of small-angle pendula, mass-spring rigs, LC circuits, and tuning forks. Nonlinear oscillation, where the restoring force bends (x'' + sin(x) = 0 for a real [[Pendulum|pendulum]], x'' + x + alpha x^3 = 0 for the Duffing oscillator), produces periodic but anharmonic motion whose period grows with amplitude and whose phase portraits curve into eyes, figure-eights, or scroll patterns. Self-sustained oscillation, where a system pumps energy into itself against dissipation (x'' - mu (1 - x^2) x' + x = 0 for Van der Pol), produces a limit cycle the trajectory falls onto from anywhere: the regime of heart pacemaker cells, tube oscillators, and the cocktail-party hum of a vibrating reed. Coupled oscillators add normal modes, beats, and synchronisation; chaotic oscillation breaks period altogether. The single-DoF picture is the universal first chapter. ## See also - Room hub: [[Energy]] - p5.js Editor conventions: P5 JS EDITOR - Wiki root: MAIN --- *Scaffolded by `generative-microsim` from row 0 of the Energy sheet on 2026-04-30T08:51:48Z.* Letters: oscillation · energy · amplitude · cycle · damping · harmonic · attractor_chaos · flow <!-- CRAFT-LINK:START g12 --> *Built to the [[WT!P5_js_Microsim_Master_Class|p5.js Master Class]].* <!-- CRAFT-LINK:END --> <!-- ACOUSIM:BEGIN g22 — Acoustics portal microsim (framework build, specs/acoustics/sims/Oscillation.json); do not hand-edit inside --> **Microsim — three.js (Wikitube framework):** *Oscillation* <div class="wt-sim" data-src="https://wikitube-3d-microsims.netlify.app/acoustics/Oscillation.html" data-title="Oscillation"></div> *Built from `MICROSIM_GUIDE/specs/acoustics/sims/Oscillation.json`; part of the [[PORTAL_Acoustics|Acoustics portal]] spine (section sims and See-also variants).* <!-- ACOUSIM:END --> ## Wikipedia : Wikitube **Strict pair:** [Wikipedia](https://en.wikipedia.org/wiki/Oscillation) : [Wikitube](https://en.wikitube.io/wiki/Oscillation) ## Previous hub tags Tree parents: [[Complex_system]] · [[Dynamical_system]] · [[Feedback]]. Legacy hubs: `GENERATIVE`. --- *Sources: 1 legacy note. Minted wave 1, 2026-07-30 (v1.6 order).*