Scalar m,n indexing to allow n = 0.
Former-commit-id: 4b6f2f3611a00e2019b54bfe73c407baafdd8355
This commit is contained in:
parent
16ce3a6ba8
commit
e11f995b52
60
qpms/ewald.c
60
qpms/ewald.c
|
@ -66,15 +66,15 @@ qpms_ewald32_constants_t *qpms_ewald32_constants_init(const qpms_l_t lMax /*, co
|
|||
qpms_ewald32_constants_t *c = malloc(sizeof(qpms_ewald32_constants_t));
|
||||
//if (c == NULL) return NULL; // Do I really want to do this?
|
||||
c->lMax = lMax;
|
||||
c->nelem = qpms_lMax2nelem(lMax);
|
||||
c->s1_jMaxes = malloc(c->nelem * sizeof(qpms_l_t));
|
||||
c->s1_constfacs = malloc(c->nelem * sizeof(complex double *));
|
||||
c->nelem_sc = qpms_lMax2nelem_sc(lMax);
|
||||
c->s1_jMaxes = malloc(c->nelem_sc * sizeof(qpms_l_t));
|
||||
c->s1_constfacs = malloc(c->nelem_sc * sizeof(complex double *));
|
||||
//if (c->s1_jMaxes == NULL) return NULL;
|
||||
|
||||
//determine sizes
|
||||
size_t s1_constfacs_sz = 0;
|
||||
for (qpms_y_t y = 0; y < c->nelem; ++y) {
|
||||
qpms_l_t n; qpms_m_t m; qpms_y2mn_p(y, &m, &n);
|
||||
for (qpms_y_t y = 0; y < c->nelem_sc; ++y) {
|
||||
qpms_l_t n; qpms_m_t m; qpms_y2mn_sc_p(y, &m, &n);
|
||||
if ((m + n) % 2 == 0)
|
||||
s1_constfacs_sz += 1 + (c->s1_jMaxes[y] = (n-abs(m))/2);
|
||||
else
|
||||
|
@ -82,10 +82,10 @@ qpms_ewald32_constants_t *qpms_ewald32_constants_init(const qpms_l_t lMax /*, co
|
|||
}
|
||||
|
||||
c->s1_constfacs[0]; //WTF???
|
||||
c->s1_constfacs_base = malloc(c->nelem * sizeof(complex double));
|
||||
c->s1_constfacs_base = malloc(c->nelem_sc * sizeof(complex double));
|
||||
size_t s1_constfacs_sz_cumsum = 0;
|
||||
for (qpms_y_t y = 0; y < c->nelem; ++y) {
|
||||
qpms_l_t n; qpms_m_t m; qpms_y2mn_p(y, &m, &n);
|
||||
for (qpms_y_t y = 0; y < c->nelem_sc; ++y) {
|
||||
qpms_l_t n; qpms_m_t m; qpms_y2mn_sc_p(y, &m, &n);
|
||||
if ((m + n) % 2 == 0) {
|
||||
c->s1_constfacs[y] = c->s1_constfacs_base + s1_constfacs_sz_cumsum;
|
||||
// and here comes the actual calculation
|
||||
|
@ -151,7 +151,7 @@ int ewald32_sigma0(complex double *result, double *err,
|
|||
|
||||
|
||||
int ewald32_sigma_long_shiftedpoints (
|
||||
complex double *target, // must be c->nelem long
|
||||
complex double *target, // must be c->nelem_sc long
|
||||
double *err,
|
||||
const qpms_ewald32_constants_t *c,
|
||||
const double eta, const double k, const double unitcell_area,
|
||||
|
@ -159,16 +159,16 @@ int ewald32_sigma_long_shiftedpoints (
|
|||
const point2d particle_shift // target - src
|
||||
)
|
||||
{
|
||||
const qpms_y_t nelem = c->nelem;
|
||||
const qpms_y_t nelem_sc = c->nelem_sc;
|
||||
const qpms_l_t lMax = c->lMax;
|
||||
|
||||
// Manual init of the ewald summation targets
|
||||
complex double *target_c = calloc(nelem, sizeof(complex double));
|
||||
memset(target, 0, nelem * sizeof(complex double));
|
||||
complex double *target_c = calloc(nelem_sc, sizeof(complex double));
|
||||
memset(target, 0, nelem_sc * sizeof(complex double));
|
||||
double *err_c = NULL;
|
||||
if (err) {
|
||||
err_c = calloc(nelem, sizeof(double));
|
||||
memset(err, 0, nelem * sizeof(double));
|
||||
err_c = calloc(nelem_sc, sizeof(double));
|
||||
memset(err, 0, nelem_sc * sizeof(double));
|
||||
}
|
||||
|
||||
const double commonfac = 1/(k*k*unitcell_area); // used in the very end (CFC)
|
||||
|
@ -197,11 +197,11 @@ int ewald32_sigma_long_shiftedpoints (
|
|||
|
||||
// TODO optimisations: all the j-dependent powers can be done for each j only once, stored in array
|
||||
// and just fetched for each n, m pair
|
||||
for(qpms_l_t n = 1; n <= lMax; ++n)
|
||||
for(qpms_l_t n = 0; n <= lMax; ++n)
|
||||
for(qpms_m_t m = -n; m <= n; ++m) {
|
||||
if((m+n) % 2 != 0) // odd coefficients are zero.
|
||||
continue;
|
||||
qpms_y_t y = qpms_mn2y(m, n);
|
||||
qpms_y_t y = qpms_mn2y_sc(m, n);
|
||||
complex double e_imalpha_pq = cexp(I*m*arg_pq);
|
||||
complex double jsum, jsum_c; ckahaninit(&jsum, &jsum_c);
|
||||
double jsum_err, jsum_err_c; kahaninit(&jsum_err, &jsum_err_c); // TODO do I really need to kahan sum errors?
|
||||
|
@ -225,10 +225,10 @@ int ewald32_sigma_long_shiftedpoints (
|
|||
|
||||
free(err_c);
|
||||
free(target_c);
|
||||
for(qpms_y_t y = 0; y < nelem; ++y) // CFC common factor from above
|
||||
for(qpms_y_t y = 0; y < nelem_sc; ++y) // CFC common factor from above
|
||||
target[y] *= commonfac;
|
||||
if(err)
|
||||
for(qpms_y_t y = 0; y < nelem; ++y)
|
||||
for(qpms_y_t y = 0; y < nelem_sc; ++y)
|
||||
err[y] *= commonfac;
|
||||
return 0;
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ static int ewald32_sr_integral(double r, double k, int n, double eta,
|
|||
}
|
||||
|
||||
int ewald32_sigma_short_shiftedpoints(
|
||||
complex double *target, // must be c->nelem long
|
||||
complex double *target, // must be c->nelem_sc long
|
||||
double *err,
|
||||
const qpms_ewald32_constants_t *c, // N.B. not too useful here
|
||||
const double eta, const double k,
|
||||
|
@ -279,18 +279,18 @@ int ewald32_sigma_short_shiftedpoints(
|
|||
const point2d particle_shift // used only in the very end to multiply it by the phase
|
||||
)
|
||||
{
|
||||
const qpms_y_t nelem = c->nelem;
|
||||
const qpms_y_t nelem_sc = c->nelem_sc;
|
||||
const qpms_l_t lMax = c->lMax;
|
||||
gsl_integration_workspace *workspace =
|
||||
gsl_integration_workspace_alloc(INTEGRATION_WORKSPACE_LIMIT);
|
||||
|
||||
// Manual init of the ewald summation targets
|
||||
complex double *target_c = calloc(nelem, sizeof(complex double));
|
||||
memset(target, 0, nelem * sizeof(complex double));
|
||||
complex double *target_c = calloc(nelem_sc, sizeof(complex double));
|
||||
memset(target, 0, nelem_sc * sizeof(complex double));
|
||||
double *err_c = NULL;
|
||||
if (err) {
|
||||
err_c = calloc(nelem, sizeof(double));
|
||||
memset(err, 0, nelem * sizeof(double));
|
||||
err_c = calloc(nelem_sc, sizeof(double));
|
||||
memset(err, 0, nelem_sc * sizeof(double));
|
||||
}
|
||||
|
||||
|
||||
|
@ -304,7 +304,7 @@ int ewald32_sigma_short_shiftedpoints(
|
|||
double Rpq_shifted_arg = atan2(Rpq_shifted.x, Rpq_shifted.y); // POINT-DEPENDENT
|
||||
complex double e_beta_Rpq = cexp(I*cart2_dot(beta, Rpq_shifted)); // POINT-DEPENDENT
|
||||
|
||||
for(qpms_l_t n = 1; n <= lMax; ++n) {
|
||||
for(qpms_l_t n = 0; n <= lMax; ++n) {
|
||||
double complex prefacn = - I * pow(2./k, n+1) * M_2_SQRTPI / 2; // TODO put outside the R-loop and multiply in the end
|
||||
double R_pq_pown = pow(r_pq_shifted, n);
|
||||
// TODO the integral here
|
||||
|
@ -317,7 +317,7 @@ int ewald32_sigma_short_shiftedpoints(
|
|||
continue; // nothing needed, already done by memset
|
||||
complex double e_imf = cexp(I*m*Rpq_shifted_arg);
|
||||
double leg = c->legendre0[gsl_sf_legendre_array_index(n, m)];
|
||||
qpms_y_t y = qpms_mn2y(m,n);
|
||||
qpms_y_t y = qpms_mn2y_sc(m,n);
|
||||
if(err)
|
||||
kahanadd(err + y, err_c + y, cabs(leg * (prefacn / I) * R_pq_pown
|
||||
* interr)); // TODO include also other errors
|
||||
|
@ -339,7 +339,7 @@ int ewald32_sigma_short_shiftedpoints(
|
|||
|
||||
|
||||
int ewald32_sigma_long_points_and_shift (
|
||||
complex double *target_sigmalr_y, // must be c->nelem long
|
||||
complex double *target_sigmalr_y, // must be c->nelem_sc long
|
||||
const qpms_ewald32_constants_t *c,
|
||||
double eta, double k, double unitcell_area,
|
||||
size_t npoints, const point2d *Kpoints,
|
||||
|
@ -347,21 +347,21 @@ int ewald32_sigma_long_points_and_shift (
|
|||
point2d particle_shift
|
||||
);
|
||||
int ewald32_sigma_long_shiftedpoints_rordered(
|
||||
complex double *target_sigmalr_y, // must be c->nelem long
|
||||
complex double *target_sigmalr_y, // must be c->nelem_sc long
|
||||
const qpms_ewald32_constants_t *c,
|
||||
double eta, double k, double unitcell_area,
|
||||
const points2d_rordered_t *Kpoints_plus_beta_rordered,
|
||||
point2d particle_shift
|
||||
);
|
||||
int ewald32_sigma_short_points_and_shift(
|
||||
complex double *target_sigmasr_y, // must be c->nelem long
|
||||
complex double *target_sigmasr_y, // must be c->nelem_sc long
|
||||
const qpms_ewald32_constants_t *c, // N.B. not too useful here
|
||||
double eta, double k,
|
||||
size_t npoints, const point2d *Rpoints,
|
||||
point2d particle_shift
|
||||
);
|
||||
int ewald32_sigma_short_points_rordered(
|
||||
complex double *target_sigmasr_y, // must be c->nelem long
|
||||
complex double *target_sigmasr_y, // must be c->nelem_sc long
|
||||
const qpms_ewald32_constants_t *c, // N.B. not too useful here
|
||||
double eta, double k,
|
||||
const points2d_rordered_t *Rpoints_plus_particle_shift_rordered,
|
||||
|
|
26
qpms/ewald.h
26
qpms/ewald.h
|
@ -27,7 +27,7 @@
|
|||
/* Object holding the constant factors from [1, (4.5)] */
|
||||
typedef struct {
|
||||
qpms_l_t lMax;
|
||||
qpms_y_t nelem;
|
||||
qpms_y_t nelem_sc;
|
||||
qpms_l_t *s1_jMaxes;
|
||||
complex double **s1_constfacs; // indices [y][j] where j is same as in [1, (4.5)]
|
||||
// TODO probably normalisation and equatorial legendre polynomials should be included, too
|
||||
|
@ -88,8 +88,8 @@ int ewald32_sigma0(complex double *result, double *err,
|
|||
// are not included.
|
||||
|
||||
int ewald32_sigma_long_shiftedpoints_e (
|
||||
complex double *target_sigmalr_y, // must be c->nelem long
|
||||
double *target_sigmalr_y_err, // must be c->nelem long or NULL
|
||||
complex double *target_sigmalr_y, // must be c->nelem_sc long
|
||||
double *target_sigmalr_y_err, // must be c->nelem_sc long or NULL
|
||||
const qpms_ewald32_constants_t *c,
|
||||
double eta, double k, double unitcell_area,
|
||||
size_t npoints, const point2d *Kpoints_plus_beta,
|
||||
|
@ -97,8 +97,8 @@ int ewald32_sigma_long_shiftedpoints_e (
|
|||
point2d particle_shift
|
||||
);
|
||||
int ewald32_sigma_long_points_and_shift (//NI
|
||||
complex double *target_sigmalr_y, // must be c->nelem long
|
||||
double *target_sigmalr_y_err, // must be c->nelem long or NULL
|
||||
complex double *target_sigmalr_y, // must be c->nelem_sc long
|
||||
double *target_sigmalr_y_err, // must be c->nelem_sc long or NULL
|
||||
const qpms_ewald32_constants_t *c,
|
||||
double eta, double k, double unitcell_area,
|
||||
size_t npoints, const point2d *Kpoints,
|
||||
|
@ -106,8 +106,8 @@ int ewald32_sigma_long_points_and_shift (//NI
|
|||
point2d particle_shift
|
||||
);
|
||||
int ewald32_sigma_long_shiftedpoints_rordered(//NI
|
||||
complex double *target_sigmalr_y, // must be c->nelem long
|
||||
double *target_sigmalr_y_err, // must be c->nelem long or NULL
|
||||
complex double *target_sigmalr_y, // must be c->nelem_sc long
|
||||
double *target_sigmalr_y_err, // must be c->nelem_sc long or NULL
|
||||
const qpms_ewald32_constants_t *c,
|
||||
double eta, double k, double unitcell_area,
|
||||
const points2d_rordered_t *Kpoints_plus_beta_rordered,
|
||||
|
@ -115,8 +115,8 @@ int ewald32_sigma_long_shiftedpoints_rordered(//NI
|
|||
);
|
||||
|
||||
int ewald32_sigma_short_shiftedpoints(
|
||||
complex double *target_sigmasr_y, // must be c->nelem long
|
||||
double *target_sigmasr_y_err, // must be c->nelem long or NULL
|
||||
complex double *target_sigmasr_y, // must be c->nelem_sc long
|
||||
double *target_sigmasr_y_err, // must be c->nelem_sc long or NULL
|
||||
const qpms_ewald32_constants_t *c, // N.B. not too useful here
|
||||
double eta, double k,
|
||||
size_t npoints, const point2d *Rpoints_plus_particle_shift,
|
||||
|
@ -124,16 +124,16 @@ int ewald32_sigma_short_shiftedpoints(
|
|||
point2d particle_shift // used only in the very end to multiply it by the phase
|
||||
);
|
||||
int ewald32_sigma_short_points_and_shift(//NI
|
||||
complex double *target_sigmasr_y, // must be c->nelem long
|
||||
double *target_sigmasr_y_err, // must be c->nelem long or NULL
|
||||
complex double *target_sigmasr_y, // must be c->nelem_sc long
|
||||
double *target_sigmasr_y_err, // must be c->nelem_sc long or NULL
|
||||
const qpms_ewald32_constants_t *c, // N.B. not too useful here
|
||||
double eta, double k,
|
||||
size_t npoints, const point2d *Rpoints,
|
||||
point2d particle_shift
|
||||
);
|
||||
int ewald32_sigma_short_points_rordered(//NI
|
||||
complex double *target_sigmasr_y, // must be c->nelem long
|
||||
double *target_sigmasr_y_err, // must be c->nelem long or NULL
|
||||
complex double *target_sigmasr_y, // must be c->nelem_sc long
|
||||
double *target_sigmasr_y_err, // must be c->nelem_sc long or NULL
|
||||
const qpms_ewald32_constants_t *c, // N.B. not too useful here
|
||||
double eta, double k,
|
||||
const points2d_rordered_t *Rpoints_plus_particle_shift_rordered,
|
||||
|
|
|
@ -25,4 +25,28 @@ static inline qpms_y_t qpms_lMax2nelem(qpms_l_t lmax){
|
|||
return lmax * ((qpms_y_t)lmax + 2);
|
||||
}
|
||||
|
||||
// Scalar versions: they have a place for the 0, 0 term in the beginning
|
||||
|
||||
static inline qpms_y_t qpms_mn2y_sc(qpms_m_t m, qpms_l_t n) {
|
||||
return n * (n + 1) + m;
|
||||
}
|
||||
|
||||
static inline qpms_lm_t qpms_y2n_sc(qpms_y_t y) {
|
||||
//return (sqrt(5+y)-2)/2; // the cast will truncate the fractional part, which is what we want
|
||||
return sqrt(y);
|
||||
}
|
||||
|
||||
static inline qpms_m_t qpms_yn2m_sc(qpms_y_t y, qpms_l_t n) {
|
||||
return y-qpms_mn2y_sc(0,n);
|
||||
}
|
||||
|
||||
static inline void qpms_y2mn_sc_p(qpms_y_t y, qpms_m_t *m, qpms_l_t *n){
|
||||
*m=qpms_yn2m_sc(y,*n=qpms_y2n_sc(y));
|
||||
}
|
||||
|
||||
static inline qpms_y_t qpms_lMax2nelem_sc(qpms_l_t lmax){
|
||||
return lmax * ((qpms_y_t)lmax + 2) + 1;
|
||||
}
|
||||
|
||||
|
||||
#endif //QPMS_INDEXING_H
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
// implementation of the [LT(4.16)] test
|
||||
|
||||
#include <qpms/ewald.h>
|
||||
|
||||
typedef struct ewaldtest_hex_params {
|
||||
qpms_l_t lMax;
|
||||
poinnt2d beta;
|
||||
double k;
|
||||
double h;
|
||||
double eta;
|
||||
} ewaldtest_hex_params;
|
||||
|
||||
|
||||
ewaldtest_hex_paraps paramslist = {
|
||||
{ 3, {1.1, 0.23}, 2.3, 0.97, 0.3},
|
||||
// end:
|
||||
{ 0, {0, 0}, 0, 0, 0}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue