Buckets:
| #!/usr/bin/env python | |
| """ | |
| 2D wave equation solved by finite differences. | |
| Very preliminary version. | |
| """ | |
| import time | |
| from scitools.std import * | |
| def scheme_ij(u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x, y, t_1, | |
| i, j, im1, ip1, jm1, jp1): | |
| """ | |
| Right-hand side of finite difference at point [i,j]. | |
| im1, ip1 denote i-1, i+1, resp. Similar for jm1, jp1. | |
| t_1 corresponds to u_1 (previous time level relative to u). | |
| """ | |
| u_ij = - k_2*u_2[i,j] + k_1*2*u_1[i,j] | |
| u_xx = k_3*Cx2*(u_1[im1,j] - 2*u_1[i,j] + u_1[ip1,j]) | |
| u_yy = k_3*Cx2*(u_1[i,jm1] - 2*u_1[i,j] + u_1[i,jp1]) | |
| f_term = k_4*dt2*f(x, y, t_1) | |
| return u_ij + u_xx + u_yy + f_term | |
| def scheme_scalar_mesh(u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x, y, t_1, Nx, Ny, | |
| bc): | |
| Ix = range(0, u.shape[0]) | |
| Iy = range(0, u.shape[1]) | |
| # Interior points | |
| for i in Ix[1:-1]: | |
| for j in Iy[1:-1]: | |
| im1 = i-1; ip1 = i+1; jm1 = j-1; jp1 = j+1 | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| # Boundary points | |
| i = Ix[0] | |
| ip1 = i+1 | |
| im1 = ip1 | |
| if bc['W'] is None: | |
| for j in Iy[1:-1]: | |
| jm1 = j-1; jp1 = j+1 | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| for j in Iy[1:-1]: | |
| u[i,j] = bc['W'](x[i], y[j]) | |
| i = Ix[-1] | |
| im1 = i-1 | |
| ip1 = im1 | |
| if bc['E'] is None: | |
| for j in Iy[1:-1]: | |
| jm1 = j-1; jp1 = j+1 | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| for j in Iy[1:-1]: | |
| u[i,j] = bc['E'](x[i], y[j]) | |
| j = Iy[0] | |
| jp1 = j+1 | |
| jm1 = jp1 | |
| if bc['S'] is None: | |
| for i in Ix[1:-1]: | |
| im1 = i-1; ip1 = i+1 | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| for i in Ix[1:-1]: | |
| u[i,j] = bc['S'](x[i], y[j]) | |
| j = Iy[-1] | |
| jm1 = j-1 | |
| jp1 = jm1 | |
| if bc['N'] is None: | |
| for i in Ix[1:-1]: | |
| im1 = i-1; ip1 = i+1 | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| for i in Ix[1:-1]: | |
| u[i,j] = bc['N'](x[i], y[j]) | |
| # Corner points | |
| i = j = Iy[0] | |
| ip1 = i+1; jp1 = j+1 | |
| im1 = ip1; jm1 = jp1 | |
| if bc['S'] is None: | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| u[i,j] = bc['S'](x[i], y[j]) | |
| i = Ix[-1]; j = Iy[0] | |
| im1 = i-1; jp1 = j+1 | |
| ip1 = im1; jm1 = jp1 | |
| if bc['S'] is None: | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| u[i,j] = bc['S'](x[i], y[j]) | |
| i = Ix[-1]; j = Iy[-1] | |
| im1 = i-1; jm1 = j-1 | |
| ip1 = im1; jp1 = jm1 | |
| if bc['N'] is None: | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| u[i,j] = bc['N'](x[i], y[j]) | |
| i = Ix[0]; j = Iy[-1] | |
| ip1 = i+1; jm1 = j-1 | |
| im1 = ip1; jp1 = jm1 | |
| if bc['N'] is None: | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| u[i,j] = bc['N'](x[i], y[j]) | |
| return u | |
| def scheme_vectorized_mesh(u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x, y, t_1, Nx, Ny, | |
| bc): | |
| # Interior points | |
| i = slice(1, Nx) | |
| j = slice(1, Ny) | |
| im1 = slice(0, Nx-1) | |
| ip1 = slice(2, Nx+1) | |
| jm1 = slice(0, Ny-1) | |
| jp1 = slice(2, Ny+1) | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, xv[i,:], yv[j,:], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| # Boundary points | |
| i = slice(1, Nx) | |
| ip1 = slice(2, Nx+1) | |
| im1 = ip1 | |
| j = slice(1, Ny) | |
| jm1 = slice(0, Ny-1) | |
| jp1 = slice(2, Ny+1) | |
| if bc['W'] is None: | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, xv[i,:], yv[:,j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| u[i,j] = bc['W'](xv[i,:], yv[:,j]) | |
| # The rest is not done yet..... | |
| i = Ix[-1] | |
| im1 = i-1 | |
| ip1 = im1 | |
| if bc['E'] is None: | |
| for j in Iy[1:-1]: | |
| jm1 = j-1; jp1 = j+1 | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| for j in Iy[1:-1]: | |
| u[i,j] = bc['E'](x[i], y[j]) | |
| j = Iy[0] | |
| jp1 = j+1 | |
| jm1 = jp1 | |
| if bc['S'] is None: | |
| for i in Ix[1:-1]: | |
| im1 = i-1; ip1 = i+1 | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| for i in Ix[1:-1]: | |
| u[i,j] = bc['S'](x[i], y[j]) | |
| j = Iy[-1] | |
| jm1 = j-1 | |
| jp1 = jm1 | |
| if bc['N'] is None: | |
| for i in Ix[1:-1]: | |
| im1 = i-1; ip1 = i+1 | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| for i in Ix[1:-1]: | |
| u[i,j] = bc['N'](x[i], y[j]) | |
| # Corner points | |
| i = j = Iy[0] | |
| ip1 = i+1; jp1 = j+1 | |
| im1 = ip1; jm1 = jp1 | |
| if bc['S'] is None: | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| u[i,j] = bc['S'](x[i], y[j]) | |
| i = Ix[-1]; j = Iy[0] | |
| im1 = i-1; jp1 = j+1 | |
| ip1 = im1; jm1 = jp1 | |
| if bc['S'] is None: | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| u[i,j] = bc['S'](x[i], y[j]) | |
| i = Ix[-1]; j = Iy[-1] | |
| im1 = i-1; jm1 = j-1 | |
| ip1 = im1; jp1 = jm1 | |
| if bc['N'] is None: | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| u[i,j] = bc['N'](x[i], y[j]) | |
| i = Ix[0]; j = Iy[-1] | |
| ip1 = i+1; jm1 = j-1 | |
| im1 = ip1; jp1 = jm1 | |
| if bc['N'] is None: | |
| u[i,j] = scheme_ij( | |
| u, u_1, u_2, k_1, k_2, k_3, k_4, | |
| f, dt2, Cx2, Cy2, x[i], y[j], t_1, | |
| i, j, im1, ip1, jm1, jp1) | |
| else: | |
| u[i,j] = bc['N'](x[i], y[j]) | |
| return u | |
| def solver(I, f, c, bc, Lx, Ly, Nx, Ny, dt, T, | |
| user_action=None, version='scalar', | |
| verbose=True): | |
| """ | |
| Solve the 2D wave equation u_tt = u_xx + u_yy + f(x,t) on (0,L) with | |
| u = bc(x,y, t) on the boundary and initial condition du/dt = 0. | |
| Nx and Ny are the total number of grid cells in the x and y | |
| directions. The grid points are numbered as (0,0), (1,0), (2,0), | |
| ..., (Nx,0), (0,1), (1,1), ..., (Nx, Ny). | |
| dt is the time step. If dt<=0, an optimal time step is used. | |
| T is the stop time for the simulation. | |
| I, f, bc are functions: I(x,y), f(x,y,t), bc(x,y,t) | |
| user_action: function of (u, x, xv, y, yv, t, n) called at each time | |
| level (x and y are one-dimensional coordinate vectors). | |
| This function allows the calling code to plot the solution, | |
| compute errors, etc. | |
| verbose: true if a message at each time step is written, | |
| false implies no output during the simulation. | |
| """ | |
| x = linspace(0, Lx, Nx+1) # mesh points in x dir | |
| y = linspace(0, Ly, Ny+1) # mesh points in y dir | |
| dx = x[1] - x[0] | |
| dy = y[1] - y[0] | |
| xv = x[:,newaxis] # for vectorized function evaluations | |
| yv = y[newaxis,:] | |
| if dt <= 0: # max time step? | |
| dt = (1/float(c))*(1/sqrt(1/dx**2 + 1/dy**2)) | |
| Nt = int(round(T/float(dt))) | |
| t = linspace(0, T, Nt+1) # mesh points in time | |
| Cx2 = (c*dt/dx)**2; Cy2 = (c*dt/dy)**2 # help variables | |
| dt2 = dt**2 | |
| u = zeros((Nx+1,Ny+1)) # solution array | |
| u_1 = zeros((Nx+1,Ny+1)) # solution at t-dt | |
| u_2 = zeros((Nx+1,Ny+1)) # solution at t-2*dt | |
| Ix = range(0, Nx+1) | |
| Iy = range(0, Ny+1) | |
| It = range(0, Nt+1) | |
| # Load initial condition into u_1 | |
| for i in Ix: | |
| for j in Iy: | |
| u_1[i,j] = I(x[i], y[j]) | |
| if user_action is not None: | |
| user_action(u_1, x, xv, y, yv, t, 0) | |
| # Special formula for first time step | |
| if version == 'scalar': | |
| u = scheme_scalar_mesh(u, u_1, u_2, 0.5, 0, 0.5, 0.5, | |
| f, dt2, Cx2, Cy2, x, y, t[0], | |
| Nx, Ny, bc) | |
| if user_action is not None: | |
| user_action(u, x, xv, y, yv, t, 1) | |
| u_2[:,:] = u_1; u_1[:,:] = u | |
| for n in It[1:-1]: | |
| if version == 'scalar': | |
| u = scheme_scalar_mesh(u, u_1, u_2, 1, 1, 1, 1, | |
| f, dt2, Cx2, Cy2, x, y, t[n], | |
| Nx, Ny, bc) | |
| if user_action is not None: | |
| if user_action(u, x, xv, y, yv, t, n+1): | |
| break | |
| # Update data structures for next step | |
| #u_2[:] = u_1; u_1[:] = u # slower | |
| u_2, u_1, u = u_1, u, u_2 | |
| return dt # dt might be computed in this function | |
| def test_Gaussian(plot_u=1, version='scalar'): | |
| """ | |
| Initial Gaussian bell in the middle of the domain. | |
| plot: not plot: 0; mesh: 1, surf: 2. | |
| """ | |
| # Clean up plot files | |
| for name in glob('tmp_*.png'): | |
| os.remove(name) | |
| Lx = 10 | |
| Ly = 10 | |
| c = 1.0 | |
| def I(x, y): | |
| return exp(-(x-Lx/2.0)**2/2.0 -(y-Ly/2.0)**2/2.0) | |
| def f(x, y, t): | |
| return 0.0 | |
| bc = dict(N=None, W=None, E=None, S=None) | |
| def action(u, x, xv, y, yv, t, n): | |
| #print 'action, t=',t,'\nu=',u, '\Nx=',x, '\Ny=', y | |
| if t[n] == 0: | |
| time.sleep(2) | |
| if plot_u == 1: | |
| mesh(x, y, u, title='t=%g' % t[n], zlim=[-1,1], | |
| caxis=[-1,1]) | |
| elif plot_u == 2: | |
| surf(xv, yv, u, title='t=%g' % t[n], zlim=[-1, 1], | |
| colorbar=True, colormap=hot(), caxis=[-1,1]) | |
| if plot_u > 0: | |
| time.sleep(0) # pause between frames | |
| filename = 'tmp_%04d.png' % n | |
| #savefig(filename) # time consuming... | |
| Nx = 40; Ny = 40; T = 15 | |
| dt = solver(I, f, c, bc, Lx, Ly, Nx, Ny, 0, T, | |
| user_action=action, version='scalar') | |
| def test_1D(plot=1, version='scalar'): | |
| """ | |
| 1D test problem with exact solution. | |
| """ | |
| Lx = 10 | |
| Ly = 10 | |
| c = 1.0 | |
| def I(x, y): | |
| """Plug profile as initial condition.""" | |
| if abs(x-L/2.0) > 0.1: | |
| return 0 | |
| else: | |
| return 1 | |
| def f(x, y, t): | |
| """Return 0, but in vectorized mode it must be an array.""" | |
| if isinstance(x, (float,int)): | |
| return 0 | |
| else: | |
| return zeros(x.size) | |
| bc=dict(N=None, E=None, S=None, W=None) | |
| def action(u, x, xv, y, yv, t, n): | |
| #print 'action, t=',t,'\nu=',u, '\Nx=',x, '\Ny=', y | |
| if plot: | |
| mesh(xv, yv, u, title='t=%g') | |
| time.sleep(0.2) # pause between frames | |
| Nx = 40; Ny = 40; T = 700 | |
| dt = solver(I, f, c, bc, | |
| Lx, Ly, Nx, Ny, 0, T, | |
| user_action=action, | |
| version='scalar') | |
| def test_const(plot=1, version='scalar'): | |
| """ | |
| Test problem with constant solution. | |
| """ | |
| Lx = 10 | |
| Ly = 10 | |
| c = 1.0 | |
| C = 1.2 | |
| def I(x,y): | |
| """Plug profile as initial condition.""" | |
| return C | |
| def f(x, y, t): | |
| """Return 0, but in vectorized mode it must be an array.""" | |
| if isinstance(x, (float,int)): | |
| return 0 | |
| else: | |
| return zeros(x.size) | |
| u0 = lambda x, y, t=0: C | |
| bc=dict(N=u0, E=u0, S=u0, W=u0) | |
| def action(u, x, xv, y, yv, t, n): | |
| print t | |
| print u | |
| Nx = 4; Ny = 3; T = 5 | |
| dt = solver(I, f, c, bc, Lx, Ly, Nx, Ny, 0, T, action, 'scalar') | |
| if __name__ == '__main__': | |
| import sys | |
| if len(sys.argv) < 2: | |
| print """Usage %s function arg1 arg2 arg3 ...""" % sys.argv[0] | |
| sys.exit(0) | |
| cmd = '%s(%s)' % (sys.argv[1], ', '.join(sys.argv[2:])) | |
| print cmd | |
| eval(cmd) | |
Xet Storage Details
- Size:
- 13 kB
- Xet hash:
- b223d7ff5173d446eca983c8ff26fca18e73668e40a69ebb7934701bc63792ff
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.