Create Your Own Lattice Boltzmann Simulation (With Python)
By: Philip Mocz
Tags: Python, Lattice, Physics, Fluid Mechanics, Simulation

Fluid dynamics on a Lattice

We will begin with a microscopic description of a fluid that lives on a lattice. For this exercise, we will consider a 2 dimensional lattice with 9 possible velocities at each lattice site (D2Q9). There are 4 connections running North, South, East, and, West, 4 diagonal connections, and 1 connection from a node to itself representing zero velocity. Each lattice site also has a weight wᵢ associated with it:

The microscopic particles that make up a fluid can be described with the distribution function f(x,v), which describes the the phase-space density of fluids at location x traveling with velocity v.

The particles will do two things. Stream and collide. This behavior can be captured by the BGK approximation:

where the left-hand side represents streaming, and the right-hand side approximates collisions. In this approximation, τ is the timescale of which collisions happen, and the distribution function f tends towards some equilibrium state f^eq as a result.

The equation may be discretized onto the lattice as follows

where i denotes 1 out of the 9 lattice directions (with velocity vᵢ).

Moments of the discrete distribution function can be taken to recover fluid variables at each lattice site. For example, the density:

and momentum:

where the sum is over all lattice directions.

It can be shown that this description approximates the Navier-Stokes fluid equations.

Streaming

The first step in the Lattice Boltzmann method is to stream the particles. This step is incredibly simple. Conceptually, here is what happens. At each lattice site, for each direction i, the value Fᵢ is shifted over to the neighboring lattice site along the connection.

Typically in the Lattice Boltzmann method uses units of Δt=Δx=1 and we will use this convention throughout. The streaming velocities are hence: (0,0), (0,1), (0,-1), (1,0), (-1,0), (1,1), (1,-1), (-1,1), (-1,-1).

Collisions

Next we need to define the equilibrium state as a result of collisions. This depends on the fluid model’s equation of state. For this example, we will assume an isothermal (constant temperature) fluid, which has a constant sound speed. We define units using common conventions such that the lattice speed is c=1 (which corresponds soundspeed²=1/3). The equilibrium state is given by:

which corresponds to the isothermal Navier-Stokes equations with a dynamic viscosity:

Boundary

Boundary conditions in Lattice Boltzmann are implemented on the microscopic level. In our simulation, we wish to add a solid cylinder. Lattice sites part of this cylinder may be flagged. Here particles will behave differently. In our example, we will consider reflective boundary conditions. Instead of collisions that lead to equilibrium, particles will simply bounce back. This is easily accomplished by swapping lattice directions:

where i and j correspond to lattice directions that point in opposite directions.

Lattice Boltzmann Method

That’s it conceptually. Let’s put it all together! The following code sets up the lattice and initial condition for Fᵢ, and alternates streaming and collision(+boundary) operators to evolve the system. It is remarkable that this restricted microscopic representation is able to capture macroscopic fluid behavior.

Flow Past Cylinder

The initial conditions above place a static cylinder into a periodic box with rightward moving fluid. As the flow progresses, turbulence develops in the wake behind the cylinder. This is known as the Kármán vortex street.