Skip to content

Commit 0c62f39

Browse files
author
maruthinh
committed
first commit: D2Q9 code to solve lod driven cavity test case
without using any for-loops.
0 parents  commit 0c62f39

File tree

6 files changed

+296
-0
lines changed

6 files changed

+296
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ignoring some folder related to python probably gets
2+
generated by spyder IDE
3+
D2Q9/__pycache__/
4+
.idea
5+
__pycache__
6+
*.png

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
D2Q9 LBM code to solve lid driven cavity problem. This code has zero for loops
2+
3+
To run the code
4+
5+
```
6+
python3.8 lid_driven_cavity.py
7+
```
8+
Velocity contour plot obtained from the solver. Simulation is carried out
9+
with 64 x 64 grid points. Solution has converged to 1e-10
10+

bc.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from d2q9 import D2Q9
2+
3+
4+
class BoundaryConditions(D2Q9):
5+
6+
def __init__(self, f):
7+
self.f = f
8+
self.f[:, 0, :] = self.f[:, 1, :]
9+
self.f[:, -1, :] = self.f[:, -2, :]
10+
self.f[:, :, 0] = self.f[:, :, 1]
11+
self.f[:, :, -1] = self.f[:, :, -2]
12+
D2Q9.__init__(self)
13+
14+
def periodic_in_x(self):
15+
"""
16+
To apply periodic boundary condition in x
17+
"""
18+
self.f[1, 0, 1:-1] = self.f[1, -1, 1:-1]
19+
self.f[8, 0, 1:-1] = self.f[8, -1, 1:-1]
20+
self.f[5, 0, 1:-1] = self.f[5, -1, 1:-1]
21+
22+
self.f[6, -1, 1:-1] = self.f[6, 0, 1:-1]
23+
self.f[3, -1, 1:-1] = self.f[3, 0, 1:-1]
24+
self.f[7, -1, 1:-1] = self.f[7, 0, 1:-1]
25+
26+
def bounce_back_right(self):
27+
"""
28+
Apply bounce back on right wall
29+
"""
30+
self.f[3, -2, 2:-2] = self.f[1, -1, 2:-2]
31+
self.f[6, -2, 2:-2] = self.f[8, -1, 2:-2]
32+
self.f[7, -2, 2:-2] = self.f[5, -1, 2:-2]
33+
34+
def bounce_back_left(self):
35+
"""
36+
Apply bounce back on right wall
37+
"""
38+
self.f[8, 1, 2:-2] = self.f[6, 0, 2:-2]
39+
self.f[1, 1, 2:-2] = self.f[3, 0, 2:-2]
40+
self.f[5, 1, 2:-2] = self.f[7, 0, 2:-2]
41+
42+
def bounce_back_bottom(self):
43+
"""
44+
Apply bounce back on right wall
45+
"""
46+
self.f[2, 2:-2, 1] = self.f[4, 2:-2, 0]
47+
self.f[6, 2:-2, 1] = self.f[8, 2:-2, 0]
48+
self.f[5, 2:-2, 1] = self.f[7, 2:-2, 0]
49+
50+
def moving_wall_bc_top(self, u_wall):
51+
"""
52+
Apply moving wall bounce back on top wall
53+
"""
54+
density=self.f.sum(axis=0)
55+
self.f[4, 1:-1, -2] = self.f[2, 1:-1, -1]
56+
self.f[7, 1:-1, -2] = self.f[5, 1:-1, -1] + 6.0 * density[1:-1, -1] * self.w[7] * self.c[0][7] * u_wall
57+
self.f[8, 1:-1, -2] = self.f[6, 1:-1, -1] + 6.0 * density[1:-1, -1] * self.w[8] * self.c[0][8] * u_wall
58+
59+
def bot_left_corner_correction(self):
60+
"""
61+
Bottom left corner
62+
"""
63+
self.f[2, 1, 1] = self.f[4, 1, 0]
64+
self.f[5, 1, 1] = self.f[7, 1, 0]
65+
self.f[1, 1, 1] = self.f[3, 1, 0]
66+
self.f[8, 1, 1] = self.f[6, 1, 0]
67+
self.f[6, 1, 1] = self.f[8, 1, 0]
68+
69+
def bot_right_corner_correction(self):
70+
"""
71+
Bottom right corner
72+
"""
73+
self.f[2, -2, 1] = self.f[4, -2, 0]
74+
self.f[6, -2, 1] = self.f[8, -2, 0]
75+
self.f[3, -2, 1] = self.f[1, -2, 0]
76+
self.f[5, -2, 1] = self.f[7, -2, 0]
77+
self.f[7, -2, 1] = self.f[5, -2, 0]
78+
79+
def top_left_corner_correction(self):
80+
"""
81+
Top left corner
82+
"""
83+
self.f[5, 1, -2] = self.f[7, 1, -1]
84+
self.f[7, 1, -2] = self.f[5, 1, -1]
85+
self.f[1, 1, -2] = self.f[3, 1, -1]
86+
self.f[8, 1, -2] = self.f[6, 1, -1]
87+
self.f[4, 1, -2] = self.f[2, 1, -1]

d2q9.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import numpy as np
2+
3+
4+
class D2Q9:
5+
6+
def __init__(self):
7+
self.c = np.array([[0.0, 1.0, 0.0, -1.0, 0.0, 1.0, -1.0, -1.0, 1.0],
8+
[0.0, 0.0, 1.0, 0.0, -1.0, 1.0, 1.0, -1.0, -1.0]])
9+
self.w = np.array([4.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0,
10+
1.0 / 36.0, 1.0 / 36.0, 1.0 / 36.0, 1.0 / 36.0])
11+
self.q = 9
12+
self.T0 = 1 / 3.0
13+
self.a = np.sqrt(self.T0)
14+
15+
def feq(self, moments):
16+
"""
17+
To compute equilibrium distribution function.
18+
"""
19+
20+
feq = np.zeros((self.q, moments.shape[1], moments.shape[2]))
21+
22+
udotc = (np.array([[self.c[0]]]).T*moments[1]) + (np.array([[self.c[1]]]).T*moments[2])
23+
usq = moments[1] * moments[1] + moments[2] * moments[2]
24+
feq = (np.array([[self.w]]).T*moments[0]) * (1.0 + 3.0 * udotc - 1.5 * usq + 4.5 * udotc ** 2
25+
+ 4.5 * udotc ** 3 - 4.5 * usq * udotc)
26+
return feq
27+
28+
def moments(self, f):
29+
"""
30+
Compute moments (rho, u, v) from populations
31+
"""
32+
mom = np.zeros((3, f.shape[1], f.shape[2]))
33+
34+
mom[0] = f.sum(axis=0)
35+
mom[1] = (np.array([[self.c[0]]]).T*f).sum(axis=0)/mom[0]
36+
mom[2] = (np.array([[self.c[1]]]).T*f).sum(axis=0)/mom[0]
37+
38+
return mom
39+
40+
def collision(self, f, beta, alpha=2.0):
41+
"""
42+
computes collision term
43+
"""
44+
45+
feq = self.feq(self.moments(f))
46+
47+
f += alpha * beta * (feq - f)
48+
f.cumsum(axis=0)
49+
50+
51+
@staticmethod
52+
def advection(f):
53+
"""
54+
Streaming of velocities
55+
"""
56+
57+
f[3, :-1, :] = f[3, 1:, :]
58+
f[4, :, :-1] = f[4, :, 1:]
59+
f[7, :-1, :-1] = f[7, 1:, 1:]
60+
f[8, 1:, :-1] = f[8, :-1, 1:]
61+
62+
f[1, -1:0:-1, ::-1] = f[1, -2::-1, ::-1]
63+
f[2, ::-1, -1:0:-1] = f[2, ::-1, -2::-1]
64+
f[5, -1:0:-1, -1:0:-1] = f[5, -2::-1, -2::-1]
65+
f[6, -2:0:-1, -1:0:-1] = f[6, -1:1:-1, -2::-1]

lid_driven_cavity.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
import time
4+
5+
from d2q9 import D2Q9
6+
from bc import BoundaryConditions
7+
from sim_params import SimParams
8+
9+
nx = 64
10+
ny = 64
11+
ghost_x = 2
12+
ghost_y = 2
13+
tot_nx = nx + ghost_x
14+
tot_ny = ny + ghost_y
15+
ndim = 2
16+
model = D2Q9()
17+
sim_params = SimParams(mach=0.1, reynolds_num=100, ref_len=1.0, res=0.02)
18+
q = model.q
19+
20+
rho_ini = 1.0
21+
p = rho_ini * model.T0
22+
u_ini = 0.0
23+
v_ini = 0.0
24+
25+
#initialization of arrays required
26+
f = np.zeros((q, tot_nx, tot_ny))
27+
moments = np.zeros((3, tot_nx, tot_ny))
28+
moments[0] = rho_ini
29+
moments[1] = u_ini
30+
moments[2] = v_ini
31+
32+
u0 = np.zeros((tot_nx, tot_ny))
33+
v0 = np.zeros((tot_nx, tot_ny))
34+
35+
36+
f = model.feq(moments)
37+
38+
iter = 0
39+
err = 1.0
40+
start = time.time()
41+
42+
#main iteration loop
43+
while(err>1e-10):
44+
iter+=1
45+
model.collision(f, sim_params.beta)
46+
bc = BoundaryConditions(f)
47+
model.advection(f)
48+
bc.bounce_back_left()
49+
bc.bounce_back_bottom()
50+
bc.bounce_back_right()
51+
bc.moving_wall_bc_top(sim_params.ref_vel)
52+
53+
if iter % 1000 == 0:
54+
moments=model.moments(f)
55+
e1 = np.sum(np.sqrt((moments[1] - u0) ** 2 + (moments[2] - v0) ** 2))
56+
e2 = np.sum(np.sqrt(moments[1] ** 2 + moments[2] ** 2))
57+
err = e1 / e2
58+
print('error is = ', err)
59+
u0 = moments[1]
60+
v0 = moments[2]
61+
62+
print("total time taken: ", time.time()-start)
63+
64+
# to plot contours of velocity
65+
x = np.linspace(0, 1, nx)
66+
y = np.linspace(0, 1, ny)
67+
X, Y = np.meshgrid(x, y)
68+
VelNorm = np.sqrt(moments[1, 1:-1, 1:-1] * moments[1, 1:-1, 1:-1]
69+
+ moments[2, 1:-1, 1:-1] * moments[2, 1:-1, 1:-1])
70+
71+
plt.figure()
72+
# cp = plt.contourf(X, Y, np.transpose(VelNorm), 25, cmap=plt.cm.viridis)
73+
cp = plt.contour(X, Y, np.transpose(VelNorm), 15)
74+
cbar=plt.colorbar(cp)
75+
cbar.set_label('Velocity', fontsize=12)
76+
plt.xlabel('x', fontsize=12)
77+
plt.ylabel('y', fontsize=12)
78+
plt.xticks(fontsize=12)
79+
plt.yticks(fontsize=12)
80+
plt.savefig('velocity_cont1.png', bbox_inches='tight')
81+

sim_params.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from d2q9 import D2Q9
2+
3+
4+
class SimParams(D2Q9):
5+
def __init__(self, mach, reynolds_num, ref_len, res):
6+
self.mach_num = mach
7+
self.reynolds = reynolds_num
8+
self.ref_len = ref_len
9+
self.res = res
10+
self.dt = self.res
11+
D2Q9.__init__(self)
12+
13+
@property
14+
def ref_vel(self):
15+
"""
16+
Compute reference velocity
17+
"""
18+
return self.mach_num * self.a
19+
20+
@property
21+
def knudsen(self):
22+
"""
23+
Compute Knudsen number
24+
"""
25+
return self.mach_num / self.reynolds
26+
27+
@property
28+
def nu(self):
29+
"""
30+
Compute viscosity from reference length, velocity and Reynolds number
31+
"""
32+
return self.ref_len * self.ref_vel / self.reynolds
33+
34+
@property
35+
def tau0(self):
36+
return self.nu / self.T0
37+
38+
@property
39+
def tau_ndim(self):
40+
return self.tau0 / self.dt
41+
42+
@property
43+
def beta(self):
44+
"""
45+
Relaxation
46+
"""
47+
return 1.0 / (2.0 * self.tau_ndim + 1.0)

0 commit comments

Comments
 (0)