% Several methods for the advection equation u_t + a u_x = 0 are compared eps % controls the multiple of the Laplacian that is added to the centered finite % difference operator in space. this introduces some numerical dissipation % that smoothes out high frequencies. Different values of eps correspond to % different methods (Forward Euler, Lax-Friedrichs, upwind and Lax-Wendroff). % Of course it is more efficient to write the schemes directly without using % matrices! The leapfrog method is also implemented, however the first for % loop has to be commented out and the last for loop uncommented. See "Finite % Difference Methods for Ordinary and Partial Differential Equations", R. % LeVeque. n=100; x = linspace(0,1,n)'; utrue = @(x) max(1-abs(6*(mod(x,1)-1/2)),0) + max(1-abs(20*(mod(x,1)-0.2)),0); u = utrue(x); a = 2; e = ones(n,1); h = 1/n; A = -(a/2/h)*spdiags([-e,e],[-1,1],n,n); A(1,n)=a/2/h; A(n,1)=-a/2/h; B = (1/h^2)*spdiags([e,-2*e,e],-1:1,n,n); B(1,n)=1/h^2; B(n,1)=1/h^2; k = 0.9*h/abs(a); %eps = 0; % Euler (unstable) %eps=h^2/2/k; % Lax-Friedrichs eps=abs(a)*h/2; % upwind %eps=-a*h/2; % upwind with wrong sign %eps=a^2*k/2; % Lax-Wendroff Aeps = A + eps*B; figure(1); t=linspace(0,2*pi); lambda=eig(full(k*Aeps)); plot(real(lambda),imag(lambda),'*',-1+cos(t),sin(t),'r-'); axis equal fprintf('h=%f, k=%d, |a*k/h| = %f\n',h,k,abs(a*k/h)); figure(2) % Forward Euler, Lax-Friedrichs, upwind and Lax-Wendroff for i=1:n, u = u + k*Aeps*u; plot(x,u,x,utrue(x-a*k*i)); axis([0 1 -0.5 1.5]); title(sprintf('t=%d\n',k*i)); pause(0.1); end; %% Leapfrog %uol=u; %u = uol + k*A*uol; %for i=1:1000, % unew = uol + 2*k*A*u; % uol=u; % u=unew; % plot(x,u,x,utrue(x-a*k*i)); axis([0 1 -0.5 1.5]); % title(sprintf('t=%d\n',k*(i-1))); % pause(0.1); %end;