|
# Wave Interference
**Interference patterns without a wave equation — only quantum particles, with real and local rules, that don't know each other exist. Classically this is supposed to be impossible.**
Using the FRQTL engine, two convenience `PointSource` emitters fire quanta (leaf Frames) radially. Where the two streams overlap, fringes emerge — with no wave function, no superposition term, no interference formula anywhere in the engine.
*New to FRQTL? Start with **Hello, FRQTL** (`getting-started-hello-frqtl`) for the `caps.frqtl` setup-module + declarative-canvas basics this notebook assumes.*
|
Two radial emitters and their (visual-only) source circles — editable user code:
|
/* setupWaveInterference — 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/setupWaveInterference.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 { setupWaveInterference as _setupWaveInterference } from '@frqtl/setups/wave-interference';
export function setupWaveInterference(frqtl, universe, options) {
return _setupWaveInterference(universe, options);
}
|
Declare a canvas that runs it. The canvas names the setup module (`setup="#"`); the shim synthesizes and runs the builder boilerplate in the realm. `opts` is the validated driving knob, `stage`/`seed` configure the runner. Click **Run** (or **Run All**):
|
|
## What just happened
The two black circles are the point sources. Particles stream outward from each; where the streams overlap, regions of constructive and destructive density build into the banded fringe pattern — the classically "impossible" result, produced with no wave equation. Each particle only ever obeyed *move 1 pixel per tick*; the wave behavior is **emergent**.
**The fringe spacing is a knob.** It is set by the universe `wavelengthScale` (`wavelength = floor((capacity / mass) × WAVELENGTH_CONSTANT)`). Raising it 2 → 32 widens the fringes from a near-uniform dense cloud to sparse, widely-separated radial spokes; lowering it tightens them until they blur together. The captured sweep is in [`docs/internal/physics-lab/wave-interference-wavelength.md`](../../docs/internal/physics-lab/wave-interference-wavelength.md).
Note the two distinct "wavelength" controls: a `PointSource`'s `opts.wavelength` sets each particle's **mass** (`mass = capacity / wavelength`), while the universe `wavelengthScale` is the global scale on **every** particle's wavelength — the fringe-spacing knob above.
**Edit the physics:** try the `quanta` knob on the canvas (`opts="quanta=200"` or `"quanta=1500"`), or open the `./setups/wave-interference.js` tab and pass an option override to the canonical factory — e.g. change the adapter's `_setupWaveInterference(universe, options)` call to `_setupWaveInterference(universe, Object.assign({ fundamentalWaveLength: 48 }, options))` (also try `sourceSeparation`) — then re-Run. The fringes change because you edited the construction. (The physics body itself lives in the canonical `lib/frqtl/objects/setup/setupWaveInterference.js` — this cell is a thin, engine-agnostic adapter over it.) The simulation runs live in your browser on the compiled FRQTL (WASM) engine.
|