From e486e04e2f2be69a794b526db0dbbdb4ea4c6cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ne=C4=8Dada?= Date: Fri, 23 Oct 2020 16:23:45 +0300 Subject: [PATCH] WIP documentation on phase/normalisation implementation. --- notes/conventions.md | 6 +- notes/conventions_qpms.md | 114 ++++++++++++++++++++++++++++++++++++++ qpms/qpms_types.h | 4 +- 3 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 notes/conventions_qpms.md diff --git a/notes/conventions.md b/notes/conventions.md index 127a11f..ba71cb5 100644 --- a/notes/conventions.md +++ b/notes/conventions.md @@ -1,6 +1,10 @@ VSWF conventions {#vswf_conventions} ==================================== +*This page provides reference about the VSWF conventions used in the literature. +For VSWF convention specification in QPMS API, see +[SWF Conventions in QPMS](@ref swf_conventions_qpms).* + In general, the (transversal) VSWFs can be defined using (some) vector spherical harmonics as follows: \f[ \wfm\pr{k\vect r}_{lm} = \sphbes_l(kr) \vshrot_{lm} (\uvec r),\\ @@ -50,7 +54,7 @@ where the connection to negative orders is \dlmfFer{\nu}{m}(x) = (-1)^m \frac{\Gamma\pr{\nu-m+1}}{\Gamma\pr{\nu+m+1}}\dlmfFer{\nu}{m}(x),\\ %\dlmfLeg{\nu}{m}(x) = \frac{\Gamma\pr{\nu-m+1}}{\Gamma\pr{\nu+m+1}}\dlmfLeg{\nu}{m}(x).\\ \f] -Note that there are called "Ferrers" functions in DLMF, while the "Legendre" functions have slightly +Note that they are called "Ferrers" functions in DLMF, while the "Legendre" functions have slightly different meaning / conventions (Ferrers functions being defined for \f$ \abs{x} \le 1 \f$, whereas Legendre for \f$ \abs{x} \ge 1 \f$. We will not use the DLMF "Legendre" functions here. diff --git a/notes/conventions_qpms.md b/notes/conventions_qpms.md new file mode 100644 index 0000000..a87a6a5 --- /dev/null +++ b/notes/conventions_qpms.md @@ -0,0 +1,114 @@ +SWF conventions in QPMS {#swf_conventions_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 + + diff --git a/qpms/qpms_types.h b/qpms/qpms_types.h index 4d465ba..7b7bd3b 100644 --- a/qpms/qpms_types.h +++ b/qpms/qpms_types.h @@ -99,7 +99,9 @@ typedef enum { * These bit flags are used by the functions declared in normalisation.h * that return the appropriate convention-dependent factors. * - * See @ref vswf_conventions for comparison of the various conventions used. + * \see @ref vswf_conventions for comparison of the various conventions used. + * \see @ref swf_conventions_qpms for description how the conventions are used internally and in the QPMS API. + * */ typedef enum { QPMS_NORMALISATION_UNDEF = 0, ///< Convention undefined. This should not happen.