Quantum Double Slit
One electron wave packet meets an ideal barrier with two slits. Cyan shows probability density; amber accumulates probability absorbed by the detector. Ordinary Hyle evolves a 192 × 160 Schrödinger lattice with norm-preserving pair rotations. Run roughly 800 ticks to collect the transmitted packet; Step and the timeline reveal diffraction and interference. CPU-64 is the reference; GPU-32 supports this program. This is a 2D nonrelativistic model with ideal walls and approximate absorbing boundaries. The detector shows expected probabilities, not individual random electron hits. Recompile restores the normalized incident packet. See Hyle docs: Learn / Quantum double slit.
Inside this simulation
Every named building block is public and reusable. These are the exact versions published with this simulation.
Source
// Quantum Double Slit — one nonrelativistic electron in a 2D cross-section.
// Ordinary Hyle, embedded at z=0. No fluid/LBM solver or scripted interference.
// hbar=m=1, dx=1, dt=0.4; physical time = tick * dt.
// psi = real + i*imag. Sum(real^2 + imag^2 + received + sink) = 1.
// Real-space symmetric Suzuki-Trotter pair rotations; kinetic global phase omitted.
// Ref: https://trotter-suzuki-mpi.github.io/md_TSapproximation.html
// open=0 is an ideal reflecting Dirichlet wall; open=1 is the accessible domain.
// absorb is the amplitude multiplier for EACH half-step; geometry stores exp(-gamma*dt/2).
// received accumulates detector absorption; sink accounts for other absorbing edges.
// +/-2 guards only satisfy compiler intervals: normalized amplitudes never approach them.
// The displayed detector is expected probability, not sampled individual detections.
// CPU-64 is the reference. GPU-32 is an approximation: check conservation after long runs.
property Quantum {
absorb: Float<1.0> [0.0 1.0] ~1e-10;
detector: Float<0.0> [0.0 1.0];
imag: Float<0.0> ~1e-10;
open: Float<1.0> [0.0 1.0];
real: Float<0.0> ~1e-10;
received: Float<0.0> ~1e-10;
sink: Float<0.0> ~1e-10;
xEven: Float<0.0> [0.0 1.0];
yEven: Float<0.0> [0.0 1.0];
}
model Wave : Quantum;
world { dimensions 3; cell Cube; neighborhood VonNeumann; }
behavior Absorb for Quantum {
update when self.open > 0.5 {
let p = self.real * self.real + self.imag * self.imag;
let lost = p * (1.0 - self.absorb * self.absorb);
set self.received = clamp(self.received + self.detector * lost, 0.0, 2.0);
set self.sink = clamp(self.sink + (1.0 - self.detector) * lost, 0.0, 2.0);
set self.real = clamp(self.real * self.absorb, -2.0, 2.0);
set self.imag = clamp(self.imag * self.absorb, -2.0, 2.0);
}
}
behavior XEven for Quantum {
update when self.open > 0.5 && self.xEven == 1.0 {
let linked = (neighbors[Quantum, +X].open else 0.0);
let c = 1.0 + linked * (0.99500416527802571 - 1.0);
let s = linked * 0.09983341664682815;
let r = self.real * c - (neighbors[Quantum, +X].imag else 0.0) * s;
let i = self.imag * c + (neighbors[Quantum, +X].real else 0.0) * s;
set self.real = clamp(r, -2.0, 2.0);
set self.imag = clamp(i, -2.0, 2.0);
}
update when self.open > 0.5 && self.xEven == 0.0 {
let linked = (neighbors[Quantum, -X].open else 0.0);
let c = 1.0 + linked * (0.99500416527802571 - 1.0);
let s = linked * 0.09983341664682815;
let r = self.real * c - (neighbors[Quantum, -X].imag else 0.0) * s;
let i = self.imag * c + (neighbors[Quantum, -X].real else 0.0) * s;
set self.real = clamp(r, -2.0, 2.0);
set self.imag = clamp(i, -2.0, 2.0);
}
}
behavior XOdd for Quantum {
update when self.open > 0.5 && self.xEven == 1.0 {
let linked = (neighbors[Quantum, -X].open else 0.0);
let c = 1.0 + linked * (0.99500416527802571 - 1.0);
let s = linked * 0.09983341664682815;
let r = self.real * c - (neighbors[Quantum, -X].imag else 0.0) * s;
let i = self.imag * c + (neighbors[Quantum, -X].real else 0.0) * s;
set self.real = clamp(r, -2.0, 2.0);
set self.imag = clamp(i, -2.0, 2.0);
}
update when self.open > 0.5 && self.xEven == 0.0 {
let linked = (neighbors[Quantum, +X].open else 0.0);
let c = 1.0 + linked * (0.99500416527802571 - 1.0);
let s = linked * 0.09983341664682815;
let r = self.real * c - (neighbors[Quantum, +X].imag else 0.0) * s;
let i = self.imag * c + (neighbors[Quantum, +X].real else 0.0) * s;
set self.real = clamp(r, -2.0, 2.0);
set self.imag = clamp(i, -2.0, 2.0);
}
}
behavior YEven for Quantum {
update when self.open > 0.5 && self.yEven == 1.0 {
let linked = (neighbors[Quantum, +Y].open else 0.0);
let c = 1.0 + linked * (0.99500416527802571 - 1.0);
let s = linked * 0.09983341664682815;
let r = self.real * c - (neighbors[Quantum, +Y].imag else 0.0) * s;
let i = self.imag * c + (neighbors[Quantum, +Y].real else 0.0) * s;
set self.real = clamp(r, -2.0, 2.0);
set self.imag = clamp(i, -2.0, 2.0);
}
update when self.open > 0.5 && self.yEven == 0.0 {
let linked = (neighbors[Quantum, -Y].open else 0.0);
let c = 1.0 + linked * (0.99500416527802571 - 1.0);
let s = linked * 0.09983341664682815;
let r = self.real * c - (neighbors[Quantum, -Y].imag else 0.0) * s;
let i = self.imag * c + (neighbors[Quantum, -Y].real else 0.0) * s;
set self.real = clamp(r, -2.0, 2.0);
set self.imag = clamp(i, -2.0, 2.0);
}
}
behavior YOdd for Quantum {
update when self.open > 0.5 && self.yEven == 1.0 {
let linked = (neighbors[Quantum, -Y].open else 0.0);
let c = 1.0 + linked * (0.98006657784124163 - 1.0);
let s = linked * 0.19866933079506122;
let r = self.real * c - (neighbors[Quantum, -Y].imag else 0.0) * s;
let i = self.imag * c + (neighbors[Quantum, -Y].real else 0.0) * s;
set self.real = clamp(r, -2.0, 2.0);
set self.imag = clamp(i, -2.0, 2.0);
}
update when self.open > 0.5 && self.yEven == 0.0 {
let linked = (neighbors[Quantum, +Y].open else 0.0);
let c = 1.0 + linked * (0.98006657784124163 - 1.0);
let s = linked * 0.19866933079506122;
let r = self.real * c - (neighbors[Quantum, +Y].imag else 0.0) * s;
let i = self.imag * c + (neighbors[Quantum, +Y].real else 0.0) * s;
set self.real = clamp(r, -2.0, 2.0);
set self.imag = clamp(i, -2.0, 2.0);
}
}
phase absorb_in { run Absorb on Wave; }
phase x_even_in { run XEven on Wave; }
phase x_odd_in { run XOdd on Wave; }
phase y_even_in { run YEven on Wave; }
phase y_odd { run YOdd on Wave; }
phase y_even_out { run YEven on Wave; }
phase x_odd_out { run XOdd on Wave; }
phase x_even_out { run XEven on Wave; }
phase absorb_out { run Absorb on Wave; }
visual Probability for Quantum {
color {
let density = clamp(self.real * self.real + self.imag * self.imag, 0.0, 4.0);
let p = clamp(density / (density + 0.00003), 0.0, 1.0);
let film = clamp(self.received * 16000.0, 0.0, 1.0);
let wall = 1.0 - self.open;
rgba(clamp(0.09 + wall * 0.35 + film * 0.9, 0.0, 1.0),
clamp(0.16 + p * 0.7 + film * 0.5 + wall * 0.25, 0.0, 1.0),
clamp(0.3 + p * 0.68 + wall * 0.15, 0.0, 1.0),
clamp(wall * 0.95 + p + film + self.detector * 0.04, 0.0, 1.0))
}
}
visualize Wave with Probability;