Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Some ECMWF data produced by the IFS is stored in GRIB with gridType=sh to indicate that the values are stored as spherical harmonic coefficients.  These are the X(n,m) coefficients in the discrete representation of the data on a grid at time, t, and vertical coordinate, η, by a continuous function expressed as a truncated series of spherical harmonics:

Mathdisplay
\begin{eqnarray*}
A(\lambda,\mu,\eta,t) & = &  \sum_{n=0m=-\mbox{T}}^{\mbox{T}} \, \sum_{m=-nn=|m|}^{\mbox{nT}}  X(n,m) (\eta,t) \overline{P}_{n}^{m}(\mu) e^{im\lambda}
\end{eqnarray*}

where μ = sinθ with λ  the longitude and θ the latitude of the grid point, T is the triangular spectral truncation number , Pnm and eimλ are the Fourier functions.  The normalised associated Legendre polynomials of the first kind ,  and  eimλ are the Fourier functions.  The order of the summations can be interchanged to provide an equivalent expressionof degree n and order m are denoted by

Mathinline
\overline{P}_n^m

with the normalisation defined by:

Mathdisplay
\begin{eqnarray*}
A(\lambda,\mu,\eta,t) & = &  \sum_{m=-\mbox{T}}^{\mbox{T}} \frac{1}{2} \int_{-1}^{1}\, \sum_{n=|m|}^{\mbox{T}}  X(n,m) (\eta,t) P\overline{P}_{n}^{m}(\mu) e^{im\lambda}\}^2 \,d\mu = 1\, .
\end{eqnarray*}

In the GRIB binary data section, the complex X(n,m) coefficients are stored for m ≥ 0 as pairs of real numbers Re(X(n,m)) and Im(X(n,m)) ordered with n increasing from m to T, first for m = 0 and then for m = 1, 2, . . . T.  

Hence, the ecCodes values array contains the coefficients in the order Re(X(0,0)), Im(X(0,0)), Re(X(1,0,1)), Im(X(1,0,1), Re(X(2,0,2)), Im(X(2,0,2)), … , Re(X(T,0,T)), Im(X(T,0,T)), Re(X(1,1)), Im(X(1,1)), Re(X(2,1,2)), Im(X(2,1.2)), … , Re(X(T,1,T)), Im(X(T,1,T)), ... ,Re(X(T,T-1,T)), Im(X(T,T-1,T)), Re(X(T,T)), Im(X(T,T)).

Note
iconfalse

Only the coefficients for m ≥ 0 are stored.  The coefficients for m < 0 are obtained from the complex conjugates of the corresponding coefficient with m > 0 :  as X(n,-m)= X*(n,m) / (-1)m

The spherical harmonic (n, m) wave number space is shown in the figure.

...

Code Block
languagepy
linenumberstrue
# Copyright 2020 ECMWF.
#
# This software is licensed under the terms of the Apache Licence Version 2.0
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
#
# In applying this licence, ECMWF does not waive the privileges and immunities
# granted to it by virtue of its status as an intergovernmental organisation
# nor does it submit to any jurisdiction.
 
from __future__ import print_functionsys
import traceback
import sys

from eccodes import *
 
INPUT = "../../data/spherical_model_level.grib2"
VERBOSE = 1  # verbose error reporting
 
def example():
    f = open(INPUT, "rb")
 
    while 1:
        gid = codes_grib_new_from_file(f)
        if gid is None:
            break

        # Get the values. This will be a numpy array
        values = codes_get_array(gid,"values")
 
        # Store the real and imaginary parts of the coefficients in arrays a and b, respectively
        # The real parts 'a' stored in every second element starting at element 0
        a = values[0::2]
        # The imaginary parts 'b' stored in every second element starting at element 1
        b = values[1::2]
  
        codes_release(gid)

        # Loop through the values and print the m and n indices together with the corresponding
        # real and imaginary parts of the coefficients  
        m = 0
        n = 0
        for i in range(len(a)):
            print("%d\t n=%d\t m=%d %.10f\t%.10f" % (i, n, m, a[i], b[i]))
            n += 1
            if n > T:
                m += 1
                n = m 
 
    f.close()
 
def main():
    try:
        example()
    except CodesInternalError as err:
        if VERBOSE:
            traceback.print_exc(file=sys.stderr)
        else:
            sys.stderr.write(err.msg + "\n")
 
        return 1
 
 
if __name__ == "__main__":
    sys.exit(main())

...