Code covered by the BSD License

### Highlights fromUsing Numerical Computing with MATLAB in the Classroom

from Using Numerical Computing with MATLAB in the Classroom by Cleve Moler
M-files used in the webinar held on April 27, 2004.

membranetx(k,m,n,np)
```function [L,lambda] = membranetx(k,m,n,np)
%MEMBRANETX  Textbook version of MEMBRANE, eigenfunctions of L-membrane.
%
%   L = MEMBRANETX(k) is the k-th eigenfunction of the L-shaped membrane.
%   [L,lambda] = MEMBRANETX(k) also returns the k-th eigenvalue.
%
%   L = MEMBRANETX(k,m,n,np) sets some mesh and accuracy parameters:
%
%     k = index of eigenfunction, default k = 1.
%     m = number of points on one edge of one square.
%         The output L is 2*m+1-by-2*m+1.  The default m = 30.
%     n = number of terms in sum, default n = min(m,20).
%     np = number of terms in partial sum, default np = n.
%     With np = n, the eigenfunction is zero on the boundary.
%     With np < n, such as np = 2, the boundary is not tied down.
%
%   L = ROT90(MEMBRANETX(1,15,9,2),-1) is the MathWorks logo.

% Default parameters

if nargin < 1, k = 1; end
if nargin < 2, m = 30; end
if nargin < 3, n = min(m,20); end
if nargin < 4, np = n; end

% Compute eigenvalue and symmetry class.
% sym = 1, symmetric about center line
% sym = 2, antisymmetric about center line
% sym >= 3, eigenvalue of the square, reflected into other squares

[lambda,sym] = membraneval(k,m,n);
if m == 1, L = lambda(k); return, end

% The null vector from the SVD of the boundary matrix gives coefficients.

[sigma,c,alfa] = membranesvd(lambda,sym,m,n);

% Evaluate the eigenfunction on a square grid.

L = membranefun(lambda,sym,c,alfa,m,n,np);

% ------------------------------

function [lambda,sym] = membraneval(k,m,n);
% MEMBRANEVAL
% [lambda,sym] = membraneval(k,m,n) is the k-th eigenvalue of
% the L shaped membrane, and its symmetry class.
% m = number of points on one edge of one square.
% n = number of terms in sum.

persistent lambdas syms

if isempty(lambdas) & exist('membrane.mat')
end

if length(lambdas) < k
% Compute eigenvalues beyond those already computed.
% Algorithm:
% Use direct search to get near local minima of membranesvd(lambda).
% Then use "fmintx" to home in on the minimizers.
% The step size delta controls the direct search.
% Increasing delta decreases computer time, but might miss some eigenvalues.
% kmax = number of eigenvalues.
% delta = search increment.
% tol = tolerance for fmintx
kmax = k;
delta = .01;
tol = 1.e-12;
k = length(lambdas);
if k == 0
lambdas(1) = fmintx(@membranesvd,9.6,9.7,tol,1,m,n);
syms(1) = 1;
k = 1;
fprintf(1,'%4.0d %18.12f %4.0d\n',k,lambdas(k),syms(k))
end
xstart = delta*floor(lambdas(k)/delta);
x = [0 0 xstart];
f = zeros(3,3);

% Look for x so that f(x) < both f(x-delta) and f(x+delta).
while k < kmax
x(1:2) = x(2:3);
x(3) =  x(3) + delta;
for s = 1:3    % Symmetry class.
f(s,1:2) = f(s,2:3);
f(s,3) = membranesvd(x(3),s,m,n);
if f(s,2) < f(s,1) & f(s,2) < f(s,3);
lam = fmintx(@membranesvd,x(1),x(3),tol,s,m,n);
if s < 3
mult = 1;
else
% Multiple eigenvalues are integer multiples of pi^2
p = round(lam/pi^2);
lam = p*pi^2;
[i,j] = ndgrid(1:sqrt(p));
mult = sum(p == i(:).^2+j(:).^2);
end
for mu = 1:mult
k = k+1;
lambdas(k,1) = lam;
syms(k,1) = s+mu-1;
fprintf(1,'%4.0d %18.12f %4.0d\n',k,lambdas(k),syms(k))
pause(0)
end
end
end
end
end

[lambdas,p] = sort(lambdas);
syms = syms(p);
% save membrane lambdas syms
lambda = lambdas(k);
sym = syms(k);

% ------------------------------

function [sigma,c,alfa] = membranesvd(lambda,sym,m,n)
% MEMBRANESVD
% Evaluate fundamental solutions on boundary of L-shaped region.
% sigma = membranesvd(lambda,s,m,n) is the smallest singular value of the
% matrix obtained by evaluating n fundamental solutions with symmetry class
% s at 3*m+1 points on the boundary of the L.  If lambda is chosen to give
% a local minima of this function, the resulting null vector, c, provides
% coeffients for a linear combination over the entire region that nearly
% vanishes on the boundary.
%
% Input:
%   lambda = eigenvalue parameter, vary this to minimize the resulting sigma.
%   sym = symmetry class.
%   m = number of points on edge of one square.
%   n = number of fundamental solutions.
%
% Output:
%   sigma = smallest singular value.
%   c = null vector = coefficients.
%   alfa = 1-by-n vector of Bessel function orders for given symmetry.

% Bessel function orders.
% sym = 1, alfa = (2/3) * [1 5 7 11 13 ... ], (odd, not divisible by 3)
% sym = 2, alfa = (2/3) * [2 4 8 10 14 ... ], (even, not divisible by 3)
% sym >= 3, alfa = [2 4 6 8 10 ... ] = even integers

switch sym
case {1,2}
j = (sym:2:3*n);
j(mod(j,3)==0) = [];
alfa = (2/3)*j;
otherwise
alfa = 2*(1:n);
end

% Use polar coordinates to describe three-eighths of the boundary.

x = [ones(m,1); (m:-1:-m)'/m];
y = [(0:m-1)'/m; ones(2*m+1,1)];
theta = atan2(y,x);
r = sqrt(x.^2 + y.^2);

% Evaluate the fundamental solutions on the boundary.
% A is a (3*m+1)-by-n matrix.

A = besselj(alfa,sqrt(lambda)*r).*sin(theta*alfa);

% Scale to make columns comparable.

scale = diag(sparse(1./sqrt(sum(A.*A))));
A = A*scale;

% Compute SVD and obtain coefficients from null vector(s).

[U,S,V] = svd(A,0);
if sym > 3, n = n-(sym-3); end    % Multiple eigenvalue
sigma = S(n,n);
c = scale*V(:,n);

% ------------------------------

function L = membranefun(lambda,sym,c,alfa,m,n,np)
% MEMBRANEFUN  Evaluate the eigenfunction on a square grid.
% L = membranefun(lambda,sym,c,alfa,m,n,np)
% Used by MEMBRANETX.

[x,y] = meshgrid((-m:m)/m,(m:-1:0)'/m);
r = sqrt(x.*x + y.*y);
theta = atan2(y,x);
theta(m+1,m+1) = 0;
S = zeros(m+1,2*m+1);
for j = 1:np
S = S + c(j)*besselj(alfa(j),sqrt(lambda)*r).*sin(alfa(j)*theta);
end
S = S/S(min(find(abs(S(:)) == max(abs(S(:))))));
L = zeros(2*m+1,2*m+1);
switch sym
case 1
L(1:m+1,:) = triu(S);
L = L + L' - diag(diag(L));
case 2
L(1:m+1,:) = triu(S);
L = L - L';
otherwise
L(1:m,1:m) = S(1:m,1:m);
L(m+2:2*m+1,1:m) = -flipud(L(1:m,1:m));
L(1:m,m+2:2*m+1) = -fliplr(L(1:m,1:m));
end
```