Buckets:
| #!/usr/bin/env python | |
| """ | |
| 1D wave equation with u=0 at the boundary. | |
| Simplest possible implementation. | |
| The key function is:: | |
| u, x, t, cpu = (I, V, f, c, L, dt, C, T, user_action) | |
| which solves the wave equation u_tt = c**2*u_xx on (0,L) with u=0 | |
| on x=0,L, for t in (0,T]. Initial conditions: u=I(x), u_t=V(x). | |
| T is the stop time for the simulation. | |
| dt is the desired time step. | |
| C is the Courant number (=c*dt/dx), which specifies dx. | |
| f(x,t) is a function for the source term (can be 0 or None). | |
| I and V are functions of x. | |
| user_action is a function of (u, x, t, n) where the calling | |
| code can add visualization, error computations, etc. | |
| """ | |
| import numpy as np | |
| def solver(I, V, f, c, L, dt, C, T, user_action=None): | |
| """Solve u_tt=c^2*u_xx + f on (0,L)x(0,T].""" | |
| Nt = int(round(T/dt)) | |
| t = np.linspace(0, Nt*dt, Nt+1) # Mesh points in time | |
| dx = dt*c/float(C) | |
| Nx = int(round(L/dx)) | |
| x = np.linspace(0, L, Nx+1) # Mesh points in space | |
| C2 = C**2 # Help variable in the scheme | |
| if f is None or f == 0 : | |
| f = lambda x, t: 0 | |
| if V is None or V == 0: | |
| V = lambda x: 0 | |
| u = np.zeros(Nx+1) # Solution array at new time level | |
| u_1 = np.zeros(Nx+1) # Solution at 1 time level back | |
| u_2 = np.zeros(Nx+1) # Solution at 2 time levels back | |
| import time; t0 = time.clock() # for measuring CPU time | |
| # Load initial condition into u_1 | |
| 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) | |
| # Special formula for first time step | |
| n = 0 | |
| for i in range(1, Nx): | |
| u[i] = u_1[i] + dt*V(x[i]) + \ | |
| 0.5*C2*(u_1[i-1] - 2*u_1[i] + u_1[i+1]) + \ | |
| 0.5*dt**2*f(x[i], t[n]) | |
| u[0] = 0; u[Nx] = 0 | |
| if user_action is not None: | |
| user_action(u, x, t, 1) | |
| # Switch variables before next step | |
| u_2[:] = u_1; u_1[:] = u | |
| for n in range(1, Nt): | |
| # Update all inner points at time t[n+1] | |
| for i in range(1, Nx): | |
| u[i] = - u_2[i] + 2*u_1[i] + \ | |
| C2*(u_1[i-1] - 2*u_1[i] + u_1[i+1]) + \ | |
| dt**2*f(x[i], t[n]) | |
| # Insert boundary conditions | |
| u[0] = 0; u[Nx] = 0 | |
| if user_action is not None: | |
| if user_action(u, x, t, n+1): | |
| break | |
| # Switch variables before next step | |
| u_2[:] = u_1; u_1[:] = u | |
| cpu_time = t0 - time.clock() | |
| return u, x, t, cpu_time | |
| def test_quadratic(): | |
| """Check that u(x,t)=x(L-x)(1+t/2) is exactly reproduced.""" | |
| def u_exact(x, t): | |
| return x*(L-x)*(1 + 0.5*t) | |
| def I(x): | |
| return u_exact(x, 0) | |
| def V(x): | |
| return 0.5*u_exact(x, 0) | |
| def f(x, t): | |
| return 2*(1 + 0.5*t)*c**2 | |
| L = 2.5 | |
| c = 1.5 | |
| C = 0.75 | |
| Nx = 6 # Very coarse mesh for this exact test | |
| dt = C*(L/Nx)/c | |
| T = 18 | |
| def assert_no_error(u, x, t, n): | |
| u_e = u_exact(x, t[n]) | |
| diff = np.abs(u - u_e).max() | |
| tol = 1E-13 | |
| assert diff < tol | |
| solver(I, V, f, c, L, dt, C, T, | |
| user_action=assert_no_error) | |
| def test_constant(): | |
| """Check that u(x,t)=Q=0 is exactly reproduced.""" | |
| u_const = 0 # Require 0 because of the boundary conditions | |
| C = 0.75 | |
| dt = C # Very coarse mesh | |
| u, x, t, cpu = solver(I=lambda x: | |
| 0, V=0, f=0, c=1.5, L=2.5, | |
| dt=dt, C=C, T=18) | |
| tol = 1E-14 | |
| assert np.abs(u - u_const).max() < tol | |
| def viz( | |
| I, V, f, c, L, dt, C, T, # PDE paramteres | |
| umin, umax, # Interval for u in plots | |
| animate=True, # Simulation with animation? | |
| tool='matplotlib', # 'matplotlib' or 'scitools' | |
| solver_function=solver, # Function with numerical algorithm | |
| ): | |
| """Run solver and visualize u at each time level.""" | |
| def plot_u_st(u, x, t, n): | |
| """user_action function for solver.""" | |
| plt.plot(x, u, 'r-', | |
| xlabel='x', ylabel='u', | |
| axis=[0, L, umin, umax], | |
| title='t=%f' % t[n], show=True) | |
| # Let the initial condition stay on the screen for 2 | |
| # seconds, else insert a pause of 0.2 s between each plot | |
| time.sleep(2) if t[n] == 0 else time.sleep(0.2) | |
| plt.savefig('frame_%04d.png' % n) # for movie making | |
| class PlotMatplotlib: | |
| def __call__(self, u, x, t, n): | |
| """user_action function for solver.""" | |
| if n == 0: | |
| plt.ion() | |
| self.lines = plt.plot(x, u, 'r-') | |
| plt.xlabel('x'); plt.ylabel('u') | |
| plt.axis([0, L, umin, umax]) | |
| plt.legend(['t=%f' % t[n]], loc='lower left') | |
| else: | |
| self.lines[0].set_ydata(u) | |
| plt.legend(['t=%f' % t[n]], loc='lower left') | |
| plt.draw() | |
| time.sleep(2) if t[n] == 0 else time.sleep(0.2) | |
| plt.savefig('tmp_%04d.png' % n) # for movie making | |
| if tool == 'matplotlib': | |
| import matplotlib.pyplot as plt | |
| plot_u = PlotMatplotlib() | |
| elif tool == 'scitools': | |
| import scitools.std as plt # scitools.easyviz interface | |
| plot_u = plot_u_st | |
| import time, glob, os | |
| # Clean up old movie frames | |
| for filename in glob.glob('tmp_*.png'): | |
| os.remove(filename) | |
| # Call solver and do the simulaton | |
| user_action = plot_u if animate else None | |
| u, x, t, cpu = solver_function( | |
| I, V, f, c, L, dt, C, T, user_action) | |
| # Make video files | |
| fps = 4 # frames per second | |
| codec2ext = dict(flv='flv', libx264='mp4', libvpx='webm', | |
| libtheora='ogg') # video formats | |
| filespec = 'tmp_%04d.png' | |
| movie_program = 'ffmpeg' # or 'avconv' | |
| for codec in codec2ext: | |
| ext = codec2ext[codec] | |
| cmd = '%(movie_program)s -r %(fps)d -i %(filespec)s '\ | |
| '-vcodec %(codec)s movie.%(ext)s' % vars() | |
| os.system(cmd) | |
| if tool == 'scitools': | |
| # Make an HTML play for showing the animation in a browser | |
| plt.movie('tmp_*.png', encoder='html', fps=fps, | |
| output_file='movie.html') | |
| return cpu | |
| def guitar(C): | |
| """Triangular wave (pulled guitar string).""" | |
| L = 0.75 | |
| x0 = 0.8*L | |
| a = 0.005 | |
| freq = 440 | |
| wavelength = 2*L | |
| c = freq*wavelength | |
| omega = 2*pi*freq | |
| num_periods = 1 | |
| T = 2*pi/omega*num_periods | |
| # Choose dt the same as the stability limit for Nx=50 | |
| dt = L/50./c | |
| def I(x): | |
| return a*x/x0 if x < x0 else a/(L-x0)*(L-x) | |
| umin = -1.2*a; umax = -umin | |
| cpu = viz(I, 0, 0, c, L, dt, C, T, umin, umax, | |
| animate=True, tool='scitools') | |
| if __name__ == '__main__': | |
| test_quadratic() | |
| import sys | |
| try: | |
| C = float(sys.argv[1]) | |
| print 'C=%g' % C | |
| except IndexError: | |
| C = 0.85 | |
| print 'Courant number: %.2f' % C | |
| guitar(C) | |
Xet Storage Details
- Size:
- 6.92 kB
- Xet hash:
- 506b0e6815cae0960140d9063e41a3b0d717c6ef6406f9fccc9d78edb023db9d
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.