MATLAB code: Finite difference projection method for 2D incompressible Navier-Stokes equations
Date:
%The space is discretized with finite difference method. The first-order pressure projection algorithm is used to update velocities and pressure. The intermediate velocities are updated with an explicit Euler method. The pressure Poisson equation is solved with a Gauss-Seidel-type iteration.
clear all; clc; close all;
nx = 64; ny = nx;
xleft = 0; xright = 1; yleft = 0; yright = ny/nx*xright;
h = (xright - xleft)/nx; h2 = h^2;
bdvel = 1; % boundary velocity at top
x = linspace(xleft+0.5h, xright-0.5h, nx);
y = linspace(yleft+0.5h, yright-0.5h, ny);
max_it = 10000; ns = max_it/10;
Re = 10000; dt = 0.01h2Re; tol = 0.00001;
% initialization
p = zeros(nx,ny); u = zeros(nx+1,ny+2); v = zeros(nx+2,ny+1);
nu=u; nv=v; tu = zeros(nx+1,ny); tv = zeros(nx,ny+1);
adv_u = tu; adv_v = tv; uu = zeros(nx,ny); vv = zeros(nx,ny);
f = zeros(nx,ny);
for it = 1:max_it
% boundary condition of u
for i = 1:nx+1
u(i,1) = -u(i,2); u(i,ny+2) = 2*bdvel - u(i,ny+1);
end
% boundary condition of v
for j = 1:ny+1
v(1,j) = -v(2,j); v(nx+2,j) = -v(nx+1,j);
end
% advection term using the upwind scheme
for i = 2:nx
for j = 2:ny+1
if u(i,j) > 0
adv_u(i,j-1) = u(i,j)*(u(i,j) - u(i-1,j))/h;
else
adv_u(i,j-1) = u(i,j)*(u(i+1,j) - u(i,j))/h;
end
vc = 0.25*(v(i,j-1) + v(i+1,j-1) + v(i,j) + v(i+1,j));
if vc > 0
adv_u(i,j-1) = adv_u(i,j-1) + vc*(u(i,j) - u(i,j-1))/h;
else
adv_u(i,j-1) = adv_u(i,j-1) + vc*(u(i,j+1) - u(i,j))/h;
end
end
end
for i = 2:nx+1
for j = 2:ny
if v(i,j) > 0
adv_v(i-1,j) = v(i,j)*(v(i,j) - v(i,j-1))/h;
else
adv_v(i-1,j) = v(i,j)*(v(i,j+1) - v(i,j))/h;
end
uc = 0.25*(u(i-1,j) + u(i-1,j+1) + u(i,j) + u(i,j+1));
if uc > 0
adv_v(i-1,j) = adv_v(i-1,j) + uc*(v(i,j) - v(i,j-1))/h;
else
adv_v(i-1,j) = adv_v(i-1,j) + uc*(v(i+1,j) - v(i,j))/h;
end
end
end
% temporal velocity u
for i = 2:nx
for j = 2:ny+1
tu(i,j-1)=u(i,j)+dt*(-adv_u(i,j-1)+(u(i+1,j) ...
+ u(i-1,j) - 4*u(i,j) + u(i,j+1) + u(i,j-1))/(Re*h2));
end
end
% temporal velocity v
for i = 2:nx+1
for j = 2:ny
tv(i-1,j)=v(i,j)+dt*(-adv_v(i-1,j)+(v(i+1,j)+v(i-1,j) ...
-4*v(i,j)+v(i,j+1)+v(i,j-1))/(Re*h2));
end
end
% Poisson equation / source term
for i = 1:nx
for j = 1:ny
f(i,j)=(tu(i+1,j)-tu(i,j)+tv(i,j+1)-tv(i,j))/(h*dt);
end
end
err = 1.0; pold = p; count = 0;
% relaxation using the Gauss-Seidel iterative method
while ( err > tol )
count = count + 1;
for i = 1:nx
for j = 1:ny
sor = f(i,j);
if i == 1
sor = sor - p(i+1,j)/h2; cof = -1;
elseif i == nx
sor = sor - p(i-1,j)/h2; cof = -1;
else
sor = sor - (p(i+1,j) + p(i-1,j))/h2; cof = -2;
end
if j == 1
sor = sor - p(i,j+1)/h2; cof = cof - 1;
elseif j == ny
sor = sor - p(i,j-1)/h2; cof = cof - 1;
else
sor = sor - (p(i,j+1) + p(i,j-1))/h2; cof = cof - 2;
end
p(i,j) = sor/cof*h2;
end
end
% update pressure
p = p - sum(sum(p))/(nx*ny);
err = norm(pold-p,2);
pold = p;
end
count
% updating u
for i = 2:nx
for j = 2:ny+1
nu(i,j)=tu(i,j-1)-dt*(p(i,j-1)-p(i-1,j-1))/h;
end
end
% updating v
for i = 2:nx+1
for j = 2:ny
nv(i,j)=tv(i-1,j)-dt*(p(i-1,j)-p(i-1,j-1))/h;
end
end
u = nu; v = nv;
it
% post-processing
if mod(it,ns) == 0
figure(it); clf; hold on
for i = 2:nx+1
for j = 2:ny+1
uu(i-1,j-1) = 0.5*(u(i-1,j) + u(i,j));
vv(i-1,j-1) = 0.5*(v(i,j-1) + v(i,j));
end
end
sh = 2; s = 0.2;
q = quiver(x(1:sh:end),y(1:sh:end), ...
s*uu(1:sh:end,1:sh:end)',s*vv(1:sh:end,1:sh:end)',0);
st=streamline(x,y,uu',vv',rand(10,1),rand(10,1),[0.1 500]);
set(st,'color','red','linewidth',1);
axis image; box on; axis([0 1 0 1]);
end
end