QPMS
Electromagnetic multiple scattering library and toolkit.
ewald.h
Go to the documentation of this file.
1 
27 #ifndef EWALD_H
28 #define EWALD_H
29 #include <gsl/gsl_sf_result.h>
30 #include <stdlib.h>
31 #include <gsl/gsl_sf_legendre.h>
32 #include <gsl/gsl_errno.h>
33 #include <math.h> // for inlined lilgamma
34 #include <complex.h>
35 #include "qpms_types.h"
36 #include "lattices.h"
37 
38 
39 typedef enum {
40  QPMS_EWALD_LONG_RANGE = 1,
41  QPMS_EWALD_SHORT_RANGE = 2,
42  QPMS_EWALD_0TERM = 4,
43  QPMS_EWALD_FULL = QPMS_EWALD_LONG_RANGE | QPMS_EWALD_SHORT_RANGE | QPMS_EWALD_0TERM,
44 } qpms_ewald_part;
45 
46 
48 gsl_error_handler_t IgnoreUnderflowsGSLErrorHandler;
49 
50 
52 
56 typedef struct qpms_ewald3_constants_t {
57  qpms_l_t lMax;
58  qpms_y_t nelem_sc;
62  complex double **s1_constfacs; // indices [y][j] where j is same as in [1, (4.5)]
63  /* These are the actual numbers now: (in the EWALD32_CONSTANTS_AGNOSTIC version)
64  * for m + n EVEN:
65  *
66  * s1_constfacs[y(m,n)][j] =
67  *
68  * -2 * I**(n+1) * sqrt(π) * ((n-m)/2)! * ((n+m)/2)! * (-1)**j
69  * -----------------------------------------------------------
70  * j! * ((n-m)/2 - j)! * ((n+m)/2 + j)!
71  *
72  * for m + n ODD:
73  *
74  * s1_constfacs[y(m,n)][j] = 0
75  */
76  complex double *s1_constfacs_base;
77  // similarly for the 1D z-axis aligned case; now the indices are [n][j] (as m == 0)
79 
85 
86  // TODO indexing mechanisms
87 
89  complex double **S1_constfacs; // indices [y][j] where j is same as in [1, (4.5)]
90  /* These are the actual numbers now: (in the EWALD32_CONSTANTS_AGNOSTIC version)
91  * for m + n EVEN:
92  *
93  * S1_constfacs[y(m,n)][x(j,s)] =
94  *
95  * -2 * I**(n+1) * sqrt(π) * ((n-m)/2)! * ((n+m)/2)! * (-1)**j / j \
96  * ----------------------------------------------------------- | |
97  * j! * ((n - m - s)/2)! * ((n + m - s)/2)! \ 2j - s /
98  *
99  * for m + n ODD:
100  *
101  * S1_constfacs[y(m,n)][j] = 0
102  */
103  complex double *S1_constfacs_base;
105 
111  complex double **s1_constfacs_1Dz;
112  /* These are the actual numbers now:
113  * s1_constfacs_1Dz[n][j] =
114  *
115  * -I**(n+1) (-1)**j * n!
116  * --------------------------
117  * j! * 2**(2*j) * (n - 2*j)!
118  */
119  complex double *s1_constfacs_1Dz_base;
120 
121  double *legendre0; /* now with GSL_SF_LEGENDRE_NONE normalisation, because this is what is
122  * what the multipliers from translations.c count with.
123  */
124  double *legendre_plus1; // needed? TODO; in any case, nonzero only for m=0
125  double *legendre_minus1; // needed? TODO; in any case, nonzero only for m=0
126  gsl_sf_legendre_t legendre_normconv;
127  int legendre_csphase; /* 1 or -1; csphase of the Legendre polynomials saved in legendre0 etc.
128  This is because I dont't actually consider this fixed in
129  translations.c */
130 
132 
137 
138 
140 
141 typedef struct qpms_csf_result {
142  complex double val;
143  double err;
145 
146 
147 // [1, (A.9)]
148 static inline complex double lilgamma(double t) {
149  t = fabs(t);
150  if (t >= 1)
151  return sqrt(t*t - 1);
152  else
153  return -I * sqrt(1 - t*t);
154 }
155 
156 // [1, (A.8)], complex version of lilgamma()
157 static inline complex double clilgamma(complex double z) {
158  complex double a1 = z - 1, a2 = z + 1;
159  // ensure -pi/2 < arg(z + 1) < 3*pi/2
160  if (creal(a2) < 0 && cimag(a2) <= 0)
161  a2 = -csqrt(a2);
162  else
163  a2 = csqrt(a2);
164  // ensure -3*pi/2 < arg(z - 1) < pi/2
165  if (creal(a1) < 0 && cimag(a1) >= 0)
166  a1 = -csqrt(a1);
167  else
168  a1 = csqrt(a1);
169  return a1 * a2;
170 }
171 
173 
183 int cx_gamma_inc_series_e(double a, complex double z, qpms_csf_result * result);
184 
186 
195 int cx_gamma_inc_CF_e(double a, complex double z, qpms_csf_result * result);
196 
198 
212 int complex_gamma_inc_e(double a, complex double x,
214 
224  int m,
225  qpms_csf_result *result);
226 
228 
229 int complex_expint_n_e(int n, complex double x, qpms_csf_result *result);
230 
231 
233 int hyperg_2F2_series(double a, double b, double c, double d, double x,
234  gsl_sf_result *result);
235 
236 #if 0
237 // The integral from (4.6); maybe should be static and not here.
238 int ewald32_sr_integral(double r, double k, double n, double eta, double *result, double *err, gsl_integration_workspace *workspace);
239 #endif
240 
242 
248 void ewald3_2_sigma_long_Delta(complex double *target, double *target_err, int maxn, complex double x,
249  int xbranch, complex double z);
250 
252 
255 void ewald3_2_sigma_long_Delta_recurrent(complex double *target, double *target_err, int maxn, complex double x,
256  int xbranch, complex double z, _Bool bigimz);
257 
259 
266 void ewald3_2_sigma_long_Delta_series(complex double *target, double *target_err, int maxn, complex double x,
267  int xbranch, complex double z);
268 
269 // General functions acc. to [2], sec. 4.6 – currently valid for 2D and 1D lattices in 3D space
270 
272 int ewald3_sigma0(complex double *result,
273  double *err,
274  const qpms_ewald3_constants_t *c,
275  double eta,
276  complex double wavenumber
277 );
278 
281  complex double *target_sigmasr_y,
282  double *target_sigmasr_y_err,
283  const qpms_ewald3_constants_t *c,
284  double eta,
285  complex double wavenumber,
287 
288  LatticeDimensionality latdim,
290 
296  PGen *pgen_R,
298 
304  bool pgen_generates_shifted_points,
306  cart3_t k,
308  cart3_t particle_shift
309  );
310 
312 int ewald3_sigma_long( // calls ewald3_21_sigma_long or ewald3_3_sigma_long, depending on latdim
313  complex double *target_sigmalr_y,
314  double *target_sigmalr_y_err,
315  const qpms_ewald3_constants_t *c,
316  double eta,
317  complex double wavenumber,
318  double unitcell_volume,
320  LatticeDimensionality latdim,
322 
328  PGen *pgen_K,
330 
335  bool pgen_generates_shifted_points,
337  cart3_t k,
339  cart3_t particle_shift
340  );
341 
342 #endif //EWALD_H
qpms_ewald3_constants_t * qpms_ewald3_constants_init(qpms_l_t lMax, int csphase)
Constructor for qpms_ewald3_constants_t.
Definition: ewald.c:104
struct qpms_ewald3_constants_t qpms_ewald3_constants_t
Object holding the Ewald sum constant factors.
int ewald3_sigma_long(complex double *target_sigmalr_y, double *target_sigmalr_y_err, const qpms_ewald3_constants_t *c, double eta, complex double wavenumber, double unitcell_volume, LatticeDimensionality latdim, PGen *pgen_K, bool pgen_generates_shifted_points, cart3_t k, cart3_t particle_shift)
Long-range part of outgoing scalar spherical wavefunctions' lattice sum .
Definition: ewald.c:645
void ewald3_2_sigma_long_Delta_series(complex double *target, double *target_err, int maxn, complex double x, int xbranch, complex double z)
The Delta_n factor from [Kambe II], Appendix 3, used in 2D-in-3D long range sum.
Definition: ewaldsf.c:382
int cx_gamma_inc_series_e(double a, complex double z, qpms_csf_result *result)
Incomplete Gamma function as a series.
Definition: ewaldsf.c:50
int hyperg_2F2_series(double a, double b, double c, double d, double x, gsl_sf_result *result)
Hypergeometric 2F2, used to calculate some errors.
Definition: ewaldsf.c:233
int complex_gamma_inc_e(double a, complex double x, int m, qpms_csf_result *result)
Incomplete gamma for complex second argument.
Definition: ewaldsf.c:174
void qpms_ewald3_constants_free(qpms_ewald3_constants_t *)
Destructor for qpms_ewald3_constants_t.
Definition: ewald.c:245
struct qpms_csf_result qpms_csf_result
Structure for holding complex-valued result of computation and an error estimate.
int complex_expint_n_e(int n, complex double x, qpms_csf_result *result)
Exponential integral for complex second argument.
Definition: ewaldsf.c:214
void ewald3_2_sigma_long_Delta(complex double *target, double *target_err, int maxn, complex double x, int xbranch, complex double z)
The Delta_n factor from [Kambe II], Appendix 3, used in 2D-in-3D long range sum.
Definition: ewaldsf.c:442
void ewald3_2_sigma_long_Delta_recurrent(complex double *target, double *target_err, int maxn, complex double x, int xbranch, complex double z, _Bool bigimz)
The Delta_n factor from [Kambe II], Appendix 3, used in 2D-in-3D long range sum.
int ewald3_sigma0(complex double *result, double *err, const qpms_ewald3_constants_t *c, double eta, complex double wavenumber)
The Ewald sum "self-interaction" term that appears in the lattice sums with zero (direct-space) Brava...
Definition: ewald.c:260
gsl_error_handler_t IgnoreUnderflowsGSLErrorHandler
Use this handler to ignore underflows of incomplete gamma.
Definition: ewald.h:48
int ewald3_sigma_short(complex double *target_sigmasr_y, double *target_sigmasr_y_err, const qpms_ewald3_constants_t *c, double eta, complex double wavenumber, LatticeDimensionality latdim, PGen *pgen_R, bool pgen_generates_shifted_points, cart3_t k, cart3_t particle_shift)
Short-range part of outgoing scalar spherical wavefunctions' lattice sum .
Definition: ewald.c:764
int cx_gamma_inc_CF_e(double a, complex double z, qpms_csf_result *result)
Incomplete Gamma function as continued fractions.
Definition: ewaldsf.c:154
Lattice point generators and lattice vector analysis / transformation.
Common qpms types.
size_t qpms_y_t
Type for the (l, m) multiindex of transversal (M or N -type) VSWFs.
Definition: qpms_types.h:44
int qpms_l_t
Type for spherical harmonic degree l.
Definition: qpms_types.h:27
Generic lattice point generator type.
Definition: lattices.h:120
3D cartesian coordinates. See also vectors.h.
Definition: qpms_types.h:186
Structure for holding complex-valued result of computation and an error estimate.
Definition: ewald.h:141
double err
Error estimate.
Definition: ewald.h:143
complex double val
Calculation result.
Definition: ewald.h:142
Object holding the Ewald sum constant factors.
Definition: ewald.h:56
complex double ** S1_constfacs
The constant factors for the long range part of a 1D Ewald sum along the z axis.
Definition: ewald.h:89
complex double * s1_constfacs_1Dz_base
Internal pointer holding memory for the 1D Ewald sum constant factors.
Definition: ewald.h:119
qpms_l_t * s1_jMaxes
The values of maximum j's in the long-range part summation, [(l-|m|/2)].
Definition: ewald.h:60
complex double * S1_constfacs_base
Definition: ewald.h:103
complex double ** s1_constfacs
The constant factors for the long range part of a 2D Ewald sum.
Definition: ewald.h:62
complex double ** s1_constfacs_1Dz
The constant factors for the long range part of a 1D Ewald sum along the z axis.
Definition: ewald.h:111
complex double * s1_constfacs_base
Internal pointer holding memory for the 2D Ewald sum constant factors.
Definition: ewald.h:76