Back_Solve.m000064400024030002403000000001610710705366700141220ustar00harperharper00005130026413%
% Work in progress. Needs to be written to pay heed to sparsity.
%
function [x] = Back_Solve(A,b)
x = A\b;Band_Solve.m000064400024030002403000000020511105311447000141070ustar00harperharper00005130026413%
% Written by M. Harper Langston - 5/10/00
% harper@cims.nyu.edu
%
% For this sparse LU solver of Ax = b, A has band s.
% For example, the following matrix has band s = 1
%
% x x 0 0 0 0
% x x x 0 0 0
% 0 x x x 0 0
% 0 0 x x x 0
% 0 0 0 x x x
% 0 0 0 0 x x
%
%
function [x] = Band_Solve(A,b)
% Here, s is the band number
[m,n] = size(A);
if m~=n
error('Matrix not sqaure') % Want square matrix for simplicity
end
% Find the band of A
for l = 1:n
if A(m,l)~=0
s = n-l;
break;
end
end
% Do the sparse LU decomposition for a matrix of band s
for j = 1:m
if j >= m-s
L(j:m,j) = A(j:m,j)./A(j,j);
U(j,j:m) = A(j,j:m);
A(j:m,j:m) = A(j:m,j:m) - L(j:m,j)*U(j,j:m);
else
L(j:j+s,j) = A(j:j+s,j)./A(j,j);
U(j,j:j+s) = A(j,j:j+s);
A(j:j+s,j:j+s) = A(j:j+s,j:j+s) - L(j:j+s,j)*U(j,j:j+s);
end
end
L = sparse(L);
U = sparse(U);
% Call backsolve routine, which I wrote to pay heed to sparsity.
[y] = Back_Solve(L,b);
[x] = Back_Solve(U,y);
%
% Written by M. Harper Langston - 5/10/00
% ffunc.m000064400024030002403000000005231105311451300131740ustar00harperharper00005130026413% function, f for poisson.m
%
% Assume x and y of same length.
% f is returned as a matrix, analyzed at all interior points of the grid
% if f = 0, make sure f is a matrix of zeros, the size of x, NOT JUST ONE VALUE = 0!
function f = ffunc(x,y)
f = exp(x.*y);
%
% Written by M. Harper Langston - 5/10/00
% harper@cims.nyu.edu
%
Form_Boundary.m000064400024030002403000000011361105311461400146440ustar00harperharper00005130026413% Boundary conditions for poisson.m
%
% Form the boundaries of the Dirichlet problem in a box.
% Here gb = bottom condition, gl = left cond., gr = right, gt = top.
% Used in poisson.m. BOUNDARY CONDITIONS MUST BE CONTINUOUS
% make sure that if any of them are zero, that they are the length of x.
function [gb,gt,gl,gr] = Form_Boundary(x,y)
% gb is for u(x,0)
% gt is for u(x,endpoint)
% gl is for u(0,y)
% gr is for u(endpoint,y)
gb = (1/2).*sin(6*pi.*x);
gt = sin(pi*2.*x);
gl = 5.*y.*(y-1);
gr = -y.*((y-1).^4);
%
% Written by M. Harper Langston - 5/10/00
% harper@cims.nyu.edu
%
Form_Gamma.m000064400024030002403000000035501105311457200141100ustar00harperharper00005130026413%
% Written by M. Harper Langston - 5/10/00
% harper@cims.nyu.edu
%
% Using Lemma 10.5, form the orthogonal matrix, Q, the block matrix of
% matrices of eigenvectors of a TST block matrix. Then use this to form Gamma
% See Iselres page 246 or Lemma 10.5 for more info for Q.
% Gamma will be transformed into a plain tridiagonal matrix, using the method
% in Iserles, page 247 and 249.
function [Gam] = Form_Gamma(m,N)
for j = 1:m
for k = 1:m
Q(j,k) = sqrt(2/(m+1))*sin(pi*j*k/(m+1));
end
end
% Now, form Gamma. As per Iserles, page 247, we can rearrange columns into
% rows of the vectors, so Gamma will be tridiagonal. The only difference is
% that in the problem, Gamma*t = c, solving for t, c must be converted and
% then t will have to be converted back. See Iselres, pages 247 and 249
% for more informtion.
if N==9 | N==10
S = (diag((-10/3)*ones(m,1)) + diag((2/3)*ones(m-1,1),1) + diag((2/3)*ones(m-1,1),-1));
T = (diag((2/3)*ones(m,1)) + diag((1/6)*ones(m-1,1),1) + diag((1/6)*ones(m-1,1),-1));
elseif N==5
S = (diag((-4)*ones(m,1)) + diag((1)*ones(m-1,1),1) + diag((1)*ones(m-1,1),-1));
T = diag((1)*ones(m,1));
elseif N==101 % N = 101 is called by Modified_Right.m only, to speed up
% the modified 9=point scheme
S = (diag((2/3)*ones(m,1)) + diag((1/12)*ones(m-1,1),1) + diag((1/12)*ones(m-1,1),-1));
T = (diag((1/12)*ones(m,1)));
else
error('Must either use 5 or 9-point scheme (N=5 or N=9 in poisson.m)');
end
% inv(Q) = Q, so don't need to invert Q to diagonalize S and T
GS = diag(Q*S*Q);
GT = diag(Q*T*Q);
Gam = sparse(zeros(size(Q)));
for j = 1:m
temp = (j-1)*m +1;
Gam(temp:j*m,temp:j*m) = diag(GS(j)*ones(m,1)) ...
+ diag((GT(j))*ones(m-1,1),1) + diag((GT(j))*ones(m-1,1),-1);
end
Gam = sparse(Gam);
%
% Written by M. Harper Langston - 5/10/00
% harper@cims.nyu.edu
%Form_Right.m000064400024030002403000000037030710705367400141550ustar00harperharper00005130026413%
% Written by M. Harper Langston - 5/10/00
% mhl219@cims.nyu.edu or harper_langston@hotmail.com
%
% Form right-hand side of the Poisson problem in a box.
% the gt,gb,gl and gr are the boundary conditions (see Form_Boundary.m)
% and m is the size of each block and number of such blocks in the matrix,
% h = 1/m+1 from poisson.m, f is the vector f(x,y) and N is the scheme we
% are using (5-point, 9-point or modified 9-point).
% Gamma is passed for the modified 9 point scheme since don't want to recompute
% Gamma. Helps if multiplying f by new modified matrix scheme.
function [v] = Form_Right(m,h,f,gb,gt,gl,gr,N);
%length of f
g = f(2:m+1,2:m+1);
len = length(g(:));
% gnew is the correction vector we will subtract from fnew.
% This is one of the trickier steps, following the method used by Prof. Chen
% in the lecture from 2/24/00, forming the vector with components from the bndry
if N==5
gnew = gl(2:length(gl)-1);
gnew(len-m+1:len) = gr(2:length(gr)-1);
for k = 1:m
gnew((k-1)*m + 1) = gnew((k-1)*m + 1) + gb(k+1);
gnew(m*k) = gnew(m*k) + gt(k+1);
end
gnew = gnew';
elseif N==9 | N == 10
gnew = zeros(len,1);
for k = 1:m
gnew(k) = (1/6)*gl(k)+(2/3)*gl(k+1)+(1/6)*gl(k+2);
gnew(len-m+k) = (1/6)*gr(k)+(2/3)*gr(k+1)+(1/6)*gr(k+2);
end
for k = 1:m
gnew((k-1)*m + 1) = gnew((k-1)*m + 1) + (1/6)*gb(k)+(2/3)*gb(k+1)+(1/6)*gb(k+2);
gnew(m*k) = gnew(m*k) + (1/6)*gt(k)+(2/3)*gt(k+1)+(1/6)*gt(k+2);
end
gnew(1) = gnew(1) - (1/6)*gl(1);
gnew(m) = gnew(m) - (1/6)*gl(m+2);
gnew(len-m+1) = gnew(len-m+1) - (1/6)*gr(1);
gnew(end) = gnew(end) - (1/6)*gr(end);
end
% Call to Modified_Right forms the vector, f, which is just f if N=9 or 5,
% but f is altered as in the modified nine-point scheme if N = 10 (page 127 of Iserles)
[f] = Modified_Right(f,m,N);
v = (h^2).*f-gnew;
%
% Written by M. Harper Langston - 5/10/00
% mhl219@cims.nyu.edu or harper_langston@hotmail.com
%sed for the modified 9 point scheme since don't want to recomModified_Right.m000064400024030002403000000045221105311464700147630ustar00harperharper00005130026413%
% Written by M. Harper Langston - 5/10/00
% harper@cims.nyu.edu
%
% Right-hand vector is modified according to whether you're using
% the 5,9, or 9-point modified scheme. This is called bt Form_Right.m
% which is called by poisson.m If you are using the 5 or 9-point scheme,
% the result is straightforward, merely throwing away the boundary values
% in f.
% If you are using the modified nine-point scheme (corresponding to N=10),
% then the right hand side has a five-point stencil applied to it as per
% Iserles, page 127.
function [v] = Modified_Right(f,m,N)
% Form the blocks, S, T and Z
if N==5 | N==9
f = f(2:m+1,2:m+1);
v = f(:);
% The modified 9-point scheme can be computed quickly using the Gamma
% matrix found from before and then using fast sine transforms.
elseif N==10 % Modified step for right side. See Iserles, page 127
% Compute Gamma for the modified scheme. I let N = 101 here.
% Here,S = [1/12 2/3 1/12], T = [1/12] in a five-point manner. See Form_Gamma.m
% for more info.
[Gam] = Form_Gamma(m,101);
% Remove boundaries of f since we will apply a five-point stencil to it
fbot = f(1,1:end); fleft = f(1:end,1); ftop = f(end,1:end); fright = f(1:end,end);
% After removing boundaries, make f one long vector
f = f(2:m+1,2:m+1); f = f(:); len = length(f);
% As in 5-point stencil, make a new vector of the boundary points
fnew = fleft(2:length(fleft)-1);
fnew(len-m+1:len) = fright(2:length(fright)-1);
for k = 1:m
fnew((k-1)*m + 1) = fnew((k-1)*m + 1) + fbot(k+1);
fnew(m*k) = fnew(m*k) + ftop(k+1);
end
c = Transform(m,f)';
% Having formed c, rearrange rows into columns, so have to convert c to
% matrix format. Only takes O(m) time which is negligible
for j = 1:m
cnew(1:m,j) = c((j-1)*m + 1:(j-1)*m + m);
end
c = cnew'; c = c(:);
% Gam is tridiagonal and stored as sparse, so Gam*c is cheap.
t = Gam*c;
% The resulting vector t must be rearranged back so columns are rows: O(m)
for j = 1:m
tnew(1:m,j) = t((j-1)*m + 1:(j-1)*m + m);
end
t = tnew'; t = t(:);
% Call the DF sine Transform routine for speed to get the final result,u:
v = Transform(m,t)';
v = v + (1/12).*fnew;
else
error('Must use 9 or 5 point scheme (N = 5 ot N=9 in poisson.m)')
end
%
% Written by M. Harper Langston - 5/10/00
% harper@cims.nyu.edu
%poisson.m000064400024030002403000000077311105311470400135770ustar00harperharper00005130026413% poisson(m,endpt,N) - (m,endpt and N are described below)
%
% Written by M. Harper Langston - 5/10/00
% harper@cims.nyu.edu
%
% Fast poisson solver implementation in a SQUARE with CONTINUOUS DIRICHLET BNDRY CONDS.
% This file requires quite a few additional files:
%
% These first two are the only ones that need to be changed, depending on the situation:
% Form_Boundary.m - Stores the Dirichlet boundary condition
% ffunc.m - Stores f(x,y)
%
% The rest of these files are necessary, but MUST NOT BE changed (except by
% expert hands :) so that everything works ok)
% Form_Right.m - returns the right-hand side of the problem, given the boundary conditions
% and the vector, f. The result, b, incorporates boundary correction
% Modified_Right.m - Called in Form_Right.m, for the modified-nine-point scheme.
% This returns the matrix, B, which multiplies f(x,y)
% Form_Gamma.m - Forms the block matrix, Gamma, the block (tridiagonal) matrix of e-values.
% It does this by forming Q and then diagonalizing each block in A.
% It's important to note that Q is orthogonal such that inv(Q) = Q;
% This makes computation faster when we need it.
% Band_Solve.m - Finds the band of a Matrix and solves Ax = b
% according to A's sparsity and then does sparse LU decomposition
% Back_Solve.m - Called by Band_Solve.m to do the actual solving. It is a separate
% function since Band_Solve calls it twice.
% Transform.m - Last, but not least, Transform.m contains the call to the
% discrete fourier transform, and implements a fast sine transform
% by looking only at the imaginary part, up to a scaling factor.
% This is used to quickly compute y = Q*b and u = Q*y where the
% eigenvector-columns of Q are already known.
function poisson(m,endpt,N)
% m = refinement of mesh (best to keep below 100 on a 300 MhZ Home PC if you ever want it
% to finish; you can test this on your system).
% Note that x and y are discretized in the same manner.
% endpt = the endpoint of x and y, i.e., 0