2019-07-11 21:51:06 +03:00
|
|
|
|
/*! \file translations.h
|
|
|
|
|
* \brief VSWF translation operator.
|
|
|
|
|
*
|
|
|
|
|
* ### Argument conventions
|
2018-09-03 19:49:33 +03:00
|
|
|
|
*
|
|
|
|
|
* A single wave with indices mu, nu is re-expanded at kdlj into waves with indices m, n,
|
|
|
|
|
* i.e. in the following functions, the first arguments over which one sums (multiplied
|
|
|
|
|
* by the waves with new origin).
|
|
|
|
|
*
|
|
|
|
|
* HOWEVER, this means that if a field has an expansion with coeffs a(mu, nu)
|
|
|
|
|
* at the original origin, with the basis at the new origin, the coeffs will be
|
|
|
|
|
* a(m, n) = \sum_{mu,nu} A(m, n, mu, nu) a(mu, nu).
|
|
|
|
|
*
|
|
|
|
|
* With qpms_trans_calculator_get_AB_arrays_buf (and other functions from *AB_arrays*
|
|
|
|
|
* family), one can choose the stride. And it seems that the former stride argument (now called
|
|
|
|
|
* destride) and the latter (now called srcstride) are connected to (m,n) and (mu,nu) indices,
|
|
|
|
|
* respectively. Seems consistent.
|
|
|
|
|
*
|
2019-07-11 21:51:06 +03:00
|
|
|
|
*
|
|
|
|
|
* #### r_ge_d argument:
|
2018-09-19 06:12:35 +03:00
|
|
|
|
*
|
|
|
|
|
* If r_ge_d == true, the translation coefficients are calculated using regular bessel functions,
|
|
|
|
|
* regardless of what J argument is.
|
|
|
|
|
*
|
2019-07-11 21:51:06 +03:00
|
|
|
|
*
|
2018-09-19 06:12:35 +03:00
|
|
|
|
*/
|
2019-07-11 21:51:06 +03:00
|
|
|
|
#ifndef QPMS_TRANSLATIONS_H
|
|
|
|
|
#define QPMS_TRANSLATIONS_H
|
2022-03-30 09:47:06 +03:00
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-07-11 21:51:06 +03:00
|
|
|
|
#include "vectors.h"
|
|
|
|
|
#include "qpms_types.h"
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
|
|
#if defined LATTICESUMS32 || defined LATTICESUMS31
|
|
|
|
|
#include "ewald.h"
|
|
|
|
|
#endif
|
2018-09-19 06:12:35 +03:00
|
|
|
|
|
2017-04-19 17:43:24 +03:00
|
|
|
|
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double qpms_trans_single_A(qpms_normalisation_t norm, qpms_m_t m, qpms_l_t n, qpms_m_t mu, qpms_l_t nu, csph_t kdlj,
|
2018-05-06 22:13:10 +03:00
|
|
|
|
bool r_ge_d, qpms_bessel_t J);
|
2018-02-08 05:01:41 +02:00
|
|
|
|
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double qpms_trans_single_B(qpms_normalisation_t norm, qpms_m_t m, qpms_l_t n, qpms_m_t mu, qpms_l_t nu, csph_t kdlj,
|
2018-05-06 22:13:10 +03:00
|
|
|
|
bool r_ge_d, qpms_bessel_t J);
|
2018-02-08 05:01:41 +02:00
|
|
|
|
|
2019-07-11 21:51:06 +03:00
|
|
|
|
/// Structure holding the constant factors in normalisation operators.
|
|
|
|
|
/**
|
|
|
|
|
* The VSWF translation operator elements are rather complicated linear
|
|
|
|
|
* combinations of Bessel functions and spherical harmonics.
|
|
|
|
|
* The preceding factors are rather complicated but need to be calculated
|
|
|
|
|
* (for a single normalisation convention)
|
|
|
|
|
* only once and then recycled during the operator evaluation for different
|
|
|
|
|
* translations.
|
|
|
|
|
*
|
|
|
|
|
* This structure is initialised with qpms_trans_calculator_t() and
|
|
|
|
|
* holds all the constant factors up to a truncation
|
|
|
|
|
* degree \a lMax.
|
|
|
|
|
*
|
|
|
|
|
* The destructor function is qpms_trans_calculator_free().
|
|
|
|
|
*
|
|
|
|
|
* If Ewald sums are enabled at build, it also holds the constant
|
|
|
|
|
* factors useful for lattice sums of translation operator.
|
|
|
|
|
*/
|
2017-04-20 16:25:28 +03:00
|
|
|
|
typedef struct qpms_trans_calculator {
|
2018-05-06 22:13:10 +03:00
|
|
|
|
qpms_normalisation_t normalisation;
|
|
|
|
|
qpms_l_t lMax;
|
|
|
|
|
qpms_y_t nelem;
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double **A_multipliers;
|
|
|
|
|
_Complex double **B_multipliers;
|
2018-02-07 15:39:41 +02:00
|
|
|
|
#if 0
|
|
|
|
|
// Normalised values of the Legendre functions and derivatives
|
|
|
|
|
// for θ == π/2, i.e. for the 2D case.
|
|
|
|
|
double *leg0;
|
|
|
|
|
double *pi0;
|
|
|
|
|
double *tau0;
|
|
|
|
|
// Spherical Bessel function coefficients:
|
|
|
|
|
// TODO
|
|
|
|
|
#endif
|
2018-09-19 06:12:35 +03:00
|
|
|
|
|
2018-11-14 08:37:59 +02:00
|
|
|
|
#if defined LATTICESUMS32 || defined LATTICESUMS31
|
2019-04-03 16:41:10 +03:00
|
|
|
|
qpms_ewald3_constants_t *e3c;
|
2018-05-14 09:16:39 +03:00
|
|
|
|
#endif
|
2018-09-02 06:19:50 +03:00
|
|
|
|
double *legendre0; // Zero-argument Legendre functions – this might go outside #ifdef in the end...
|
2017-04-20 16:25:28 +03:00
|
|
|
|
} qpms_trans_calculator;
|
|
|
|
|
|
2019-07-11 21:51:06 +03:00
|
|
|
|
/// Initialise a qpms_trans_calculator_t instance for a given convention and truncation degree.
|
|
|
|
|
qpms_trans_calculator *qpms_trans_calculator_init(qpms_l_t lMax, ///< Truncation degree.
|
|
|
|
|
qpms_normalisation_t nt
|
|
|
|
|
);
|
|
|
|
|
/// Destructor for qpms_trans_calculator_t.
|
2017-04-20 16:25:28 +03:00
|
|
|
|
void qpms_trans_calculator_free(qpms_trans_calculator *);
|
|
|
|
|
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double qpms_trans_calculator_get_A(const qpms_trans_calculator *c,
|
2019-11-06 18:13:50 +02:00
|
|
|
|
qpms_m_t m, qpms_l_t n, qpms_m_t mu, qpms_l_t nu, csph_t kdlj,
|
2017-04-25 22:14:41 +03:00
|
|
|
|
bool r_ge_d, qpms_bessel_t J);
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double qpms_trans_calculator_get_B(const qpms_trans_calculator *c,
|
2019-11-06 18:13:50 +02:00
|
|
|
|
qpms_m_t m, qpms_l_t n, qpms_m_t mu, qpms_l_t nu, csph_t kdlj,
|
2018-02-07 15:39:41 +02:00
|
|
|
|
bool r_ge_d, qpms_bessel_t J);
|
|
|
|
|
int qpms_trans_calculator_get_AB_p(const qpms_trans_calculator *c,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double *Adest, _Complex double *Bdest,
|
2019-11-06 18:13:50 +02:00
|
|
|
|
qpms_m_t m, qpms_l_t n, qpms_m_t mu, qpms_l_t nu, csph_t kdlj,
|
2017-04-25 22:14:41 +03:00
|
|
|
|
bool r_ge_d, qpms_bessel_t J);
|
2018-02-07 15:39:41 +02:00
|
|
|
|
int qpms_trans_calculator_get_AB_arrays(const qpms_trans_calculator *c,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double *Adest, _Complex double *Bdest,
|
2018-02-07 15:39:41 +02:00
|
|
|
|
size_t deststride, size_t srcstride,
|
2019-11-06 18:13:50 +02:00
|
|
|
|
csph_t kdlj, bool r_ge_d, qpms_bessel_t J);
|
2017-04-26 14:12:29 +03:00
|
|
|
|
|
2018-02-07 15:39:41 +02:00
|
|
|
|
// TODO update the types later
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double qpms_trans_calculator_get_A_ext(const qpms_trans_calculator *c,
|
|
|
|
|
int m, int n, int mu, int nu, _Complex double kdlj_r,
|
2017-04-26 14:12:29 +03:00
|
|
|
|
double kdlj_th, double kdlj_phi, int r_ge_d, int J);
|
2018-02-07 15:39:41 +02:00
|
|
|
|
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double qpms_trans_calculator_get_B_ext(const qpms_trans_calculator *c,
|
|
|
|
|
int m, int n, int mu, int nu, _Complex double kdlj_r,
|
2017-04-26 14:12:29 +03:00
|
|
|
|
double kdlj_th, double kdlj_phi, int r_ge_d, int J);
|
|
|
|
|
|
2017-04-26 14:44:16 +03:00
|
|
|
|
int qpms_trans_calculator_get_AB_p_ext(const qpms_trans_calculator *c,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double *Adest, _Complex double *Bdest,
|
|
|
|
|
int m, int n, int mu, int nu, _Complex double kdlj_r,
|
2017-04-26 14:44:16 +03:00
|
|
|
|
double kdlj_th, double kdlj_phi, int r_ge_d, int J);
|
2017-04-25 22:14:41 +03:00
|
|
|
|
|
2017-05-02 00:18:01 +03:00
|
|
|
|
int qpms_trans_calculator_get_AB_arrays_ext(const qpms_trans_calculator *c,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double *Adest, _Complex double *Bdest,
|
2017-05-02 00:18:01 +03:00
|
|
|
|
size_t deststride, size_t srcstride,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double kdlj_r, double kdlj_theta, double kdlj_phi,
|
2017-05-02 00:18:01 +03:00
|
|
|
|
int r_ge_d, int J);
|
2017-05-03 05:45:14 +03:00
|
|
|
|
|
2019-03-09 09:36:09 +02:00
|
|
|
|
// Convenience functions using VSWF base specs
|
|
|
|
|
qpms_errno_t qpms_trans_calculator_get_trans_array(const qpms_trans_calculator *c,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double *target,
|
2019-03-09 09:36:09 +02:00
|
|
|
|
/// Must be destspec->lMax <= c-> lMax && destspec->norm == c->norm.
|
|
|
|
|
const qpms_vswf_set_spec_t *destspec, size_t deststride,
|
|
|
|
|
/// Must be srcspec->lMax <= c-> lMax && srcspec->norm == c->norm.
|
|
|
|
|
const qpms_vswf_set_spec_t *srcspec, size_t srcstride,
|
2019-11-06 18:13:50 +02:00
|
|
|
|
csph_t kdlj, bool r_ge_d, qpms_bessel_t J);
|
2019-03-09 09:36:09 +02:00
|
|
|
|
|
|
|
|
|
/// Version with \a k and cartesian particle positions
|
2019-07-21 21:14:11 +03:00
|
|
|
|
/// and with automatic \a r_ge_d = `false`.
|
2019-03-09 09:36:09 +02:00
|
|
|
|
qpms_errno_t qpms_trans_calculator_get_trans_array_lc3p(
|
|
|
|
|
const qpms_trans_calculator *c,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double *target,
|
2019-03-09 09:36:09 +02:00
|
|
|
|
/// Must be destspec->lMax <= c-> lMax && destspec->norm == c->norm.
|
|
|
|
|
const qpms_vswf_set_spec_t *destspec, size_t deststride,
|
|
|
|
|
/// Must be srcspec->lMax <= c-> lMax && srcspec->norm == c->norm.
|
|
|
|
|
const qpms_vswf_set_spec_t *srcspec, size_t srcstride,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double k, cart3_t destpos, cart3_t srcpos,
|
2019-07-21 21:14:11 +03:00
|
|
|
|
qpms_bessel_t J
|
2019-03-09 09:36:09 +02:00
|
|
|
|
/// Workspace has to be at least 2 * c->neleme**2 long
|
|
|
|
|
);
|
|
|
|
|
|
2018-09-19 06:12:35 +03:00
|
|
|
|
#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)
|
|
|
|
|
|
2018-12-12 11:40:18 +02:00
|
|
|
|
|
|
|
|
|
int qpms_trans_calculator_get_AB_arrays_e32(const qpms_trans_calculator *c,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double *Adest, double *Aerr,
|
|
|
|
|
_Complex double *Bdest, double *Berr,
|
2018-12-12 11:40:18 +02:00
|
|
|
|
const ptrdiff_t deststride, const ptrdiff_t srcstride,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
const double eta, const _Complex double wavenumber,
|
2018-12-12 11:40:18 +02:00
|
|
|
|
cart2_t b1, cart2_t b2,
|
|
|
|
|
const cart2_t beta,
|
2020-05-31 14:13:56 +03:00
|
|
|
|
const cart3_t particle_shift,
|
2018-12-12 11:40:18 +02:00
|
|
|
|
double maxR, double maxK
|
|
|
|
|
);
|
|
|
|
|
|
2019-11-04 09:38:23 +02:00
|
|
|
|
int qpms_trans_calculator_get_AB_arrays_e32_e(const qpms_trans_calculator *c,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double *Adest, double *Aerr,
|
|
|
|
|
_Complex double *Bdest, double *Berr,
|
2019-11-04 09:38:23 +02:00
|
|
|
|
const ptrdiff_t deststride, const ptrdiff_t srcstride,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
const double eta, const _Complex double wavenumber,
|
2019-11-04 09:38:23 +02:00
|
|
|
|
cart2_t b1, cart2_t b2,
|
|
|
|
|
const cart2_t beta,
|
2020-05-31 14:13:56 +03:00
|
|
|
|
const cart3_t particle_shift,
|
2019-11-04 09:38:23 +02:00
|
|
|
|
double maxR, double maxK,
|
|
|
|
|
qpms_ewald_part parts
|
|
|
|
|
);
|
|
|
|
|
|
2019-09-23 08:59:18 +03:00
|
|
|
|
// Convenience functions using VSWF base specs
|
|
|
|
|
qpms_errno_t qpms_trans_calculator_get_trans_array_e32(const qpms_trans_calculator *c,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double *target, double *err,
|
2019-09-23 08:59:18 +03:00
|
|
|
|
/// Must be destspec->lMax <= c-> lMax && destspec->norm == c->norm.
|
|
|
|
|
const qpms_vswf_set_spec_t *destspec, size_t deststride,
|
|
|
|
|
/// Must be srcspec->lMax <= c-> lMax && srcspec->norm == c->norm.
|
|
|
|
|
const qpms_vswf_set_spec_t *srcspec, size_t srcstride,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
const double eta, const _Complex double wavenumber,
|
2019-09-23 08:59:18 +03:00
|
|
|
|
cart2_t b1, cart2_t b2,
|
|
|
|
|
const cart2_t beta,
|
2020-05-31 14:13:56 +03:00
|
|
|
|
const cart3_t particle_shift,
|
2019-09-23 08:59:18 +03:00
|
|
|
|
double maxR, double maxK
|
|
|
|
|
);
|
|
|
|
|
|
2019-11-04 09:38:23 +02:00
|
|
|
|
qpms_errno_t qpms_trans_calculator_get_trans_array_e32_e(const qpms_trans_calculator *c,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double *target, double *err,
|
2019-11-04 09:38:23 +02:00
|
|
|
|
/// Must be destspec->lMax <= c-> lMax && destspec->norm == c->norm.
|
|
|
|
|
const qpms_vswf_set_spec_t *destspec, size_t deststride,
|
|
|
|
|
/// Must be srcspec->lMax <= c-> lMax && srcspec->norm == c->norm.
|
|
|
|
|
const qpms_vswf_set_spec_t *srcspec, size_t srcstride,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
const double eta, const _Complex double wavenumber,
|
2019-11-04 09:38:23 +02:00
|
|
|
|
cart2_t b1, cart2_t b2,
|
|
|
|
|
const cart2_t beta,
|
2020-05-31 14:13:56 +03:00
|
|
|
|
const cart3_t particle_shift,
|
2019-11-04 09:38:23 +02:00
|
|
|
|
double maxR, double maxK,
|
|
|
|
|
qpms_ewald_part parts
|
|
|
|
|
);
|
|
|
|
|
|
2018-09-19 06:12:35 +03:00
|
|
|
|
#endif //LATTICESUMS32
|
|
|
|
|
|
2018-11-14 08:37:59 +02:00
|
|
|
|
#ifdef LATTICESUMS31
|
|
|
|
|
// e31z means that the particles are positioned along the z-axis;
|
|
|
|
|
// their positions and K-values are then denoted by a single z-coordinate
|
2019-04-03 16:41:10 +03:00
|
|
|
|
int qpms_trans_calculator_get_AB_arrays_e31z_both_points_and_shift(const qpms_trans_calculator *c,
|
2022-03-30 09:06:47 +03:00
|
|
|
|
_Complex double *Adest, double *Aerr,
|
|
|
|
|
_Complex double *Bdest, double *Berr,
|
2018-11-14 08:37:59 +02:00
|
|
|
|
const ptrdiff_t deststride, const ptrdiff_t srcstride,
|
|
|
|
|
const double eta, const double k,
|
|
|
|
|
const double unitcell_area, // just lattice period
|
|
|
|
|
const size_t nRpoints, const cart2_t *Rpoints,
|
|
|
|
|
const size_t nKpoints, const cart2_t *Kpoints,
|
|
|
|
|
const double beta,
|
|
|
|
|
const double particle_shift
|
|
|
|
|
);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2018-09-19 06:12:35 +03:00
|
|
|
|
|
2018-05-14 09:16:39 +03:00
|
|
|
|
|
2017-05-03 05:45:14 +03:00
|
|
|
|
#ifdef QPMS_COMPILE_PYTHON_EXTENSIONS
|
2017-05-03 08:43:29 +03:00
|
|
|
|
#include <Python.h>
|
2017-05-03 05:45:14 +03:00
|
|
|
|
#include <numpy/npy_common.h>
|
|
|
|
|
int qpms_cython_trans_calculator_get_AB_arrays_loop(
|
2018-05-06 22:13:10 +03:00
|
|
|
|
const qpms_trans_calculator *c, qpms_bessel_t J, const int resnd,
|
|
|
|
|
int daxis, int saxis,
|
|
|
|
|
char *A_data, const npy_intp *A_shape, const npy_intp *A_strides,
|
|
|
|
|
char *B_data, const npy_intp *B_shape, const npy_intp *B_strides,
|
|
|
|
|
const char *r_data, const npy_intp *r_shape, const npy_intp *r_strides,
|
|
|
|
|
const char *theta_data, const npy_intp *theta_shape, const npy_intp *theta_strides,
|
|
|
|
|
const char *phi_data, const npy_intp *phi_shape, const npy_intp *phi_strides,
|
|
|
|
|
const char *r_ge_d_data, const npy_intp *r_ge_d_shape, const npy_intp *r_ge_d_strides);
|
2017-05-03 05:45:14 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif //QPMS_COMPILE_PYTHON_EXTENSIONS
|
|
|
|
|
|
2017-04-25 22:14:41 +03:00
|
|
|
|
|
2022-03-30 09:47:06 +03:00
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2017-04-12 14:17:07 +03:00
|
|
|
|
#endif // QPMS_TRANSLATIONS_H
|