uvswf evaluation with complex kr; ss field ewald done, untested

Former-commit-id: 63048ddf2a9260742510a4fa246a59b8360381ce
This commit is contained in:
Marek Nečada 2019-06-24 17:19:25 +03:00
parent a3f5f98736
commit 37b864effc
4 changed files with 60 additions and 23 deletions

View File

@ -66,7 +66,7 @@ qpms_dbgmsg_flags qpms_dbgmsg_enable(qpms_dbgmsg_flags types);
#define QPMS_ENSURE(x, msg, ...) {if(!(x)) qpms_pr_error_at_flf(__FILE__,__LINE__,__func__,msg, ##__VA_ARGS__); } #define QPMS_ENSURE(x, msg, ...) {if(!(x)) qpms_pr_error_at_flf(__FILE__,__LINE__,__func__,msg, ##__VA_ARGS__); }
#define QPMS_ASSERT(x) {if(!(x)) qpms_pr_error_at_flf(__FILE__,__LINE__,__func__, "Unexpected error. This is most certainly a bug.") #define QPMS_ASSERT(x) {if(!(x)) qpms_pr_error_at_flf(__FILE__,__LINE__,__func__, "Unexpected error. This is most certainly a bug.");}
#define QPMS_NOT_IMPLEMENTED(msg, ...) qpms_pr_error_at_flf(__FILE__,__LINE__,__func__, \ #define QPMS_NOT_IMPLEMENTED(msg, ...) qpms_pr_error_at_flf(__FILE__,__LINE__,__func__, \
"Not implemented:" msg, ##__VA_ARGS__) "Not implemented:" msg, ##__VA_ARGS__)

View File

@ -1461,7 +1461,6 @@ complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR(
return target_packed; return target_packed;
} }
#if 0 // must allow for complex kr in qpms_eval_uvswf
ccart3_t qpms_scatsys_eval_E(const qpms_scatsys_t *ss, ccart3_t qpms_scatsys_eval_E(const qpms_scatsys_t *ss,
const complex double *cvf, const cart3_t where, const complex double *cvf, const cart3_t where,
const complex double k) { const complex double k) {
@ -1485,7 +1484,6 @@ ccart3_t qpms_scatsys_eval_E(const qpms_scatsys_t *ss,
} }
return res; return res;
} }
#endif
#if 0 #if 0
ccart3_t qpms_scatsys_eval_E_irrep(const qpms_scatsys_t *ss, ccart3_t qpms_scatsys_eval_E_irrep(const qpms_scatsys_t *ss,

View File

@ -7,6 +7,7 @@
#include "qpms_specfunc.h" #include "qpms_specfunc.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "qpms_error.h"
qpms_vswf_set_spec_t *qpms_vswf_set_spec_init() { qpms_vswf_set_spec_t *qpms_vswf_set_spec_init() {
@ -150,18 +151,19 @@ void qpms_vswfset_sph_pfree(qpms_vswfset_sph_t *w) {
free(w); free(w);
} }
csphvec_t qpms_vswf_L00(sph_t kdrj, qpms_bessel_t btyp, csphvec_t qpms_vswf_L00(csph_t kr, qpms_bessel_t btyp,
qpms_normalisation_t norm) { qpms_normalisation_t norm) {
QPMS_UNTESTED; QPMS_UNTESTED;
// CHECKME Is it OK to ignore norm?? (Is L_0^0 the same for all conventions?) // CHECKME Is it OK to ignore norm?? (Is L_0^0 the same for all conventions?)
complex double bessel0; complex double bessel0;
QPMS_ENSURE_SUCCESS(qpms_sph_bessel_fill(btyp, 0, kr.r, &bessel0)); QPMS_ENSURE_SUCCESS(qpms_sph_bessel_fill(btyp, 0, kr.r, &bessel0));
return {0.25 * M_2_SQRTPI * bessel0, 0, 0}; csphvec_t result = {0.25 * M_2_SQRTPI * bessel0, 0, 0};
return result;
} }
qpms_errno_t qpms_vswf_fill(csphvec_t *const longtarget, qpms_errno_t qpms_vswf_fill_csph(csphvec_t *const longtarget,
csphvec_t * const mgtarget, csphvec_t * const eltarget, qpms_l_t lMax, csphvec_t * const mgtarget, csphvec_t * const eltarget, qpms_l_t lMax,
sph_t kr, qpms_bessel_t btyp, qpms_normalisation_t norm) { csph_t kr, qpms_bessel_t btyp, qpms_normalisation_t norm) {
assert(lMax >= 1); assert(lMax >= 1);
complex double *bessel = malloc((lMax+1)*sizeof(complex double)); complex double *bessel = malloc((lMax+1)*sizeof(complex double));
if(qpms_sph_bessel_fill(btyp, lMax, kr.r, bessel)) abort(); if(qpms_sph_bessel_fill(btyp, lMax, kr.r, bessel)) abort();
@ -214,6 +216,14 @@ qpms_errno_t qpms_vswf_fill(csphvec_t *const longtarget,
return QPMS_SUCCESS; return QPMS_SUCCESS;
} }
qpms_errno_t qpms_vswf_fill(csphvec_t *const longtarget,
csphvec_t * const mgtarget, csphvec_t * const eltarget, qpms_l_t lMax,
sph_t kr, qpms_bessel_t btyp, qpms_normalisation_t norm) {
csph_t krc = {kr.r, kr.theta, kr.phi};
return qpms_vswf_fill_csph(longtarget, mgtarget, eltarget, lMax,
krc, btyp, norm);
}
// consistency check: this should give the same results as the above function (up to rounding errors) // consistency check: this should give the same results as the above function (up to rounding errors)
qpms_errno_t qpms_vswf_fill_alternative(csphvec_t *const longtarget, csphvec_t * const mgtarget, csphvec_t * const eltarget, qpms_errno_t qpms_vswf_fill_alternative(csphvec_t *const longtarget, csphvec_t * const mgtarget, csphvec_t * const eltarget,
qpms_l_t lMax, sph_t kr, qpms_l_t lMax, sph_t kr,
@ -385,7 +395,7 @@ qpms_errno_t qpms_planewave2vswf_fill_cart(cart3_t wavedir_cart /*allow complex
longcoeff, mgcoeff, elcoeff, lMax, norm); longcoeff, mgcoeff, elcoeff, lMax, norm);
} }
csphvec_t qpms_eval_vswf(sph_t kr, csphvec_t qpms_eval_vswf_csph(csph_t kr,
complex double * const lc, complex double *const mc, complex double *const ec, complex double * const lc, complex double *const mc, complex double *const ec,
qpms_l_t lMax, qpms_bessel_t btyp, qpms_normalisation_t norm) qpms_l_t lMax, qpms_bessel_t btyp, qpms_normalisation_t norm)
{ {
@ -398,7 +408,7 @@ csphvec_t qpms_eval_vswf(sph_t kr,
if(lc) lset = malloc(nelem * sizeof(csphvec_t)); if(lc) lset = malloc(nelem * sizeof(csphvec_t));
if(mc) mset = malloc(nelem * sizeof(csphvec_t)); if(mc) mset = malloc(nelem * sizeof(csphvec_t));
if(ec) eset = malloc(nelem * sizeof(csphvec_t)); if(ec) eset = malloc(nelem * sizeof(csphvec_t));
qpms_vswf_fill(lset, mset, eset, lMax, kr, btyp, norm); qpms_vswf_fill_csph(lset, mset, eset, lMax, kr, btyp, norm);
if(lc) for(qpms_y_t y = 0; y < nelem; ++y) if(lc) for(qpms_y_t y = 0; y < nelem; ++y)
csphvec_kahanadd(&lsum, &lcomp, csphvec_scale(lc[y], lset[y])); csphvec_kahanadd(&lsum, &lcomp, csphvec_scale(lc[y], lset[y]));
if(mc) for(qpms_y_t y = 0; y < nelem; ++y) if(mc) for(qpms_y_t y = 0; y < nelem; ++y)
@ -414,18 +424,24 @@ csphvec_t qpms_eval_vswf(sph_t kr,
return esum; return esum;
} }
csphvec_t qpms_eval_vswf(sph_t kr,
complex double * const lc, complex double *const mc, complex double *const ec,
qpms_l_t lMax, qpms_bessel_t btyp, qpms_normalisation_t norm) {
csph_t krc = {kr.r, kr.theta, kr.phi};
return qpms_eval_vswf_csph(krc, lc, mc, ec, lMax, btyp, norm);
}
csphvec_t qpms_eval_uvswf(const qpms_vswf_set_spec_t *setspec, csphvec_t qpms_eval_uvswf(const qpms_vswf_set_spec_t *bspec,
const complex double *coeffs, const sph_t kr, const complex double *coeffs, const csph_t kr,
const qpms_bessel_t btyp) { const qpms_bessel_t btyp) {
QPMS_UNTESTED; QPMS_UNTESTED;
const qpms_l_t lMax = b->lMax; const qpms_l_t lMax = bspec->lMax;
complex double *cM = NULL, *cN = NULL, *cL = NULL, cL00 = 0; complex double *cM = NULL, *cN = NULL, *cL = NULL, cL00 = 0;
if (b->lMax_L > 0) if (bspec->lMax_L > 0)
QPMS_CRASHING_CALLOC(cL, lMax, sizeof(complex double)); QPMS_CRASHING_CALLOC(cL, lMax, sizeof(complex double));
if (b->lMax_M > 0) if (bspec->lMax_M > 0)
QPMS_CRASHING_CALLOC(cM, lMax, sizeof(complex double)); QPMS_CRASHING_CALLOC(cM, lMax, sizeof(complex double));
if (b->lMax_N > 0) if (bspec->lMax_N > 0)
QPMS_CRASHING_CALLOC(cN, lMax, sizeof(complex double)); QPMS_CRASHING_CALLOC(cN, lMax, sizeof(complex double));
for (size_t i = 0; i < bspec->n; ++i) { for (size_t i = 0; i < bspec->n; ++i) {
if (bspec->ilist[i] == 0) // L00, needs special care if (bspec->ilist[i] == 0) // L00, needs special care
@ -452,10 +468,10 @@ csphvec_t qpms_eval_uvswf(const qpms_vswf_set_spec_t *setspec,
} }
} }
} }
csphvec_t result = qpms_eval_vswf(kr, cL, cM, cN, lMax, btyp, norm); csphvec_t result = qpms_eval_vswf_csph(kr, cL, cM, cN, lMax, btyp, bspec->norm);
free(cM); free(cN); free(cL);
if(cL00) if(cL00)
result = csphvec_add(result, result = csphvec_add(result,
scphvec_scale(cL00, qpms_vswf_L00(kr, btyp, norm))); csphvec_scale(cL00, qpms_vswf_L00(kr, btyp, bspec->norm)));
return result; return result;
} }

View File

@ -42,20 +42,22 @@ static inline ssize_t qpms_vswf_set_spec_find_uvswfi(const qpms_vswf_set_spec_t
return -1; return -1;
} }
/// NOT IMPLEMENTED Evaluates a set of VSWF basis functions at a given point. /// Evaluates a set of VSWF basis functions at a given point.
/** The list of basis wave indices is specified in \a setspec; /** The list of basis wave indices is specified in \a setspec;
* \a setspec->norm must be set as well. * \a setspec->norm must be set as well.
*/ */
qpms_errno_t qpms_uvswf_fill( qpms_errno_t qpms_uvswf_fill(
csphvec_t *const target, csphvec_t *const target, ///< Target array of size at least setspec->n.
const qpms_vswf_set_spec_t *setspec, const qpms_vswf_set_spec_t *setspec,
sph_t evaluation_point, qpms_bessel_t btyp); csph_t kr, ///< Evaluation point.
qpms_bessel_t btyp);
/// Evaluates field specified by SVWF coefficients at a given point. /// Evaluates field specified by SVWF coefficients at a given point.
/** SVWF coefficients in \a coeffs must be ordered according to \a setspec->ilist. /** SVWF coefficients in \a coeffs must be ordered according to \a setspec->ilist.
*/ */
csphvec_t qpms_eval_uvswf(const qpms_vswf_set_spec_t *setspec, csphvec_t qpms_eval_uvswf(const qpms_vswf_set_spec_t *setspec,
const complex double *coeffs, sph_t evaluation_point, const complex double *coeffs, ///< SVWF coefficient vector of size setspec->n.
csph_t kr, ///< Evaluation point.
qpms_bessel_t btyp); qpms_bessel_t btyp);
/// Electric wave N. /// Electric wave N.
@ -86,7 +88,7 @@ qpms_errno_t qpms_legendre_deriv_y_fill(double *where, double *where_deriv, doub
/// Evaluate the zeroth-degree longitudinal VSWF \f$ \mathbf{L}_0^0 \f$. /// Evaluate the zeroth-degree longitudinal VSWF \f$ \mathbf{L}_0^0 \f$.
csphvec_t qpms_vswf_L00( csphvec_t qpms_vswf_L00(
sph_t kdrj, //< VSWF evaluation point. csph_t kdrj, //< VSWF evaluation point.
qpms_bessel_t btyp, qpms_bessel_t btyp,
qpms_normalisation_t norm); qpms_normalisation_t norm);
@ -106,10 +108,28 @@ qpms_errno_t qpms_vswf_fill(
qpms_l_t lMax, //< Maximum multipole degree to be calculated. qpms_l_t lMax, //< Maximum multipole degree to be calculated.
sph_t kdrj, //< VSWF evaluation point. sph_t kdrj, //< VSWF evaluation point.
qpms_bessel_t btyp, qpms_normalisation_t norm); qpms_bessel_t btyp, qpms_normalisation_t norm);
// Should give the same results: for consistency checks // Should give the same results: for consistency checks
qpms_errno_t qpms_vswf_fill_alternative(csphvec_t *resultL, csphvec_t *resultM, csphvec_t *resultN, qpms_l_t lMax, sph_t kdrj, qpms_errno_t qpms_vswf_fill_alternative(csphvec_t *resultL, csphvec_t *resultM, csphvec_t *resultN, qpms_l_t lMax, sph_t kdrj,
qpms_bessel_t btyp, qpms_normalisation_t norm); qpms_bessel_t btyp, qpms_normalisation_t norm);
/// Evaluate VSWFs at a given point from \a l = 1 up to a given degree \a lMax (complex \a kr version).
/**
* The target arrays \a resultL, \a resultM, \a resultN have to be large enough to contain
* \a lMax * (\a lMax + 2) elements. If NULL is passed instead, the corresponding SVWF type
* is not evaluated.
*
* Does not evaluate the zeroth-order wave \f$ \mathbf{L}_0^0 \f$.
* If you need that, use qpms_vswf_L00().
*/
qpms_errno_t qpms_vswf_fill_csph(
csphvec_t *resultL, //< Target array for longitudinal VSWFs.
csphvec_t *resultM, //< Target array for magnetic VSWFs.
csphvec_t *resultN, //< Target array for electric VSWFs.
qpms_l_t lMax, //< Maximum multipole degree to be calculated.
csph_t kdrj, //< VSWF evaluation point.
qpms_bessel_t btyp, qpms_normalisation_t norm);
qpms_errno_t qpms_vecspharm_fill(csphvec_t *const a1target, csphvec_t *const a2target, csphvec_t *const a3target, qpms_errno_t qpms_vecspharm_fill(csphvec_t *const a1target, csphvec_t *const a2target, csphvec_t *const a3target,
qpms_l_t lMax, sph_t dir, qpms_normalisation_t norm); qpms_l_t lMax, sph_t dir, qpms_normalisation_t norm);
qpms_errno_t qpms_vecspharm_dual_fill(csphvec_t *const a1target, csphvec_t *const a2target, csphvec_t *const a3target, qpms_errno_t qpms_vecspharm_dual_fill(csphvec_t *const a1target, csphvec_t *const a2target, csphvec_t *const a3target,
@ -127,6 +147,9 @@ csphvec_t qpms_eval_vswf(sph_t where,
complex double *longcoeffs, complex double *mgcoeffs, complex double *elcoeffs, complex double *longcoeffs, complex double *mgcoeffs, complex double *elcoeffs,
qpms_l_t lMax, qpms_bessel_t btyp, qpms_normalisation_t norm); qpms_l_t lMax, qpms_bessel_t btyp, qpms_normalisation_t norm);
csphvec_t qpms_eval_vswf_csph(csph_t where,
complex double *longcoeffs, complex double *mgcoeffs, complex double *elcoeffs,
qpms_l_t lMax, qpms_bessel_t btyp, qpms_normalisation_t norm);
qpms_vswfset_sph_t *qpms_vswfset_make(qpms_l_t lMax, sph_t kdlj, qpms_vswfset_sph_t *qpms_vswfset_make(qpms_l_t lMax, sph_t kdlj,
qpms_bessel_t btyp, qpms_normalisation_t norm);//NI qpms_bessel_t btyp, qpms_normalisation_t norm);//NI