This project is an interactive real-time 2D fluid simulation that brings fluid dynamics to your browser. Built on Jos Stam's landmark "Stable Fluids" paper, it visualizes incompressible flow using a grid-based Eulerian approach—no particle systems, just pure mathematics rendered on canvas.
The simulation models smoke or dye moving through air, driven by velocity fields and pressure gradients. Move your mouse, click and drag, or watch the built-in nozzle emitter create swirling, turbulent patterns that emerge naturally from the underlying physics.
- Move mouse — add velocity to the fluid
- Click and drag — add density and velocity
- Config panel — adjust simulation parameters
This simulation solves the Navier-Stokes equations for incompressible fluid flow:
For incompressible flow (constant density), this simplifies to:
This is the divergence-free constraint — the velocity field must have zero divergence everywhere. This is enforced by the projection step.
- First term: acceleration
- Second term: advection (self-advection of the velocity field)
- Third term: pressure gradient force
- Fourth term: viscosity/diffusion
Jos Stam's "Stable Fluids" (1999) solves these equations on a grid using operator splitting:
Inject velocity and density from the nozzle or mouse input:
Solve the diffusion equation using Gauss-Seidel relaxation:
where
This implicitly handles viscosity, making the simulation stable for any timestep.
This is the heart of incompressible flow. Two substeps:
1. Compute divergence:
2. Solve Poisson equation for pressure:
Using Gauss-Seidel again:
3. Subtract pressure gradient to make velocity divergence-free:
Move quantities along the velocity field using semi-Lagrangian advection:
- For each grid cell, trace backwards along the velocity:
$\mathbf{x}_{prev} = \mathbf{x} - \Delta t \cdot \mathbf{u}$ - Interpolate the old value at
$\mathbf{x}_{prev}$ using bilinear interpolation
This is unconditionally stable (no CFL constraint) because we trace backwards.
No-slip boundaries are implemented by reflecting velocity at edges:
- Left/right walls:
$u(0,y) = -u(1,y)$ - Top/bottom walls:
$v(x,0) = -v(x,1)$
Corners average their neighbors for stability.
| Theorem | Relevance |
|---|---|
| Helmholtz Decomposition | Any vector field can be decomposed into curl-free and divergence-free components. Projection exploits this. |
| Poisson Equation |
|
| Lax Equivalence Theorem | For linear systems, consistency + stability = convergence (justifies implicit methods) |
