python codes cfd
python codes cfd
Pros:
• Simple and robust
• Works well for steady problems
Cons:
• Slow convergence
• Not suitable for transient or compressible
flows
Hyperbolic
Equation
Algorithm
:
• Initialize velocity (u, v) and pressure (p)
• Loop over time:
1.Solve momentum equations with guessed pressure
2.Solve pressure correction (Poisson-type) from continuity
3.Correct velocity and pressure
4.Apply boundary conditions
• Repeat until time reaches desired value
Code
clc; clear; % --- Boundary conditions ---
: u(1,:) = 1.0; % inlet
% Grid setup u(end,:) = u(end-1,:); % outlet
nx = 100; ny = 50; u(:,[1 end]) = 0;
Lx = 2; Ly = 1; v(:,[1 end]) = 0;
dx = Lx / nx; dy = Ly / ny; v(1,:) = 0; v(end,:) = 0;
x = linspace(0, Lx, nx+2);
y = linspace(0, Ly, ny+2); % No-slip on airfoil
[X, Y] = meshgrid(x, y); for i = 2:nx+1
for j = 2:ny+1
% Physical parameters if airfoil(j,i)
rho = 1.0; u(i,j) = 0;
dt = 0.001; t_end = 0.5; nt = round(t_end/dt); v(i,j) = 0;
end
% Initialize fields end
u = zeros(nx+1, ny+2); end
v = zeros(nx+2, ny+1);
p = zeros(nx+2, ny+2); % --- Momentum equations (inviscid hyperbolic
form) ---
% Elliptic airfoil mask for i = 2:nx
cx = Lx/2; cy = Ly/2; rx = 0.1; ry = 0.05; for j = 2:ny+1
airfoil = ((X - cx).^2 / rx^2 + (Y - cy).^2 / ry^2) if airfoil(j,i), continue; end
<= 1; u_adv = -u(i,j) * (u(i+1,j) - u(i-1,j)) /
(2*dx) ...
% SIMPLE loop for hyperbolic flow - v(i,j) * (u(i,j+1) - u(i,j-1)) / (2*dy);
for t = 1:nt u_pres = -(p(i+1,j) - p(i,j)) / dx / rho;
u_old = u; v_old = v; p_old = p; u(i,j) = u(i,j) + dt * (u_adv + u_pres);
end
for i = 2:nx+1 for i = 2:nx+1
for j = 2:ny for j = 2:ny
if airfoil(j,i), continue; end v(i,j) = v(i,j) - dt * (p(i,j+1) - p(i,j)) / dy / rho;
v_adv = -u(i,j) * (v(i+1,j) - v(i-1,j)) / end
(2*dx) ... end
- v(i,j) * (v(i,j+1) - v(i,j-1)) / (2*dy);
v_pres = -(p(i,j+1) - p(i,j)) / dy / rho; % --- Print progress ---
v(i,j) = v(i,j) + dt * (v_adv + v_pres); if mod(t, 50) == 0
end fprintf("Time step %d/%d complete\n", t,
end nt);
end
% --- Pressure correction (Poisson-type from end
continuity) ---
div_uv = zeros(nx+2, ny+2); % --- Plot results ---
for i = 2:nx+1 u_c = 0.5 * (u(1:end-1,:) + u(2:end,:));
for j = 2:ny+1 v_c = 0.5 * (v(:,1:end-1) + v(:,2:end));
div_uv(i,j) = (u(i-1,j)-u(i,j))/dx + (v(i,j-1)- u_c(airfoil) = NaN;
v(i,j))/dy; v_c(airfoil) = NaN;
end
end figure;
p = p + 0.3 * rho * div_uv; % relaxation quiver(X', Y', u_c, v_c, 'k');
factor hold on;
% --- Correct velocity (SIMPLE) --- contour(X, Y, airfoil, [1 1], 'r', 'LineWidth', 2);
for i = 2:nx xlabel('X'); ylabel('Y');
for j = 2:ny+1 title('SIMPLE - Hyperbolic (Unsteady Inviscid
u(i,j) = u(i,j) - dt * (p(i+1,j) - p(i,j)) / dx / Flow)');
rho; axis equal tight;
end
end continued..
Parabolic
Equation
Algorithm
:
• Discretize domain in x and y.
• Apply inlet profile (e.g., uniform u, v = 0).
• For each marching step in x:
1.Guess pressure.
2.Solve momentum equation (only in x-
direction) for u.
3.Solve pressure correction equation from
continuity.
4.Correct u and compute v from continuity.
• Apply boundary conditions and iterate
% Apply wall and farfield BCs
Code u(1,i) = 0; % wall (no-slip)
% Domain
: nx = 200; ny = 100;
v(1,i) = 0;
u(end,i) = U_inlet; % free-stream
Lx = 1.0; Ly = 0.5;
v(end,i) = 0;
dx = Lx / nx; dy = Ly / ny;
x = linspace(0, Lx, nx+1);
% Iterative SIMPLE loop at each x-location
y = linspace(0, Ly, ny+1);
for iter = 1:max_iter
u_star = u(:,i);
% Parameters
p_corr = zeros(ny+1,1);
rho = 1.0;
nu = 1.5e-5;
% Solve x-momentum (only y-derivatives
U_inlet = 1.0;
matter in boundary layer)
for j = 2:ny
% Initialize
dudy = (u(j+1,i) - 2*u(j,i) + u(j-1,i)) /
u = zeros(ny+1, nx+1); % velocity in x-
dy^2;
direction
conv = u(j,i-1)*(u(j,i-1) - u(j-1,i-1))/dy;
v = zeros(ny+1, nx+1); % velocity in y-
% upstream conv
direction
u_star(j) = u(j,i-1) + dx * (nu * dudy -
p = zeros(ny+1, nx+1); % pressure
conv);
u(:,1) = U_inlet; % inlet condition
end
% Solve pressure correction using continuity
% SIMPLE parameters
for j = 2:ny
alpha_u = 0.7;
div = (u_star(j) - u_star(j-1))/dy;
alpha_p = 0.3;
p_corr(j) = p_corr(j) - alpha_p * rho * div;
max_iter = 500;
end
tol = 1e-5;
% Correct u
% Marching in x (parabolic treatment)
for j = 2:ny
for i = 2:nx+1
u(j,i) = u_star(j) - dx/rho * (p_corr(j+1) -
% Recompute v from continuity
for j = 2:ny
v(j,i) = v(j-1,i) - dy * (u(j,i) - u(j,i-1)) / dx;
end
% Check convergence
if max(abs(u(:,i) - u_star)) < tol
break;
end
end
end
% Plot results
[X, Y] = meshgrid(x, y);
figure;
contourf(X, Y, u, 20, 'LineColor', 'none');
colorbar;
xlabel('x'); ylabel('y');
title('Velocity Profile u(x,y) - SIMPLE for
Parabolic Flow');
figure;
quiver(X, Y, u, v, 2);
xlabel('x'); ylabel('y');
title('Velocity Field (u, v)');
Elliptic
Equation
Algorithm
•
:
Guess velocity and pressure fields.
• Solve momentum equations using current pressure.
• Solve pressure correction equation (from continuity).
• Correct velocities and pressure.
• Iterate until convergence.
% Boundary conditions
Code for i = 2:nx+1 u(:,1) = U_inlet; % Inlet
for j = 2:ny
: if airfoil(j,i), continue; end
u(:,end) = u(:,end-1);
(Neumann)
% Outlet
figure;
quiver(X, Y, u_c, v_c, 2);
hold on;
contour(X, Y, airfoil, [1 1], 'r', 'LineWidth', 2);
title('Velocity Field (u, v)');
xlabel('x'); ylabel('y');
axis equal tight;
SIMPLER Python Algorithms-
Flow over an airfoil
(SIMPLE Revised)
Type: Iterative with pre-correction
Best for: Complex steady flows
Pros:
• More stable
• Faster convergence for some problems
Cons:
• Slightly more complex than SIMPLE
Hyperbolic
Equation
Algorithm
:
• Discretize domain in x and y.
• Apply inlet profile (e.g., uniform u, v = 0).
• For each marching step in x:
1.Guess pressure.
2.Solve momentum equation (only in x-
direction) for u.
3.Solve pressure correction equation from
continuity.
4.Correct u and compute v from continuity.
• Apply boundary conditions and iterate
% Boundary Conditions
Code u(j,i) = u(j,i) + 0.1 * ( ...
u(1,:) = 1.0; % Inlet
-du2dx - duvdy - dpdx/rho + nu*(d2udx2 +
u(end,:) = u(end-1,:); % Outlet (Neumann)
: d2udy2) );
u(:,[1 end]) = 0; v(:,[1 end]) = 0;
end
end
% Apply mask (airfoil no-penetration)
for i = 2:nx+1
for i = 2:nx+1
for j = 2:ny+1
for j = 2:ny+1
if airfoil(j,i)
if airfoil(j,i), continue; end
u(i,j) = 0; v(i,j) = 0;
vn = v(j+1,i); vs = v(j-1,i);
end
ve = v(j,i+1); vw = v(j,i-1);
end
ue = u(j,i+1); uw = u(j,i);
end
dv2dy = (vn^2 - vs^2) / (2*dy);
duvdx = ((u(j,i+1)*v(j,i+1) - u(j,i-1)*v(j,i-
% --- Momentum update (Euler equations) ---
1)) / (2*dx));
for i = 2:nx
dpdy = (p(j+1,i) - p(j,i)) / dy;
for j = 2:ny+1
d2vdx2 = (ve - 2*v(j,i) + vw) / dx^2;
if airfoil(j,i), continue; end
d2vdy2 = (vn - 2*v(j,i) + vs) / dy^2;
dpdx = (p(i+1,j) - p(i-1,j)) / (2*dx);
v(j,i) = v(j,i) + 0.1 * ( ...
u(i,j) = u(i,j) - alpha_u * dpdx / rho(i,j);
-duvdx - dv2dy - dpdy/rho +
end
nu*(d2vdx2 + d2vdy2) );
end
end
end
for i = 2:nx+1
% --- Pressure correction from continuity ---
for j = 2:ny
div = zeros(size(p));
if airfoil(j,i), continue; end
for i = 2:nx+1
dpdy = (p(i,j+1) - p(i,j-1)) / (2*dy);
for j = 2:ny+1
v(i,j) = v(i,j) - alpha_u * dpdy / rho(i,j);
div(j,i) = ((u(j,i) - u(j,i-1))/dx + (v(j,i) -
end
v(j-1,i))/dy);
end
% --- Pressure correction (SIMPLER style) ---
for i = 2:nx+1
for j = 2:ny+1
if airfoil(j,i), continue; end
title('SIMPLER - Euler-like Compressible Flow
div = ((u(i-1,j) - u(i,j))/dx + (v(i,j-1) -
(Hyperbolic)');
v(i,j))/dy);
axis equal;
p(i,j) = p(i,j) + alpha_p * rho(i,j) * div;
end
end
(SIMPLE-Consistent)
Type: Enhanced SIMPLE
Best for: Steady flows, faster
convergence
Pros:
• Faster convergence than SIMPLE
• More accurate velocity correction
Cons:
• Still not ideal for highly transient
problems
Hyperbolic
Equation
Algorithm
:
• Discretize domain in x and y.
• Apply inlet profile (e.g., uniform u, v = 0).
• For each marching step in x:
1.Guess pressure.
2.Solve momentum equation (only in x-
direction) for u.
3.Solve pressure correction equation from
continuity.
4.Correct u and compute v from continuity.
• Apply boundary conditions and iterate
import numpy as np def apply_boundary_conditions():
Code import matplotlib.pyplot as plt u[0, :] = u_inlet # Inlet
: # Grid parameters
u[-1, :] = u[-2, :] # Outlet
u[:, 0] = 0 # Bottom wall (no-
nx, ny = 50, 50 slip)
Lx, Ly = 1.0, 1.0 u[:, -1] = 0 # Top wall (no-slip)
dx, dy = Lx/nx, Ly/ny v[0, :] = 0
v[-1, :] = 0
# Flow properties v[:, 0] = 0
rho = 1.0 # Density (kg/m^3) v[:, -1] = 0
mu = 0.01 # Dynamic viscosity
(Pa.s) def solve_momentum_equations():
u_inlet = 1.0 # Inlet velocity (m/s) for i in range(1, nx+1):
max_iter = 1000 for j in range(1, ny+1):
tol = 1e-4 u[i,j] = ((mu*(u[i+1,j] + u[i-1,j]) /
dx**2 +
# Initialize fields mu*(u[i,j+1] + u[i,j-1]) /
u = np.zeros((nx+2, ny+2)) # x- dy**2 -
velocity (p[i+1,j] - p[i-1,j]) /
v = np.zeros((nx+2, ny+2)) # y- (2*dx)) /
velocity (2*mu*(1/dx*2 + 1/dy*2)))
p = np.zeros((nx+2, ny+2)) # v[i,j] = ((mu*(v[i+1,j] + v[i-1,j]) /
pressure dx**2 +
pc = np.zeros_like(p) mu*(v[i,j+1] + v[i,j-1]) /
dy**2 -
# Coefficients (p[i,j+1] - p[i,j-1]) /
aE = np.zeros_like(p) (2*dy)) /
aW = np.zeros_like(p) (2*mu*(1/dx*2 + 1/dy*2)))
aN = np.zeros_like(p)
def correct_velocity_pressure():
for i in range(1, nx+1):
for j in range(1, ny+1): # Plotting velocity contours
p[i,j] += 1.8 * pc[i,j] # Over- X, Y = np.meshgrid(np.linspace(0, Lx, nx+2),
relaxation np.linspace(0, Ly, ny+2))
u[i,j] += -(dx/rho) * (pc[i+1,j] - velocity = np.sqrt(u.T*2 + v.T*2)
pc[i,j])
v[i,j] += -(dy/rho) * (pc[i,j+1] - plt.figure(figsize=(8, 6))
pc[i,j]) cp = plt.contourf(X, Y, velocity, levels=20, cmap='jet')
plt.colorbar(cp, label="Velocity magnitude (m/s)")
def check_convergence(u_old, v_old): plt.title("Velocity Contours Over Airfoil-like Surface")
diff_u = np.linalg.norm(u - u_old) plt.xlabel("X")
diff_v = np.linalg.norm(v - v_old) plt.ylabel("Y")
return diff_u < tol and diff_v < tol plt.tight_layout()
plt.show()
# Main SIMPLEC loop
for it in range(max_iter):
u_old = u.copy()
v_old = v.copy()
apply_boundary_conditions()
solve_momentum_equations()
solve_pressure_correction()
correct_velocity_pressure()
if check_convergence(u_old, v_old):
print(f"Converged in {it}
iterations.")
break
Elliptic
Equation
Algorithm
:
• Discretize domain in x and y.
• Apply inlet profile (e.g., uniform u, v = 0).
• For each marching step in x:
1.Guess pressure.
2.Solve momentum equation (only in x-
direction) for u.
3.Solve pressure correction equation from
continuity.
4.Correct u and compute v from continuity.
• Apply boundary conditions and iterate
% Create airfoil mask (elliptical obstacle in
Code clc; clear; center)
: % Domain and grid
cx = Lx/2; cy = Ly/2;
rx = 0.1; ry = 0.05;
nx = 100; ny = 50; airfoil_mask = ((X - cx).^2 / rx^2 + (Y - cy).^2 /
Lx = 2; Ly = 1; ry^2) <= 1;
dx = Lx / nx; dy = Ly / ny;
% Main loop
% Grid for iter = 1:max_iter
x = linspace(0, Lx, nx+2); u_old = u; v_old = v; p_old = p;
y = linspace(0, Ly, ny+2);
[X, Y] = meshgrid(x, y); % --- Apply boundary conditions ---
u(1,:) = U_in; % inlet
% Flow properties u(end,:) = u(end-1,:); % outlet (Neumann)
rho = 1.0; u(:,[1 end]) = 0; % top/bottom wall
mu = 1.5e-5; v(1,:) = 0; v(end,:) = 0;
U_in = 1.0; v(:,[1 end]) = 0;
Pros:
• Fast convergence per time step
• No need for under-relaxation
• Accurate for unsteady problems
Cons:
• Higher memory cost
• Less efficient for purely steady flows
Hyperbolic
Equation
Algorithm
:
• Predict velocity from momentum (ignore pressure gradient).
• Solve pressure correction using continuity (mass conservation).
• Correct velocity.
• Repeat pressure-velocity coupling for second corrector step
(PISO-specific).
• March forward in time.
% Compute fluxes in x and y directions
Code clc; clear;
Fx = [rhou; rhou.^2 ./ rho + p; rhou.*rhov ./ rho; (E + p).*u];
: % Domain
Fy = [rhov; rhou.*rhov ./ rho; rhov.^2 ./ rho + p; (E + p).*v];
nx = 100; ny = 50;
% Update using finite volume
Lx = 4; Ly = 2;
for i = 2:nx-1
dx = Lx / nx; dy = Ly / ny;
for j = 2:ny-1
x = linspace(0, Lx, nx);
if blunt(j,i), continue; end
y = linspace(0, Ly, ny);
rho(j,i) = rho(j,i) - dt/dx * (rhou(j,i+1) - rhou(j,i));
[X, Y] = meshgrid(x, y);
u(j,i) = u(j,i) - dt/dx * ((u(j,i+1)^2 + p(j,i+1)/rho(j,i+1))
- ...
% Flow parameters
(u(j,i)^2 + p(j,i)/rho(j,i)));
gamma = 1.4;
v(j,i) = v(j,i) - dt/dy * ((v(j+1,i)^2 + p(j+1,i)/rho(j+1,i))
rho = ones(ny, nx);
- ...
u = ones(ny, nx) * 2;% Mach 2 inflow
(v(j,i)^2 + p(j,i)/rho(j,i)));
v = zeros(ny, nx);
p(j,i) = p(j,i) - gamma * p(j,i) * ( ...
p = ones(ny, nx);
(u(j,i+1) - u(j,i))/dx + (v(j+1,i) - v(j,i))/dy ) * dt;
dt = 0.001;
end
time_steps = 500;
end
% PISO Correction Step 1
% Blunt body (circular)
% Recalculate pressure correction from continuity
cx = Lx/3; cy = Ly/2; r = 0.3;
% Correct u, v accordingly (basic form shown)
blunt = ((X - cx).^2 + (Y - cy).^2) <= r^2;
for i = 2:nx-1
% Main time loop
for j = 2:ny-1
for t = 1:time_steps
if blunt(j,i), continue; end
% Step 1: Predictor - compute momentum
div_uv = (u(j,i+1) - u(j,i-1))/(2*dx) + (v(j+1,i) -
fluxes
v(j-1,i))/(2*dy);
rhou = rho .* u;
p(j,i) = p(j,i) - gamma * p(j,i) * div_uv * dt;
rhov = rho .* v;
Parabolic
Equation
Algorithm
:
• Predict velocity field using previous pressure.
• Correct pressure by solving pressure Poisson equation from
continuity.
• Correct velocities using pressure corrections.
• Optional: apply a second pressure correction (PISO's edge).
• Advance to the next time step.
clc; clear; % Apply inlet and wall BCs
Code u(:,1) = 1; % Inlet
: % Domain setup
nx = 100; ny = 100;
u(:,end) = u(:,end-1);
v(:,1) = 0; v(:,end) = 0;
% Outlet (Neumann)