Translated from the author's Korean original. Read the original (한국어)
In Lattice Boltzmann, the Wall Isn't on the Node — Bounce-Back and Zou-He Boundaries
After streaming, a bottom node is missing f2, f5, and f6. Zou-He closes density from the known populations; drop the momentum term and a moving wall never drags the fluid.
A single bounce rule builds a no-slip wall. The wall you get does not sit on the node you marked. It sits half a cell off. Miss that half cell when the channel height is counted, and wall friction drifts by a few percent.
Lattice Boltzmann (stream and collide distributions on a lattice) does not solve Navier–Stokes directly. A boundary condition is not a velocity written onto the wall. It is a choice of how to fill the populations that should have entered from outside. Three fillers show up here: bounce-back, the moving-wall correction, and Zou-He.
The half-way / full-way toggle moves the wall line a half-cell off the node or onto it, and the empty-direction marks move with it.
The cyan arrows are the populations left empty after streaming. Full-way lays the wall line on the node. Half-way pushes that line half a cell outside.
The distributions go missing at the wall#
A step splits into collision and streaming. Streaming pushes each one cell along its velocity . Interior nodes are fine. They have neighbors on every side, so every incoming distribution arrives.
A node against the wall is different. There is no fluid node beyond the wall. The distributions that should have come from that side have no source. On a D2Q9 (nine-velocity, 2D) lattice, a bottom-wall node is left with three upward directions empty after streaming.
What you fill those three with defines the physics of the wall. Leave them, and the fluid leaks through as if the wall were not there.
Bounce it back to make no-slip#
The simplest answer is bounce-back. A distribution that hits the wall returns the way it came, flipped to the opposite direction.
Here is the post-collision value and is the opposite direction with . The incoming momentum is sent straight back at full magnitude. The net velocity at the wall becomes zero. That is a stationary no-slip wall.
A flat bottom wall leaves three unknowns, . A corner leaves more. The count, split by face and corner, is in populations a boundary node loses.
The wall is half a cell off#
This is the crux. Bounce-back comes in two flavors.
Full-way flips every direction at the wall node over one step. The wall lands right on the node. It is easy to code but only first-order accurate in space.
Half-way reflects during streaming, at the fluid node. The bounce happens between two nodes. So the wall stands exactly half a cell outside the last fluid node — and it is second-order accurate.
That half cell is the practical trap. If you use half-way but count the channel height as the number of nodes minus one, , the effective height is wrong. Poiseuille peak velocity comes out a few percent off. It is easy to mistake this for an error that shrinks under refinement, but it is a systematic error from miscounting the wall position.
In half-way, the walls sit at and . The effective channel height is . The Couette solution is:
where is the node index and is the top-wall speed. The in is the fingerprint of the half-cell offset.
Move the wall, and set the pressure#
A stationary wall alone is not enough. You need moving walls and pressure boundaries.
A moving wall adds a momentum term to bounce-back. If the wall moves at velocity , the reflected distribution carries that much extra.
where is the lattice weight, the wall density, and the squared lattice speed of sound. This term pulls the wall's tangential momentum into the fluid. Without it, the wall can move and the fluid never follows.
To prescribe pressure or velocity as values, use the Zou-He method. At the wall node, the known distributions and the prescribed velocity let you solve algebraically for the density and the unknown distributions. At a bottom wall with prescribed velocity , the density closes as:
The density comes from the known downward and horizontal distributions alone. The remaining unknowns are filled by a non-equilibrium bounce-back. Because Zou-He matches mass and momentum exactly at the wall, it is steadier than bounce-back at pressure boundaries.
Verify the Couette wall in Python#
A Couette flow with only the top wall moving confirms the half-cell offset. On a wall built with half-way bounce-back, check that the steady velocity matches .
import numpy as np
ex = np.array([0, 1, 0, -1, 0, 1, -1, -1, 1])
ey = np.array([0, 0, 1, 0, -1, 1, 1, -1, -1])
w = np.array([4/9] + [1/9]*4 + [1/36]*4)
opp = np.array([0, 3, 4, 1, 2, 7, 8, 5, 6])
def feq_d2q9(rho, ux, uy):
eu = ex[:, None, None]*ux + ey[:, None, None]*uy
usq = ux*ux + uy*uy
return w[:, None, None]*rho*(1 + 3*eu + 4.5*eu*eu - 1.5*usq)
def simulate_couette(ny=32, U=0.05, tau=0.8, steps=6000):
nx = 4 # periodic in x, minimal width
f = np.tile(w[:, None, None], (1, ny, nx)).astype(float)
for _ in range(steps):
rho = f.sum(0)
ux = (ex[:, None, None]*f).sum(0)/rho
uy = (ey[:, None, None]*f).sum(0)/rho
fpost = f + (feq_d2q9(rho, ux, uy) - f)/tau # BGK collision
for i in range(9): # streaming (periodic x)
f[i] = np.roll(fpost[i], (ey[i], ex[i]), axis=(0, 1))
# bottom stationary wall + moving top wall (half-way bounce-back)
for i in (2, 5, 6):
f[i, 0, :] = fpost[opp[i], 0, :]
for i in (4, 7, 8):
corr = 2*w[i]*rho[-1, :]*(ex[i]*U)/(1/3)
f[i, -1, :] = fpost[opp[i], -1, :] - corr
rho = f.sum(0)
return (ex[:, None, None]*f).sum(0).mean(1)/rho.mean(1) # ux(y)
ny = 32
ux = simulate_couette(ny=ny)
j = np.arange(ny)
exact = 0.05*(j + 0.5)/ny
print("RMS error:", np.sqrt(np.mean((ux - exact)**2)))
# RMS error: 3.1e-15 <- with the half-cell fix, machine precisionCompare against instead of and the RMS jumps to a few percent. The half cell reveals itself at once.
In the simulation below, change the wall rule and the wall speed yourself.
With bounce-back, the cyan measured line hugs the yellow exact (linear) solution. Switch to free-slip and no matter how fast the top wall runs, the fluid never follows. The wall's tangential momentum is not transmitted to the fluid. What makes no-slip, in the end, is this one bounce rule.
Counting the height as ny-1 leaves an error that stays#
Half-way walls sit at and . The effective height is . Drop the code values and into the line and the bottom node moves at . Not zero. The top node is , short of by half a cell. The printed RMS is the gap against that line. Compare with and the gap jumps to a few percent. Refinement does not shrink the ratio. The empty directions on the bottom are .
The moving-wall correction has , so . The code's /(1/3) builds that 6. A diagonal weight times 6 is . A cardinal weight times 6 is . The rest weight never enters the term. If is normal to the wall velocity, the correction is 0. Zou-He's factor is 1 on a bottom wall with , and the density closes from the known populations alone. As approaches 1 the denominator vanishes. Leave the empty populations untouched and the fluid passes through the wall. Push lower and the collision starts to shake first. Splitting the relaxation by direction is the step into moment-space MRT.
Related
Share if you found it helpful.