function [wmodes,pmodes,ce]=dynmodes(Nsq,p,nmodes)
% DYNMODES calculates ocean dynamic vertical modes
%  taking a column vector of Brunt-Vaisala values (Nsq) at
%  different pressures (p) and calculating some number of 
%  dynamic modes (nmodes). 
%  Note: The input pressures need not be uniformly spaced, 
%    and the deepest pressure is assumed to be the bottom.
%
%  USAGE: [wmodes,pmodes,ce]=dynmodes(Nsq,p,nmodes);
%                               or
%                            dynmodes;  % to show demo 
%
%     Inputs: 	Nsq = column vector of Brunt-Vaisala buoyancy frequency (s^-2)
%		    	  p = column vector of pressure (decibars)
%           nmodes = number of vertical modes to calculate 
%  
%       Outputs:   wmodes = vertical velocity structure
%                  pmodes = horizontal velocity structure
%                      ce = modal speed (m/s)
%  developed by J. Klinck. July, 1999
%  send comments and corrections to klinck@ccpo.odu.edu

if nargin<1
   help(mfilename);
   nplot=3;
%    test problems
%      problem 1
%    solution is h = ho sin(z /ce) where ce = 1 / n pi
%     ce = 0.3183 / n = [ 0.3183 0.1591 0.1061]
%p=0:.05:1;
%z=-p;
%n=length(p);
%Nsq(1:n)=1;
%
%      problem 2
%    solution is h = ho sin(No z /ce) where ce = No H / n pi
%    for No=1.e-3 and H = 400, the test values are 
%     ce = 0.127324 / n = [ 0.127324, 0.063662, 0.042441]
%
	p=0:10:400;
	z=-p;
	n=length(p);
	Nsq(1:n)=1.e-6;

	nmodes=3;

	[wmodes,pmodes,ce]=dynmodes(Nsq,p,nmodes);

	figure(1)
	plot(Nsq,z);
	title('Buoyancy Frequency Squared (s^{-2})')

	figure(2)
	plot(ce(1:nplot),'r:o');
	title(' Modal Speed (m/s)')

	figure(3)
	plot(wmodes(:,1:nplot),z);
	title('Vertical Velocity Structure')

	figure(4)
	plot(pmodes(:,1:nplot),z);
	title('Horizontal Velocity Structure')

        figure(gcf)
        return
end
  
rho0=1028;

%    convert to column vector if necessary
[m,n] = size(p);
if n == 1
   p=p';
end
[m,n] = size(Nsq);
if n == 1
   Nsq=Nsq';
   n=m;
end

%                 check for surface value
if p(1) > 0
%             add surface pressure with top Nsq value
    z(1)=0;
    z(2:n+1)=-p(1:n);
    N2(1)=Nsq(1);
    N2(2:n+1)=Nsq(1:n);
    nz=n+1;
else
    z=-p;
    N2=Nsq;
    nz=n;
end

%          calculate depths and spacing
%        spacing
dz(1:nz-1)=z(1:nz-1)-z(2:nz);
%        midpoint depth
zm(1:nz-1)=z(1:nz-1)-.5*dz(1:nz-1)'';
%        midpoint spacing
dzm=zeros(1,nz);
dzm(2:nz-1)=zm(1:nz-2)-zm(2:nz-1);
dzm(1)=dzm(2);
dzm(nz)=dzm(nz-1);

%        get dynamic modes
A = zeros(nz,nz);
B = zeros(nz,nz);
%             create matrices   
for i=2:nz-1
  A(i,i) = 1/(dz(i-1)*dzm(i))  + 1/(dz(i)*dzm(i));
  A(i,i-1) = -1/(dz(i-1)*dzm(i));
  A(i,i+1) = -1/(dz(i)*dzm(i));
end
for i=1:nz
  B(i,i)=N2(i);
end
%             set boundary conditions
A(1,1)=-1.;
A(nz,1)=-1.;

[wmodes,e] = eig(A,B);

%          extract eigenvalues
e=diag(e);
%
ind=find(imag(e)==0);
e=e(ind);
wmodes=wmodes(:,ind);
%
ind=find(e>=1.e-10);
e=e(ind);
wmodes=wmodes(:,ind);
%
[e,ind]=sort(e);
wmodes=wmodes(:,ind);

nm=length(e);
ce=1./sqrt(e);
%                   create pressure structure
pmodes=zeros(size(wmodes));

for i=1:nm
%           calculate first deriv of vertical modes
  pr=diff(wmodes(:,i));   
  pr(1:nz-1)= pr(1:nz-1)./dz(1:nz-1)';
  pr=pr*rho0*ce(i)*ce(i);
%       linearly interpolate back to original depths
  pmodes(2:nz-1,i)=.5*(pr(2:nz-1)+pr(1:nz-2));
  pmodes(1,i)=pr(1);
  pmodes(nz,i)=pr(nz-1);
end
