# # This code was downloded at https://lorenabarba.com/blog/cfd-python-12-steps-to-navier-stokes/ # import numpy from matplotlib import pyplot, cm from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import pylab as p plt.interactive(True) nx = 41 ny = 41 nt = 500 nit = 50 c = 1 dx = 2 / (nx - 1) dy = 2 / (ny - 1) x = numpy.linspace(0, 2, nx) y = numpy.linspace(0, 2, ny) X, Y = numpy.meshgrid(x, y) rho = 1 nu = .1 dt = .001 u = numpy.zeros((ny, nx)) v = numpy.zeros((ny, nx)) p = numpy.zeros((ny, nx)) b = numpy.zeros((ny, nx)) # The pressure Poisson equation that's written above can be hard to write out without typos. # The function build_up_b below represents the contents of the square brackets, # so that the entirety of the PPE is slightly more manageable. def build_up_b(b, rho, dt, u, v, dx, dy): b[1:-1, 1:-1] = (rho * (1 / dt * ((u[1:-1, 2:] - u[1:-1, 0:-2]) / (2 * dx) + (v[2:, 1:-1] - v[0:-2, 1:-1]) / (2 * dy)) - ((u[1:-1, 2:] - u[1:-1, 0:-2]) / (2 * dx))**2 - 2 * ((u[2:, 1:-1] - u[0:-2, 1:-1]) / (2 * dy) * (v[1:-1, 2:] - v[1:-1, 0:-2]) / (2 * dx))- ((v[2:, 1:-1] - v[0:-2, 1:-1]) / (2 * dy))**2)) return b # The function pressure_poisson is also defined to help segregate the different rounds of calculations. Note the presence of the pseudo-time variable nit. This sub-iteration in the Poisson calculation helps ensure a divergence-free field. def pressure_poisson(p, dx, dy, b): pn = numpy.empty_like(p) pn = p.copy() for q in range(nit): pn = p.copy() p[1:-1, 1:-1] = (((pn[1:-1, 2:] + pn[1:-1, 0:-2]) * dy**2 + (pn[2:, 1:-1] + pn[0:-2, 1:-1]) * dx**2) / (2 * (dx**2 + dy**2)) - dx**2 * dy**2 / (2 * (dx**2 + dy**2)) * b[1:-1,1:-1]) p[:, -1] = p[:, -2] # dp/dx = 0 at x = 2 p[0, :] = p[1, :] # dp/dy = 0 at y = 0 p[:, 0] = p[:, 1] # dp/dx = 0 at x = 0 p[-1, :] = 0 # p = 0 at y = 2 return p # Finally, the rest of the cavity flow equations are wrapped inside the function cavity_flow, allowing us to easily plot the results of the cavity flow solver for different lengths of time. def cavity_flow(nt, u, v, dt, dx, dy, p, rho, nu): print('caviry dlow called: nt=',nt) un = numpy.empty_like(u) vn = numpy.empty_like(v) b = numpy.zeros((ny, nx)) for n in range(nt): un = u.copy() vn = v.copy() b = build_up_b(b, rho, dt, u, v, dx, dy) p = pressure_poisson(p, dx, dy, b) u[1:-1, 1:-1] = (un[1:-1, 1:-1]- un[1:-1, 1:-1] * dt / dx * (un[1:-1, 1:-1] - un[1:-1, 0:-2]) - vn[1:-1, 1:-1] * dt / dy * (un[1:-1, 1:-1] - un[0:-2, 1:-1]) - dt / (2 * rho * dx) * (p[1:-1, 2:] - p[1:-1, 0:-2]) + nu * (dt / dx**2 * (un[1:-1, 2:] - 2 * un[1:-1, 1:-1] + un[1:-1, 0:-2]) + dt / dy**2 * (un[2:, 1:-1] - 2 * un[1:-1, 1:-1] + un[0:-2, 1:-1]))) v[1:-1,1:-1] = (vn[1:-1, 1:-1] - un[1:-1, 1:-1] * dt / dx * (vn[1:-1, 1:-1] - vn[1:-1, 0:-2]) - vn[1:-1, 1:-1] * dt / dy * (vn[1:-1, 1:-1] - vn[0:-2, 1:-1]) - dt / (2 * rho * dy) * (p[2:, 1:-1] - p[0:-2, 1:-1]) + nu * (dt / dx**2 * (vn[1:-1, 2:] - 2 * vn[1:-1, 1:-1] + vn[1:-1, 0:-2]) + dt / dy**2 * (vn[2:, 1:-1] - 2 * vn[1:-1, 1:-1] + vn[0:-2, 1:-1]))) u[0, :] = 0 u[:, 0] = 0 u[:, -1] = 0 u[-1, :] = 1 # set velocity on cavity lid equal to 1 v[0, :] = 0 v[-1, :] = 0 v[:, 0] = 0 v[:, -1] = 0 return u, v, p # Let's start with nt = 100 and see what the solver gives us: u = numpy.zeros((ny, nx)) v = numpy.zeros((ny, nx)) p = numpy.zeros((ny, nx)) b = numpy.zeros((ny, nx)) nt = 100 u, v, p = cavity_flow(nt, u, v, dt, dx, dy, p, rho, nu) fig = pyplot.figure(figsize=(11,7), dpi=100) # plotting the pressure field as a contour pyplot.contourf(X, Y, p, alpha=0.5, cmap=cm.viridis) pyplot.colorbar() # plotting the pressure field outlines pyplot.contour(X, Y, p, cmap=cm.viridis) plt.savefig('p_NS.png',bbox_inches='tight') # plotting velocity field pyplot.quiver(X[::2, ::2], Y[::2, ::2], u[::2, ::2], v[::2, ::2]) pyplot.xlabel('X') pyplot.ylabel('Y'); plt.savefig('vect_NS.png',bbox_inches='tight') ########################################## iso u fig1,ax1 = plt.subplots() plt.subplots_adjust(left=0.20,bottom=0.20) im=plt.pcolormesh(X,Y,p, vmin=-1,vmax=1,cmap=plt.get_cmap('hot'),shading='gouraud') fig1.colorbar(im) plt.arrow(x=0.8, y=2.1, dx=0.4, dy=0, width=.03,facecolor='black') plt.text(1,2.2,'$U_{wall}$') plt.axis('equal') #plt.colorbar() plt.axis('off') plt.box(on=None) plt.savefig('u_NS_iso.png')