Texto y código sujeto bajo Creative Commons Attribution license, CC-BY-SA. (c) Original por Lorena A. Barba y Gilbert Forsyth en 2013, traducido por F.J. Navarro-Brull para CAChemE.org from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm import matplotlib.pyplot as plt import numpy as np ## Declaración de variables nx = 81 ny = 81 c = 1 dx = 2.0/(nx-1) dy = 2.0/(ny-1) ## Condiciones iniciales p = np.zeros((ny,nx)) ##create a XxY vector of 0's ## Guías de la figura (malla) x = np.linspace(0,2,nx) y = np.linspace(0,1,ny) ## Condiciones de frontera p[:,0] = 0 ##p = 0 @ x = 0 p[:,-1] = y ##p = y @ x = 2 p[0,:] = p[1,:] ##dp/dy = 0 @ y = 0 p[-1,:] = p[-2,:] ##dp/dy = 0 @ y = 1 def laplace2d(p, y, dx, dy, l1norm_target): l1norm = 1 pn = np.empty_like(p) while l1norm > l1norm_target: pn[:] = p[:] p[1:-1,1:-1] = (dy**2*(pn[2:,1:-1]+pn[0:-2,1:-1])+dx**2*(pn[1:-1,2:]+pn[1:-1,0:-2]))/(2*(dx**2+dy**2)) p[0,0] = (dy**2*(pn[1,0]+pn[-1,0])+dx**2*(pn[0,1]+pn[0,-1]))/(2*(dx**2+dy**2)) p[-1,-1] = (dy**2*(pn[0,-1]+pn[-2,-1])+dx**2*(pn[-1,0]+pn[-1,-2]))/(2*(dx**2+dy**2)) p[:,0] = 0 ##p = 0 @ x = 0 p[:,-1] = y ##p = y @ x = 2 p[0,:] = p[1,:] ##dp/dy = 0 @ y = 0 p[-1,:] = p[-2,:] ##dp/dy = 0 @ y = 1 l1norm = (np.sum(np.abs(p[:])-np.abs(pn[:])))/np.sum(np.abs(pn[:])) return p %%timeit laplace2d(p, y, dx, dy, .00001) def laplace2d_vanilla(p, y, dx, dy, l1norm_target): l1norm = 1 pn = np.empty_like(p) nx, ny = len(y), len(y) while l1norm > l1norm_target: pn[:] = p[:] for i in range(1, nx-1): for j in range(1, ny-1): p[i,j] = (dy**2*(pn[i+1,j]+pn[i-1,j])+dx**2*(pn[i,j+1]-pn[i,j-1]))/(2*(dx**2+dy**2)) p[0,0] = (dy**2*(pn[1,0]+pn[-1,0])+dx**2*(pn[0,1]+pn[0,-1]))/(2*(dx**2+dy**2)) p[-1,-1] = (dy**2*(pn[0,-1]+pn[-2,-1])+dx**2*(pn[-1,0]+pn[-1,-2]))/(2*(dx**2+dy**2)) p[:,0] = 0 ##p = 0 @ x = 0 p[:,-1] = y ##p = y @ x = 2 p[0,:] = p[1,:] ##dp/dy = 0 @ y = 0 p[-1,:] = p[-2,:] ##dp/dy = 0 @ y = 1 l1norm = (np.sum(np.abs(p[:])-np.abs(pn[:])))/np.sum(np.abs(pn[:])) return p %%timeit laplace2d_vanilla(p, y, dx, dy, .00001) 32*1e-3/(206*1e-6) from numba import autojit @autojit def laplace2d_numba(p, y, dx, dy, l1norm_target): l1norm = 1 pn = np.empty_like(p) while l1norm > l1norm_target: pn[:] = p[:] p[1:-1,1:-1] = (dy**2*(pn[2:,1:-1]+pn[0:-2,1:-1])+dx**2*(pn[1:-1,2:]+pn[1:-1,0:-2]))/(2*(dx**2+dy**2)) p[0,0] = (dy**2*(pn[1,0]+pn[-1,0])+dx**2*(pn[0,1]+pn[0,-1]))/(2*(dx**2+dy**2)) p[-1,-1] = (dy**2*(pn[0,-1]+pn[-2,-1])+dx**2*(pn[-1,0]+pn[-1,-2]))/(2*(dx**2+dy**2)) p[:,0] = 0 ##p = 0 @ x = 0 p[:,-1] = y ##p = y @ x = 2 p[0,:] = p[1,:] ##dp/dy = 0 @ y = 0 p[-1,:] = p[-2,:] ##dp/dy = 0 @ y = 1 l1norm = (np.sum(np.abs(p[:])-np.abs(pn[:])))/np.sum(np.abs(pn[:])) return p %%timeit laplace2d_numba(p, y, dx, dy, .00001) @autojit def laplace2d_vanilla_numba(p, y, dx, dy, l1norm_target): l1norm = 1 pn = np.empty_like(p) nx, ny = len(y), len(y) while l1norm > l1norm_target: pn[:] = p[:] for i in range(1, nx-1): for j in range(1, ny-1): p[i,j] = (dy**2*(pn[i+1,j]+pn[i-1,j])+dx**2*(pn[i,j+1]-pn[i,j-1]))/(2*(dx**2+dy**2)) p[0,0] = (dy**2*(pn[1,0]+pn[-1,0])+dx**2*(pn[0,1]+pn[0,-1]))/(2*(dx**2+dy**2)) p[-1,-1] = (dy**2*(pn[0,-1]+pn[-2,-1])+dx**2*(pn[-1,0]+pn[-1,-2]))/(2*(dx**2+dy**2)) p[:,0] = 0 ##p = 0 @ x = 0 p[:,-1] = y ##p = y @ x = 2 p[0,:] = p[1,:] ##dp/dy = 0 @ y = 0 p[-1,:] = p[-2,:] ##dp/dy = 0 @ y = 1 l1norm = (np.sum(np.abs(p[:])-np.abs(pn[:])))/np.sum(np.abs(pn[:])) return p %%timeit laplace2d_vanilla_numba(p, y, dx, dy, .00001) from IPython.core.display import HTML def css_styling(): styles = open("../styles/custom.css", "r").read() return HTML(styles) css_styling()