Ewald A, B coefficient calculator (for arrays).

Former-commit-id: ae5fffb48a91a70dfd89c8caa82914801250dcd3
This commit is contained in:
Marek Nečada 2018-09-19 03:12:35 +00:00
parent f660107925
commit 803f1525b4
3 changed files with 226 additions and 1 deletions

View File

@ -493,6 +493,9 @@ void qpms_trans_calculator_free(qpms_trans_calculator *c) {
free(c->A_multipliers); free(c->A_multipliers);
free(c->B_multipliers[0]); free(c->B_multipliers[0]);
free(c->B_multipliers); free(c->B_multipliers);
#ifdef LATTICESUMS
qpms_ewald32_constants_free(e32c);
#endif
#ifdef LATTICESUMS_OLD #ifdef LATTICESUMS_OLD
free(c->hct); free(c->hct);
#endif #endif
@ -845,7 +848,7 @@ int qpms_trans_calculator_multipliers_B(qpms_normalisation_t norm, complex doubl
} }
qpms_trans_calculator qpms_trans_calculator
*qpms_trans_calculator_init (int lMax, qpms_normalisation_t normalisation) { *qpms_trans_calculator_init (const int lMax, const qpms_normalisation_t normalisation) {
assert(lMax > 0); assert(lMax > 0);
qpms_trans_calculator *c = malloc(sizeof(qpms_trans_calculator)); qpms_trans_calculator *c = malloc(sizeof(qpms_trans_calculator));
c->lMax = lMax; c->lMax = lMax;
@ -907,6 +910,9 @@ qpms_trans_calculator
free(qmaxes); free(qmaxes);
#ifdef LATTICESUMS_OLD #ifdef LATTICESUMS_OLD
c->hct = hankelcoefftable_init(2*lMax+1); c->hct = hankelcoefftable_init(2*lMax+1);
#endif
#ifdef LATTICESUMS32
c->e32c = qpms_ewald32_constants_init(2 * lMax + 1, /*csphase*/ qpms_normalisation_t_csphase(normalisation));
#endif #endif
c->legendre0 = malloc(gsl_sf_legendre_array_n(2*lMax+1) * sizeof(double)); c->legendre0 = malloc(gsl_sf_legendre_array_n(2*lMax+1) * sizeof(double));
if (gsl_sf_legendre_array_e(GSL_SF_LEGENDRE_NONE,2*lMax+1, if (gsl_sf_legendre_array_e(GSL_SF_LEGENDRE_NONE,2*lMax+1,
@ -1149,6 +1155,147 @@ int qpms_trans_calculator_get_AB_arrays(const qpms_trans_calculator *c,
} }
#ifdef LATTICESUMS32
int qpms_trans_calculator_get_AB_arrays_e32_both_points_and_shift(const qpms_trans_calculator *c,
complex double * const Adest, double * const Aerr,
complex double * const Bdest, double * const Berr,
const ptrdiff_t deststride, const ptrdiff_t srcstride,
/* qpms_bessel_t J*/ // assume QPMS_HANKEL_PLUS
const double eta, const double k,
const size_t nRpoints, const cart2_t *Rpoints,
const size_t nKpoints, const cart2_t *Kpoinst,
const cart2_t beta,
const cart2_t particle_shift
)
{
const qpms_y_t nelem2_sc = qpms_lMax2nelem_sc(c->e32c->lMax);
const qpms_y_t nelem = qpms_lMax2nelem(c->lMax);
const bool doerr = Aerr || Berr;
const bool do_sigma0 = ((particle_shift.x == 0) && (particle_shift.y == 0)); // FIXME ignoring the case where particle_shift equals to lattice vector
complex double *sigmas_short = malloc(sizeof(complex double)*nelem2_sc);
complex double *sigmas_long = malloc(sizeof(complex double)*nelem2_sc);
complex double *sigmas_total = malloc(sizeof(complex double)*nelem_sc);
double *serr_short, *serr_long, *serr_total;
if(doerr) {
serr_short = malloc(sizeof(double)*nelem2_sc);
serr_long = malloc(sizeof(double)*nelem2_sc);
serr_total = malloc(sizeof(double)*nelem2_sc);
} else serr_short = serr_long = serr_total = NULL;
int retval;
retval = ewald32_sigma_long_points_and_shift(sigmas_long, serr_long,
c->e32c, eta, k, nKpoints, Kpoints, beta, particle_shift);
if (retval) abort();
retval = ewald32_sigma_short_points_and_shift(sigmas_short, serr_short,
c->e32c, eta, k, nRpoints, Rpoints, beta, particle_shift);
if (retval) abort();
for(qpms_y_t y = 0; y < nelem2_sc; ++y)
sigmas_total[y] = sigmas_short[y] + sigmas_long[y];
if (doerr) for(qpms_y_t y = 0; y < nelem2_sc; ++y)
serr_total[y] = serr_short[y] + serr_long[y];
complex double sigma0 = 0; double sigma0_err = 0;
if (do_sigma0) {
retval = ewald32_sigma0(&sigma0, &sigma0_err, c->e32c, eta, k);
if(retval) abort();
const qpms_l_t y = qpms_mn2y_sc(0,0);
sigmas_total[y] += sigma0;
if(doerr) serr_total[y] += sigma0_err;
}
switch(qpms_normalisation_t_normonly(c->normalisation)) {
case QPMS_NORMALISATION_TAYLOR:
case QPMS_NORMALISATION_POWER:
case QPMS_NORMALISATION_NONE:
{
ptrdiff_t desti = 0, srci = 0;
for (qpms_l_t n = 1; n <= c->lMax; ++n) for (qpms_m_t m = -n; m <= n; ++m) {
for (qpms_l_t nu = 1; nu <= c->lMax; ++nu) for (qpms_m_t mu = -nu; mu <= nu; ++mu){
const size_t i = qpms_trans_calculator_index_mnmu(c, m, n, mu, nu);
const size_t qmax = c->A_multipliers[i+1] - c->A_multipliers[i] - 1;
complex double Asum, Asumc; ckahaninit(&Asum, &Asumc);
double Asumerr, Asumerrc; if(Aerr) kahaninit(&Asumerr, &Asumerrc);
const qpms_m_t mu_m = mu - m;
// TODO skip if ...
for(qpms_l_t q = 0; q <= qmax; ++q) {
const qpms_l_t p = n + nu - 2*q;
const qpms_y_t y_sc = qpms_mn2y_sc(mu_m, p);
const complex double multiplier = c->A_multipliers[i][q];
complex double sigma = sigmas_total[y_sc];
ckahanadd(&Asum, &Asumc, multiplier * sigma);
if (Aerr) kahanadd(&Asumerr, &Asumerrc, multiplier * serr_total[y_sc]);
}
*(Adest + deststride * desti + srcstride * srci) = Asum;
if (Aerr) *(Aerr + deststride * desti + srcstride * srci) = Asumerr;
// TODO skip if ...
complex double Bsum, Bsumc; ckahaninit(&Bsum, &Bsumc);
double Bsumerr, Bsumerrc; if(Berr) kahaninit(&Bsumerr, &Bsumerrc);
for(qpms_l_t q = 0; q <= qmax; ++q) {
const qpms_l_t p_ = n + nu - 2*q + 1;
const qpms_y_t y_sc = qpms_mn2y_sc(mu_m, p_);
const complex double multiplier = c->A_multipliers[i][q-BQ_OFFSET];
complex double sigma = sigmas_total[y_sc];
ckahanadd(&Bsum, &Bsumc, multiplier * sigma);
if (Berr) kahanadd(&Bsumerr, &Bsumerrc, multiplier * serr_total[y_sc]);
}
*(Bdest + deststride * desti + srcstride * srci) = Bsum;
if (Berr) *(Berr + deststride * desti + srcstride * srci) = Bsumerr;
++srci;
}
++desti;
srci = 0;
}
}
break;
default:
abort()
}
free(sigmas_short);
free(sigmas_long);
free(sigmas_total);
if(doerr) {
free(serr_short);
free(serr_long);
free(serr_total);
}
return 0;
}
#if 0
int qpms_trans_calculator_e32_long_points_and_shift(const qpms_trans_calculator *c,
complex double *Adest_long, double *Aerr_long,
complex double *Bdest_long, double *Berr_long,
double eta, double k, double unitcell_area,
size_t npoints, const cart2_t *Kpoints,
cart2_t beta,
cart2_t particle_shift
)
{
}
int qpms_trans_calculator_e32_short_points_and_shift(const qpms_trans_calculator *c,
complex double *Adest_short, double *Aerr_short,
complex double *Bdest_short, double *Berr_short,
double eta, double k,
size_t npoints, const cart2_t *Rpoints,
cart2_t beta,
cart2_t particle_shift
};
#endif // 0
#endif // LATTICESUMS32
#ifdef LATTICESUMS_OLD #ifdef LATTICESUMS_OLD
int qpms_trans_calculator_get_shortrange_AB_arrays_buf(const qpms_trans_calculator *c, int qpms_trans_calculator_get_shortrange_AB_arrays_buf(const qpms_trans_calculator *c,

View File

@ -10,6 +10,10 @@
#include "bessels.h" #include "bessels.h"
#endif #endif
#ifdef LATTICESUMS32
#include "ewald.h"
#endif
/* /*
* Argument conventions: * Argument conventions:
@ -29,6 +33,15 @@
* *
*/ */
/*
* r_ge_d argument:
*
* If r_ge_d == true, the translation coefficients are calculated using regular bessel functions,
* regardless of what J argument is.
*
*/
// TODO replace the xplicit "Taylor" functions with general, // TODO replace the xplicit "Taylor" functions with general,
// taking qpms_normalisation_t argument. // taking qpms_normalisation_t argument.
complex double qpms_trans_single_A_Taylor(qpms_m_t m, qpms_l_t n, qpms_m_t mu, qpms_l_t nu, sph_t kdlj, complex double qpms_trans_single_A_Taylor(qpms_m_t m, qpms_l_t n, qpms_m_t mu, qpms_l_t nu, sph_t kdlj,
@ -64,6 +77,10 @@ typedef struct qpms_trans_calculator {
// Spherical Bessel function coefficients: // Spherical Bessel function coefficients:
// TODO // TODO
#endif #endif
#ifdef LATTICESUMS32
qpms_ewald32_constants_t *e32c;
#endif
#ifdef LATTICESUMS_OLD #ifdef LATTICESUMS_OLD
complex double *hct; // Hankel function coefficient table complex double *hct; // Hankel function coefficient table
#endif #endif
@ -138,6 +155,45 @@ int qpms_trans_calculator_get_2DFT_longrange_AB_arrays(const qpms_trans_calculat
#endif // LATTICESUMS_OLD #endif // LATTICESUMS_OLD
#ifdef LATTICESUMS32
// for the time being there are only those relatively low-level quick&dirty functions
// according to what has been implemented from ewald.h;
// TODO more high-level functions with more advanced lattice generators etc. (after
// the prerequisities from lattices2d.h are implememted)
#if 0 // NI
int qpms_trans_calculator_e32_long_points_and_shift(const qpms_trans_calculator *c,
complex double *Adest_long, double *Aerr_long,
complex double *Bdest_long, double *Berr_long,
double eta, double k, double unitcell_area,
size_t npoints, const cart2_t *Kpoints,
cart2_t beta,
cart2_t particle_shift
);
int qpms_trans_calculator_e32_short_points_and_shift(const qpms_trans_calculator *c,
complex double *Adest_short, double *Aerr_short,
complex double *Bdest_short, double *Berr_short,
double eta, double k,
size_t npoints, const cart2_t *Rpoints,
cart2_t beta,
cart2_t particle_shift
);
#endif
int qpms_trans_calculator_e32_both_points_and_shift(const qpms_trans_calculator *c,
complex double *Adest, double *Aerr,
complex double *Bdest, double *Berr,
const ptrdiff_t deststride, const ptrdiff_t srcstride,
const double eta, const double k,
const size_t nRpoints, const cart2_t *Rpoints,
const size_t nKpoints, const cart2_t *Kpoinst,
const cart2_t beta,
const cart2_t particle_shift
);
#endif //LATTICESUMS32
#ifdef QPMS_COMPILE_PYTHON_EXTENSIONS #ifdef QPMS_COMPILE_PYTHON_EXTENSIONS
#include <Python.h> #include <Python.h>

View File

@ -111,6 +111,28 @@ ewaldtest_triang_params paramslist[] = {
{ 2, {1.1*0.5,-1.1*0.8}, {0.4,0.25}, 2.3, 0.97, 2.5, 20, 160, 1., TRIANGULAR_VERTICAL}, { 2, {1.1*0.5,-1.1*0.8}, {0.4,0.25}, 2.3, 0.97, 2.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 2, {1.1*0.5,-1.1*0.8}, {0.4,0.25}, 2.3, 0.97, 3.5, 20, 160, 1., TRIANGULAR_VERTICAL}, { 2, {1.1*0.5,-1.1*0.8}, {0.4,0.25}, 2.3, 0.97, 3.5, 20, 160, 1., TRIANGULAR_VERTICAL},
// miniposun
{ 3, {3.1*0.5,-3.1*0.8}, {0.004,0.0025}, 2.3, 0.97, 0.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {3.1*0.5,-3.1*0.8}, {0.004,0.0025}, 2.3, 0.97, 1.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {3.1*0.5,-3.1*0.8}, {0.004,0.0025}, 2.3, 0.97, 2.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {3.1*0.5,-3.1*0.8}, {0.004,0.0025}, 2.3, 0.97, 3.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {1.1*0.5,-1.1*0.8}, {0.004,0.0025}, 2.3, 0.97, 0.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {1.1*0.5,-1.1*0.8}, {0.004,0.0025}, 2.3, 0.97, 1.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {1.1*0.5,-1.1*0.8}, {0.004,0.0025}, 2.3, 0.97, 2.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {1.1*0.5,-1.1*0.8}, {0.004,0.0025}, 2.3, 0.97, 3.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {3.1*0.5,-3.1*0.8}, {-0.004,-0.0025}, 2.3, 0.97, 0.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {3.1*0.5,-3.1*0.8}, {-0.004,-0.0025}, 2.3, 0.97, 1.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {3.1*0.5,-3.1*0.8}, {-0.004,-0.0025}, 2.3, 0.97, 2.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {3.1*0.5,-3.1*0.8}, {-0.004,-0.0025}, 2.3, 0.97, 3.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {1.1*0.5,-1.1*0.8}, {-0.004,-0.0025}, 2.3, 0.97, 0.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {1.1*0.5,-1.1*0.8}, {-0.004,-0.0025}, 2.3, 0.97, 1.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {1.1*0.5,-1.1*0.8}, {-0.004,-0.0025}, 2.3, 0.97, 2.5, 20, 160, 1., TRIANGULAR_VERTICAL},
{ 3, {1.1*0.5,-1.1*0.8}, {-0.004,-0.0025}, 2.3, 0.97, 3.5, 20, 160, 1., TRIANGULAR_VERTICAL},
/* /*