Fluid Simulation

8 Nov 2022


This was a guest lecture by Dr. John Keyser

To simulate fluids, we can simulate a velocity field which is applied to liquid or suspended particles.

There are two types of simulation:

  • Lagrangian, where material is discretized as in smoothed-particle hydrodynamics (SPH).
  • Eulerian, where space is discretized as in stable fluids.

§ Smoothed-Particle Hydrodynamics

See: review of Smoothed particle hydrodynamics (Monaghan, 2005).

  • Use particles to represent fluid.
    • Particle motion is the same as material transport.
  • The particles hold information.
    • The information is accurate at the particle's position, however, it falls off with distance
  • The fall-off can be given by a weight function W(r)=W(xixj),W(r) = W(\|\vec{x}_i - \vec{x}_j\|), typically called a kernel for SPH.
    • Characteristics of W:W:
      • Radial symmetry
      • Finite support
      • Integrated volume
      • Monotonically decreasing, with max at r=0r = 0
      • Smooth gradient at boundary
      • See: poly6 kernel

If particles have some characteristic that they carry (e.g. velocity), we can compute a weighted average of influence to determine the characteristic at any point in space.

Let φi\varphi_i be some characteristic measured at particle i.i. Then,

φ(x)=iφimiW(xxi)imiW(xxi)\varphi(\vec{x}) = \frac{\sum_{i} \varphi_i m_i W\left(\|\vec{x} - \vec{x}_i\|\right)}{\sum_{i} m_i W\left(\|\vec{x} - \vec{x}_i\|\right)}

where mim_i is the mass of the particle, typically mi=1m_i = 1 everywhere.

The denominator of the above is the particle density,

ρi=jmjW(xixj).\rho_i = \sum_j m_j W(\|\vec{x}_i - \vec{x}_j\|).

Then, a characteristic can be computed for any xR3\vec{x} \in \mathbb{R}^3, not just particle position xk:\vec{x}_k:

φ(x)=iφimiρ(x)W(xxi)\varphi(\vec{x}) = \sum_i \varphi_i \frac{m_i}{\rho(\vec{x})} W(\|\vec{x} - \vec{x}_i\|)

This also makes it easy to compute the derivatives of characteristics,

φ(x)=iφimiρ(x)W(xxi)=iφimiρ(x)W(xxi)2φ(x)=iφimiρ(x)2W(xxi)\begin{align*} \nabla\varphi(\vec{x}) &= \nabla \sum_i \varphi_i \frac{m_i}{\rho(\vec{x})} W(\|\vec{x} - \vec{x}_i\|)\\ &= \sum_i \varphi_i \frac{m_i}{\rho(\vec{x})} \nabla W(\|\vec{x} - \vec{x}_i\|)\\ \nabla^2 \varphi(\vec{x}) &= \sum_i \varphi_i \frac{m_i}{\rho(\vec{x})} \nabla^2 W(\|\vec{x} - \vec{x}_i\|) \end{align*}

§ Fluid Forces

Force is defined by

F=ma.F = m\vec{a}.

In fluids, instead of mass we have density

F=ρa    a=1ρF.F = \rho\vec{a} \iff \vec{a} = \frac{1}{\rho} F.

Then, we can define the pressure force as p-\nabla p:

pjρpj=imi(piρi2+pjρj2)W(xixj).\frac{\nabla p_j}{\rho p_j} = \sum_i m_i \left(\frac{p_i}{\rho^2_i} + \frac{p_j}{\rho^2_j}\right) \nabla W(\|\vec{x}_i - \vec{x}_j\|).

p=kρ0γ[(ρρ0)γ1]pi=k(ρiρ0)\begin{align*} p &= \frac{k \rho_0}{\gamma} \left[\left(\frac{\rho}{\rho_0}\right)^{\gamma} - 1\right]\\ p_i &= k (\rho_i - \rho_0) \end{align*}

where ρ0\rho_0 is rest density, kk is a stiffness constant, and usually γ=1.\gamma = 1.

We can compute pip_i for each particle, then compute the pressure force from that.

§ Diffusion and Viscosity

Fviscosity=ν2v=νv=νdiv(v)=jmivivjρj2W(xixj).\begin{align*} F^{\textrm{viscosity}} &= \nu \nabla^2 \vec{v} = \nu \nabla \cdot \nabla \vec{v} = \nu\,\textrm{div}(\nabla \vec{v})\\ &= \sum_j m_i \frac{\vec{v}_i - \vec{v}_j}{\rho_j} \nabla^2 W(\|\vec{x}_i - \vec{x}_j\|). \end{align*}

where ν\nu is the kinematic viscosity.

Other forces can also be applied such as gravity or surface tension.

§ Stable Fluids (1999)

See: Stable Fluids (Stam, 1999).

The the algorithm is as follows:

Stable Fluids

  • while simulation loop do
    • u(n)\vec{u}^{(n)} \leftarrow velocity at time n.n.
    • w0=u(n)\vec{w}_0 = \vec{u}^{(n)}
    •  
    • w1=w0+ΔtFρ\vec{w}_1 = \vec{w}_0 + \Delta t \frac{\vec{F}}{\rho}
    •  
    • w2=backtrace(w1,Δt)\vec{w}_2 = \verb|backtrace|(\vec{w}_1, \Delta t)
    • w^2=FFT(w2)\hat{w}_2 = \mathrm{FFT}(\vec{w}_2)
    •  
    • w^3=w^2(IνΔt2)1\hat{w}_3 = \hat{w}_2 \left(\mathbf{I} - \nu \Delta t \nabla^2\right)^{-1} [a]
    •  
    • w^4=w^3φ\hat{w}_4 = \hat{w}_3 - \nabla \varphi
    • w4=FFT1(w^4)\vec{w}_4 = \mathrm{FFT}^{-1}(\hat{w}_4) [b]

Backtrace

In each step, want to know what the new velocity is at a point based on the prior velocity.

In other words, we want to advect the fluid's velocity.

If we simply move the velocity forward along its direction, we may end up with more velocity (energy) than we started with.

A simple solution is to use a 'semi-Lagrangian' method trace a "particle" backward from the point that we want to know.

[a]: This step applies the fluid's viscosity, as noted in the paper it is equivalent to the following diffusion equation:

w2t=ν2w2.\frac{\partial \vec{w}_2}{\partial t} = \nu \nabla^2 \vec{w}_2.

By recognizing the fact that we can discretize the Laplacian 2\nabla^2 (because we have discretized the space), we can apply the Fourier transform to convolve the space with the Laplacian kernel then do the inverse Fourier to recover the field.

[b]: This step is about projecting the field onto a divergence-free field.

The scalar field φ\varphi is a result of the Helmholtz-Hodge decomposition.

Helmholtz-Hodge Decomposition

Any vector field w\vec{w} can be split intop the sum of a divergence-free vector field u\vec{u} and a curl-free vector field v.\vec{v}.

w=u+v,u=0,×v=0.\vec{w} = \vec{u} + \vec{v}, \nabla \cdot \vec{u} = \mathbf{0}, \nabla \times \vec{v} = \mathbf{0}.

Divergence free: u\vec{u} is incompressible (no sources/sinks)

Curl free     v\iff \vec{v} is the gradient of some scalar field φ,\varphi, i.e. v=φ.\vec{v} = \nabla \varphi.

Following Helmholtz-Hodge:

u=wv=wφw=u+v=v=2φ\begin{align*} \vec{u} &= \vec{w} - \vec{v}\\ &= \vec{w} - \nabla \varphi\\ \nabla \cdot \vec{w} &= \nabla \cdot \vec{u} + \nabla \cdot \vec{v}\\ &= \nabla \vec{v}\\ &= \nabla^2 \varphi \end{align*}

Then, plugging in w3\vec{w}_3, we get that w3=2φ\nabla \cdot \vec{w}_3 = \nabla^2 \varphi in which we solve for φ\varphi.