qpms/notes/conventions_qpms.md

4.4 KiB
Raw Blame History

SWF conventions in QPMS

This page describes how (V)SWF conventions are specified internally and in QPMS API. For a general overview of VSWF conventions in the literature, see [VSWF Conventions](@ref vswf_conventions).

Convention enumerator

Most of the meaningful phase and normalisation conventions for spherical waves can be specified by the enum type @ref qpms_normalisation_t.

The type can be also used to specify conventions that are currently not fully supported in QPMS (such as those based on real spherical harmonics).

As an enum type, it does not cover all the conventions possibly imaginable, but it does cover the most meaningful ones and most of those that can be found in the literature.

(Most notably, it does not cover the “anti-normalisation” that does appear in certain expressions in some literature where the spherical harmonics contain unnormalised Legendre functions, so that the basis set of of spherical harmonics has different norms for different signs of m for the same l. This is a bad idea overall and an absolutely atrocious approach for numerics. Do not use that.)

VSWF evaluation

Evaluation of VSWFs using qpms_vswf_fill(), qpms_eval_vswf(), qpms_uvswf_fill() and other functions from vswf.h are evaluated as follows. These fuctions take a @ref qpms_normalisation_t as an argument. The Ferrers-Legendre functions and the π, τ functions are evaluated by qpms_pitau_get(), which internally uses gsl_sf_legendre_deriv_array_e().

Note only the information about the Condon-Shortley phase is passed to qpms_pitau_get() the result of this function uses always the GSL_SF_LEGENDRE_SPHARM normalisation, and possible normalisation and other phase factors are evaluated afterwards using the inline functions qpms_normalisation_factor_L_noCS(), qpms_normalisation_factor_M_noCS(), qpms_normalisation_factor_N_noCS().

Evaluation of vector spherical harmonics only with qpms_vecspharm_fill() works similarly but TODO.

TODO reference to pi, tau.

VSWF translation operator evaluation

In practice, translation operators are calculated by first creating an instance of the qpms_trans_calculator structure, which contains a table of constant normalisation factors for a given phase/normalisation convention (it is assumed that the phase/normalisation conventions do not change with the translation), and then calling qpms_trans_calculator_get_AB_arrays() (or others).

The precomputed factor table in qpms_trans_calculator_t contains a CS phase related factor (via qpms_trans_normfac()).

Function qpms_trans_calculator_get_AB_arrays_buf() then calculates the unnormalised (GSL_SF_LEGENDRE_NONE) associated Legendre functions always with CS phase -1; and the A, B arrays are filled (via qpms_trans_calculator_get_AB_arrays_precalcbuf()) by individual calls of qpms_trans_calculator_get_A_precalcbuf() and qpms_trans_calculator_B_precalcbuf(), which basically just multiply and sum the precalculated constant factors with the radial (Bessel), polar (Legendre) and azimuthal (exponential/trigonometric) functions. This means that the normalisation and phase convention is fully embedded in the constant factor tables, and nothing is calculated during "runtime".

The "higher-level" qpms_trans_calculator_get_trans_array() currently just calls qpms_trans_calculator_get_AB_arrays() and then reorders the elements (using qpms_trans_array_from_AB()), asserting that the normalisation conventions remain the same.

There seems to be an inconsistency between qpms_trans_calculator_get_B_buf() and qpms_trans_calculator_get_A_buf() on one hand, and qpms_trans_calculator_get_AB_buf_p() and qpms_trans_calculator_get_AB_arrays_buf() on the other. While the latter two functions use always -1 as the CS phase, the former two take it from the normalisation enumerator. Although the former two are probably used nowhere in the production, this needs to be fixed.

Lattice sums

Scalar SWFs

Translation operators

Function qpms_trans_calculator_get_AB_arrays_e32_e() first compute the scalar lattice sums (using ewald3_sigma_short(), ewald3_sigma_long() and ewald3_sigma0() calls).

These are then transformed into the VSWF translation operator elements in a similar manner as in qpms_trans_calculator_get_A_precalcbuf() and qpms_trans_calculator_get_B_precalcbuf(), although there some optical differences (CHECK!).

VSWFs