VSH Module

Scalar and vector spherical harmonics (VSH), Legendre functions, and the angular-momentum coupling coefficients (Clebsch-Gordan, Wigner 3-j, and Geppert-Wiebicke) used to build them.

Two vector bases are provided over the same underlying scalar spherical harmonic : the "polar" basis (PVSH_RAD/PVSH_POL/PVSH_TOR, indexed by directly) familiar from the poloidal/toroidal decomposition of divergence-free vector fields in MHD, and the "standard" total-angular-momentum-coupled basis (VSH_TOR/VSH_POL_DN/VSH_POL_UP, indexed by the coupled total angular momentum ) familiar from the quantum-mechanical vector-spherical-harmonic literature (e.g. Barrera et al., 1985). Every routine has a single-point form (one mode at one ) and a batch _ALL form (every mode at one point in a single call, reusing shared recurrences internally for efficiency).

All angles are in radians, with the colatitude (, from the north pole) and the longitude (). Every spherical harmonic here uses the fully-normalized convention () with the Condon-Shortley phase, matching common physics/quantum-mechanics conventions (e.g. Edmonds, 1960).


Uses

  • module~~vsh~~UsesGraph module~vsh VSH module~globals GLOBALS module~vsh->module~globals module~kinds KINDS module~vsh->module~kinds module~globals->module~kinds

Used by

  • module~~vsh~~UsedByGraph module~vsh VSH module~benchmark BENCHMARK module~benchmark->module~vsh module~tests TESTS module~tests->module~vsh program~convergence_main CONVERGENCE_MAIN program~convergence_main->module~vsh program~convergence_main->module~tests program~dipole_flux_expulsion DIPOLE_FLUX_EXPULSION program~dipole_flux_expulsion->module~vsh program~dipole_synthesis DIPOLE_SYNTHESIS program~dipole_synthesis->module~vsh program~dipole_uniform_sphere DIPOLE_UNIFORM_SPHERE program~dipole_uniform_sphere->module~vsh program~gwi_gwj_sweep GWI_GWJ_SWEEP program~gwi_gwj_sweep->module~vsh program~stability_main STABILITY_MAIN program~stability_main->module~vsh program~unnorm_stability_main UNNORM_STABILITY_MAIN program~unnorm_stability_main->module~vsh program~vsh_decomposition VSH_DECOMPOSITION program~vsh_decomposition->module~vsh program~vsh_decomposition_tor VSH_DECOMPOSITION_TOR program~vsh_decomposition_tor->module~vsh program~bench_main BENCH_MAIN program~bench_main->module~benchmark program~main MAIN program~main->module~tests

Interfaces

public interface ASSOC_LEGENDRE

  • private function ASSOC_LEGENDRE_DP(L, K, X) result(ASSOC_LEGENDRE)

    Associated Legendre function , Condon-Shortley phase convention, computed by the classic Bonnet-type upward recurrence starting from . For negative order, . Unnormalized (unlike ASSOC_LEGENDRE_NORM_ALL); loses numerical stability well before the intermediate values literally overflow, since the later upward-in- recurrence involves a subtraction of two comparably huge terms (catastrophic cancellation).

    Warning

    Numerical stability: verified accurate (relative error < 3e-14) for at any -- the worst case, , occurs near the equator ( degrees) at ; safety improves toward either pole. This supersedes an earlier "" claim, verified too optimistic by direct comparison against an arbitrary-precision reference. Full methodology and per-degree table: STABILITY_FINDINGS.md at the repo root, Part 2 (regenerable via the opt-in VSH_BUILD_STABILITY CMake target's vsh_unnorm_stability executable).

    Returns: .

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: X

    Argument, (typically ).

    Return Value real(kind=dp)

public interface ASSOC_LEGENDRE_ALL

  • private subroutine ASSOC_LEGENDRE_ALL_DP(P, LMAX, X)

    All unnormalized associated Legendre functions for , via the Bonnet recurrence, in one pass (amortizing shared recurrence terms across every at fixed -- far cheaper than independent ASSOC_LEGENDRE calls). Condon-Shortley phase; same recurrence and same stability limit as ASSOC_LEGENDRE (see ASSOC_LEGENDRE_NORM_ALL for the far-more-stable normalized alternative, itself safe to ).

    Warning

    Numerical stability: verified accurate (relative error < 3e-14) for at any -- the worst case, , occurs near the equator ( degrees) at ; safety improves toward either pole. This supersedes an earlier "" claim, verified too optimistic by direct comparison against an arbitrary-precision reference. Full methodology and per-degree table: STABILITY_FINDINGS.md at the repo root, Part 2 (regenerable via the opt-in VSH_BUILD_STABILITY CMake target's vsh_unnorm_stability executable).

    PLM_INDEX(l,m).

    Arguments

    Type IntentOptional Attributes Name
    real(kind=dp), intent(out) :: P((LMAX+1)*(LMAX+2)/2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: X

    Argument, (typically ).

public interface ASSOC_LEGENDRE_NORM_ALL

  • private subroutine ASSOC_LEGENDRE_NORM_ALL_DP(PNORM, LMAX, X)

    All -normalized associated Legendre functions , (i.e. the real-valued radial part of SSH, for ), using the Holmes & Featherstone (2002) modified forward-column recurrence. The normalization is folded directly into the recurrence coefficients, keeping every intermediate value rather than letting itself grow/shrink combinatorially like the unnormalized ASSOC_LEGENDRE_ALL/Bonnet recurrence does. This is the recurrence SSH_ALL and every batch VSH routine build on.

    Warning

    Numerical stability: verified safe for at any . Beyond that, safety depends on : this recurrence has a distinct failure mode near the classical turning point of the associated Legendre ODE () -- for within about 30-56 degrees of either pole, values can blow up by 100+ orders of magnitude once exceeds a -dependent onset (as low as in the worst case, degrees). Near the poles ( degrees) or equator ( degrees) it remains accurate at least to (untested beyond that). This supersedes an earlier, overly optimistic "stable to " claim that didn't account for the -dependence. Full methodology, per-degree onset table, and a (\ell,\theta) heatmap: STABILITY_FINDINGS.md at the repo root (regenerable via the opt-in VSH_BUILD_STABILITY CMake target).

    PLM_INDEX(l,m).

    Arguments

    Type IntentOptional Attributes Name
    real(kind=dp), intent(out) :: PNORM((LMAX+1)*(LMAX+2)/2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: X

    Argument, (typically ).

public interface CGCOEFF

  • private function CGCOEFF_DP(J1, M1, J2, M2, J3, M3) result(CGCOEFF)

    Clebsch-Gordan coefficient for coupling two angular momenta to a total , via the closed-form Racah sum (evaluated in log-factorial form for numerical stability at large arguments -- see LOG_FACT): where . Adapted from David Simpson (NASA GSFC). Automatically returns 0 for any invalid combination -- violated triangle inequality , , or -- so it is always safe to call with an arbitrary sextuple of integers, e.g. when sweeping a parameter range.

    Returns: , real (0 if selection rules are violated).

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: J1

    First angular momentum, .

    integer(kind=i4), intent(in) :: M1

    First projection, .

    integer(kind=i4), intent(in) :: J2

    Second angular momentum, .

    integer(kind=i4), intent(in) :: M2

    Second projection, .

    integer(kind=i4), intent(in) :: J3

    Coupled angular momentum, .

    integer(kind=i4), intent(in) :: M3

    Coupled projection, .

    Return Value real(kind=dp)

public interface DDX_ASSOC_LEGENDRE

  • private function DDX_ASSOC_LEGENDRE_DP(L, K, X) result(RES)

    Derivative of the associated Legendre function, via ASSOC_LEGENDRE_AND_DERIV (thin wrapper that discards itself).

    Warning

    Inherits ASSOC_LEGENDRE's stability limit (safe for at any ) -- see STABILITY_FINDINGS.md at the repo root, Part 2.

    Returns: evaluated at X; 0 at the poles () or for .

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: X

    Argument, .

    Return Value real(kind=dp)

public interface DDX_ASSOC_LEGENDRE_ALL

  • private subroutine DDX_ASSOC_LEGENDRE_ALL_DP(DP_OUT, P, LMAX, X)

    All derivatives for , reusing a precomputed ASSOC_LEGENDRE_ALL table rather than recomputing from scratch.

    Warning

    Inherits ASSOC_LEGENDRE_ALL's stability limit (safe for at any ) -- see STABILITY_FINDINGS.md at the repo root, Part 2.

    by PLM_INDEX(l,m); 0 at the poles (). ASSOC_LEGENDRE_ALL, same size/indexing. P).

    Arguments

    Type IntentOptional Attributes Name
    real(kind=dp), intent(out) :: DP_OUT((LMAX+1)*(LMAX+2)/2)
    real(kind=dp), intent(in) :: P((LMAX+1)*(LMAX+2)/2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, (must match P's).

    real(kind=dp), intent(in) :: X

    Argument, (must match the X used to build

public interface DDX_ASSOC_LEGENDRE_NORM_ALL

  • private subroutine DDX_ASSOC_LEGENDRE_NORM_ALL_DP(DPNORM, PNORM, LMAX, X)

    All derivatives of the normalized associated Legendre functions, for , reusing a precomputed ASSOC_LEGENDRE_NORM_ALL table: This is the recurrence VSH_CORE (and therefore every batch VSH routine) uses for the component.

    Warning

    Inherits ASSOC_LEGENDRE_NORM_ALL's -dependent stability limit (safe for unconditionally) -- see STABILITY_FINDINGS.md at the repo root.

    by PLM_INDEX(l,m); 0 at the poles (). ASSOC_LEGENDRE_NORM_ALL, same size/indexing. PNORM).

    Arguments

    Type IntentOptional Attributes Name
    real(kind=dp), intent(out) :: DPNORM((LMAX+1)*(LMAX+2)/2)
    real(kind=dp), intent(in) :: PNORM((LMAX+1)*(LMAX+2)/2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, (must match PNORM's).

    real(kind=dp), intent(in) :: X

    Argument, (must match the X used to build

public interface DDX_LEGENDRE

  • private function DDX_LEGENDRE_DP(L, X) result(DDX_LEGENDRE)

    Derivative of the Legendre polynomial, via away from the poles, and the closed-form pole values at .

    Returns: evaluated at X.

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    real(kind=dp), intent(in) :: X

    Argument, .

    Return Value real(kind=dp)

public interface DOT

  • private function DOT_DP(VSH1, VSH2) result(DOT)

    Dot product of two 3-vectors (typically two VSH values evaluated at the same ): . Note this is a plain component-wise product, not a Hermitian inner product -- callers wanting must conjugate VSH2 themselves first (as done throughout src/tests.f90 and the examples/ drivers).

    Returns: , complex scalar.

    Arguments

    Type IntentOptional Attributes Name
    complex(kind=dp), intent(in), DIMENSION(3) :: VSH1

    First complex 3-vector .

    complex(kind=dp), intent(in), DIMENSION(3) :: VSH2

    Second complex 3-vector .

    Return Value complex(kind=dp)

public interface GRAD_SSH

  • private function GRAD_SSH_DP(L, K, THETA, PHI) result(GRAD_SSH)

    Angular (surface) gradient of the scalar spherical harmonic, . Returned as a 3-vector with a zero radial component, since the gradient of a purely angular function is purely tangential.

    Warning

    Built on the unnormalized ASSOC_LEGENDRE_AND_DERIV -- inherits its stability limit (safe for at any ), not GRAD_SSH_ALL's . See STABILITY_FINDINGS.md at the repo root, Part 2.

    Returns: , complex 3-vector.

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

    Return Value complex(kind=dp), DIMENSION(3)

public interface GRAD_SSH_ALL

  • private subroutine GRAD_SSH_ALL_DP(OUT, LMAX, THETA, PHI)

    All angular gradients (GRAD_SSH) for , from one VSH_CORE pass.

    Warning

    Inherits ASSOC_LEGENDRE_NORM_ALL's -dependent stability limit (safe for unconditionally) -- see STABILITY_FINDINGS.md at the repo root.

    1= (always 0), 2=, 3=; mode axis indexed by YLM_INDEX(l,m).

    Arguments

    Type IntentOptional Attributes Name
    complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

public interface GWI

  • private function GWI_DP(J1, M1, J2, M2, L, M) result(GWI)

    Geppert-Wiebicke axisymmetric coupling coefficient (Geppert & Wiebicke, 1991), a compact shorthand for the generation/amplification amplitude of a two-mode interaction in the Hall-MHD induction equation: This is algebraically the standard Gaunt coefficient -- the closed form for -- written in terms of two CGCOEFF evaluations. Built entirely from CGCOEFF, which guards all selection rules, so GWI is safe to call with any integer sextuple and returns 0 for invalid combinations (unlike GWJ, see its own selection-rule note).

    Returns: , complex (real-valued in practice, but returned as COMPLEX for a uniform interface with GWJ).

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: J1

    First coupled degree, .

    integer(kind=i4), intent(in) :: M1

    First coupled order, .

    integer(kind=i4), intent(in) :: J2

    Second coupled degree, .

    integer(kind=i4), intent(in) :: M2

    Second coupled order, .

    integer(kind=i4), intent(in) :: L

    Resulting degree, .

    integer(kind=i4), intent(in) :: M

    Resulting order, .

    Return Value complex(kind=dp)

public interface GWJ

  • private function GWJ_DP(J1, M1, J2, M2, L, M) result(GWJ)

    Geppert-Wiebicke non-axisymmetric coupling coefficient (Geppert & Wiebicke, 1991), the companion to GWI encoding the amplitude of a two-mode Hall-MHD interaction that generates or amplifies a non-axisymmetric component: Cross-validated against an independent VSH-dot-product expansion in TEST2_GW (src/tests.f90).

    Warning

    Unlike GWI, the extra square-root factor above is not internally selection-rule-guarded by CGCOEFF alone -- it can go negative for out-of-range (J1,J2,L) triples. This routine guards it explicitly (returning 0, matching the mathematically correct value) so it is still safe to call with any integer sextuple.

    Returns: , complex.

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: J1

    First coupled degree, .

    integer(kind=i4), intent(in) :: M1

    First coupled order, .

    integer(kind=i4), intent(in) :: J2

    Second coupled degree, .

    integer(kind=i4), intent(in) :: M2

    Second coupled order, .

    integer(kind=i4), intent(in) :: L

    Resulting degree, .

    integer(kind=i4), intent(in) :: M

    Resulting order, .

    Return Value complex(kind=dp)

public interface LEGENDRE

  • private function LEGENDRE_DP(L, X) result(LEGENDRE)

    Legendre polynomial , degree , via the standard three-term recurrence

    Returns: .

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=I4), intent(in) :: L

    Degree, .

    real(kind=dp), intent(in) :: X

    Argument, (typically ).

    Return Value real(kind=dp)

public interface LOG_FACT

  • private function LOG_FACT_DP(N) result(LOG_FACT)

    , via (the intrinsic LOG_GAMMA). Used throughout CGCOEFF, SSH, and ASSOC_LEGENDRE to evaluate factorial ratios like as without overflowing the individual factorials for large .

    Returns: .

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: N

    Non-negative integer argument ( returns 0).

    Return Value real(kind=dp)

public interface L_SSH

  • private function L_SSH_DP(L, K, THETA, PHI) result(L_SSH)

    The angular-momentum-operator field (proportional to the quantum-mechanical orbital angular-momentum operator acting on the scalar harmonic). Simply GRAD_SSH rotated 90 degrees within the tangent plane: .

    Warning

    Built on the unnormalized ASSOC_LEGENDRE_AND_DERIV -- inherits its stability limit (safe for at any ), not L_SSH_ALL's . See STABILITY_FINDINGS.md at the repo root, Part 2.

    Returns: , complex 3-vector.

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

    Return Value complex(kind=dp), DIMENSION(3)

public interface L_SSH_ALL

  • private subroutine L_SSH_ALL_DP(OUT, LMAX, THETA, PHI)

    All angular-momentum-operator fields (L_SSH) for , from one VSH_CORE pass.

    Warning

    Inherits ASSOC_LEGENDRE_NORM_ALL's -dependent stability limit (safe for unconditionally) -- see STABILITY_FINDINGS.md at the repo root.

    1= (always 0), 2=, 3=; mode axis indexed by YLM_INDEX(l,m).

    Arguments

    Type IntentOptional Attributes Name
    complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

public interface PVSH_POL

  • private function PVSH_POL_DP(L, K, THETA, PHI) result(PVSH_POL)

    Poloidal (horizontal) member of the polar vector spherical harmonic basis, -- purely horizontal (zero radial component), i.e. GRAD_SSH normalized by . Combined with a radial stream function , this is the horizontal-field piece of a poloidal field, . Zero for (a constant has no horizontal gradient).

    Warning

    Built on the unnormalized ASSOC_LEGENDRE_AND_DERIV -- inherits its stability limit (safe for at any ), not PVSH_POL_ALL's . See STABILITY_FINDINGS.md at the repo root, Part 2.

    Returns: , complex 3-vector.

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

    Return Value complex(kind=dp), DIMENSION(3)

public interface PVSH_POL_ALL

  • private subroutine PVSH_POL_ALL_DP(OUT, LMAX, THETA, PHI)

    All poloidal (horizontal) polar VSH members PVSH_POL for , from one VSH_CORE pass. Zero for .

    Warning

    Inherits ASSOC_LEGENDRE_NORM_ALL's -dependent stability limit (safe for unconditionally) -- see STABILITY_FINDINGS.md at the repo root.

    1= (always 0), 2=, 3=; mode axis indexed by YLM_INDEX(l,m).

    Arguments

    Type IntentOptional Attributes Name
    complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

public interface PVSH_RAD

  • private function PVSH_RAD_DP(L, K, THETA, PHI) result(PVSH_RAD)

    Radial member of the polar vector spherical harmonic basis, . Purely radial by construction (zero horizontal components) -- combined with a radial stream function , this is the -generating piece of a poloidal magnetic (or any divergence-free) field, .

    Warning

    Built on SSH -- inherits the unnormalized ASSOC_LEGENDRE's stability limit (safe for at any ), not PVSH_RAD_ALL's . See STABILITY_FINDINGS.md at the repo root, Part 2.

    Returns: , complex 3-vector.

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

    Return Value complex(kind=dp), DIMENSION(3)

public interface PVSH_RAD_ALL

  • private subroutine PVSH_RAD_ALL_DP(OUT, LMAX, THETA, PHI)

    All radial polar VSH members PVSH_RAD for , from one VSH_CORE pass.

    Warning

    Inherits ASSOC_LEGENDRE_NORM_ALL's -dependent stability limit (safe for unconditionally) -- see STABILITY_FINDINGS.md at the repo root.

    1==, 2= (always 0), 3= (always 0); mode axis indexed by YLM_INDEX(l,m).

    Arguments

    Type IntentOptional Attributes Name
    complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

public interface PVSH_TOR

  • private function PVSH_TOR_DP(L, K, THETA, PHI) result(PVSH_TOR)

    Toroidal member of the polar vector spherical harmonic basis, -- purely horizontal (zero radial component), identical in form to L_SSH but normalized by . This is the horizontal-field piece of a toroidal magnetic field, for a toroidal stream function . Zero for (no toroidal monopole).

    Warning

    Built on the unnormalized ASSOC_LEGENDRE_AND_DERIV -- inherits its stability limit (safe for at any ), not PVSH_TOR_ALL's . See STABILITY_FINDINGS.md at the repo root, Part 2.

    Returns: , complex 3-vector.

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

    Return Value complex(kind=dp), DIMENSION(3)

public interface PVSH_TOR_ALL

  • private subroutine PVSH_TOR_ALL_DP(OUT, LMAX, THETA, PHI)

    All toroidal polar VSH members PVSH_TOR for , from one VSH_CORE pass. Zero for .

    Warning

    Inherits ASSOC_LEGENDRE_NORM_ALL's -dependent stability limit (safe for unconditionally) -- see STABILITY_FINDINGS.md at the repo root.

    1= (always 0), 2=, 3=; mode axis indexed by YLM_INDEX(l,m).

    Arguments

    Type IntentOptional Attributes Name
    complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

public interface SHGLQ

  • private subroutine SHGLQ_DP(ZERO, W, LMAX)

    Gauss-Legendre quadrature nodes and weights, exact for integrating any polynomial of degree using only points -- the natural quadrature for spherical harmonic transforms, since is a polynomial in times , and the transform integral separates exactly into this -quadrature times a uniform sum over (itself exact for finite Fourier content). Nodes are the zeros of , found by Newton iteration (converges to machine precision in under 10 steps); weights are .

    ascending from -1 to +1. \sum_i w_i f(x_i) ), size LMAX+1. uses LMAX+1 quadrature points.

    Arguments

    Type IntentOptional Attributes Name
    real(kind=dp), intent(out) :: ZERO(LMAX+1)
    real(kind=dp), intent(out) :: W(LMAX+1)
    integer(kind=i4), intent(in) :: LMAX

    Requested exactness is degree ;

public interface SSH

  • private function SSH_DP(L, K, THETA, PHI) result(SSH)

    Scalar spherical harmonic , fully normalized with the Condon-Shortley phase:

    Warning

    Built on the unnormalized ASSOC_LEGENDRE -- inherits its stability limit (safe for at any ), not SSH_ALL's (that routine uses the normalized recurrence instead). See STABILITY_FINDINGS.md at the repo root, Part 2.

    Returns: , complex.

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

    Return Value complex(kind=dp)

public interface SSH_ALL

  • private subroutine SSH_ALL_DP(YLM, LMAX, THETA, PHI)

    All scalar spherical harmonics for , in one call. Computes ASSOC_LEGENDRE_NORM_ALL once, then fills directly and via the conjugate symmetry rather than a second recurrence pass.

    Warning

    Inherits ASSOC_LEGENDRE_NORM_ALL's -dependent stability limit (safe for unconditionally) -- see STABILITY_FINDINGS.md at the repo root.

    Arguments

    Type IntentOptional Attributes Name
    complex(kind=dp), intent(out) :: YLM((LMAX+1)**2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

public interface SYMBOL3J

  • private function SYMBOL3J_DP(J1, M1, J2, M2, J3, M3) result(SYMBOL3J)

    Wigner 3-j symbol , via the standard conversion from CGCOEFF: Inherits CGCOEFF's selection-rule guards -- safe to call with any integer sextuple, returning 0 for invalid combinations.

    Returns: The Wigner 3-j symbol, real (0 if selection rules are violated).

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: J1

    First angular momentum, .

    integer(kind=i4), intent(in) :: M1

    First projection, .

    integer(kind=i4), intent(in) :: J2

    Second angular momentum, .

    integer(kind=i4), intent(in) :: M2

    Second projection, .

    integer(kind=i4), intent(in) :: J3

    Third angular momentum, .

    integer(kind=i4), intent(in) :: M3

    Third projection, .

    Return Value real(kind=dp)

public interface VSH_POL_DN

  • private function VSH_POL_DN_DP(L, K, THETA, PHI) result(VSH_POL_DN)

    The member of the standard (total-angular-momentum coupled) vector spherical harmonic basis, built from the polar basis by i.e. PVSH_RAD and PVSH_POL rotated together by an -dependent angle (see VSH_POL_UP for the companion rotation). Zero for (no ).

    Warning

    At this does not reproduce the classic 2:1 magnetic-dipole radial:horizontal ratio -- VSH_POL_DN(1,0,...) is proportional to , a 1:-1 ratio. VSH_POL_UP is the one that reproduces the dipole pattern.

    Warning

    Built on the unnormalized ASSOC_LEGENDRE_AND_DERIV -- inherits its stability limit (safe for at any ), not VSH_POL_DN_ALL's . See STABILITY_FINDINGS.md at the repo root, Part 2.

    Returns: , complex 3-vector.

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

    Return Value complex(kind=dp), DIMENSION(3)

public interface VSH_POL_DN_ALL

  • private subroutine VSH_POL_DN_ALL_DP(OUT, LMAX, THETA, PHI)

    All standard-VSH members VSH_POL_DN for , from one VSH_CORE pass: . Zero for -- see VSH_POL_DN for the dipole-ratio caveat at .

    Warning

    Inherits ASSOC_LEGENDRE_NORM_ALL's -dependent stability limit (safe for unconditionally) -- see STABILITY_FINDINGS.md at the repo root.

    1=, 2=, 3=; mode axis indexed by YLM_INDEX(l,m).

    Arguments

    Type IntentOptional Attributes Name
    complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

public interface VSH_POL_UP

  • private function VSH_POL_UP_DP(L, K, THETA, PHI) result(VSH_POL_UP)

    The member of the standard (total-angular-momentum coupled) vector spherical harmonic basis, built from the polar basis by the companion rotation to VSH_POL_DN's . Unlike VSH_POL_DN this is well-defined (nonzero radial part) at , since still exists when .

    Note

    At , VSH_POL_UP(1,0,...) is proportional to -- the classic 2:1 magnetic-dipole radial:horizontal ratio.

    Warning

    Built on the unnormalized ASSOC_LEGENDRE_AND_DERIV -- inherits its stability limit (safe for at any ), not VSH_POL_UP_ALL's . See STABILITY_FINDINGS.md at the repo root, Part 2.

    Returns: , complex 3-vector.

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

    Return Value complex(kind=dp), DIMENSION(3)

public interface VSH_POL_UP_ALL

  • private subroutine VSH_POL_UP_ALL_DP(OUT, LMAX, THETA, PHI)

    All standard-VSH members VSH_POL_UP for , from one VSH_CORE pass: . Well-defined (nonzero) at -- see VSH_POL_UP for the dipole-ratio note at .

    Warning

    Inherits ASSOC_LEGENDRE_NORM_ALL's -dependent stability limit (safe for unconditionally) -- see STABILITY_FINDINGS.md at the repo root.

    1=, 2=, 3=; mode axis indexed by YLM_INDEX(l,m).

    Arguments

    Type IntentOptional Attributes Name
    complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

public interface VSH_TOR

  • private function VSH_TOR_DP(L, K, THETA, PHI) result(VSH_TOR)

    Toroidal member of the "standard" (total-angular-momentum-coupled) vector spherical harmonic basis, . Identical to PVSH_TOR -- the toroidal member is common to both the polar and standard bases, since already carries total angular momentum with no admixture.

    Warning

    Identical to PVSH_TOR -- inherits the unnormalized ASSOC_LEGENDRE_AND_DERIV's stability limit (safe for at any ), not VSH_TOR_ALL's . See STABILITY_FINDINGS.md at the repo root, Part 2.

    Returns: , complex 3-vector (identical to PVSH_TOR).

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

    Return Value complex(kind=dp), DIMENSION(3)

public interface VSH_TOR_ALL

  • private subroutine VSH_TOR_ALL_DP(OUT, LMAX, THETA, PHI)

    All toroidal standard-VSH members VSH_TOR for . Identical to PVSH_TOR_ALL (thin wrapper) -- the toroidal member is common to both bases.

    Warning

    Inherits ASSOC_LEGENDRE_NORM_ALL's -dependent stability limit (safe for unconditionally) -- see STABILITY_FINDINGS.md at the repo root.

    1= (always 0), 2=, 3=; mode axis indexed by YLM_INDEX(l,m).

    Arguments

    Type IntentOptional Attributes Name
    complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .

private interface ASSOC_LEGENDRE_AND_DERIV

  • private subroutine ASSOC_LEGENDRE_AND_DERIV_DP(L, K, X, PLK, DPLK)

    Private helper: and together, from a single upward recurrence pass. Avoids the redundant separate ASSOC_LEGENDRE calls that DDX_ASSOC_LEGENDRE would otherwise need, and the repeated SSH + DDX_ASSOC_LEGENDRE evaluation that GRAD_SSH and L_SSH both build on.

    Warning

    Inherits ASSOC_LEGENDRE's stability limit (safe for at any ) -- see STABILITY_FINDINGS.md at the repo root, Part 2.

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: L

    Degree, .

    integer(kind=i4), intent(in) :: K

    Order, .

    real(kind=dp), intent(in) :: X

    Argument, .

    real(kind=dp), intent(out) :: PLK

    Output ; 0 for or .

    real(kind=dp), intent(out) :: DPLK

    Output ; 0 at the poles ().

private interface FACTORIAL

  • private function FACTORIAL_DP(K) result(FACTORIAL)

    Factorial for , computed by direct multiplication.

    Returns: as a double-precision real (avoids integer overflow for moderate K; see LOG_FACT for large-K stability).

    Arguments

    Type IntentOptional Attributes Name
    integer(kind=i4), intent(in) :: K

    Non-negative integer argument.

    Return Value real(kind=dp)

private interface VSH_CORE

  • private subroutine VSH_CORE_DP(YLM_OUT, GSSH_TH, GSSH_PH, LMAX, THETA, PHI)

    Private helper shared by every batch VSH routine (GRAD_SSH_ALL, L_SSH_ALL, PVSH_RAD_ALL, PVSH_POL_ALL, PVSH_TOR_ALL, VSH_TOR_ALL, VSH_POL_UP_ALL, VSH_POL_DN_ALL): computes and its two angular gradient components (GRAD_SSH's parts) for every in one pass, so each caller only has to apply its own linear combination/normalization on top.

    Warning

    Inherits ASSOC_LEGENDRE_NORM_ALL's -dependent stability limit (safe for unconditionally) -- see STABILITY_FINDINGS.md at the repo root.

    YLM_INDEX(l,m). Y_\ell^m ), same size/indexing. Y_\ell^m ), same size/indexing.

    Arguments

    Type IntentOptional Attributes Name
    complex(kind=dp), intent(out) :: YLM_OUT((LMAX+1)**2)
    complex(kind=dp), intent(out) :: GSSH_TH((LMAX+1)**2)
    complex(kind=dp), intent(out) :: GSSH_PH((LMAX+1)**2)
    integer(kind=i4), intent(in) :: LMAX

    Maximum degree, .

    real(kind=dp), intent(in) :: THETA

    Colatitude in radians, .

    real(kind=dp), intent(in) :: PHI

    Longitude in radians, .


Functions

public function PLM_INDEX(L, M)

1D packed-triangular index for into the output arrays of ASSOC_LEGENDRE_ALL, DDX_ASSOC_LEGENDRE_ALL, ASSOC_LEGENDRE_NORM_ALL, and DDX_ASSOC_LEGENDRE_NORM_ALL (all of which only need , by conjugate/parity symmetry). Matches the SHTOOLS PlmIndex convention.

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: M

Order, .

Return Value integer(kind=i4)

public function YLM_INDEX(L, M)

1D index for into the output arrays of every batch _ALL routine that needs the full range (SSH_ALL, GRAD_SSH_ALL, L_SSH_ALL, and every batch VSH routine).

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: M

Order, .

Return Value integer(kind=i4)

private function ASSOC_LEGENDRE_DP(L, K, X) result(ASSOC_LEGENDRE)

Associated Legendre function , Condon-Shortley phase convention, computed by the classic Bonnet-type upward recurrence starting from . For negative order, . Unnormalized (unlike ASSOC_LEGENDRE_NORM_ALL); loses numerical stability well before the intermediate values literally overflow, since the later upward-in- recurrence involves a subtraction of two comparably huge terms (catastrophic cancellation).

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: X

Argument, (typically ).

Return Value real(kind=dp)

private function CGCOEFF_DP(J1, M1, J2, M2, J3, M3) result(CGCOEFF)

Clebsch-Gordan coefficient for coupling two angular momenta to a total , via the closed-form Racah sum (evaluated in log-factorial form for numerical stability at large arguments -- see LOG_FACT): where . Adapted from David Simpson (NASA GSFC). Automatically returns 0 for any invalid combination -- violated triangle inequality , , or -- so it is always safe to call with an arbitrary sextuple of integers, e.g. when sweeping a parameter range.

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: J1

First angular momentum, .

integer(kind=i4), intent(in) :: M1

First projection, .

integer(kind=i4), intent(in) :: J2

Second angular momentum, .

integer(kind=i4), intent(in) :: M2

Second projection, .

integer(kind=i4), intent(in) :: J3

Coupled angular momentum, .

integer(kind=i4), intent(in) :: M3

Coupled projection, .

Return Value real(kind=dp)

private function DDX_ASSOC_LEGENDRE_DP(L, K, X) result(RES)

Derivative of the associated Legendre function, via ASSOC_LEGENDRE_AND_DERIV (thin wrapper that discards itself).

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: X

Argument, .

Return Value real(kind=dp)

private function DDX_LEGENDRE_DP(L, X) result(DDX_LEGENDRE)

Derivative of the Legendre polynomial, via away from the poles, and the closed-form pole values at .

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

real(kind=dp), intent(in) :: X

Argument, .

Return Value real(kind=dp)

private function DOT_DP(VSH1, VSH2) result(DOT)

Dot product of two 3-vectors (typically two VSH values evaluated at the same ): . Note this is a plain component-wise product, not a Hermitian inner product -- callers wanting must conjugate VSH2 themselves first (as done throughout src/tests.f90 and the examples/ drivers).

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=dp), intent(in), DIMENSION(3) :: VSH1

First complex 3-vector .

complex(kind=dp), intent(in), DIMENSION(3) :: VSH2

Second complex 3-vector .

Return Value complex(kind=dp)

private function FACTORIAL_DP(K) result(FACTORIAL)

Factorial for , computed by direct multiplication.

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: K

Non-negative integer argument.

Return Value real(kind=dp)

private function GRAD_SSH_DP(L, K, THETA, PHI) result(GRAD_SSH)

Angular (surface) gradient of the scalar spherical harmonic, . Returned as a 3-vector with a zero radial component, since the gradient of a purely angular function is purely tangential.

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

Return Value complex(kind=dp), DIMENSION(3)

private function GWI_DP(J1, M1, J2, M2, L, M) result(GWI)

Geppert-Wiebicke axisymmetric coupling coefficient (Geppert & Wiebicke, 1991), a compact shorthand for the generation/amplification amplitude of a two-mode interaction in the Hall-MHD induction equation: This is algebraically the standard Gaunt coefficient -- the closed form for -- written in terms of two CGCOEFF evaluations. Built entirely from CGCOEFF, which guards all selection rules, so GWI is safe to call with any integer sextuple and returns 0 for invalid combinations (unlike GWJ, see its own selection-rule note).

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: J1

First coupled degree, .

integer(kind=i4), intent(in) :: M1

First coupled order, .

integer(kind=i4), intent(in) :: J2

Second coupled degree, .

integer(kind=i4), intent(in) :: M2

Second coupled order, .

integer(kind=i4), intent(in) :: L

Resulting degree, .

integer(kind=i4), intent(in) :: M

Resulting order, .

Return Value complex(kind=dp)

private function GWJ_DP(J1, M1, J2, M2, L, M) result(GWJ)

Geppert-Wiebicke non-axisymmetric coupling coefficient (Geppert & Wiebicke, 1991), the companion to GWI encoding the amplitude of a two-mode Hall-MHD interaction that generates or amplifies a non-axisymmetric component: Cross-validated against an independent VSH-dot-product expansion in TEST2_GW (src/tests.f90).

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: J1

First coupled degree, .

integer(kind=i4), intent(in) :: M1

First coupled order, .

integer(kind=i4), intent(in) :: J2

Second coupled degree, .

integer(kind=i4), intent(in) :: M2

Second coupled order, .

integer(kind=i4), intent(in) :: L

Resulting degree, .

integer(kind=i4), intent(in) :: M

Resulting order, .

Return Value complex(kind=dp)

private function LEGENDRE_DP(L, X) result(LEGENDRE)

Legendre polynomial , degree , via the standard three-term recurrence

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=I4), intent(in) :: L

Degree, .

real(kind=dp), intent(in) :: X

Argument, (typically ).

Return Value real(kind=dp)

private function LOG_FACT_DP(N) result(LOG_FACT)

, via (the intrinsic LOG_GAMMA). Used throughout CGCOEFF, SSH, and ASSOC_LEGENDRE to evaluate factorial ratios like as without overflowing the individual factorials for large .

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: N

Non-negative integer argument ( returns 0).

Return Value real(kind=dp)

private function L_SSH_DP(L, K, THETA, PHI) result(L_SSH)

The angular-momentum-operator field (proportional to the quantum-mechanical orbital angular-momentum operator acting on the scalar harmonic). Simply GRAD_SSH rotated 90 degrees within the tangent plane: .

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

Return Value complex(kind=dp), DIMENSION(3)

private function PVSH_POL_DP(L, K, THETA, PHI) result(PVSH_POL)

Poloidal (horizontal) member of the polar vector spherical harmonic basis, -- purely horizontal (zero radial component), i.e. GRAD_SSH normalized by . Combined with a radial stream function , this is the horizontal-field piece of a poloidal field, . Zero for (a constant has no horizontal gradient).

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

Return Value complex(kind=dp), DIMENSION(3)

private function PVSH_RAD_DP(L, K, THETA, PHI) result(PVSH_RAD)

Radial member of the polar vector spherical harmonic basis, . Purely radial by construction (zero horizontal components) -- combined with a radial stream function , this is the -generating piece of a poloidal magnetic (or any divergence-free) field, .

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

Return Value complex(kind=dp), DIMENSION(3)

private function PVSH_TOR_DP(L, K, THETA, PHI) result(PVSH_TOR)

Toroidal member of the polar vector spherical harmonic basis, -- purely horizontal (zero radial component), identical in form to L_SSH but normalized by . This is the horizontal-field piece of a toroidal magnetic field, for a toroidal stream function . Zero for (no toroidal monopole).

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

Return Value complex(kind=dp), DIMENSION(3)

private function SSH_DP(L, K, THETA, PHI) result(SSH)

Scalar spherical harmonic , fully normalized with the Condon-Shortley phase:

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

Return Value complex(kind=dp)

private function SYMBOL3J_DP(J1, M1, J2, M2, J3, M3) result(SYMBOL3J)

Wigner 3-j symbol , via the standard conversion from CGCOEFF: Inherits CGCOEFF's selection-rule guards -- safe to call with any integer sextuple, returning 0 for invalid combinations.

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: J1

First angular momentum, .

integer(kind=i4), intent(in) :: M1

First projection, .

integer(kind=i4), intent(in) :: J2

Second angular momentum, .

integer(kind=i4), intent(in) :: M2

Second projection, .

integer(kind=i4), intent(in) :: J3

Third angular momentum, .

integer(kind=i4), intent(in) :: M3

Third projection, .

Return Value real(kind=dp)

private function VSH_POL_DN_DP(L, K, THETA, PHI) result(VSH_POL_DN)

The member of the standard (total-angular-momentum coupled) vector spherical harmonic basis, built from the polar basis by i.e. PVSH_RAD and PVSH_POL rotated together by an -dependent angle (see VSH_POL_UP for the companion rotation). Zero for (no ).

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

Return Value complex(kind=dp), DIMENSION(3)

private function VSH_POL_UP_DP(L, K, THETA, PHI) result(VSH_POL_UP)

The member of the standard (total-angular-momentum coupled) vector spherical harmonic basis, built from the polar basis by the companion rotation to VSH_POL_DN's . Unlike VSH_POL_DN this is well-defined (nonzero radial part) at , since still exists when .

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

Return Value complex(kind=dp), DIMENSION(3)

private function VSH_TOR_DP(L, K, THETA, PHI) result(VSH_TOR)

Toroidal member of the "standard" (total-angular-momentum-coupled) vector spherical harmonic basis, . Identical to PVSH_TOR -- the toroidal member is common to both the polar and standard bases, since already carries total angular momentum with no admixture.

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

Return Value complex(kind=dp), DIMENSION(3)


Subroutines

private subroutine ASSOC_LEGENDRE_ALL_DP(P, LMAX, X)

All unnormalized associated Legendre functions for , via the Bonnet recurrence, in one pass (amortizing shared recurrence terms across every at fixed -- far cheaper than independent ASSOC_LEGENDRE calls). Condon-Shortley phase; same recurrence and same stability limit as ASSOC_LEGENDRE (see ASSOC_LEGENDRE_NORM_ALL for the far-more-stable normalized alternative, itself safe to ).

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=dp), intent(out) :: P((LMAX+1)*(LMAX+2)/2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: X

Argument, (typically ).

private subroutine ASSOC_LEGENDRE_AND_DERIV_DP(L, K, X, PLK, DPLK)

Private helper: and together, from a single upward recurrence pass. Avoids the redundant separate ASSOC_LEGENDRE calls that DDX_ASSOC_LEGENDRE would otherwise need, and the repeated SSH + DDX_ASSOC_LEGENDRE evaluation that GRAD_SSH and L_SSH both build on.

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: L

Degree, .

integer(kind=i4), intent(in) :: K

Order, .

real(kind=dp), intent(in) :: X

Argument, .

real(kind=dp), intent(out) :: PLK

Output ; 0 for or .

real(kind=dp), intent(out) :: DPLK

Output ; 0 at the poles ().

private subroutine ASSOC_LEGENDRE_NORM_ALL_DP(PNORM, LMAX, X)

All -normalized associated Legendre functions , (i.e. the real-valued radial part of SSH, for ), using the Holmes & Featherstone (2002) modified forward-column recurrence. The normalization is folded directly into the recurrence coefficients, keeping every intermediate value rather than letting itself grow/shrink combinatorially like the unnormalized ASSOC_LEGENDRE_ALL/Bonnet recurrence does. This is the recurrence SSH_ALL and every batch VSH routine build on.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=dp), intent(out) :: PNORM((LMAX+1)*(LMAX+2)/2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: X

Argument, (typically ).

private subroutine DDX_ASSOC_LEGENDRE_ALL_DP(DP_OUT, P, LMAX, X)

All derivatives for , reusing a precomputed ASSOC_LEGENDRE_ALL table rather than recomputing from scratch.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=dp), intent(out) :: DP_OUT((LMAX+1)*(LMAX+2)/2)
real(kind=dp), intent(in) :: P((LMAX+1)*(LMAX+2)/2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, (must match P's).

real(kind=dp), intent(in) :: X

Argument, (must match the X used to build

private subroutine DDX_ASSOC_LEGENDRE_NORM_ALL_DP(DPNORM, PNORM, LMAX, X)

All derivatives of the normalized associated Legendre functions, for , reusing a precomputed ASSOC_LEGENDRE_NORM_ALL table: This is the recurrence VSH_CORE (and therefore every batch VSH routine) uses for the component.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=dp), intent(out) :: DPNORM((LMAX+1)*(LMAX+2)/2)
real(kind=dp), intent(in) :: PNORM((LMAX+1)*(LMAX+2)/2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, (must match PNORM's).

real(kind=dp), intent(in) :: X

Argument, (must match the X used to build

private subroutine GRAD_SSH_ALL_DP(OUT, LMAX, THETA, PHI)

All angular gradients (GRAD_SSH) for , from one VSH_CORE pass.

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

private subroutine L_SSH_ALL_DP(OUT, LMAX, THETA, PHI)

All angular-momentum-operator fields (L_SSH) for , from one VSH_CORE pass.

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

private subroutine PVSH_POL_ALL_DP(OUT, LMAX, THETA, PHI)

All poloidal (horizontal) polar VSH members PVSH_POL for , from one VSH_CORE pass. Zero for .

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

private subroutine PVSH_RAD_ALL_DP(OUT, LMAX, THETA, PHI)

All radial polar VSH members PVSH_RAD for , from one VSH_CORE pass.

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

private subroutine PVSH_TOR_ALL_DP(OUT, LMAX, THETA, PHI)

All toroidal polar VSH members PVSH_TOR for , from one VSH_CORE pass. Zero for .

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

private subroutine SHGLQ_DP(ZERO, W, LMAX)

Gauss-Legendre quadrature nodes and weights, exact for integrating any polynomial of degree using only points -- the natural quadrature for spherical harmonic transforms, since is a polynomial in times , and the transform integral separates exactly into this -quadrature times a uniform sum over (itself exact for finite Fourier content). Nodes are the zeros of , found by Newton iteration (converges to machine precision in under 10 steps); weights are .

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=dp), intent(out) :: ZERO(LMAX+1)
real(kind=dp), intent(out) :: W(LMAX+1)
integer(kind=i4), intent(in) :: LMAX

Requested exactness is degree ;

private subroutine SSH_ALL_DP(YLM, LMAX, THETA, PHI)

All scalar spherical harmonics for , in one call. Computes ASSOC_LEGENDRE_NORM_ALL once, then fills directly and via the conjugate symmetry rather than a second recurrence pass.

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=dp), intent(out) :: YLM((LMAX+1)**2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

private subroutine VSH_CORE_DP(YLM_OUT, GSSH_TH, GSSH_PH, LMAX, THETA, PHI)

Private helper shared by every batch VSH routine (GRAD_SSH_ALL, L_SSH_ALL, PVSH_RAD_ALL, PVSH_POL_ALL, PVSH_TOR_ALL, VSH_TOR_ALL, VSH_POL_UP_ALL, VSH_POL_DN_ALL): computes and its two angular gradient components (GRAD_SSH's parts) for every in one pass, so each caller only has to apply its own linear combination/normalization on top.

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=dp), intent(out) :: YLM_OUT((LMAX+1)**2)
complex(kind=dp), intent(out) :: GSSH_TH((LMAX+1)**2)
complex(kind=dp), intent(out) :: GSSH_PH((LMAX+1)**2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

private subroutine VSH_POL_DN_ALL_DP(OUT, LMAX, THETA, PHI)

All standard-VSH members VSH_POL_DN for , from one VSH_CORE pass: . Zero for -- see VSH_POL_DN for the dipole-ratio caveat at .

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

private subroutine VSH_POL_UP_ALL_DP(OUT, LMAX, THETA, PHI)

All standard-VSH members VSH_POL_UP for , from one VSH_CORE pass: . Well-defined (nonzero) at -- see VSH_POL_UP for the dipole-ratio note at .

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .

private subroutine VSH_TOR_ALL_DP(OUT, LMAX, THETA, PHI)

All toroidal standard-VSH members VSH_TOR for . Identical to PVSH_TOR_ALL (thin wrapper) -- the toroidal member is common to both bases.

Read more…

Arguments

Type IntentOptional Attributes Name
complex(kind=dp), intent(out) :: OUT(3,(LMAX+1)**2)
integer(kind=i4), intent(in) :: LMAX

Maximum degree, .

real(kind=dp), intent(in) :: THETA

Colatitude in radians, .

real(kind=dp), intent(in) :: PHI

Longitude in radians, .