QPMS
Electromagnetic multiple scattering library and toolkit.
normalisation.h
Go to the documentation of this file.
1 
6 #ifndef NORMALISATION_H
7 #define NORMALISATION_H
8 
9 #include "qpms_types.h"
10 #include "qpms_error.h"
11 #include <math.h>
12 #include <complex.h>
13 #include "indexing.h"
14 #include "optim.h"
15 
17 
19  switch (QPMS_EXPECT(norm & QPMS_NORMALISATION_NORM_BITS, norm & QPMS_NORMALISATION_DEFAULT)) {
21  return 1;
23  return sqrt(l*(l+1));
24  case QPMS_NORMALISATION_NORM_NONE: // TODO more precision
25  return sqrt(l*(l+1) * 4*M_PI / (2*l+1)) *
26  exp(0.5*(lgamma(l+m+1) - lgamma(l-m+1)));
27  default:
28  QPMS_WTF;
29  }
30 }
31 
32 
33 
35 
40  complex double fac = qpms_normalisation_normfactor(norm, l, m);
41  if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_M_MINUS)) fac *= -1;
42  if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_M_I)) fac *= I;
43  if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_INVERSE)) fac = 1/fac;
44  return fac;
45 }
46 
47 
49 
54 static inline complex double qpms_normalisation_factor_M(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m) {
55  complex double fac = qpms_normalisation_factor_M_noCS(norm, l, m);
56  return ((norm & QPMS_NORMALISATION_CSPHASE) && (m % 2)) ? -fac : fac;
57 }
58 
59 
61 
66  complex double fac = qpms_normalisation_normfactor(norm, l, m);
67  if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_N_MINUS)) fac *= -1;
68  if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_N_I)) fac *= I;
69  if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_INVERSE)) fac = 1/fac;
70  return fac;
71 }
72 
73 
75 
80 static inline complex double qpms_normalisation_factor_N(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m) {
81  complex double fac = qpms_normalisation_factor_N_noCS(norm, l, m);
82  return ((norm & QPMS_NORMALISATION_CSPHASE) && (m % 2)) ? -fac : fac;
83 }
84 
85 
87 static inline complex double qpms_normalisation_factor_N_M(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m) {
88  return qpms_normalisation_factor_N_noCS(norm, l, m)
90 }
91 
92 
94 
99  complex double fac = qpms_normalisation_normfactor(norm, l, m);
100  if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_L_MINUS)) fac *= -1;
101  if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_L_I)) fac *= I;
102  if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_INVERSE)) fac = 1/fac;
103  return fac;
104 }
105 
107 
112 static inline complex double qpms_normalisation_factor_L(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m) {
113  complex double fac = qpms_normalisation_factor_L_noCS(norm, l, m);
114  return ((norm & QPMS_NORMALISATION_CSPHASE) && (m % 2)) ? -fac : fac;
115 }
116 
118 static inline complex double qpms_normalisation_factor_uvswfi(const qpms_normalisation_t norm, qpms_uvswfi_t ui) {
120  qpms_uvswfi2tmn(ui, &t, &m, &l);
121  switch(t) {
122  case QPMS_VSWF_MAGNETIC:
123  return qpms_normalisation_factor_M(norm, l, m);
124  case QPMS_VSWF_ELECTRIC:
125  return qpms_normalisation_factor_N(norm, l, m);
127  return qpms_normalisation_factor_L(norm, l, m);
128  default:
129  QPMS_WTF;
130  }
131 }
132 
133 
135 
142  if (!(norm & QPMS_NORMALISATION_SPHARM_REAL))
144  return norm;
145 }
146 
148 
159 static inline complex double qpms_spharm_azimuthal_part(qpms_normalisation_t norm, qpms_m_t m, double phi) {
160  switch(QPMS_EXPECT(norm, QPMS_NORMALISATION_DEFAULT)
162  case 0:
163  return cexp(I*m*phi);
165  return cexp(-I*m*phi);
167  if (m > 0) return M_SQRT2 * cos(m*phi);
168  else if (m < 0) return M_SQRT2 * sin(m*phi);
169  else return 1.;
170  default:
171  QPMS_WTF;
172  }
173 }
174 
176 
197 static inline complex double qpms_spharm_azimuthal_part_derivative_div_m(qpms_normalisation_t norm, qpms_m_t m, double phi) {
198  if(m==0) return 0;
199  switch(QPMS_EXPECT(norm, QPMS_NORMALISATION_DEFAULT)
201  case 0:
202  return I*cexp(I*m*phi);
204  return -I*cexp(-I*m*phi);
206  if (m > 0) return -M_SQRT2 * sin(m*phi);
207  else if (m < 0) return M_SQRT2 * cos(m*phi);
208  else return -1;
209  default:
210  QPMS_WTF;
211  }
212 }
213 
214 #if 0 // legacy code moved from qpms_types.h. TODO cleanup
216 static inline int qpms_normalisation_t_normonly(qpms_normalisation_t norm) {
217  return norm & (~QPMS_NORMALISATION_T_CSBIT);
218 }
219 
220 /* Normalisation of the spherical waves is now scattered in at least three different files:
221  * here, we have the norm in terms of radiated power of outgoing wave.
222  * In file legendre.c, function qpms_pitau_get determines the norm used in the vswf.c
223  * spherical vector wave norms. The "dual" waves in vswf.c use the ..._abssquare function below.
224  * In file translations.c, the normalisations are again set by hand using the normfac and lognormfac
225  * functions.
226  */
227 #include <math.h>
228 #include <assert.h>
229 // relative to QPMS_NORMALISATION_KRISTENSSON_CS, i.e.
230 // P_l^m[normtype] = P_l^m[Kristensson]
231 static inline double qpms_normalisation_t_factor(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m) {
232  int csphase = qpms_normalisation_t_csphase(norm);
233  norm = qpms_normalisation_t_normonly(norm);
234  double factor;
235  switch (norm) {
236  case QPMS_NORMALISATION_KRISTENSSON:
237  factor = 1.;
238  break;
239  case QPMS_NORMALISATION_TAYLOR:
240  factor = sqrt(l*(l+1));
241  break;
242  case QPMS_NORMALISATION_NONE:
243  factor = sqrt(l*(l+1) * 4 * M_PI / (2*l+1) * exp(lgamma(l+m+1)-lgamma(l-m+1)));
244  break;
245 #ifdef USE_XU_ANTINORMALISATION // broken probably in legendre.c
246  case QPMS_NORMALISATION_XU:
247  factor = sqrt(4 * M_PI) / (2*l+1) * exp(lgamma(l+m+1)-lgamma(l-m+1));
248  break;
249 #endif
250  default:
251  assert(0);
252  }
253  factor *= (m%2)?(-csphase):1;
254  return factor;
255 }
256 
257 
258 // TODO move elsewhere
259 static inline double qpms_normalisation_t_factor_abssquare(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m) {
260  norm = qpms_normalisation_t_normonly(norm);
261  switch (norm) {
262  case QPMS_NORMALISATION_KRISTENSSON:
263  return 1.;
264  break;
265  case QPMS_NORMALISATION_TAYLOR:
266  return l*(l+1);
267  break;
268  case QPMS_NORMALISATION_NONE:
269  return l*(l+1) * 4 * M_PI / (2*l+1) * exp(lgamma(l+m+1)-lgamma(l-m+1));
270  break;
271 #ifdef USE_XU_ANTINORMALISATION // broken probably in legendre.c
272  case QPMS_NORMALISATION_XU:
273  {
274  double fac = sqrt(4 * M_PI) / (2*l+1) * exp(lgamma(l+m+1)-lgamma(l-m+1));
275  return fac * fac;
276  }
277  break;
278 #endif
279  default:
280  assert(0);
281  return NAN;
282  }
283 }
284 #endif
285 
286 #endif //NORMALISATION_H
Various index conversion functions.
static qpms_errno_t qpms_uvswfi2tmn(qpms_uvswfi_t u, qpms_vswf_type_t *t, qpms_m_t *m, qpms_l_t *n)
Conversion from universal VSWF index u to type, order and degree.
Definition: indexing.h:70
static complex double qpms_spharm_azimuthal_part_derivative_div_m(qpms_normalisation_t norm, qpms_m_t m, double phi)
Returns derivative of the asimuthal part of a spherical harmonic divided by m.
Definition: normalisation.h:197
static complex double qpms_normalisation_factor_N_M(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m)
Returns the factors of a electric basis VSWF divided by the factor of a magnetic VWFS of a given conv...
Definition: normalisation.h:87
static double qpms_normalisation_normfactor(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m)
Returns the (real positive) common norm factor of a given normalisation compared to the reference con...
Definition: normalisation.h:18
static complex double qpms_normalisation_factor_L(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m)
Returns the factors of a longitudinal basis VSWF of a given convention compared to the reference conv...
Definition: normalisation.h:112
static complex double qpms_normalisation_factor_M(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m)
Returns the factors of a magnetic basis VSWF of a given convention compared to the reference conventi...
Definition: normalisation.h:54
static complex double qpms_normalisation_factor_uvswfi(const qpms_normalisation_t norm, qpms_uvswfi_t ui)
Returns the factors of a basis VSWF of a given convention compared to the reference convention.
Definition: normalisation.h:118
static complex double qpms_normalisation_factor_N(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m)
Returns the factors of a electric basis VSWF of a given convention compared to the reference conventi...
Definition: normalisation.h:80
static complex double qpms_spharm_azimuthal_part(qpms_normalisation_t norm, qpms_m_t m, double phi)
Returns the asimuthal part of a spherical harmonic.
Definition: normalisation.h:159
static complex double qpms_normalisation_factor_L_noCS(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m)
Returns the factors of a longitudinal basis VSWF of a given convention compared to the reference conv...
Definition: normalisation.h:98
static complex double qpms_normalisation_factor_N_noCS(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m)
Returns the factors of a electric basis VSWF of a given convention compared to the reference conventi...
Definition: normalisation.h:65
static complex double qpms_normalisation_factor_M_noCS(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m)
Returns the factors of a magnetic basis VSWF of a given convention compared to the reference conventi...
Definition: normalisation.h:39
static qpms_normalisation_t qpms_normalisation_dual(qpms_normalisation_t norm)
Returns normalisation flags corresponding to the dual spherical harmonics / waves.
Definition: normalisation.h:140
Macros for compiler optimisation.
QPMS miscellanous internal error handling functions and macros.
#define QPMS_WTF
Prints an "unexpected error" message and aborts the program.
Definition: qpms_error.h:181
Common qpms types.
static int qpms_normalisation_t_csphase(qpms_normalisation_t norm)
Determine whether the convention includes Condon-Shortley phase (-1) or not (+1).
Definition: qpms_types.h:171
qpms_normalisation_t
Vector spherical wavefuction normalisation and phase convention codes.
Definition: qpms_types.h:104
@ QPMS_NORMALISATION_NORM_POWER
The VSWFs shall be power-normalised. This is the "default".
Definition: qpms_types.h:140
@ QPMS_NORMALISATION_INVERSE
Flag indicating that qpms_normalisition_factor_* should actually return values inverse to the default...
Definition: qpms_types.h:107
@ QPMS_NORMALISATION_SPHARM_REAL
Flag indicating use of the real spherical harmonics.
Definition: qpms_types.h:116
@ QPMS_NORMALISATION_L_MINUS
Include an additional -factor into the longitudinal waves.
Definition: qpms_types.h:130
@ QPMS_NORMALISATION_M_I
Include an additional i -factor into the magnetic waves.
Definition: qpms_types.h:125
@ QPMS_NORMALISATION_M_MINUS
Include an additional -factor into the magnetic waves.
Definition: qpms_types.h:126
@ QPMS_NORMALISATION_L_I
Include an additional i -factor into the longitudinal waves.
Definition: qpms_types.h:129
@ QPMS_NORMALISATION_N_MINUS
Include an additional -factor into the magnetic waves.
Definition: qpms_types.h:128
@ QPMS_NORMALISATION_N_I
Include an additional i -factor into the electric waves.
Definition: qpms_types.h:127
@ QPMS_NORMALISATION_REVERSE_AZIMUTHAL_PHASE
Definition: qpms_types.h:111
@ QPMS_NORMALISATION_DEFAULT
Default VSWF convention. We might encourage the compiler to expect this one.
Definition: qpms_types.h:167
@ QPMS_NORMALISATION_CSPHASE
Flag indicating usage of Condon-Shortley phase.
Definition: qpms_types.h:124
@ QPMS_NORMALISATION_NORM_SPHARM
The VSWFs shall be normalised as in .
Definition: qpms_types.h:143
@ QPMS_NORMALISATION_NORM_NONE
The VSWFs shall be created using spherical harmonics without any normalisation. Do not use.
Definition: qpms_types.h:152
int qpms_l_t
Type for spherical harmonic degree l.
Definition: qpms_types.h:27
qpms_vswf_type_t
Codes of the VSWF types (electric/N, magnetic/M, longitudinal/L).
Definition: qpms_types.h:62
@ QPMS_VSWF_ELECTRIC
"Electric" (N -type) transversal wave.
Definition: qpms_types.h:63
@ QPMS_VSWF_LONGITUDINAL
Longitudinal (L -type) wave (not relevant for radiation).
Definition: qpms_types.h:65
@ QPMS_VSWF_MAGNETIC
"Magnetic" (M -type) transversal wave.
Definition: qpms_types.h:64
unsigned long long qpms_uvswfi_t
Exhaustive index type for VSWF basis functions.
Definition: qpms_types.h:81
qpms_lm_t qpms_m_t
Type for spherical harmonic order m.
Definition: qpms_types.h:31
A VSWF representation element of the qpms_l_t l
< The O(3) element in the quaternion representation.
Definition: quaternions.h:214