|
# Blackbody Radiation
**The Planck curve emerges from collisions — no energy quanta assumed.**
Particles bounce in a walled cavity. The frequency histogram converges to the Planck distribution. No discrete energy quanta, no Planck's constant inserted — the quantization is a consequence of the discrete pixel/tick lattice. Classically this is supposed to produce the Rayleigh-Jeans divergence (infinite energy at high frequencies); the discrete lattice cuts it off and yields the Planck curve instead.
*New to FRQTL? Start with **Hello, FRQTL** (`getting-started-hello-frqtl`) for the `caps.frqtl` setup-module + declarative-canvas basics this notebook assumes.*
|
Bounce-walled oven cavity with thermostat — editable user code:
|
/* setupBlackbody — THIN ADAPTER over the canonical setup factory
* (WS gym-controls-as-sugar Bite 0: this cell used to hand-copy the physics —
* a divergent fork of lib/frqtl/objects/setup/setupBlackbody.js that had
* already drifted onto a stale `universe.init(...)` positional-argument call the
* engine now FAIL-LOUDs on. The canonical factory is imported by BARE SPECIFIER
* (a relative path here would 404 — see lib/shim/notebook/frqtl-setups-importmap.js);
* this cell only bridges the notebook builder's `(frqtl, universe, options)` call
* shape to the factory's `(universe, options)` shape — ZERO physics here.)
*/
import { setupBlackbody as _setupBlackbody } from '@frqtl/setups/blackbody';
export function setupBlackbody(frqtl, universe, options) {
return _setupBlackbody(universe, options);
}
|
Declare a canvas that runs it. `setup="#"` + `stage`/`seed`; the shim synthesizes and runs the builder boilerplate in the realm. Click **Run** (or **Run All**):
|
|
## What you are seeing
Particles bounce within the cavity, exchanging momentum on every collision. Energy redistributes across the population until the frequency distribution stabilizes — the emergent shape matches the Planck curve, not the diverging Rayleigh-Jeans prediction.
**`temperature` is the driving knob.** It sets the thermostat's target `activeQuanta` count. The thermostat emits `floor((temperature - activeQuanta) / 4)` new leaf Frames per emitter per tick until the target is met, then silences all emitters that tick — a discrete proportional controller over quanta count. Raising `temperature` 300 → 4000 densifies the cavity from sparse scattered leaf dots to a near-saturated mass, increases compound-frame (non-leaf, merged) formation dramatically, and widens the escaped-radiation stream through the slit in both volume and angular spread. The captured sweep is in [`docs/internal/physics-lab/blackbody-temperature.md`](../../docs/internal/physics-lab/blackbody-temperature.md).
Note: `temperature` is NOT energy or kinetic temperature in the continuous-mechanics sense — it is the integer target for `universe.activeQuanta`. The per-Frame oscillation wavelength (`wavelength = floor((capacity / mass) × WAVELENGTH_CONSTANT)`, Core Axiom §6) is unchanged by `temperature` directly; it is determined by the mass of each Frame, which grows as frames merge via collisions. Higher temperature → more collisions → larger compound frames → shorter oscillation wavelengths — the FRAQTL analog of Wien's displacement.
**Edit the physics:** open the `./setups/blackbody.js` tab and pass an option override to the canonical factory — e.g. change the adapter's `_setupBlackbody(universe, options)` call to `_setupBlackbody(universe, Object.assign({ temperature: 3000 }, options))` (also try `boxFraction` or `slitHeight`) — then re-Run. The emergent frequency spectrum changes because you edited the construction, not a label. (The physics body itself lives in the canonical `lib/frqtl/objects/setup/setupBlackbody.js` — this cell is a thin, engine-agnostic adapter over it, so every other notebook and experiment page drives the SAME construction.) The simulation runs live in your browser on the compiled FRQTL (WASM) engine.
|