function u = fps(p, isSlope) % fps -- Fast Poisson solver with boundary values. % fps(p) solves laplacian(u) = p for u, assuming the % boundary values are given along the perimeter of p % and the laplacians are given in the interior. % fps(p, isSlope) solves using the perimeter of p % as values of slope, if isSlope is logically TRUE. % fps([m n]) demonstrates itself with an n-by-n array % (default = [20 20]), with an off-center spike. % Copyright (C) 1998 Dr. Charles R. Denham, ZYDECO. % All Rights Reserved. % Disclosure without explicit written consent from the % copyright owner does not constitute publication. % Reference: Press, et al., Numerical Recipes, % Cambridge University Press, 1986 and later. % Version of 23-Oct-1998 09:02:58. % Revised 26-Oct-1998 14:29:11. % Revised 28-Oct-1998 15:36:22. % NB -- I am not happy with the zero-slope solution. % The graphs don't look correst, and they need % some scaling. if nargin < 1, help(mfilename), p = 'demo'; end if nargin < 2, isSlope = 0; end if ischar(isSlope), isSlope = eval(isSlope); end isSlope == any(isSlope(:)); if isequal(p, 'demo'), p = 20; end if ischar(p), p = eval(p); end if length(p) == 1, p = [p p]; end if length(p) == 2 theSize = p; p = zeros(theSize); [m, n] = size(p); p(ceil(m/3), ceil(n/3)) = 1; if nargout > 0 u = feval(mfilename, p, isSlope); else feval(mfilename, p, isSlope) end return end % Fold the boundary into source terms. if ~isSlope theFactor = -1; % Boundary-value scheme. else theFactor = +2; % Boundary-slope scheme. end q = p; for i = 1:2 q = q.'; q(2:end-1, 2:end-3:end-1) = ... q(2:end-1, 2:end-3:end-1) + theFactor * q(2:end-1, 1:end-1:end); end % Extract the interior. q = q(2:end-1, 2:end-1); % Symmetry: odd if 'value'; even if 'slope'. if ~isSlope theSign = -1; % Odd-symmetry, sine-transform scheme. else theSign = +1; % Even-symmetry, cosine-transform scheme. end [m, n] = size(q); q = [zeros(m, 1) q zeros(m, 1) theSign*fliplr(q)]; q = [zeros(1, 2*n+2); q; zeros(1, 2*n+2); theSign*flipud(q)]; % Fast Poisson Transform. res = fpt(q); % Retain relevant piece. if ~isSlope result = p; result(2:end-1, 2:end-1) = res(2:m+1, 2:n+1); else result = res(1:m+2, 1:n+2); end % Output or plot solution. if nargout > 0 u = result; else subplot(2, 2, 1), surf(p), axis tight title('Laplacian Data'), xlabel('x'), ylabel('y'), zlabel('p') subplot(2, 2, 2), surf(result), axis tight title('Poisson Solution'), xlabel('x'), ylabel('y'), zlabel('u') subplot(2, 2, 3), plot(p), axis tight xlabel('x'), ylabel('p') subplot(2, 2, 4), plot(result), axis tight xlabel('x'), ylabel('u') figure(gcf) end