Beyond Water

Stretching the particle framework to simulate springs, sand, ice, and more.

Part 3 of Smooth Particle Hydrodynamics

In Part 1 we built a fluid from two forces: pressure pushes crowded particles apart, and viscosity smooths out velocity differences. That gives us something that looks like water.

But the real power of SPH is that the particle framework is not limited to water. By changing the force rules, the same loop of "find neighbors, compute forces, update" can produce elastic solids, granular piles, phase transitions, and more. Each section below adds a new force or parameter on top of Part 1's foundation.

Springs Between Particles

What if nearby particles remembered each other? When two particles drift apart, a spring pulls them back. When they're pushed too close, the spring pushes them apart. This is the simplest path from fluid to solid.

The force on particle i from a spring connecting it to particle j is proportional to how far the current distance deviates from the rest length. A high stiffness makes the material rigid; a low stiffness makes it wobbly, like jelly.

Spring force
drag a particle
d = distance(i, j)              // current distance
strain = (d - restLen) / restLen // how stretched
F = -k * strain * dir(i, j)     // Hooke's law
Figure 1. Drag any particle to deform the network. Springs change color and thickness based on strain: amber when stretched, red when compressed. Try low stiffness for jelly, high for near-rigid.

Sand and Granular Materials

Sand is not a fluid, but it is not a solid either. Grains slide over each other, pile up into cones, and resist shearing. The key difference from water is friction: a force that opposes the relative tangential motion between neighboring particles.

When two particles are sliding past each other, the friction force acts perpendicular to the line connecting them, opposing the sliding direction. Combined with slightly higher viscosity and a bit of cohesion, this produces piles instead of puddles.

Friction force
watch the particles settle
v_rel = v[j] - v[i]             // relative velocity
n = normalize(r[j] - r[i])    // direction between particles
v_tan = v_rel - dot(v_rel, n) * n // tangential component
F_fric = -μ_f * v_tan * W(r, h)  // oppose sliding
Water (low viscosity, no friction)
Sand (high friction, slight cohesion)
Figure 2. Same initial drop, different parameters. Water spreads flat. Sand piles into a cone because friction resists sliding.

Temperature and Phase Transitions

Real materials change state: ice melts to water, water boils to steam. We can approximate this by giving each particle a temperature property that controls how it interacts with neighbors.

At low temperatures, particles form springs with their neighbors (like the elastic network above), creating a rigid lattice. As temperature rises, the springs weaken and break, letting particles flow freely. At high temperatures, the rest density drops and particles repel each other, expanding like a gas.

This is a simplified model. Real phase transitions involve latent heat, crystal structures, and more complex thermodynamics. But the intuition is right: temperature controls how strongly particles are bound to their neighbors.

Temperature-dependent spring stiffness
slide the temperature
T = temperature                     // 0 = cold, 1 = hot
k_eff = k_max * max(0, 1 - T / T_melt) // springs weaken with heat
ρ_rest = ρ_0 * (1 - 0.5 * max(0, T - T_boil)) // gas expands
Ice
Figure 3. Slide from cold to hot: ice (rigid lattice) to water (fluid) to gas (expanding). Particles are colored by temperature: blue is cold, red is hot.

Collisions with Solid Objects

So far our fluid lives in a box with invisible walls. But interesting simulations need obstacles: rocks in a stream, walls with openings, spinning paddles. There are two common approaches.

Boundary particles. Place fixed particles along solid surfaces. The same pressure and viscosity forces that push fluid particles apart will push them away from the boundary naturally. No special collision code needed.

Signed distance fields (SDF). For simple shapes like circles and rectangles, we can compute the shortest distance from a fluid particle to the surface. If a particle is inside the shape, push it out along the surface normal. This is faster than boundary particles for smooth shapes.

The simulation below uses SDFs for a circle and a rectangle. Drag them around to redirect the flow.

Signed distance collision
drag the shapes
d = sdf(particle, shape)        // signed distance (neg = inside)
if d < 0:                       // particle is inside shape
  pos += normal * |d|       // push to surface
  vel -= dot(vel, normal) * normal // remove inward velocity
Figure 4. Fluid particles fall onto a circle and rectangle. Drag either shape to reposition it. The SDF handles collision without any boundary particles.

Emitters, Sinks, and Force Fields

A simulation becomes much more expressive when you can control where particles come from, where they go, and what pushes them along the way.

Emitters continuously spawn particles at a location with an initial velocity. Sinks remove any particle that enters their region. Vector fields apply external forces based on position, like wind, gravity wells, or vortices. Together, these let you build flows that run indefinitely without filling up.

Click to add emitter. Shift+click to add sink.
Figure 5. Click to place emitters (green), shift+click for sinks (red). Toggle the vortex field to swirl particles around the center. Particles flow from sources to sinks through the field.

The SPH framework is a toolbox. Pressure and viscosity give you fluids. Add springs for solids, friction for sand, temperature for phase changes, SDFs for obstacles, and emitters for continuous flows. The simulation loop stays the same. Only the forces change. In Part 4 we combine all of these into an interactive sandbox.