grib2io.utils.gauss_grid
Tools for working with Gaussian grids.
Adopted from: https://gist.github.com/ajdawson/b64d24dfac618b91974f
1""" 2Tools for working with Gaussian grids. 3 4Adopted from: https://gist.github.com/ajdawson/b64d24dfac618b91974f 5""" 6from __future__ import (absolute_import, division, print_function) 7 8import functools 9 10import numpy as np 11import numpy.linalg as la 12from numpy.polynomial.legendre import legcompanion, legder, legval 13 14 15def __single_arg_fast_cache(func): 16 """Caching decorator for functions of one argument.""" 17 class CachingDict(dict): 18 19 def __missing__(self, key): 20 result = self[key] = func(key) 21 return result 22 23 @functools.wraps(func) 24 def __getitem__(self, *args, **kwargs): 25 return super(CachingDict, self).__getitem__(*args, **kwargs) 26 27 return CachingDict().__getitem__ 28 29 30@__single_arg_fast_cache 31def gaussian_latitudes(nlat): 32 """ 33 Construct latitudes for a Gaussian grid. 34 35 Parameters 36 ---------- 37 **`nlat : int`** 38 The number of latitudes in the Gaussian grid. 39 40 Returns 41 ------- 42 `numpy.ndarray` of latitudes (in degrees) with a length of `nlat`. 43 """ 44 if abs(int(nlat)) != nlat: 45 raise ValueError('nlat must be a non-negative integer') 46 # Create the coefficients of the Legendre polynomial and construct the 47 # companion matrix: 48 cs = np.array([0] * nlat + [1], dtype=int) 49 cm = legcompanion(cs) 50 # Compute the eigenvalues of the companion matrix (the roots of the 51 # Legendre polynomial) taking advantage of the fact that the matrix is 52 # symmetric: 53 roots = la.eigvalsh(cm) 54 roots.sort() 55 # Improve the roots by one application of Newton's method, using the 56 # solved root as the initial guess: 57 fx = legval(roots, cs) 58 fpx = legval(roots, legder(cs)) 59 roots -= fx / fpx 60 # The roots should exhibit symmetry, but with a sign change, so make sure 61 # this is the case: 62 roots = (roots - roots[::-1]) / 2. 63 # Convert the roots from the interval [-1, 1] to latitude values on the 64 # interval [-90, 90] degrees: 65 latitudes = np.rad2deg(np.arcsin(roots)) 66 # Flip latitudes such that it is oriented from North to South [90, -90] 67 latitudes = np.flip(latitudes) 68 return latitudes
def
gaussian_latitudes():
31@__single_arg_fast_cache 32def gaussian_latitudes(nlat): 33 """ 34 Construct latitudes for a Gaussian grid. 35 36 Parameters 37 ---------- 38 **`nlat : int`** 39 The number of latitudes in the Gaussian grid. 40 41 Returns 42 ------- 43 `numpy.ndarray` of latitudes (in degrees) with a length of `nlat`. 44 """ 45 if abs(int(nlat)) != nlat: 46 raise ValueError('nlat must be a non-negative integer') 47 # Create the coefficients of the Legendre polynomial and construct the 48 # companion matrix: 49 cs = np.array([0] * nlat + [1], dtype=int) 50 cm = legcompanion(cs) 51 # Compute the eigenvalues of the companion matrix (the roots of the 52 # Legendre polynomial) taking advantage of the fact that the matrix is 53 # symmetric: 54 roots = la.eigvalsh(cm) 55 roots.sort() 56 # Improve the roots by one application of Newton's method, using the 57 # solved root as the initial guess: 58 fx = legval(roots, cs) 59 fpx = legval(roots, legder(cs)) 60 roots -= fx / fpx 61 # The roots should exhibit symmetry, but with a sign change, so make sure 62 # this is the case: 63 roots = (roots - roots[::-1]) / 2. 64 # Convert the roots from the interval [-1, 1] to latitude values on the 65 # interval [-90, 90] degrees: 66 latitudes = np.rad2deg(np.arcsin(roots)) 67 # Flip latitudes such that it is oriented from North to South [90, -90] 68 latitudes = np.flip(latitudes) 69 return latitudes
Construct latitudes for a Gaussian grid.
Parameters
nlat : int
The number of latitudes in the Gaussian grid.
Returns
numpy.ndarray
of latitudes (in degrees) with a length of nlat
.