A C# implementation of Jos Stam's "Stable Fluids" algorithm, specifically designed for use in Rhino/Grasshopper plugins. This implementation provides real-time fluid simulation with bitmap visualization and vector field output.
This implementation answers your three key questions:
Jos Stam's 1999 "Stable Fluids" paper remains the gold standard for real-time fluid simulation. The algorithm is:
- Unconditionally stable - won't explode regardless of time step
- Fast - suitable for real-time applications
- Simple - relatively easy to implement and understand
- Widely used - still used in modern games, VFX, and interactive applications
The Stable Fluids algorithm consists of four main steps:
- Add Forces: Apply external forces (mouse input, obstacles, etc.)
- Advection: Move quantities along the velocity field using semi-Lagrangian method
- Diffusion: Smooth velocities using viscosity (solved with Jacobi iteration)
- Projection: Ensure velocity field is divergence-free (incompressible flow)
Key concepts:
- Velocity Field (u,v): 2D vector field representing fluid motion
- Pressure: Scalar field used to enforce incompressibility
- Divergence: Measures field "spreading" - must be zero for incompressible flow
- Jacobi Iteration: Iterative solver for linear systems
The provided implementation includes:
StableFluidSimulation.cs- Core simulation engineFluidVisualization.cs- Bitmap generation and streamline creationGrasshopperFluidComponent.cs- Example Grasshopper integration
- StableFluidSimulation.cs: Main simulation class implementing Jos Stam's algorithm
- FluidVisualization.cs: Visualization helpers for creating bitmaps and vector fields
- GrasshopperFluidComponent.cs: Example Grasshopper component integration
- Real-time fluid simulation
- Bitmap output for velocity and density fields
- Streamline generation
- Vector field visualization
- Mouse/cursor interaction support
- Configurable parameters (viscosity, diffusion, grid size)
// Create simulation (64x64 grid)
var simulation = new StableFluidSimulation(64, 64, 0.016f, 0.0001f, 0.0001f);
var visualization = new FluidVisualization(simulation);
// Add forces and density
simulation.AddForce(32, 32, 10.0f, 5.0f);
simulation.AddDensity(32, 32, 100.0f);
// Run simulation step
simulation.Step();
// Generate visualization
var velocityBitmap = visualization.CreateVelocityMagnitudeBitmap();
var streamlines = visualization.GenerateStreamlines(10, 50, 0.3f);The FluidSimulationComponent provides:
- Inputs: Grid size, viscosity, diffusion, force points/vectors, density points/amounts
- Outputs: Velocity bitmap, density bitmap, streamlines, velocity vectors
- Width/Height: Simulation grid resolution (higher = more detail, slower)
- Viscosity: Fluid thickness (0.0001 = water-like, 0.01 = honey-like)
- Diffusion: How quickly density spreads (0.0001 = slow, 0.01 = fast)
- Time Step: Simulation time step (0.016 ≈ 60 FPS)
- Unity-based: keijiro/StableFluids - GPU-accelerated Unity implementation
- This implementation: CPU-based, suitable for Grasshopper plugins
- Taichi: Modern GPU-accelerated physics simulation
- PyFluid: Various GitHub implementations
- NumPy/SciPy: For educational/research purposes
- Stability: Never explodes, always produces reasonable results
- Speed: Fast enough for real-time interaction
- Simplicity: Relatively easy to implement and modify
- Flexibility: Can be extended with obstacles, boundaries, different forces
- Visual Quality: Produces convincing fluid-like motion
-
Velocity Step:
- Add forces
- Diffuse velocities (viscosity)
- Project to remove divergence
- Advect velocities
- Project again
-
Density Step:
- Diffuse density
- Advect density along velocity field
- Semi-Lagrangian Advection: Trace particles backward in time
- Jacobi Iteration: Solve linear systems iteratively
- Projection: Use pressure to enforce incompressibility
- Velocity: No-slip boundaries (velocity = 0 at walls)
- Density: No-flux boundaries (density doesn't escape)
- 32x32: Very fast, low detail
- 64x64: Good balance for real-time interaction
- 128x128: High detail, may be slow for real-time
- 256x256+: Very high detail, likely too slow for real-time
- Use appropriate grid resolution for your needs
- Reduce Jacobi iterations if speed is critical (20 is good, 10 may suffice)
- Consider GPU implementation for larger grids
- Cache visualization results when possible
- Obstacles: Add solid boundaries within the fluid
- Temperature: Add buoyancy effects
- Multiple Fluids: Different density fluids
- 3D Version: Extend to three dimensions
- GPU Acceleration: Port to compute shaders
- Vorticity Confinement: Add swirl preservation
- Geometry Interaction: Use Rhino curves as obstacles
- Point Cloud Forces: Apply forces at point locations
- Animation Export: Save sequences of bitmaps
- Parameter Animation: Animate viscosity, forces over time
- Stable Fluids - Jos Stam (1999) - Original paper
- Real-Time Fluid Dynamics for Games - Jos Stam (2003) - Simplified version
- Fast Fluid Dynamics Simulation on the GPU - Mark Harris (2004) - GPU implementation
- keijiro/StableFluids - Modern Unity C# implementation
This implementation is provided as educational/research code. The original Stable Fluids algorithm is from Jos Stam's public research papers.