A pure Julia implementation of Jos Stam's Stable Fluids algorithm (1999/2003), widely used in computer graphics and games to simulate smoke, fire, and gaseous phenomena in real time. It is lightweight, unconditionally stable, and serves as the reference implementation and playground for embedded ports like ESP32-stableFluids.
This package solves the incompressible 2D Navier-Stokes equations for fluid flow:
and also an equation for transporting the density (which works as a dye)
It does so by breaking down each term of the sum and solving them separately, then summing up. Lastly, it applies a correction pressure so that we enforce that the fluid remains incompressible.
Lastly, Stable Fluids is, as per its name, unconditionally stable. That means you won't get infinite velocities under any circumstance, no matter how big the time step. However, my testing shows that increasing the time step too much does away with Stable Fluid's distinctive vortices.
Be advised!!! As a tradeoff for unconditional stability, the semi-Lagrangian advection method foregoes true physical realism. It is, by all accounts, just a mathematical trick that happens to get the job done, and not a faithful reflection of reality. You should expect smooth, highly aesthetic fluid-like motion with swirling vortices, but do not use it for high-precision CFD simulations because it will not accurately represent reality.
An interactive real-time simulation is available in JuliaImplementation/examples/rt_interactive.jl:
- Mouse Click & Drag: Spawns smoke density and imparts directional velocity momentum along the drag vector.
- W / A / S / D: Controls 2D gravity / acceleration vector dynamically (simulating an IMU accelerometer tilt).
- SPACE: Injects a dense puff of smoke at the center.
-
Adaptive Brush: Brush radius and spawn size scale dynamically to any grid resolution (
$50 \times 50$ ,$200 \times 200$ ,$300 \times 300$ , etc.). - Live FPS Counter: Real-time performance monitoring displayed in the title bar.
To launch the interactive demo:
julia --project=JuliaImplementation JuliaImplementation/examples/rt_interactive.jlRun the test suite covering grid initialization, boundary conditions, implicit diffusion, advection, projection, and continuous dissipation:
julia --project=JuliaImplementation JuliaImplementation/test/runtests.jlA list of optimizations and features I want to add to this:
- Multi-threaded Red-Black Gauss-Seidel solver with
@simdvectorization for high-resolution real-time grids ($500 \times 500+$ ). - GPU acceleration using
KernelAbstractions.jl/CUDA.jl. - Vorticity Confinement to counteract numerical dissipation and preserve fine turbulent swirls.
- Extension to 3D grid volumes with volumetric rendering.