ucar.unidata.util.GaussianLatitudes Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
package ucar.unidata.util;
import ucar.nc2.util.HashMapLRU;
import javax.annotation.concurrent.Immutable;
/**
* Calculate Gaussian Latitudes by finding the roots of the ordinary Legendre polynomial of degree
* NLAT using Newton's iteration method.
* Moderately expensive to compute, so keep LRU cache.
*
* @author caron port to Java
* @author Amy Solomon, 28 Jan 1991, via http://dss.ucar.edu/libraries/gridinterps/gaus-lats.f
*/
@Immutable
public class GaussianLatitudes {
private static final double XLIM = 1.0E-7;
private static final HashMapLRU hash = new HashMapLRU<>(10, 20);
public static GaussianLatitudes factory(int nlats) {
GaussianLatitudes glats = hash.get(nlats);
if (glats == null) {
glats = new GaussianLatitudes(nlats);
hash.put(nlats, glats);
}
return glats;
}
// all these have size nlat
public final double[] cosc; // cos(colatitude) or sin(latitude)
public final double[] colat; // the colatitudes in radians
public final double[] gaussw; // the Gaussian weights
public final double[] latd; // the latitudes in degrees
public final double[] sinc; // sin(colatitude) or cos(latitude)
public final double[] wos2; // Gaussian weight over sin**2(colatitude)
/**
* Constructor
* @param nlat the total number of latitudes from pole to pole (degree of the polynomial)
*/
private GaussianLatitudes(int nlat) {
if (nlat == 0) throw new IllegalArgumentException("nlats may not be zero");
// the number of latitudes between pole and equator
int nzero = nlat/2;
cosc = new double[nlat];
colat = new double[nlat];
gaussw = new double[nlat];
latd = new double[nlat];
sinc = new double[nlat];
wos2 = new double[nlat];
/* set first guess for cos(colat)
PI = 3.141592653589793
DO 10 I=1,NZERO
COSC(I) = SIN( (I-0.5)*PI/NLAT + PI*0.5 )
10 CONTINUE */
for (int i=0; i