% [u,err,x,t] = heat_cn(t_0,t_f,M,N) % % this solves the heat equation u_t = u_xx with initial data u_0 = % cos(x) with periodic boundary conditions using finite-differences in % space and Crank-Nicolson time-stepping. t_0 is the initial time, t_f is the % final time, N is the number of mesh-points, and M is the number of % time steps. err is the error. function [u,err,x,t] = heat_cn(t_0,t_f,M,N) % define the mesh in space dx = 2*pi/(N-1); x = 0:dx:2*pi; x = x'; % define the mesh in time dt = (t_f-t_0)/M; t = t_0:dt:t_f; % define the ratio r r = dt/dx^2 for i=1:N u(i,1) = cos(x(i)); end err(:,1) = u(:,1) - exp(-t(1))*cos(x); % for internal points, have % u_new(j) = u_old(j) + r/2*(u_old(j+1)-2*u_old(j)+u_old(j-1)) % for the two end-points, have % u_new(1) = u_old(1) + r/2*(u_old(2)-2*u_old(1)+u_old(N-1)) % u_new(N) = u_old(N) + r/2*(u_old(2)-2*u_old(N)+u_old(N-1)) % clearly the endpoints are redundant: u(1)= u(N) at all times. I just % kept them around for plotting convenience. % define the matrix A which has to be inverted at every time-step. % u_new(1) - u_old(1) = dt/h^2 (u_new(2)-2*u_new(1)+u_new(N-1) % u_new(i) - u_old(i) = dt/h^2 (u_new(i+1)-2*u_new(i)+u_new(i-1) % u_new(N) - u_old(N) = dt/h^2 (u_new(2)-2*u_new(N)+u_new(N-1) A = zeros(N-1,N-1); A(1,1) = 1+r; A(1,2) = -r/2; A(1,N-1) = -r/2; for i=2:N-2 A(i,i-1) = -r/2; A(i,i) = 1+r; A(i,i+1) = -r/2; end A(N-1,N-1) = 1+r; A(N-1,N-2) = -r/2; A(N-1,1) = -r/2; for j=1:M RHS(1) = u(1,j) + r/2*(u(2,j)-2*u(1,j)+u(N-1,j)); for i=2:N-1 RHS(i) = u(i,j) + r/2*(u(i+1,j)-2*u(i,j)+u(i-1,j)); end u(1:N-1,j+1) = periodic_tridiag(A,RHS); % impose periodicity u(N,j+1) = u(1,j+1); err(:,j+1) = u(:,j+1) - exp(-t(j+1))*cos(x); end