Buckets:
| from scipy.sparse import spdiags | |
| from scipy.sparse.linalg import spsolve, use_solver | |
| from numpy import linspace, zeros | |
| import time, os, sys, shutil | |
| def solver(I, a, L, Nx, F, T, theta=0.5, u_L=0, u_R=0, | |
| user_action=None): | |
| """ | |
| Solve the diffusion equation u_t = a*u_xx on (0,L) with | |
| boundary conditions u(0,t) = u_L and u(L,t) = u_R, | |
| for t in (0,T]. Initial condition: u(x,0) = I(x). | |
| Method: (implicit) theta-rule in time. | |
| Nx is the total number of mesh cells; mesh points are numbered | |
| from 0 to Nx. | |
| F is the dimensionless number a*dt/dx**2 and implicitly specifies the | |
| time step. No restriction on F. | |
| T is the stop time for the simulation. | |
| I is a function of x. | |
| user_action is a function of (u, x, t, n) where the calling code | |
| can add visualization, error computations, data analysis, | |
| store solutions, etc. | |
| The coefficient matrix is stored in a scipy data structure for | |
| sparse matrices. Input to the storage scheme is a set of | |
| diagonals with nonzero entries in the matrix. | |
| """ | |
| import time | |
| t0 = time.clock() | |
| x = linspace(0, L, Nx+1) # mesh points in space | |
| dx = x[1] - x[0] | |
| dt = F*dx**2/a | |
| Nt = int(round(T/float(dt))) | |
| print 'Number of time steps:', Nt | |
| t = linspace(0, T, Nt+1) # mesh points in time | |
| u = zeros(Nx+1) # solution array at t[n+1] | |
| u_1 = zeros(Nx+1) # solution at t[n] | |
| # Representation of sparse matrix and right-hand side | |
| diagonal = zeros(Nx+1) | |
| lower = zeros(Nx+1) | |
| upper = zeros(Nx+1) | |
| b = zeros(Nx+1) | |
| # Precompute sparse matrix (scipy format) | |
| Fl = F*theta | |
| Fr = F*(1-theta) | |
| diagonal[:] = 1 + 2*Fl | |
| lower[:] = -Fl #1 | |
| upper[:] = -Fl #1 | |
| # Insert boundary conditions | |
| # (upper[1:] and lower[:-1] are the active alues) | |
| upper[0:2] = 0 | |
| lower[-2:] = 0 | |
| diagonal[0] = 1 | |
| diagonal[Nx] = 1 | |
| diags = [0, -1, 1] | |
| A = spdiags([diagonal, lower, upper], diags, Nx+1, Nx+1) | |
| #print A.todense() | |
| # Set initial condition | |
| for i in range(0,Nx+1): | |
| u_1[i] = I(x[i]) | |
| if user_action is not None: | |
| user_action(u_1, x, t, 0) | |
| # Time loop | |
| for n in range(0, Nt): | |
| b[1:-1] = u_1[1:-1] + Fr*(u_1[:-2] - 2*u_1[1:-1] + u_1[2:]) | |
| b[0] = u_L; b[-1] = u_R # boundary conditions | |
| u[:] = spsolve(A, b) | |
| if user_action is not None: | |
| user_action(u, x, t, n+1) | |
| # Switch variables before next step | |
| u_1, u = u, u_1 | |
| t1 = time.clock() | |
| return u, x, t, t1-t0 | |
| # Case: initial discontinuity | |
| theta2name = {1: 'BE', 0: 'FE', 0.5: 'CN'} | |
| class PlotU: | |
| def __init__(self, theta, F, Nx, L): | |
| self.theta, self.F, self.Nx, self.L = theta, F, Nx, L | |
| self._make_plotdir() | |
| def __call__(self, u, x, t, n): | |
| from scitools.std import plot, savefig | |
| umin = -0.1; umax = 1.1 # axis limits for plotting | |
| title = 'Method: %s, F=%g, t=%f' % \ | |
| (theta2name[self.theta], self.F, t[n]) | |
| plot(x, u, 'r-', | |
| axis=[0, self.L, umin, umax], | |
| title=title) | |
| savefig(os.path.join(self.plotdir, 'frame_%04d.png' % n)) | |
| # Pause the animation initially, otherwise 0.2 s between frames | |
| if n == 0: | |
| time.sleep(2) | |
| else: | |
| time.sleep(0.2) | |
| def _make_plotdir(self): | |
| self.plotdir = '%s_F%g' % (theta2name[self.theta], self.F) | |
| if os.path.isdir(self.plotdir): | |
| shutil.rmtree(self.plotdir) | |
| os.mkdir(self.plotdir) | |
| def make_movie(self): | |
| """Go to plot directory and make movie files.""" | |
| orig_dir = os.getcwd() | |
| os.chdir(self.plotdir) | |
| cmd = 'avconv -r 1 -i frame_%04d.png -vcodec libvpx movie.webm' | |
| cmd = 'avconv -r 1 -i frame_%04d.png -vcodec flv movie.flv' | |
| cmd = 'avconv -r 1 -i frame_%04d.png -vcodec libtheora movie.ogg' | |
| os.system(cmd) | |
| cmd = 'scitools movie output_file=index.html frame*.png' | |
| os.system(cmd) | |
| os.chdir(orig_dir) | |
| def I(x): | |
| return 0 if x > 0.5 else 1 | |
| def run_command_line_args(): | |
| # Command-line arguments: Nx F theta | |
| Nx = int(sys.argv[1]) | |
| F = float(sys.argv[2]) | |
| theta = float(sys.argv[3]) | |
| plot_u = PlotU(theta, F, Nx, L=1) | |
| u, x, t, cpu = solver(I, a=1, L=1, Nx=Nx, F=F, T=T, | |
| theta=theta, u_L=1, u_R=0, | |
| user_action=plot_u) | |
| plot_u.make_movie() | |
| def run_BE_CN_FE(): | |
| # cases: list of (Nx, C, theta, T) values | |
| cases = [(7, 5, 0.5, 3), (15, 0.5, 0, 0.25), | |
| (15, 0.5, 1, 0.12),] | |
| for Nx, F, theta, T in cases: | |
| print 'theta=%g, F=%g, Nx=%d' % (theta, F, Nx) | |
| plot_u = PlotU(theta, F, Nx, L=1) | |
| u, x, t, cpu = solver(I, a=1, L=1, Nx=Nx, F=F, T=T, | |
| theta=theta, u_L=1, u_R=0, | |
| user_action=plot_u) | |
| plot_u.make_movie() | |
| raw_input('Type Return to proceed with next case: ') | |
| if __name__ == '__main__': | |
| if len(sys.argv) == 1: | |
| # No command-line arguments: run predefined cases | |
| run_BE_CN_FE() | |
| elif len(sys.argv) == 4: | |
| run_command_line_args() | |
Xet Storage Details
- Size:
- 5.2 kB
- Xet hash:
- 34e2d3746d1a0c0e672f2fdcf329b4e254d77032a7e87e8caaed487edfc7e65b
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.