Evaluate scattered electric fields in 2d-periodic system.

Former-commit-id: 36386215f9d330a3047cb9a294ccc1de55f2121f
This commit is contained in:
Marek Nečada 2020-05-31 14:13:56 +03:00
parent 3046f03734
commit 6009de6fa2
8 changed files with 215 additions and 46 deletions

11
TODO.md
View File

@ -1,11 +1,12 @@
TODO list before public release TODO list before 1.0 release
=============================== ============================
- Tests! - Tests!
- Docs! - Docs!
- Cross section calculations. - Cross section calculations. (Done in some Python scripts.)
- Field calculations. - Field calculations. (Partly done, needs more testing.)
- Complex frequencies, n's, k's. * Also test periodic vs. nonperiodic consistence (big finite lattice + absorbing medium vs. infinite lattice + absorbing medium).
- Complex frequencies, n's, k's. (Mostly done.)
- Transforming point (meta)generators. - Transforming point (meta)generators.
- Check whether moble's quaternions and my - Check whether moble's quaternions and my
quaternions give the same results in tmatrices.py quaternions give the same results in tmatrices.py

View File

@ -158,7 +158,7 @@ qpms_ewald3_constants_t *qpms_ewald3_constants_init(const qpms_l_t lMax /*, cons
// ----- New generation 2D-in-3D constants ------ // ----- New generation 2D-in-3D constants ------
// TODO it is not necessary to treat +|m| and -|m| cases separately // TODO it is not necessary to treat +|m| and -|m| cases separately
// N.B. currently, this is only valid for EWALD32_CONSTANTS_AGNOSTIC (NOT CHECKED!) // N.B. currently, this is only valid for EWALD32_CONSTANTS_AGNOSTIC (NOT CHECKED!)
c->S1_constfacs = malloc(c->nelem_sc * sizeof(complex double *)); c->S1_constfacs = malloc((1+c->nelem_sc) * sizeof(complex double *));
//determine sizes //determine sizes
size_t S1_constfacs_sz = 0; size_t S1_constfacs_sz = 0;
for (qpms_y_t y = 0; y < c->nelem_sc; ++y) { for (qpms_y_t y = 0; y < c->nelem_sc; ++y) {
@ -173,13 +173,14 @@ qpms_ewald3_constants_t *qpms_ewald3_constants_init(const qpms_l_t lMax /*, cons
} }
} }
} }
c->S1_constfacs_base = malloc(S1_constfacs_sz * sizeof(complex double)); c->S1_constfacs_base = malloc(S1_constfacs_sz * sizeof(complex double));
size_t S1_constfacs_sz_cumsum = 0; // second count size_t S1_constfacs_sz_cumsum = 0; // second count
for (qpms_y_t y = 0; y < c->nelem_sc; ++y) { 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); qpms_l_t n; qpms_m_t m; qpms_y2mn_sc_p(y, &m, &n);
const complex double yfactor = -2 * ipow(n+1) * M_SQRTPI const complex double yfactor = -2 * ipow(n+1) * M_SQRTPI
* factorial((n-m)/2) * factorial((n+m)/2); * factorial((n-m)/2) * factorial((n+m)/2);
c->S1_constfacs[y] = c->s1_constfacs_base + S1_constfacs_sz_cumsum; c->S1_constfacs[y] = c->S1_constfacs_base + S1_constfacs_sz_cumsum;
size_t coeffs_per_y = 0; size_t coeffs_per_y = 0;
const qpms_l_t L_M = n - abs(m); const qpms_l_t L_M = n - abs(m);
for(qpms_l_t j = 0; j <= L_M; ++j) { // outer sum for(qpms_l_t j = 0; j <= L_M; ++j) { // outer sum
@ -197,6 +198,7 @@ qpms_ewald3_constants_t *qpms_ewald3_constants_init(const qpms_l_t lMax /*, cons
S1_constfacs_sz_cumsum += coeffs_per_y; S1_constfacs_sz_cumsum += coeffs_per_y;
} }
QPMS_ASSERT(S1_constfacs_sz_cumsum = S1_constfacs_sz); QPMS_ASSERT(S1_constfacs_sz_cumsum = S1_constfacs_sz);
c->S1_constfacs[c->nelem_sc] = c->S1_constfacs_base + S1_constfacs_sz; // For easier limit checks
// ------ the "z-axis constants" ----- // ------ the "z-axis constants" -----
// determine sizes // determine sizes
@ -246,6 +248,8 @@ void qpms_ewald3_constants_free(qpms_ewald3_constants_t *c) {
free(c->legendre_minus1); free(c->legendre_minus1);
free(c->s1_constfacs); free(c->s1_constfacs);
free(c->s1_constfacs_base); free(c->s1_constfacs_base);
free(c->S1_constfacs);
free(c->S1_constfacs_base);
free(c->s1_constfacs_1Dz_base); free(c->s1_constfacs_1Dz_base);
free(c->s1_constfacs_1Dz); free(c->s1_constfacs_1Dz);
free(c->s1_jMaxes); free(c->s1_jMaxes);
@ -347,7 +351,7 @@ int ewald3_21_xy_sigma_long (
double Gamma_pq_err[lMax/2+1]; double Gamma_pq_err[lMax/2+1];
// CHOOSE POINT BEGIN // CHOOSE POINT BEGIN
// TODO mayby PGen_next_sph is not the best coordinate system choice here // TODO maybe PGen_next_sph is not the best coordinate system choice here
while ((pgen_retdata = PGen_next_sph(pgen_K)).flags & PGEN_NOTDONE) { // BEGIN POINT LOOP while ((pgen_retdata = PGen_next_sph(pgen_K)).flags & PGEN_NOTDONE) { // BEGIN POINT LOOP
cart3_t K_pq_cart; cart3_t K_pq_cart;
sph_t beta_pq_sph; sph_t beta_pq_sph;
@ -407,31 +411,62 @@ int ewald3_21_xy_sigma_long (
// and just fetched for each n, m pair // and just fetched for each n, m pair
for(qpms_l_t n = 0; n <= lMax; ++n) for(qpms_l_t n = 0; n <= lMax; ++n)
for(qpms_m_t m = -n; m <= n; ++m) { for(qpms_m_t m = -n; m <= n; ++m) {
if((m+n) % 2 != 0) // odd coefficients are zero. if((particle_shift.z == 0) && ((m+n) % 2 != 0)) // odd coefficients are zero.
continue; continue;
const qpms_y_t y = qpms_mn2y_sc(m, n); const qpms_y_t y = qpms_mn2y_sc(m, n);
size_t constidx = 0; // constants offset
const complex double e_imalpha_pq = cexp(I*m*arg_pq); const complex double e_imalpha_pq = cexp(I*m*arg_pq);
complex double jsum, jsum_c; ckahaninit(&jsum, &jsum_c); 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? double jsum_err, jsum_err_c; kahaninit(&jsum_err, &jsum_err_c); // TODO do I really need to kahan sum errors?
assert((n-abs(m))/2 == c->s1_jMaxes[y]); if (particle_shift.z == 0) { // TODO remove when the general case is stable and tested
for(qpms_l_t j = 0; j <= c->s1_jMaxes[y]/*(n-abs(m))/2*/; ++j) { // FIXME </<= ? assert((n-abs(m))/2 == c->s1_jMaxes[y]);
complex double summand = cpow_0lim_zi(rbeta_pq/k, n-2*j) for(qpms_l_t j = 0; j <= c->s1_jMaxes[y]/*(n-abs(m))/2*/; ++j) { // FIXME </<= ?
* e_imalpha_pq * c->legendre0[gsl_sf_legendre_array_index(n,abs(m))] * min1pow_m_neg(m) // This line can actually go outside j-loop complex double summand = cpow_0lim_zi(rbeta_pq/k, n-2*j)
* cpow(gamma_pq, 2*j-1) // * Gamma_pq[j] bellow (GGG) after error computation * e_imalpha_pq * c->legendre0[gsl_sf_legendre_array_index(n,abs(m))] * min1pow_m_neg(m) // This line can actually go outside j-loop
* c->s1_constfacs[y][j]; * cpow(gamma_pq, 2*j-1) // * Gamma_pq[j] bellow (GGG) after error computation
if(err) { * c->s1_constfacs[y][j];
// FIXME include also other errors than Gamma_pq's relative error if(err) {
kahanadd(&jsum_err, &jsum_err_c, Gamma_pq_err[j] * cabs(summand)); // FIXME include also other errors than Gamma_pq's relative error
kahanadd(&jsum_err, &jsum_err_c, Gamma_pq_err[j] * cabs(summand));
}
summand *= Gamma_pq[j]; // GGG
ckahanadd(&jsum, &jsum_c, summand);
} }
summand *= Gamma_pq[j]; // GGG jsum *= phasefac * factor1d; // PFC
ckahanadd(&jsum, &jsum_c, summand); ckahanadd(target + y, target_c + y, jsum);
}
jsum *= phasefac * factor1d; // PFC
ckahanadd(target + y, target_c + y, jsum);
#ifdef EWALD_AUTO_CUTOFF #ifdef EWALD_AUTO_CUTOFF
kahanadd(&lsum, &lsum_c, cabs(jsum)); kahanadd(&lsum, &lsum_c, cabs(jsum));
#endif #endif
if(err) kahanadd(err + y, err_c + y, jsum_err); if(err) kahanadd(err + y, err_c + y, jsum_err);
} else { // particle_shift.z != 0
const qpms_l_t L_M = n - abs(m);
for(qpms_l_t j = 0; j <= L_M; ++j) { // outer sum
complex double ssum, ssum_c; ckahaninit(&ssum, &ssum_c);
// TODO errors of ssum
// inner sum: j <= s <= min(2*j, n - |m|), s has the same parity as n - |m|
for(qpms_l_t s = j + (L_M - j) % 2;
(s <= 2 * j) && (s <= L_M);
s += 2) {
complex double ssummand = c->S1_constfacs[y][constidx]
* cpow(-k * particle_shift.z, 2*j - s) * cpow_0lim_zi(rbeta_pq / k, n - s);
ckahanadd(&ssum, &ssum_c, ssummand);
++constidx;
}
const complex double jfactor = e_imalpha_pq * Gamma_pq[j] * cpow(gamma_pq, 2*j - 1);
if (err) { // FIXME include also other sources of error than Gamma_pq's relative error
double jfactor_err = Gamma_pq_err[j] * pow(cabs(gamma_pq), 2*j - 1);
kahanadd(&jsum_err, &jsum_err_c, jfactor_err * ssum);
}
complex double jsummand = jfactor * ssum;
ckahanadd(&jsum, &jsum_c, jsummand);
}
jsum *= phasefac; // factor1d not here, off-axis sums not implemented/allowed.
ckahanadd(target + y, target_c + y, jsum);
#ifdef EWALD_AUTO_CUTOFF
kahanadd(&lsum, &lsum_c, cabs(jsum));
#endif
if(err) kahanadd(err + y, err_c + y, jsum_err);
}
} }
#ifndef NDEBUG #ifndef NDEBUG
rbeta_pq_prev = rbeta_pq; rbeta_pq_prev = rbeta_pq;

View File

@ -970,6 +970,30 @@ cdef class _ScatteringSystemAtOmegaK:
return self.sswk.eta return self.sswk.eta
def __set__(self, double eta): def __set__(self, double eta):
self.sswk.eta = eta self.sswk.eta = eta
def scattered_E(self, scatcoeffvector_full, evalpos, btyp=QPMS_HANKEL_PLUS): # TODO DOC!!!
if(btyp != QPMS_HANKEL_PLUS):
raise NotImplementedError("Only first kind Bessel function-based fields are supported")
cdef qpms_bessel_t btyp_c = BesselType(btyp)
evalpos = np.array(evalpos, dtype=float, copy=False)
if evalpos.shape[-1] != 3:
raise ValueError("Last dimension of evalpos has to be 3")
cdef np.ndarray[double,ndim=2] evalpos_a = evalpos.reshape(-1,3)
cdef np.ndarray[dtype=complex, ndim=1] scv = np.array(scatcoeffvector_full, copy=False)
cdef cdouble[::1] scv_view = scv
cdef np.ndarray[complex, ndim=2] results = np.empty((evalpos_a.shape[0],3), dtype=complex)
cdef ccart3_t res
cdef cart3_t pos
cdef size_t i
for i in range(evalpos_a.shape[0]):
pos.x = evalpos_a[i,0]
pos.y = evalpos_a[i,1]
pos.z = evalpos_a[i,2]
res = qpms_scatsyswk_scattered_E(&self.sswk, btyp_c, &scv_view[0], pos)
results[i,0] = res.x
results[i,1] = res.y
results[i,2] = res.z
return results.reshape(evalpos.shape)
cdef class _ScatteringSystemAtOmega: cdef class _ScatteringSystemAtOmega:
''' '''

View File

@ -703,6 +703,8 @@ cdef extern from "scatsystem.h":
const cdouble *f_excitation_vector_full, cart3_t where) const cdouble *f_excitation_vector_full, cart3_t where)
ccart3_t qpms_scatsysw_scattered_E__alt(const qpms_scatsys_at_omega_t *ssw, qpms_bessel_t btyp, ccart3_t qpms_scatsysw_scattered_E__alt(const qpms_scatsys_at_omega_t *ssw, qpms_bessel_t btyp,
const cdouble *f_excitation_vector_full, cart3_t where) const cdouble *f_excitation_vector_full, cart3_t where)
ccart3_t qpms_scatsyswk_scattered_E(const qpms_scatsys_at_omega_k_t *sswk, qpms_bessel_t btyp,
const cdouble *f_excitation_vector_full, cart3_t where)
double qpms_ss_adjusted_eta(const qpms_scatsys_t *ss, cdouble wavenumber, const double *wavevector); double qpms_ss_adjusted_eta(const qpms_scatsys_t *ss, cdouble wavenumber, const double *wavevector);

View File

@ -1232,7 +1232,7 @@ static inline int qpms_ss_ppair_W32xy(const qpms_scatsys_t *ss,
eta, wavenumber, eta, wavenumber,
cart3xy2cart2(ss->per.lattice_basis[0]), cart3xy2cart2(ss->per.lattice_basis[1]), cart3xy2cart2(ss->per.lattice_basis[0]), cart3xy2cart2(ss->per.lattice_basis[1]),
kvector, kvector,
cart2_substract(cart3xy2cart2(ss->p[pdest].pos), cart3xy2cart2(ss->p[psrc].pos)), cart3_substract(ss->p[pdest].pos, ss->p[psrc].pos),
maxR, maxK, parts); maxR, maxK, parts);
} }
@ -2039,6 +2039,7 @@ ccart3_t qpms_scatsys_scattered_E(const qpms_scatsys_t *ss,
ccart3_t qpms_scatsysw_scattered_E(const qpms_scatsys_at_omega_t *ssw, ccart3_t qpms_scatsysw_scattered_E(const qpms_scatsys_at_omega_t *ssw,
qpms_bessel_t btyp, qpms_bessel_t btyp,
const complex double *cvf, const cart3_t where) { const complex double *cvf, const cart3_t where) {
qpms_ss_ensure_nonperiodic_a(ssw->ss, "qpms_scatsyswk_scattered_E()");
return qpms_scatsys_scattered_E(ssw->ss, btyp, ssw->wavenumber, return qpms_scatsys_scattered_E(ssw->ss, btyp, ssw->wavenumber,
cvf, where); cvf, where);
} }
@ -2051,6 +2052,7 @@ ccart3_t qpms_scatsys_scattered_E__alt(const qpms_scatsys_t *ss,
const cart3_t where const cart3_t where
) { ) {
QPMS_UNTESTED; QPMS_UNTESTED;
qpms_ss_ensure_nonperiodic(ss);
ccart3_t res = {0,0,0}; ccart3_t res = {0,0,0};
ccart3_t res_kc = {0,0,0}; // kahan sum compensation ccart3_t res_kc = {0,0,0}; // kahan sum compensation
@ -2108,6 +2110,83 @@ ccart3_t qpms_scatsysw_scattered_E__alt(const qpms_scatsys_at_omega_t *ssw,
cvf, where); cvf, where);
} }
// For periodic lattices, we use directly the "alternative" implementation,
// using translation operator and regular dipole waves at zero
ccart3_t qpms_scatsyswk_scattered_E(const qpms_scatsys_at_omega_k_t *sswk,
qpms_bessel_t btyp,
const complex double *cvf,
const cart3_t where
) {
QPMS_UNTESTED;
if (btyp != QPMS_HANKEL_PLUS)
QPMS_NOT_IMPLEMENTED("Only scattered field with first kind Hankel functions currently implemented.");
const qpms_scatsys_t *ss = sswk->ssw->ss;
if (ss->lattice_dimension != 2)
QPMS_NOT_IMPLEMENTED("Only 2D-periodic lattices implemented");
ccart3_t res = {0,0,0};
ccart3_t res_kc = {0,0,0}; // kahan sum compensation
static const int dipspecn = 3; // We have three basis vectors
// bspec containing only electric dipoles
const qpms_vswf_set_spec_t dipspec = {
.n = dipspecn,
.ilist = (qpms_uvswfi_t[]){
qpms_tmn2uvswfi(QPMS_VSWF_ELECTRIC, -1, 1),
qpms_tmn2uvswfi(QPMS_VSWF_ELECTRIC, 0, 1),
qpms_tmn2uvswfi(QPMS_VSWF_ELECTRIC, +1, 1),
},
.lMax=1, .lMax_M=0, .lMax_N=1, .lMax_L=-1,
.capacity=0,
.norm = ss->c->normalisation,
};
ccart3_t regdipoles_0[dipspecn]; {
const sph_t origin_sph = {.r = 0, .theta = M_PI_2, .phi=0}; // Should work with any theta/phi (TESTWORTHY)
csphvec_t regdipoles_0_sph[dipspecn];
QPMS_ENSURE_SUCCESS(qpms_uvswf_fill(regdipoles_0_sph, &dipspec,
sph2csph(origin_sph), QPMS_BESSEL_REGULAR));
for(int i = 0; i < dipspecn; ++i)
regdipoles_0[i] = csphvec2ccart(regdipoles_0_sph[i], origin_sph);
}
complex double *s; // Translation matrix
QPMS_CRASHING_MALLOC(s, ss->max_bspecn * sizeof(*s) * dipspec.n);
for (qpms_ss_pi_t pi = 0; pi < ss->p_count; ++pi) {
const qpms_vswf_set_spec_t *bspec = qpms_ss_bspec_pi(ss, pi);
const cart3_t particle_pos = ss->p[pi].pos;
const complex double *particle_cv = cvf + ss->fecv_pstarts[pi];
const cart3_t origin_cart = {0, 0, 0};
QPMS_ASSERT(sswk->k[2] == 0); // At least not implemented now
QPMS_ASSERT(ss->per.lattice_basis[0].z == 0);
QPMS_ASSERT(ss->per.lattice_basis[1].z == 0);
// Same choices as in qpms_ss_ppair_W32xy; TODO make it more dynamic
const double maxR = sqrt(ss->per.unitcell_volume) * 64;
const double maxK = 2048 * 2 * M_PI / maxR;
QPMS_ENSURE_SUCCESS(qpms_trans_calculator_get_trans_array_e32(
ss->c, s, NULL,
&dipspec, 1, bspec, dipspecn,
sswk->eta, sswk->ssw->wavenumber,
cart3xy2cart2(ss->per.lattice_basis[0]), cart3xy2cart2(ss->per.lattice_basis[1]),
cart2_from_double_array(sswk->k), cart3_substract(where, particle_pos) /*CHECKSIGN*/,
maxR, maxK));
for(size_t i = 0; i < bspec->n; ++i)
for(size_t j = 0; j < dipspecn; ++j){
ccart3_t summand = ccart3_scale(particle_cv[i] * s[dipspecn*i+j], regdipoles_0[j]);
ckahanadd(&(res.x), &(res_kc.x), summand.x);
ckahanadd(&(res.y), &(res_kc.y), summand.y);
ckahanadd(&(res.z), &(res_kc.z), summand.z);
}
}
free(s);
return res;
}
#if 0 #if 0
ccart3_t qpms_scatsys_scattered_E_irrep(const qpms_scatsys_t *ss, ccart3_t qpms_scatsys_scattered_E_irrep(const qpms_scatsys_t *ss,
qpms_iri_t iri, const complex double *cvr, cart3_t where) { qpms_iri_t iri, const complex double *cvr, cart3_t where) {

View File

@ -708,7 +708,9 @@ complex double *qpms_scatsys_incident_field_vector_irrep_packed(
* *
* \see qpms_scatsysw_scattered_E() * \see qpms_scatsysw_scattered_E()
* *
* Not yet implemented for periodic systems. * \see qpms_scatsyswk_scattered_E() for periodic systems.
*
*
*/ */
ccart3_t qpms_scatsys_scattered_E( ccart3_t qpms_scatsys_scattered_E(
const qpms_scatsys_t *ss, const qpms_scatsys_t *ss,
@ -727,7 +729,7 @@ ccart3_t qpms_scatsys_scattered_E(
* *
* \see qpms_scatsys_scattered_E() * \see qpms_scatsys_scattered_E()
* *
* Not yet implemented for periodic systems. * \see qpms_scatsyswk_scattered_E() for periodic systems.
*/ */
ccart3_t qpms_scatsysw_scattered_E( ccart3_t qpms_scatsysw_scattered_E(
const qpms_scatsys_at_omega_t *ssw, const qpms_scatsys_at_omega_t *ssw,
@ -769,6 +771,25 @@ ccart3_t qpms_scatsysw_scattered_E__alt(
cart3_t evalpoint ///< A point \f$ \vect r \f$, at which the field is evaluated. cart3_t evalpoint ///< A point \f$ \vect r \f$, at which the field is evaluated.
); );
/// Evaluates scattered electric field at a point, given a full vector of scattered field coefficients. (Periodic system.)
/**
* This function evaluates the field \f$ \vect E (\vect r ) \f$, with any
* given vector of the excitation coefficients \f$ \wckcout \f$.
*
* \return Complex electric field at the point defined by \a evalpoint.
*
* \bug Currently implemented only for btyp == QPMS_HANKEL_PLUS.
*
* \see qpms_scatsys_scattered_E(), qpms_scatsysw_scattered_E() for finite systems.
*/
ccart3_t qpms_scatsyswk_scattered_E(
const qpms_scatsys_at_omega_k_t *sswk,
qpms_bessel_t typ, ///< Bessel function kind to use (for scattered fields, use QPMS_HANKEL_PLUS).
const complex double *scatcoeff_full, ///< Full vector of the scattered field coefficients \f$ \wckcout \f$.
cart3_t evalpoint ///< A point \f$ \vect r \f$, at which the field is evaluated.
);
/// Adjusted Ewadl parameter to avoid high-frequency breakdown. /// Adjusted Ewadl parameter to avoid high-frequency breakdown.
// TODO DOC // TODO DOC
double qpms_ss_adjusted_eta(const qpms_scatsys_t *ss, complex double wavenumber, const double wavevector[3]); double qpms_ss_adjusted_eta(const qpms_scatsys_t *ss, complex double wavenumber, const double wavevector[3]);

View File

@ -730,7 +730,7 @@ qpms_errno_t qpms_trans_calculator_get_trans_array_e32_e(const qpms_trans_calcul
const double eta, const complex double k, const double eta, const complex double k,
cart2_t b1, cart2_t b2, cart2_t b1, cart2_t b2,
const cart2_t beta, const cart2_t beta,
const cart2_t particle_shift, const cart3_t particle_shift,
double maxR, double maxK, double maxR, double maxK,
const qpms_ewald_part parts const qpms_ewald_part parts
) )
@ -784,7 +784,7 @@ qpms_errno_t qpms_trans_calculator_get_trans_array_e32(const qpms_trans_calculat
const double eta, const complex double k, const double eta, const complex double k,
cart2_t b1, cart2_t b2, cart2_t b1, cart2_t b2,
const cart2_t beta, const cart2_t beta,
const cart2_t particle_shift, const cart3_t particle_shift,
double maxR, double maxK double maxR, double maxK
) )
{ {
@ -931,7 +931,7 @@ int qpms_trans_calculator_get_AB_arrays_e32_e(const qpms_trans_calculator *c,
const double eta, const complex double k, const double eta, const complex double k,
const cart2_t b1, const cart2_t b2, const cart2_t b1, const cart2_t b2,
const cart2_t beta, const cart2_t beta,
const cart2_t particle_shift, const cart3_t particle_shift,
double maxR, double maxK, double maxR, double maxK,
const qpms_ewald_part parts const qpms_ewald_part parts
) )
@ -940,7 +940,7 @@ int qpms_trans_calculator_get_AB_arrays_e32_e(const qpms_trans_calculator *c,
const qpms_y_t nelem2_sc = qpms_lMax2nelem_sc(c->e3c->lMax); const qpms_y_t nelem2_sc = qpms_lMax2nelem_sc(c->e3c->lMax);
//const qpms_y_t nelem = qpms_lMax2nelem(c->lMax); //const qpms_y_t nelem = qpms_lMax2nelem(c->lMax);
const bool doerr = Aerr || Berr; 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 const bool do_sigma0 = ((particle_shift.x == 0) && (particle_shift.y == 0) && (particle_shift.z == 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_short = malloc(sizeof(complex double)*nelem2_sc);
complex double *sigmas_long = malloc(sizeof(complex double)*nelem2_sc); complex double *sigmas_long = malloc(sizeof(complex double)*nelem2_sc);
@ -972,7 +972,7 @@ int qpms_trans_calculator_get_AB_arrays_e32_e(const qpms_trans_calculator *c,
#else #else
false, false,
#endif #endif
cart22cart3xy(beta), cart22cart3xy(particle_shift))); cart22cart3xy(beta), particle_shift));
if(Kgen.stateData) // PGen not consumed entirely (converged earlier) if(Kgen.stateData) // PGen not consumed entirely (converged earlier)
PGen_destroy(&Kgen); PGen_destroy(&Kgen);
} }
@ -980,11 +980,18 @@ int qpms_trans_calculator_get_AB_arrays_e32_e(const qpms_trans_calculator *c,
if (parts & QPMS_EWALD_SHORT_RANGE) { if (parts & QPMS_EWALD_SHORT_RANGE) {
PGen Rgen = PGen_xyWeb_new(b1, b2, BASIS_RTOL, PGen Rgen = PGen_xyWeb_new(b1, b2, BASIS_RTOL,
#ifdef GEN_RSHIFTEDPOINTS #ifdef GEN_RSHIFTEDPOINTS
cart2_scale(-1 /*CHECKSIGN*/, particle_shift), cart2_scale(-1 /*CHECKSIGN*/, cart3xy2cart2(particle_shift)),
#else #else
CART2_ZERO, CART2_ZERO,
#endif #endif
0, !do_sigma0, maxR, false); 0, !do_sigma0, maxR, false);
#ifdef GEN_RSHIFTEDPOINTS // rather ugly hacks, LPTODO cleanup
if (particle_shift.z != 0) {
const cart3_t zshift = {0, 0, -particle_shift.z /*CHECKSIGN*/};
Rgen = Pgen_shifted_new(Rgen, zshift);
}
#endif
QPMS_ENSURE_SUCCESS(ewald3_sigma_short(sigmas_short, serr_short, c->e3c, eta, k, QPMS_ENSURE_SUCCESS(ewald3_sigma_short(sigmas_short, serr_short, c->e3c, eta, k,
LAT_2D_IN_3D_XYONLY, &Rgen, LAT_2D_IN_3D_XYONLY, &Rgen,
@ -993,7 +1000,7 @@ int qpms_trans_calculator_get_AB_arrays_e32_e(const qpms_trans_calculator *c,
#else #else
false, false,
#endif #endif
cart22cart3xy(beta), cart22cart3xy(particle_shift))); cart22cart3xy(beta), particle_shift));
if(Rgen.stateData) // PGen not consumed entirely (converged earlier) if(Rgen.stateData) // PGen not consumed entirely (converged earlier)
PGen_destroy(&Rgen); PGen_destroy(&Rgen);
@ -1078,7 +1085,7 @@ int qpms_trans_calculator_get_AB_arrays_e32(const qpms_trans_calculator *c,
const double eta, const complex double k, const double eta, const complex double k,
const cart2_t b1, const cart2_t b2, const cart2_t b1, const cart2_t b2,
const cart2_t beta, const cart2_t beta,
const cart2_t particle_shift, const cart3_t particle_shift,
double maxR, double maxK) double maxR, double maxK)
{ {
return qpms_trans_calculator_get_AB_arrays_e32_e( return qpms_trans_calculator_get_AB_arrays_e32_e(

View File

@ -159,10 +159,10 @@ int qpms_trans_calculator_get_AB_arrays_e32(const qpms_trans_calculator *c,
complex double *Adest, double *Aerr, complex double *Adest, double *Aerr,
complex double *Bdest, double *Berr, complex double *Bdest, double *Berr,
const ptrdiff_t deststride, const ptrdiff_t srcstride, const ptrdiff_t deststride, const ptrdiff_t srcstride,
const double eta, const complex double k, const double eta, const complex double wavenumber,
cart2_t b1, cart2_t b2, cart2_t b1, cart2_t b2,
const cart2_t beta, const cart2_t beta,
const cart2_t particle_shift, const cart3_t particle_shift,
double maxR, double maxK double maxR, double maxK
); );
@ -170,10 +170,10 @@ int qpms_trans_calculator_get_AB_arrays_e32_e(const qpms_trans_calculator *c,
complex double *Adest, double *Aerr, complex double *Adest, double *Aerr,
complex double *Bdest, double *Berr, complex double *Bdest, double *Berr,
const ptrdiff_t deststride, const ptrdiff_t srcstride, const ptrdiff_t deststride, const ptrdiff_t srcstride,
const double eta, const complex double k, const double eta, const complex double wavenumber,
cart2_t b1, cart2_t b2, cart2_t b1, cart2_t b2,
const cart2_t beta, const cart2_t beta,
const cart2_t particle_shift, const cart3_t particle_shift,
double maxR, double maxK, double maxR, double maxK,
qpms_ewald_part parts qpms_ewald_part parts
); );
@ -185,10 +185,10 @@ qpms_errno_t qpms_trans_calculator_get_trans_array_e32(const qpms_trans_calculat
const qpms_vswf_set_spec_t *destspec, size_t deststride, const qpms_vswf_set_spec_t *destspec, size_t deststride,
/// Must be srcspec->lMax <= c-> lMax && srcspec->norm == c->norm. /// Must be srcspec->lMax <= c-> lMax && srcspec->norm == c->norm.
const qpms_vswf_set_spec_t *srcspec, size_t srcstride, const qpms_vswf_set_spec_t *srcspec, size_t srcstride,
const double eta, const complex double k, const double eta, const complex double wavenumber,
cart2_t b1, cart2_t b2, cart2_t b1, cart2_t b2,
const cart2_t beta, const cart2_t beta,
const cart2_t particle_shift, const cart3_t particle_shift,
double maxR, double maxK double maxR, double maxK
); );
@ -198,10 +198,10 @@ qpms_errno_t qpms_trans_calculator_get_trans_array_e32_e(const qpms_trans_calcul
const qpms_vswf_set_spec_t *destspec, size_t deststride, const qpms_vswf_set_spec_t *destspec, size_t deststride,
/// Must be srcspec->lMax <= c-> lMax && srcspec->norm == c->norm. /// Must be srcspec->lMax <= c-> lMax && srcspec->norm == c->norm.
const qpms_vswf_set_spec_t *srcspec, size_t srcstride, const qpms_vswf_set_spec_t *srcspec, size_t srcstride,
const double eta, const complex double k, const double eta, const complex double wavenumber,
cart2_t b1, cart2_t b2, cart2_t b1, cart2_t b2,
const cart2_t beta, const cart2_t beta,
const cart2_t particle_shift, const cart3_t particle_shift,
double maxR, double maxK, double maxR, double maxK,
qpms_ewald_part parts qpms_ewald_part parts
); );