No BSD License  

Highlights from
Gauss2lats

from Gauss2lats by Tom Holt
Estimates the latitudes of a Gaussian grid.

[xlat,dlat,sinc]=gauss2lats(nlat)
% This function provides latitudes on a Gaussian grid from the
% number of latitude lines.
%
% the calling format is:
%               [xlat,dlat,sinc]=gauss2lats(nlat)
%     where: input is nlat = the number of latitude lines, e.g 94 in a T62 grid
%                             with 192 longitudes and 94 latitudes
%            outputs are:
%                      xlat = the latitudes
%                      dlat = latitude spacing
%                      sinc = sine of colatitudes (cosine of latitudes)
% 
% Adapted for Matlab from the NCAR Fortran program by Tom Holt, 23/10/2002.
%
% Possible problems:
%          1) The output may appear slightly different from other
%          estimates. I am indebted to Lee Panetta who provided the
%          following test results (21.10.2003), comparing Gauss2lats on a
%          G4 Mac with another algorithm on a Cray J90:
%                   agreement to 15 decimal places except at endpoints
%                   where agreement was to 13 decimal places.
%          2) The routine may not converge to a solution on some grids.

function [xlat,dlat,sinc]=gauss2lats(nlat)
acon=180.0/pi;

% convergence criterion for iteration of cos latitude
xlim=1.0e-7;

% initialise arrays
for i=1:720
    cosc(i)=0.;
    gwt(i)=0.;
    sinc(i)=0.;
    colat(i)=0.;
    wos2(i)=0.;
end

% the number of zeros between pole and equator
nzero=nlat/2;

% set first guess for cos(colat)
for i=1:nzero;
    cosc(i)=sin((i-0.5)*pi/nlat+pi*0.5);
end

% constants for determining the derivative of the polynomial
fi=nlat;
fi1=fi+1.0;
a=fi*fi1/sqrt(4.0*fi1*fi1-1.0);
b=fi1*fi/sqrt(4.0*fi*fi-1.0);

%loop over latitudes, iterating the search for each root
for i=1:nzero
    % determine the value of the ordinary Legendre polynomial for the current guess root
    g=gord(nlat,cosc(i));
    % determine the derivative of the polynomial at this point
    gm=gord(nlat-1,cosc(i));
    gp=gord(nlat+1,cosc(i));
    gt=(cosc(i)*cosc(i)-1.0)/(a*gp-b*gm);
    % update the estimate of the root
    delta=g*gt;
    cosc(i)=cosc(i)-delta;
 
    % if convergence criterion has not been met, keep trying
    while abs(delta) > xlim
        g=gord(nlat,cosc(i));
        gm=gord(nlat-1,cosc(i));
        gp=gord(nlat+1,cosc(i));
        gt=(cosc(i)*cosc(i)-1.0)/(a*gp-b*gm);
        delta=g*gt;
        cosc(i)=cosc(i)-delta;   
    end
    % determine the Gaussian weights
    c=2.0*(1.0-cosc(i)*cosc(i));
    d=gord(nlat-1,cosc(i));
    d=d*d*fi*fi;
    gwt(i)=c*(fi-0.5)/d;
end

% determine the colatitudes and sin(colat) and weights over sin**2
for i=1:nzero
    colat(i)=acos(cosc(i));
    sinc(i)=sin(colat(i));
    wos2(i)=gwt(i)/(sinc(i)*sinc(i));
end

% if nlat is odd, set values at the equator
if mod(nlat,2) ~= 0 
    i=nzero+1;
    cosc(i)=0.0;
    c=2.0;
    d=gord(nlat-1,cosc(i));
    d=d*d*fi*fi;
    gwt(i)=c*(fi-0.5)/d;
    colat(i)=pi*0.5;
    sinc(i)=1.0;
    wos2(i)=gwt(i);
end

% determine the southern hemisphere values by symmetry
for i=nlat-nzero+1:nlat
    cosc(i)=-cosc(nlat+1-i);
    gwt(i)=gwt(nlat+1-i);
    colat(i)=pi-colat(nlat+1-i);
    sinc(i)=sinc(nlat+1-i);
    wos2(i)=wos2(nlat+1-i);
end

ylat=90.;

% calculate latitudes and latitude spacing
for i=1:nzero
    xlat(i)=acos(sinc(i))*acon;
    dlat(i)=xlat(i)-ylat;
    ylat=xlat(i);
end




% This function calculates the value of an ordinary Legendre polynomial at a latitude.
%          inputs are:
%                n = the degree of the polynomial
%                x = cos(colatitude)
%         outputs are:
%              ggg = the value of the Legendre polynomial of degree n at 
%                    latitude asin(x)
%
function [ggg]=gord(n,x)

% determine the colatitude
colat=acos(x);

c1=sqrt(2.0);

for i=1:n
    c1=c1*sqrt(1.0-1.0/(4*i*i));
end

fn=n;
ang=fn*colat;
s1=0.0;
c4=1.0;
a=-1.0;
b=0.0;

for k=0:2:n
    if k==n 
        c4=0.5*c4;
    end
    s1=s1+c4*cos(ang);
    a=a+2.0;
    b=b+1.0;
    fk=k;
    ang=colat*(fn-fk-2.0);
    c4=(a*(fn-b+1.0)/(b*(fn+fn-a)))*c4;
end
ggg=s1*c1;

Contact us at files@mathworks.com