charm_leg#
Module to work with the fullynormalized associated Legendre functions of the first kind:
defines the
charm_pnmj
structure to store Fourier coefficients of the Legendre functions,allocates, initializes and frees
charm_pnmj
,computes Fourier coefficients of Legendre functions after Fukushima (2018).
References:
Fukushima, T. (2018) Fast computation of sine/cosine series coefficients of associated Legendre functions of arbitrary high degree and order
Fukushima T (2014) Numerical computation of spherical harmonics of arbitrary degree and order by extending exponent of floating point numbers. Computers and Geosciences 63, 1721, doi: 10.1016/j.cageo.2013.10.010
Note
This documentation is written for double precision version of CHarm.
Allocate and free the charm_pnmj structure
Functions to allocate and free charm_pnmj
.

charm_pnmj *charm_leg_pnmj_malloc(unsigned long nmax, int ordering)#
Allocates Fourier coefficients of the fullynormalized associated Legendre functions up to harmonic degree
nmax
using the ordering schemeordering
. The Fourier coefficients are uninitialized, so their values are undefined.ordering
can be set either toCHARM_LEG_PMNJ
orCHARM_LEG_PMJN
.Warning
The
charm_pnmj
structure created by this function must be deallocated by callingcharm_leg_pnmj_free()
. The usual deallocationfree
will not deallocate the memory and will lead to memory leaks. Returns:
On success, returned is a pointer to the
charm_pnmj
structure. On error,NULL
is returned.

charm_pnmj *charm_leg_pnmj_calloc(unsigned long nmax, int ordering)#
The same as
charm_leg_pnmj_malloc()
but all Fourier coefficients are initialized to zero.

void charm_leg_pnmj_free(charm_pnmj *pnmj)#
Frees the memory associated with
pnmj
. No operation is performed ifpnmj
isNULL
.
Fourier coefficients of Legendre functions
Functions to compute the Fourier coefficients of Legendre functions and some associated useful functions.

void charm_leg_pnmj_coeffs(charm_pnmj *pnmj, unsigned long nmax, charm_err *err)#
Computes Fourier coefficients of fully normalized associated Legendre functions up to degree
nmax
and saves them topnmj
. The structure ofpnmj>pnmj
depends onpnmj>ordering
. Ifnmax < pnmj>nmax
, all Fourier coefficients inpnmj>pnmj
beyondnmax
are set to zero. In case of failure, the error is written toerr
.The algorithm of Fukushima (2018) is employed.
References:
Fukushima, T. (2018) Fast computation of sine/cosine series coefficients of associated Legendre functions of arbitrary high degree and order.

unsigned long charm_leg_pnmj_j2k(unsigned long n, unsigned long j)#
Transforms a wavenumberrelated variable
j
to the wavenumberk
of a Fourier coefficient of fullynormalized associated Legendre function of degreen
(see Section C.1 of Fukushima, 2018),.\[k = \left[ 1  (1)^n \right] / 2 + 2 j{.}\] Parameters:
n – [in] Harmonic degree of the Legendre function.
j – [in] Variable related to the wavenumber
k
.
 Returns:
Wavenumber
k
of the Fourier coefficient of a Legendre function.

unsigned long charm_leg_pnmj_k2j(unsigned long k)#
Transforms a wavenumber
k
of a Fourier coefficient of fullynormalized associated Legendre function to the wavenumberrelated variablej
(see Section C.1 of Fukushima, 2018),.\[j = \left[ k / 2 \right]_{\mathrm{floor}}{.}\] Parameters:
k – [in] Wavenumber of a Fourier coefficients of Legendre function.
 Returns:
Wavenumberrelated variable
j
of the Fourier coefficient of a Legendre function.
Enums

enum [anonymous]#
Ordering scheme of
charm_pnmj.pnmj
(a 3D array).Values:

enumerator CHARM_LEG_PMNJ#
Order
m
, degreen
, wavenumberrelated variablej
. Note thatj
is not a wavenumberk
, but is related to it (seecharm_leg_pnmj_j2k()
andcharm_leg_pnmj_k2j()
).

enumerator CHARM_LEG_PMJN#
Order
m
, wavenumberrelated variablej
, degreen
.

enumerator CHARM_LEG_PMNJ#

struct charm_pnmj#
Structure to store Fourier coefficients of the fullynormalized associated Legendre functions.
Public Members

unsigned long nmax#
Maximum harmonic degree of the Fourier coefficients.

int ordering#
Ordering scheme of the Fourier coefficients in
charm_pnmj.pnmj
: eitherCHARM_LEG_PMNJ
orCHARM_LEG_PMJN
.

size_t npnmj#
Total number of Fourier coefficients \(P_{nmj}\) in
charm_pnmj.pnmj
.

double ***pnmj#
Fourier coefficients.
The structure of
charm_pnmj.pnmj
depends oncharm_pnmj.ordering
, which takes one of two constants:CHARM_LEG_PMNJ
orCHARM_LEG_PMJN
.Structure of
charm_pnmj.pnmj
whencharm_pnmj.ordering
isCHARM_LEG_PMNJ
:The first dimension of
charm_pnmj.pnmj
is related to harmonic orders, the second dimension to harmonic degrees and the third dimension to wavenumbers. Importantly,charm_pnmj.pnmj
is not a regular 3D array, as the number of elements in the second and the third dimension varies based on the first dimension. The following scheme is applied:each
charm_pnmj.pnmj[m]
, withm = 0
,1
, …,nmax
, hascharm_pnmj.nmax  m + 1
elements for harmonic degreesn = m
,m + 1
, …,charm_pnmj.nmax
(respectively),each
charm_pnmj.pnmj[m][n  m]
hasfloor(n / 2) + 1
elements for wavenumbers.
The Fourier coefficient \(P_{nmj}\), using the notation from Eq. (62) of Fukushima (2018), can therefore be access as follows
charm_pnmj.pnmj[m][n  m][j]
.Structure of
charm_pnmj.pnmj
whencharm_pnmj.ordering
isCHARM_LEG_PMJN
:The first dimension of
charm_pnmj.pnmj
is related to harmonic orders, the second dimension to wavenumbers and the third dimension to harmonic degrees. Importantly,charm_pnmj.pnmj
is not a regular 3D array, as the number of elements in the third dimension varies based on them
andj
variables. The following scheme is applied:each
charm_pnmj.pnmj[m]
, withm = 0
,1
, …,charm_pnmj.nmax
, hasfloor(charm_pnmj.nmax / 2) + 1
elements for wavenumberrelated variablej = 0
,1
, …,floor(charm_pnmj.nmax / 2)
,each
charm_pnmj.pnmj[m][j]
has(charm_pnmj.nmax  CHARM_MAX(2 * j, m) + 1)
elements for harmonic degreesCHARM_MAX(2 * j, m)
,CHARM_MAX(2 * j, m) + 1
, …,charm_pnmj.nmax
.
The Fourier coefficient \(P_{nmj}\), using the notation from Eq. (62) of Fukushima (2018), can therefore be access as follows
charm_pnmj.pnmj[m][j][n  CHARM_MAX(m, 2 * j)]
.
If
charm_pnmj.ordering
isCHARM_LEG_PMNJ
, the following loop order is recommended for fast sequential access to the \(P_{nmj}\) coefficients: harmonic orderm
, harmonic degreen
and wavenumberrelated variablej
; e.g.:charm_pnmj *pnmj = charm_leg_pnmj_calloc(nmax, CHARM_LEG_PMNJ) for (unsigned long m = 0; m <= nmax; m++) for (unsigned long n = m; n <= nmax; n++) for (unsigned long j = 0; j <= (n / 2); j++) pnmj>pnmj[m][n  m][j];
If
charm_pnmj.ordering
isCHARM_LEG_PMJN
, the recommended loop order is:charm_pnmj *pnmj = charm_leg_pnmj_calloc(nmax, CHARM_LEG_PMJN) for (unsigned long m = 0; m <= nmax; m++) for (unsigned long j = 0; j <= (nmax / 2); j++) for (unsigned long n = CHARM_MAX(m, 2 * j); n <= nmax; n++) pnmj>pnmj[m][j][n  CHARM_MAX(m, 2 * j)];
The coefficients (elements) in
charm_pnmj.pnmj
are stored in a single contiguous block of memory.Warning
j
does not represent the wavenumberk
, but it is closely related to it (seecharm_leg_pnmj_j2k()
andcharm_leg_pnmj_k2j()
).

unsigned long nmax#