Example 5.6
Approximate Factorization for the Heat Equation
This example uses matlab sparse matrices as the operators. This makes the code short and clean. But, care must be taken in applying the correct operator to the correct data. Matlab's meshgrid function stores x-values horizontally and y-values vertically in the data. When applying a matrix operator to data you are operating on the columns.
For example, say T is the data array. Ay is an operator on y-data and Ax is an operator on x-data. The application must be done in this way: Ay*T - to operate on the y-data Ax*T' - data must be transposed before applying the x operator
Note 1: An alternative to this method would be to store all of the data in a 1-dimensional array. However, this complicates the construction of the operators and plotting in matlab.
Note 2: Comments in this code use the following terms y-major: when y-data is organized in columns, the defualt state x-major: when x-data is organized in columns, usually after a transpose
Contents
Set up
close all; M = 20; % points in the x direction N = 20; % points in the y direction x0 = -1; xM = 1; y0 = -1; yN = 1; dx = (xM-x0)/M; dy = (yN-y0)/N; x = linspace(x0,xM,M+1); y = linspace(y0,yN,N+1); [X Y] = meshgrid(x,y); q = 2*(2-X.^2 - Y.^2);
operators
Ax = 1/(dx^2).*gallery('tridiag',M-1,1,-2,1); Ay = 1/(dy^2).*gallery('tridiag',N-1,1,-2,1); Ix = speye(M-1); Iy = speye(N-1);
Time advancement 1
dt = 0.05; % time step T = zeros(N+1,M+1); % initial condition t_final = 1.0; % final time time = 0:dt:t_final; % time array pt = [0.0 0.25 1.0]; % desired plot times pn = length(pt); % number of desired plots pc = 1; % plot counter rt = zeros(1,pn); % actual plot times S = zeros(N+1,M+1,pn); % solution storage for t = time % plot storage if ( t >= pt(pc) ) S(:,:,pc) = T; rt(pc) = t; pc = pc + 1; if (pc > pn) break end end r1 = (Iy + dt/2*Ay) * T(2:N,2:M); % r1 is y-major r2 = (Ix + dt/2*Ax) * r1'; % r2 is x-major r = r2 + dt*q(2:N,2:M)'; % r is x-major T1 = (Ix - dt/2*Ax) \ r; % T1 is x-major T(2:N,2:M) = (Iy - dt/2*Ay) \ T1'; % T is y-major end
Plot
figure(1); surf(X,Y,S(:,:,1)) zlim([0 1]) title(['t = ' num2str(rt(1))]) figure(2) surf(X,Y,S(:,:,2)) zlim([0 1]) title(['t = ' num2str(rt(2))]) figure(3) surf(X,Y,S(:,:,3)) zlim([0 1]) title(['t = ' num2str(rt(3))])
Compute error
% true solution P = (X.^2 - 1).*(Y.^2 - 1); % max pointwise difference mpd1 = max(max(abs(P-S(:,:,3)))) % max pointwise percentage mpp1 = max(max(abs(P(2:N,2:M)-S(2:N,2:M,3))./P(2:N,2:M))) % percentage error volume pev1 = sum(sum(abs(P-S(:,:,3))))/sum(sum(P))
mpd1 = 0.007690179217719 mpp1 = 0.007690179217719 pev1 = 0.007018872300514
Time advancement 2
dt = 1; % time step T = zeros(N+1,M+1); % initial condition t_final = 5.0; % final time time = 0:dt:t_final; % time array pt = [5.0]; % desired plot times pn = length(pt); % number of desired plots pc = 1; % plot counter rt = zeros(1,pn); % actual plot times S = zeros(N+1,M+1,pn); % solution storage for t = time % plot storage if ( t >= pt(pc) ) S(:,:,pc) = T; rt(pc) = t; pc = pc + 1; if (pc > pn) break end end r1 = (Iy + dt/2*Ay) * T(2:N,2:M); % r1 is y-major r2 = (Ix + dt/2*Ax) * r1'; % r2 is x-major r = r2 + dt*q(2:N,2:M)'; % r is x-major T1 = (Ix - dt/2*Ax) \ r; % T1 is x-major T(2:N,2:M) = (Iy - dt/2*Ay) \ T1'; % T is y-major end
Compute error
% true solution P = (X.^2 - 1).*(Y.^2 - 1); % max pointwise difference mpd2 = max(max(abs(P-S(:,:,1)))) % max pointwise percentage mpp2 = max(max(abs(P(2:N,2:M)-S(2:N,2:M,1))./P(2:N,2:M))) % percentage error volume pev2 = sum(sum(abs(P-S(:,:,1))))/sum(sum(P))
mpd2 = 3.885037657249679e-04 mpp2 = 0.006858024743513 pev2 = 2.241660343727758e-04