Physics · Thermodynamics · core
Ideal Gas Kinetics
pressure is just particles bouncing off walls
Temperature is average kinetic energy and pressure is momentum delivered to the walls. Bounce point particles in a box and PV = NkT falls out.
Particles are coloured by speed from cyan (slow) to orange (fast) inside a translucent box; the right wall is a piston that glows yellow with the measured pressure. Raise temperature or particle count, or narrow the box, and watch the glow and the P = NkT/V readout rise together.
What it is
An ideal gas is a crowd of tiny particles that never interact except by bouncing elastically off the container. Every bounce reverses one velocity component and hands the wall a momentum of 2m|v⊥|. Add up those impulses per second per square metre and you get pressure.
Temperature is the average kinetic energy per particle: ½m⟨v²⟩ = (3/2)kT. Double T and the root-mean-square speed grows by √2, particles hit walls more often and harder, and pressure doubles. Halve the volume and the same particles hit each wall twice as often. That is the whole of PV = NkT, recovered from mechanics.
Velocities in equilibrium follow the Maxwell–Boltzmann distribution: each component is a Gaussian with variance kT/m. Seeding a sim with Gaussian velocities from a proper PRNG gives the right spread of speeds from the first frame.
For games this is the template for every cheap particle system with box collisions: integrate positions at a fixed timestep, reflect on walls, and measure aggregate quantities instead of tracking every interaction. Real gases add collisions between particles, which needs spatial partitioning.
Key formulas
- Ideal gas law
- Temperature from kinetic energy
- RMS speed
- Pressure from wall impulses
- Maxwell–Boltzmann velocity component
Rules of thumb
- Room-temperature nitrogen: v_rms ≈ 517 m/s. In sim units set m = k_B = 1 so v_rms = √(3T).
- Store unit-temperature velocities and scale by √T when stepping; changing the temperature slider then rescales speeds instantly and correctly.
- Reflect position about the wall (
p = 2b − p) and flip the velocity; just clamping loses distance and biases pressure. - Average pressure over ~1–2 s of hits; with 100–300 particles single-frame readings are noisy.
- 300 instanced spheres at 120 Hz is trivial; per-particle collisions are where costs explode (O(N²) without a grid).
Implementation
export function stepGas(pos: Float32Array, vel: Float32Array, n: number,
dt: number, T: number, half: [number, number, number]) {
const s = Math.sqrt(T) // vel holds unit-temperature velocities
let impulse = 0
for (let i = 0; i < n * 3; i++) {
const b = half[i % 3]
const v = vel[i] * s
let p = pos[i] + v * dt
if (p > b || p < -b) {
p = 2 * (p > 0 ? b : -b) - p // specular reflection
vel[i] = -vel[i]
impulse += 2 * Math.abs(v)
}
pos[i] = p
}
const area = 8 * (half[0] * half[1] + half[1] * half[2] + half[0] * half[2])
return impulse / (area * dt) // instantaneous pressure; average it
}Common mistakes
- Seeding random velocities with a weak or correlated generator (e.g. an LCG seeded with the particle index), which gives nearly identical speeds instead of a Maxwellian spread.
- Using uniform random velocities: the mean energy can be right but the speed distribution is wrong.
- Clamping particles to the wall without reflecting, which slowly drains kinetic energy.
- Comparing measured pressure with NkT/V using the slider temperature instead of the gas's actual kinetic temperature for a small N.
Prompt
Build an ideal-gas box in TypeScript with Three.js. Create N ≤ 300 particles with uniform positions and Gaussian unit-temperature velocities from a seeded mulberry32 + Box–Muller generator. Each 1/120 s fixed step, advance positions by v·√T·dt, reflect specularly off the walls of a box whose width is adjustable, and return the summed wall impulse 2|v⊥|. Render with one InstancedMesh, colouring each instance from slow (cyan) to fast (orange), with no per-frame allocation. Tests: over 40,000 steps the measured pressure impulse/(area·time) matches N·T_kin/V within 3%, and 2,000 seeded particles have kinetic temperature ≈ 1.
Related
Further reading
Updated 2026-11-01