ln03 Pa
ln03 Pa
ln03 Pa
Ma ≡ u cs (3.1)
the Mach number (and – as introduced before – u the bulk velocity and cs the speed of
sound). For incompressible flow cs → ∞ . Since cs = 1 3 (in lattice units) it means that we
need to make sure that u ≪ 1 in lattice units. As we will see in the next section – which is
about how to deal with lattice units when solving real flow systems stated in SI units – the
constraint on the bulk speed u ≪ 1 effectively is a constraint on the time step.
1
Figure 3.1
This flow problem is stated in SI units. We need to translate it into lattice units and need to
make decisions regarding time step and lattice cell size. For this we translate the flow system
in dimensionless form by scaling with the input variables U and L where we indicate
dimensionless variables with ~:
ɶx = x L, ɶy = y L, ɶt = tU L , u
ɶ=u U (3.2)
Dimensional analysis of the flow problem itself shows that the Reynolds number is the all-
determining parameter:
ρUL UL
Re = = (3.3)
µ ν
From the above we now thus are tasked with performing a lid-driven cavity LB simulation at
Re=200 and we need to choose our simulation parameters. The first choice is for U LB . Since
we want to simulate an incompressible flow, the Mach number Ma needs to be sufficiently
small. Since we expect that the maximum fluid speed in the cavity is equal to the speed of the
lid, the Mach number will not exceed U LB cs . We choose U LB =0.1. With U LB =0.1,
U LB cs =0.17 which is sufficiently small. The second choice is for LLB . The spatial resolution
of the simulation is governed by LLB since LLB is the number of lattice nodes in x and y
direction. We now need some fluid dynamics intuition about the flow in a cavity at Re=200.
This is going to be a laminar flow with not much fine-scale detail; we expect a single
recirculation loop that fills the largest part of the cavity. We expect that this recirculation loop
is going to be well-resolved on a 20×20 mesh so that we choose LLB =20. In order to achieve
2
U LB LLB
Re=200, the kinematic viscosity in lattice units thus needs to be ν LB = = 0.01. This
Re
can be realized by a collision operator with a relaxation time of (see Eq. 2.9)
τ = 3ν + 12 = 0.53.
The scaling analysis for lid-driven cavity flow is relatively easy since we were given a
velocity scale in the form of the lid speed U. If we were to be asked to simulate the flow
between two flat, vertical parallel plates as a result of gravity (see Figure 3.2) our input
parameters are the distance between the plates 2D, the properties of the fluid (kinematic
viscosity ν and the density ρ ), and gravitational acceleration g. Dimensional analysis shows
that this flow is governed by the dimensionless group D 3 g ν 2 (density does not show up
since the two balancing effects of gravity and viscous forces are both proportional to the
density: ρ g and ρν ) so that in an LB simulation we must match this dimensionless number.
Some notion of the hydrodynamics of this system will make us decide on what to choose for
D in lattice units (if we expect laminar flow D=10 should be OK). We then still have two free
parameters ν and g in lattice units to decide upon. We need to do some a priori analysis to
estimate the expected flow velocities (which in this basic flow example is very simple) to
come up with a ν and g combination (in lattice units) such that we match the dimensionless
group and have flow speeds that are sufficiently low in order to meet the compressibility
constraints.
Figure 3.2
3
The lid-driven cavity example clearly shows the role of – and the need for – defining
boundary conditions. Boundary conditions in LB simulations are a topic of active research
and come in a large variety of forms and implementations. Here we discuss a few of the more
basic and most used ones.
Figure 3.3
Figure 3.4
where we used the numbering of velocities as earlier given in Figure 2.1, repeated for your
convenience in Figure 3.6.
Figure 3.5
Figure 3.6
We note that change of momentum can only achieved by a change in mass. As we can see in
Eq. 3.4, the net change in mass is equal to zero since w7 = w8 = 1 36 .
5
Figure 3.7
Figure 3.8
Figure 3.9
Inlet boundary
In principle, the no-slip boundary condition at moving wall as discussed above (see Figure
3.5) can also be applied if the velocity of the boundary has a component normal to the
boundary. In that sense it can be used to impose a velocity or a velocity profile at the inlet of a
flow system. I write “in principle” since I do not have experience with using this way of
defining an inlet. What I usually do is applying a force on the fluid at an inlet to impose an
inlet velocity, in combination with a zero-gradient boundary (see above).
Immersed boundaries
Immersed boundary methods are applied over a wide spectrum of approaches to simulating
fluid flow, the LB method being no exception. The idea is to locally exert forces on the flow
such that as a result of these forces the velocity at certain locations in the flow takes on
desired values (e.g. zero velocity if we want to impose a static no-slip condition).
6
A significant advantage of the immersed boundary method is the possibility to impose off-
grid conditions and/or moving boundaries. When applying immersed boundaries for off-grid
(e.g. curved) boundaries, one uses interpolation to estimate velocities at points that do not
coincide with lattice nodes. One uses extrapolation to distribute the forces acting on the fluid
at points not coinciding with lattice nodes to lattice nodes. For better appreciating the
workings of the immersed boundary method we first need to know how to apply forces to an
LB fluid. This topic will be discussed in LN04 where we then also will revisit the immersed
boundary method.
3.5 Coding
The ingredients of an LB computer code are
(1) Definitions: set grid size nx × ny , number of time steps, kinematic viscosity ν , weighing
factors wi .
(2) Initialize f i* (x, t = 0) , e.g. by setting it equal to the equilibrium distribution function with
uniform ρ and u = 0 .
Start the time stepping loop; what comes now is done each time step
(3) Fill the ghost cells with boundary values of f i*
(4) Stream
(5) Collide & return to (3) until the pre-set number of time steps is completed
Leave the time stepping loop and write to file, plot,… etc.
A sample code in Matlab (lusby2.m named after a 4th year project student) for lid-driven
cavity flow has been distributed under the course participants. It is a D2Q9 code with velocity
numbering as defined in LN02.
Below are coding suggestions regarding some of the main ingredients of the LB algorithm.
The pieces of computer code are in Matlab with the exception of the array (or vector if you
wish) indices. Matlab does not allow these to be smaller than 1. Since our velocity direction
numbering starts with i = 0 , I decided – for clarity – to keep this numbering in the code
fragments below.
Streaming
In streaming we execute Eq. 2.11 (repeated here as Eq. 3.5):
f i (x + ci , t + 1) = f i * ( x, t ) (3.5)
After we have dealt with our boundary conditions via populating ghost cells (as explained in
the previous section) this can be implemented in computer code as a loop over all the active
(i.e. non-ghost) lattice nodes. One could be tempted to work with two arrays
f(0…8,1…nx,1…ny)for the left-hand side of Eq. 3.5 and
fstar(0…8,0…nx+1,0…ny+1)for the right-hand side and with nx the number of active
lattice nodes in x-direction and ny the number of active nodes in y-direction. Note that
fstar needs to include ghost cells, hence the extension to 0…nx+1,0…ny+1 where f has
1…nx,1…ny. Then do something like this piece of pseudo code (where I refer to the velocity
numbering in Figure 3.6).
for j=1:ny
for i=1:nx
7
f(0,i,j)=fstar(0,i,j)
f(1,i,j)=fstar(1,i-1,j)
f(2,i,j)=fstar(2,i+1,j)
f(3,i,j)=fstar(3,i,j-1)
f(4,i,j)=fstar(4,i,j+1)
f(5,i,j)=fstar(5,i-1,j-1)
f(6,i,j)=fstar(6,i+1,j-1)
f(7,i,j)=fstar(7,i+1,j+1)
f(8,i,j)=fstar(8,i-1,j+1)
end
end
This is not a smart way to do streaming as it requires two large arrays (specifically in 3D and
for big computations these arrays can get huge) and thus eats up lots of computer memory.
We can do, however, with one array f(0…8,0…nx+1,0…ny+1). At the start of the
streaming operation this array contains f i* , including its values in the ghost nodes. Then we
run the following
for j=1:ny
for i=1:nx
f(2,i,j)=f(2,i+1,j)
f(4,i,j)=f(4,i,j+1)
f(7,i,j)=f(7,i+1,j+1)
f(8,i,j)=f(8,i-1,j+1)
end
end
for j=ny:-1:1
for i=nx:-1:1
f(1,i,j)=f(1,i-1,j)
f(3,i,j)=f(3,i,j-1)
f(5,i,j)=f(5,i-1,j-1)
f(6,i,j)=f(6,i+1,j-1)
end
end
Note that in the second double loop we go in reverse order (the -1 in the for statements). The
trick here is to update from f i* to f i in the same direction as you go through the loops so that
on the right side of the equal sign there actually is an f i* and not an already updated f i . In
one dimension this is relatively simple. In two dimensions (as is the case here) one should
realize that the data is ordered as
(i, j ) : (1,1)(2,1)⋯(nx,1) (1, 2)(2, 2)⋯(nx, 2) ⋯⋯ (1, ny )(2, ny )⋯(nx, ny )
8
% bounce back at bottom
j=0;
for i=1:nx
x(3,i,j)=x(4,i,j+1);
x(5,i,j)=x(7,i+1,j+1);
x(6,i,j)=x(8,i-1,j+1);
end
for j=1:ny
for i=1:nx
rho=x(0,i,j)+x(1,i,j)+x(2,i,j)+x(3,i,j)+x(4,i,j)+x(5,i,j)+x(6,i,j)+
x(7,i,j)+x(8,i,j);
rrho=1.0/rho;
ux=x(1,i,j)-x(3,i,j)+x(5,i,j)-x(6,i,j)-x(7,i,j)+x(8,i,j);
ux=ux*rrho;
uy=x(2,i,j)-x(4,i,j)+x(5,i,j)+x(6,i,j)-x(7,i,j)-x(8,i,j);
uy=uy*rrho;
usq=ux*ux+uy*uy;
xeq(0)=m0*rho*(1.0-1.5*usq);
cdotu=ux;
xeq(1)=m1*rho*(1.0+3.0*cdotu+4.5*cdotu*cdotu-1.5*usq);
cdotu=uy;
xeq(2)=m1*rho*(1.0+3.0*cdotu+4.5*cdotu*cdotu-1.5*usq);
cdotu=-ux;
xeq(3)=m1*rho*(1.0+3.0*cdotu+4.5*cdotu*cdotu-1.5*usq);
cdotu=-uy;
xeq(4)=m1*rho*(1.0+3.0*cdotu+4.5*cdotu*cdotu-1.5*usq);
cdotu=ux+uy;
xeq(5)=m2*rho*(1.0+3.0*cdotu+4.5*cdotu*cdotu-1.5*usq);
cdotu=-ux+uy;
xeq(6)=m2*rho*(1.0+3.0*cdotu+4.5*cdotu*cdotu-1.5*usq);
cdotu=-ux-uy;
xeq(7)=m2*rho*(1.0+3.0*cdotu+4.5*cdotu*cdotu-1.5*usq);
cdotu=ux-uy;
xeq(8)=m2*rho*(1.0+3.0*cdotu+4.5*cdotu*cdotu-1.5*usq);
for l=0:8
x(l,i,j)=(1.0-rtau)*x(l,i,j)+rtau*xeq(l);
end
end
end
9
If you do not feel like writing your own code, there are open-source code available online,
e.g.
http://www.openlb.net/
http://www.palabos.org/
10