2019-02-20 09:57:36 +02:00
|
|
|
|
/*! \file scatsystem.h
|
|
|
|
|
* \brief Modern interface for finite lattice calculations, including symmetries.
|
2019-03-06 19:32:46 +02:00
|
|
|
|
*
|
|
|
|
|
* N.B. Only "reasonably normalised" waves are supported now in most of the
|
|
|
|
|
* functions defined here, i.e. those that can be rotated by the usual
|
|
|
|
|
* Wigner matrices, i.e. the "power" or "spharm" -normalised ones.
|
|
|
|
|
*
|
|
|
|
|
* TODO FIXME check whether Condon-Shortley phase can have some nasty influence
|
|
|
|
|
* here; I fear that yes.
|
2019-02-20 09:57:36 +02:00
|
|
|
|
*/
|
|
|
|
|
#ifndef QPMS_SCATSYSTEM_H
|
|
|
|
|
#define QPMS_SCATSYSTEM_H
|
2019-02-25 18:54:59 +02:00
|
|
|
|
#include "qpms_types.h"
|
2019-07-14 23:00:43 +03:00
|
|
|
|
#include "vswf.h"
|
2020-01-09 16:57:30 +02:00
|
|
|
|
#include "tmatrices.h"
|
2019-02-21 07:18:50 +02:00
|
|
|
|
#include <stdbool.h>
|
2019-02-20 09:57:36 +02:00
|
|
|
|
|
2019-03-26 13:33:22 +02:00
|
|
|
|
/// Overrides the number of threads spawned by the paralellized functions.
|
|
|
|
|
/** TODO MORE DOC which are those? */
|
|
|
|
|
void qpms_scatsystem_set_nthreads(long n);
|
|
|
|
|
|
2019-02-20 09:57:36 +02:00
|
|
|
|
/// A particle, defined by its T-matrix and position.
|
2020-01-15 03:18:21 +02:00
|
|
|
|
/** This is rather only an auxillary intermediate structure to ultimately
|
|
|
|
|
* build an qpms_scatsys_t instance */
|
2019-02-20 09:57:36 +02:00
|
|
|
|
typedef struct qpms_particle_t {
|
|
|
|
|
// Does it make sense to ever use other than cartesian coords for this?
|
|
|
|
|
cart3_t pos; ///< Particle position in cartesian coordinates.
|
2020-01-15 03:18:21 +02:00
|
|
|
|
const qpms_tmatrix_function_t *tmg; ///< T-matrix function; not owned by qpms_particle_t.
|
|
|
|
|
qpms_tmatrix_operation_t op; ///< T-matrix transformation operation w.r.t. \a tmg.
|
2019-02-20 09:57:36 +02:00
|
|
|
|
} qpms_particle_t;
|
|
|
|
|
|
2019-03-18 15:04:21 +02:00
|
|
|
|
struct qpms_finite_group_t;
|
|
|
|
|
typedef struct qpms_finite_group_t qpms_finite_group_t;
|
2019-02-26 15:33:08 +02:00
|
|
|
|
|
|
|
|
|
/// A particle, defined by its T-matrix INDEX and position, to be used in qpms_scatsys_t.
|
|
|
|
|
typedef struct qpms_particle_tid_t {
|
|
|
|
|
// Does it make sense to ever use other than cartesian coords for this?
|
|
|
|
|
cart3_t pos; ///< Particle position in cartesian coordinates.
|
2019-02-27 11:53:33 +02:00
|
|
|
|
qpms_ss_tmi_t tmatrix_id; ///< T-matrix index
|
2019-02-26 15:33:08 +02:00
|
|
|
|
} qpms_particle_tid_t;
|
|
|
|
|
|
|
|
|
|
|
2019-02-27 17:33:46 +02:00
|
|
|
|
typedef qpms_gmi_t qpms_ss_orbit_pi_t; ///< Auxilliary type used in qpms_ss_orbit_type_t for labeling particles inside orbits.
|
2019-02-28 12:09:13 +02:00
|
|
|
|
typedef qpms_ss_tmi_t qpms_ss_oti_t; ///< Auxilliary type used for labeling orbit types.
|
2019-02-27 17:33:46 +02:00
|
|
|
|
|
|
|
|
|
/// Structure describing a particle's "orbit type" under symmetry group actions in a system.
|
|
|
|
|
/**
|
|
|
|
|
* Each particle has its orbit with respect to a symmetry group of the system in which the particle lies,
|
|
|
|
|
* i.e. a set of particles onto which the group operations map the original particle.
|
|
|
|
|
*
|
|
|
|
|
* (TODO DOC improve the following explanation:)
|
|
|
|
|
* Typically, there will be only a small number of different (T-matrix, particle
|
|
|
|
|
* <a href="https://en.wikipedia.org/wiki/Group_action#Fixed_points_and_stabilizer_subgroups">stabiliser</a>)
|
|
|
|
|
* pairs in the system. We can group the particles accordingly, into the same "orbit types"
|
|
|
|
|
* that will allow to do certain operations only once for each "orbit type", saving memory and (perhaps) time.
|
|
|
|
|
*
|
|
|
|
|
* Each particle will then have assigned:
|
|
|
|
|
* 1. an orbit type,
|
|
|
|
|
* 2. an ID inside that orbit.
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* TODO DOC how the process of assigning the particle IDs actually work, orbit type (non-)uniqueness.
|
|
|
|
|
*
|
|
|
|
|
*
|
2019-02-28 09:22:39 +02:00
|
|
|
|
* Memory is managed by qpms_scatspec_t; qpms_ss_orbit_type_t does not own anything.
|
|
|
|
|
*
|
2019-02-27 17:33:46 +02:00
|
|
|
|
*/
|
|
|
|
|
typedef struct qpms_ss_orbit_type_t {
|
2019-03-07 12:15:46 +02:00
|
|
|
|
qpms_ss_orbit_pi_t size; ///< Size of the orbit (a divisor of the group order), i.e. number of particles on the orbit.
|
|
|
|
|
size_t bspecn; ///< Individual particle's coefficient vector length. The same as ss->tm[this.tmatrices[0]]->spec->n.
|
2019-03-04 00:38:00 +02:00
|
|
|
|
/// Action of the group elements onto the elements in this orbit.
|
|
|
|
|
/** Its size is sym->order * this.size
|
|
|
|
|
* and its values lie between 0 and \a this.size − 1.
|
2019-02-27 17:33:46 +02:00
|
|
|
|
*
|
2019-03-04 00:38:00 +02:00
|
|
|
|
* Action of the group element g onto the pi-th particle
|
|
|
|
|
* is given by action[g + pi*sym->order].
|
|
|
|
|
*
|
2019-02-27 17:33:46 +02:00
|
|
|
|
*/
|
|
|
|
|
qpms_ss_orbit_pi_t *action;
|
|
|
|
|
/// T-matrix IDs of the particles on this orbit (type).
|
|
|
|
|
/**
|
|
|
|
|
* We save all the tmi's of the particles on the orbit here to make the number of array lookups
|
|
|
|
|
* and pointer dereferences constant.
|
|
|
|
|
*
|
|
|
|
|
* The size of this array is \a size.
|
|
|
|
|
*/
|
2019-02-28 09:22:39 +02:00
|
|
|
|
qpms_ss_tmi_t *tmatrices;
|
2019-03-07 06:46:19 +02:00
|
|
|
|
/// Sizes of the per-orbit irrep bases.
|
|
|
|
|
/**
|
|
|
|
|
* The order of the irreps corresponds to the order in \a ss->sym->irreps.
|
|
|
|
|
* The size of this array is (obviously) \a ss->sym->nirreps.
|
|
|
|
|
*
|
|
|
|
|
* TODO different type?
|
|
|
|
|
* TODO doc.
|
|
|
|
|
*/
|
|
|
|
|
size_t *irbase_sizes;
|
2019-03-07 12:15:46 +02:00
|
|
|
|
//The following are pretty redundant, TODO reduce them at some point.
|
2019-03-07 06:46:19 +02:00
|
|
|
|
/// Cumulative sums of irbase_sizes.
|
|
|
|
|
size_t *irbase_cumsizes;
|
2019-03-07 12:15:46 +02:00
|
|
|
|
/// TODO doc.
|
|
|
|
|
size_t *irbase_offsets;
|
2019-03-07 06:46:19 +02:00
|
|
|
|
/// Per-orbit irreducible representation orthonormal bases.
|
|
|
|
|
/** This also defines the unitary operator that transforms the orbital excitation coefficients
|
|
|
|
|
* in the symmetry-adapted basis.
|
|
|
|
|
*
|
|
|
|
|
* The size is (\a this->size * \a this->tmatrices[0].spec->n)**2.
|
|
|
|
|
*
|
|
|
|
|
* TODO doc.
|
|
|
|
|
*/
|
|
|
|
|
complex double *irbases;
|
2019-03-07 09:42:49 +02:00
|
|
|
|
/// TODO doc.
|
|
|
|
|
size_t instance_count;
|
2019-03-17 18:46:22 +02:00
|
|
|
|
/// Cumulative sum of the preceding ot->siza * ot->instance_count;
|
|
|
|
|
qpms_ss_pi_t p_offset;
|
2019-02-27 17:33:46 +02:00
|
|
|
|
} qpms_ss_orbit_type_t;
|
|
|
|
|
|
2019-07-23 08:43:25 +03:00
|
|
|
|
|
2019-03-07 12:15:46 +02:00
|
|
|
|
typedef ptrdiff_t qpms_ss_osn_t; ///< "serial number" of av orbit in a given type.
|
|
|
|
|
|
2019-02-27 17:33:46 +02:00
|
|
|
|
/// Auxillary type used in qpms_scatsys_t that identifies the particle's orbit and its id inside that orbit.
|
|
|
|
|
typedef struct qpms_ss_particle_orbitinfo {
|
2019-02-28 12:09:13 +02:00
|
|
|
|
qpms_ss_oti_t t; ///< Orbit type.
|
|
|
|
|
#define QPMS_SS_P_ORBITINFO_UNDEF (-1) ///< This labels that the particle has not yet been assigned to an orbit.
|
2019-03-07 12:15:46 +02:00
|
|
|
|
qpms_ss_osn_t osn; ///< "Serial number" of the orbit in the given type. TODO type and more doc.
|
2019-03-07 06:46:19 +02:00
|
|
|
|
qpms_ss_orbit_pi_t p; ///< Order (sija, ei rankki) of the particle inside that orbit type.
|
2019-02-27 17:33:46 +02:00
|
|
|
|
} qpms_ss_particle_orbitinfo_t;
|
|
|
|
|
|
2020-01-07 16:57:59 +02:00
|
|
|
|
/// Auxillary type used in qpms_scatsys_t: A recepy to create another T-matrices by symmetry operations.
|
2020-01-15 03:18:21 +02:00
|
|
|
|
typedef struct qpms_ss_derived_tmatrix_t {
|
2020-01-07 16:57:59 +02:00
|
|
|
|
qpms_ss_tmgi_t tmgi; ///< Index of the corresponding qpms_scatsys_t::tm element.
|
2020-01-10 11:43:35 +02:00
|
|
|
|
struct qpms_tmatrix_operation_t op; ///< Operation to derive this particular T-matrix.
|
2020-01-07 16:57:59 +02:00
|
|
|
|
} qpms_ss_derived_tmatrix_t;
|
|
|
|
|
|
|
|
|
|
|
2019-03-09 12:55:46 +02:00
|
|
|
|
struct qpms_trans_calculator;
|
2020-01-06 17:01:40 +02:00
|
|
|
|
struct qpms_epsmu_generator_t;
|
2019-02-27 17:33:46 +02:00
|
|
|
|
|
2019-02-21 17:38:43 +02:00
|
|
|
|
typedef struct qpms_scatsys_t {
|
2020-01-09 16:57:30 +02:00
|
|
|
|
struct qpms_epsmu_generator_t medium; ///< Optical properties of the background medium.
|
2020-01-07 16:57:59 +02:00
|
|
|
|
|
|
|
|
|
/// (Template) T-matrix functions in the system.
|
|
|
|
|
/** The qpms_abstract_tmatrix_t objects (onto which this array member point)
|
|
|
|
|
* are NOT owned by this and must be kept alive for the whole lifetime
|
|
|
|
|
* of all qpms_scatsys_t objects that are built upon them.
|
|
|
|
|
*/
|
2020-01-08 16:00:09 +02:00
|
|
|
|
qpms_tmatrix_function_t *tmg;
|
2020-01-07 16:57:59 +02:00
|
|
|
|
qpms_ss_tmgi_t tmg_count; ///< Number of all different original T-matrix generators in the system.
|
|
|
|
|
|
|
|
|
|
/// All the different T-matrix functions in the system, including those derived from \a tmg elements by symmetries.
|
|
|
|
|
qpms_ss_derived_tmatrix_t *tm;
|
|
|
|
|
qpms_ss_tmi_t tm_count; ///< Number of all different T-matrices in the system (length of tm[]).
|
2019-02-27 11:53:33 +02:00
|
|
|
|
qpms_ss_tmi_t tm_capacity; ///< Capacity of tm[].
|
2020-01-07 16:57:59 +02:00
|
|
|
|
|
2019-02-26 15:33:08 +02:00
|
|
|
|
qpms_particle_tid_t *p; ///< Particles.
|
2019-02-27 11:53:33 +02:00
|
|
|
|
qpms_ss_pi_t p_count; ///< Size of particles array.
|
|
|
|
|
qpms_ss_pi_t p_capacity; ///< Capacity of p[].
|
2019-02-26 15:33:08 +02:00
|
|
|
|
|
|
|
|
|
//TODO the index types do not need to be so big.
|
2019-02-28 12:09:13 +02:00
|
|
|
|
const struct qpms_finite_group_t *sym; ///< Symmetry group of the array
|
2019-02-27 11:53:33 +02:00
|
|
|
|
qpms_ss_pi_t *p_sym_map; ///< Which particles map onto which by the symmetry ops.
|
2019-02-26 15:33:08 +02:00
|
|
|
|
///< p_sym_map[idi + pi * sym->order] gives the index of pi-th particle under the idi'th sym op.
|
2019-02-27 11:53:33 +02:00
|
|
|
|
qpms_ss_tmi_t *tm_sym_map; ///< Which t-matrices map onto which by the symmetry ops. Lookup by tm_sum_map[idi + tmi * sym->order].
|
2019-02-27 17:33:46 +02:00
|
|
|
|
|
|
|
|
|
qpms_ss_oti_t orbit_type_count;
|
|
|
|
|
qpms_ss_orbit_type_t *orbit_types; ///< (Array length is \a orbit_type_count.)
|
|
|
|
|
|
2019-02-28 09:22:39 +02:00
|
|
|
|
qpms_ss_particle_orbitinfo_t *p_orbitinfo; ///< Orbit type identification of each particle. (Array length is \a p_count.)
|
2019-02-27 17:33:46 +02:00
|
|
|
|
|
2019-02-27 14:01:21 +02:00
|
|
|
|
size_t fecv_size; ///< Number of elements of a full excitation coefficient vector size.
|
2019-03-07 12:15:46 +02:00
|
|
|
|
size_t *saecv_sizes; ///< Number of elements of symmetry-adjusted coefficient vector sizes (order as in sym->irreps).
|
2019-02-27 14:01:21 +02:00
|
|
|
|
|
|
|
|
|
size_t *fecv_pstarts; ///< Indices of where pi'th particle's excitation coeffs start in a full excitation coefficient vector.
|
2019-03-07 12:15:46 +02:00
|
|
|
|
size_t *saecv_ot_offsets; ///< TODO DOC. In the packed vector, saecv_ot_offsets[iri * orbit_type_count + oti] indicates start of ot
|
|
|
|
|
/**< TODO maybe move it to qpms_ss_orbit_type_t, ffs. */
|
2019-02-27 14:01:21 +02:00
|
|
|
|
//size_t **saecv_pstarts; ///< NI. Indices of where pi'th particle's excitation coeff start in a symmetry-adjusted e.c.v.
|
|
|
|
|
///**< First index is irrep index as in sym->irreps, second index is particle index. */
|
2019-02-26 15:33:08 +02:00
|
|
|
|
|
|
|
|
|
// TODO shifted origin of the symmetry group etc.
|
|
|
|
|
// TODO some indices for fast operations here.
|
|
|
|
|
// private
|
2019-03-07 12:15:46 +02:00
|
|
|
|
size_t max_bspecn; ///< Maximum tm[...]->spec->n. Mainly for workspace allocation.
|
|
|
|
|
|
2019-03-17 18:46:22 +02:00
|
|
|
|
/// Particles grouped by orbit (in the order corresponding to the packed memory layout).
|
|
|
|
|
qpms_ss_pi_t *p_by_orbit;
|
|
|
|
|
|
2019-02-28 09:22:39 +02:00
|
|
|
|
// We keep the p_orbitinfo arrays in this chunk in order to avoid memory fragmentation
|
2019-02-28 12:09:13 +02:00
|
|
|
|
char *otspace;
|
2019-02-28 09:22:39 +02:00
|
|
|
|
char *otspace_end;
|
2019-02-26 15:33:08 +02:00
|
|
|
|
double lenscale; // radius of the array, used as a relative tolerance measure
|
2019-03-09 12:55:46 +02:00
|
|
|
|
struct qpms_trans_calculator *c;
|
2019-02-21 17:38:43 +02:00
|
|
|
|
} qpms_scatsys_t;
|
|
|
|
|
|
2020-01-08 16:00:09 +02:00
|
|
|
|
/// Retrieve the bspec of \a tmi'th element of \a ss->tm.
|
2020-01-10 11:43:35 +02:00
|
|
|
|
static inline const qpms_vswf_set_spec_t *qpms_ss_bspec_tmi(const qpms_scatsys_t *ss, qpms_ss_tmi_t tmi) {
|
2020-01-09 16:57:30 +02:00
|
|
|
|
return ss->tmg[ss->tm[tmi].tmgi].spec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Retrieve the bspec of \a pi'th particle in \a ss->p.
|
2020-01-10 11:43:35 +02:00
|
|
|
|
static inline const qpms_vswf_set_spec_t *qpms_ss_bspec_pi(const qpms_scatsys_t *ss, qpms_ss_pi_t pi) {
|
2020-01-09 16:57:30 +02:00
|
|
|
|
return ss->tmg[ss->tm[ss->p[pi].tmatrix_id].tmgi].spec;
|
2020-01-08 16:00:09 +02:00
|
|
|
|
}
|
2019-12-21 11:36:01 +02:00
|
|
|
|
|
2019-12-19 13:50:12 +02:00
|
|
|
|
typedef struct qpms_scatsys_at_omega_t {
|
2019-12-21 11:36:01 +02:00
|
|
|
|
const qpms_scatsys_t *ss; ///< Parent scattering system.
|
|
|
|
|
/// T-matrices from \a ss, evaluated at \a omega.
|
|
|
|
|
/** The T-matrices are in the same order as in \a ss,
|
2020-01-07 16:57:59 +02:00
|
|
|
|
* i.e in the order corresponding to \a ss->tm.
|
2019-12-21 11:36:01 +02:00
|
|
|
|
*/
|
|
|
|
|
qpms_tmatrix_t **tm;
|
|
|
|
|
complex double omega; ///< Angular frequency
|
2020-01-08 16:00:09 +02:00
|
|
|
|
qpms_epsmu_t medium; ///< Background medium optical properties at the given frequency
|
2019-12-21 11:36:01 +02:00
|
|
|
|
complex double wavenumber; ///< Background medium wavenumber
|
|
|
|
|
} qpms_scatsys_at_omega_t;
|
|
|
|
|
|
2020-01-07 16:57:59 +02:00
|
|
|
|
/// Creates a new scatsys by applying a symmetry group onto a "proto-scatsys", copying particles if needed.
|
|
|
|
|
/** In fact, it copies everything except the vswf set specs and qpms_abstract_tmatrix_t instances,
|
|
|
|
|
* so keep them alive until scatsys is destroyed.
|
|
|
|
|
*
|
|
|
|
|
* The following fields must be filled in the "proto- scattering system" \a orig:
|
2020-01-16 08:51:05 +02:00
|
|
|
|
* * orig->medium – The pointers are copied to the new qpms_scatsys_t instance;
|
2020-01-08 16:00:09 +02:00
|
|
|
|
* the target qpms_abstract_tmatrix_t objects must be kept alive before all the resulting
|
2020-01-15 03:18:21 +02:00
|
|
|
|
* qpms_scatsys_t instances are properly destroyed.
|
2020-01-07 16:57:59 +02:00
|
|
|
|
* * orig->tmg – The pointers are copied to the new qpms_scatsys_t instance;
|
|
|
|
|
* the target qpms_abstract_tmatrix_t objects must be kept alive before all the resulting
|
|
|
|
|
* qpms_scatsys_t instances are properly destroyed. The pointers from orig->tmg, however, are copied.
|
|
|
|
|
* * orig->tmg_count
|
|
|
|
|
* * orig->tm – Must be filled, although the operations will typically be identities
|
|
|
|
|
* (QPMS_TMATRIX_OPERATION_NOOP). N.B. these NOOPs might be replaced with some symmetrisation operation
|
|
|
|
|
* in the resulting "full" qpms_scatsys_t instance.
|
|
|
|
|
* * orig->tm_count
|
|
|
|
|
* * orig->p
|
|
|
|
|
* * orig->p_count
|
2020-01-08 16:00:09 +02:00
|
|
|
|
*
|
|
|
|
|
* The resulting qpms_scatsys_t is obtained by actually evaluating the T-matrices
|
|
|
|
|
* at the given frequency \a omega and where applicable, these are compared
|
|
|
|
|
* by their values with given tolerances. The T-matrix generators are expected
|
|
|
|
|
* to preserve the point group symmetries for all frequencies.
|
|
|
|
|
*
|
2020-01-14 09:17:13 +02:00
|
|
|
|
* This particular function will likely change in the future.
|
|
|
|
|
*
|
2020-01-08 16:00:09 +02:00
|
|
|
|
* \returns An instance \a sso of qpms_scatsys_omega_t. Note that \a sso->ss
|
|
|
|
|
* must be saved by the caller before destroying \a sso
|
|
|
|
|
* (with qpms_scatsys_at_omega_free(), and destroyed only afterwards with
|
|
|
|
|
* qpms_scatsys_free() when not needed anymore.
|
2020-01-14 09:17:13 +02:00
|
|
|
|
* \a sso->ss can be reused for different frequency by a
|
|
|
|
|
* qpms_scatsys_at_omega() call.
|
|
|
|
|
*
|
2019-02-26 15:33:08 +02:00
|
|
|
|
*/
|
2020-01-08 16:00:09 +02:00
|
|
|
|
qpms_scatsys_at_omega_t *qpms_scatsys_apply_symmetry(const qpms_scatsys_t *orig, const struct qpms_finite_group_t *sym,
|
2020-01-09 16:57:30 +02:00
|
|
|
|
complex double omega, const struct qpms_tolerance_spec_t *tol);
|
2020-01-08 16:00:09 +02:00
|
|
|
|
|
2019-03-01 12:36:11 +02:00
|
|
|
|
/// Destroys the result of qpms_scatsys_apply_symmetry or qpms_scatsys_load.
|
2019-02-26 15:33:08 +02:00
|
|
|
|
void qpms_scatsys_free(qpms_scatsys_t *s);
|
|
|
|
|
|
2020-01-14 09:17:13 +02:00
|
|
|
|
/// Destroys a qpms_scatsys_at_omega_t.
|
|
|
|
|
/** Used on results of qpms_scatsys_apply_symmetry() and qpms_scatsys_at_omega(). */
|
2020-01-09 16:57:30 +02:00
|
|
|
|
void qpms_scatsys_at_omega_free(qpms_scatsys_at_omega_t *ssw);
|
2020-01-07 16:57:59 +02:00
|
|
|
|
|
2020-01-14 09:17:13 +02:00
|
|
|
|
/// Evaluates scattering system T-matrices at a given frequency.
|
|
|
|
|
/** Free the result using qpms_scatsys_at_omega_free() when done. */
|
|
|
|
|
qpms_scatsys_at_omega_t *qpms_scatsys_at_omega(const qpms_scatsys_t *ss,
|
|
|
|
|
complex double omega);
|
|
|
|
|
|
2019-03-13 12:28:40 +02:00
|
|
|
|
/// Creates a "full" transformation matrix U that takes a full vector and projects it onto an symmetry adapted basis.
|
|
|
|
|
/** Mostly as a reference and a debugging tool, as multiplicating these big matrices would be inefficient.
|
|
|
|
|
*
|
|
|
|
|
* TODO doc about shape etc.
|
|
|
|
|
*/
|
|
|
|
|
complex double *qpms_scatsys_irrep_transform_matrix(complex double *target_U,
|
|
|
|
|
const qpms_scatsys_t *ss, qpms_iri_t iri);
|
|
|
|
|
|
|
|
|
|
/// Projects a "big" matrix onto an irrep (slow reference implementation).
|
|
|
|
|
/** TODO doc */
|
|
|
|
|
complex double *qpms_scatsys_irrep_pack_matrix_stupid(complex double *target_packed,
|
|
|
|
|
const complex double *orig_full, const qpms_scatsys_t *ss,
|
|
|
|
|
qpms_iri_t iri);
|
|
|
|
|
|
|
|
|
|
/// Transforms a big "packed" matrix into the full basis (slow reference implementation).
|
|
|
|
|
/** TODO doc */
|
|
|
|
|
complex double *qpms_scatsys_irrep_unpack_matrix_stupid(complex double *target_full,
|
|
|
|
|
const complex double *orig_packed, const qpms_scatsys_t *ss,
|
|
|
|
|
qpms_iri_t iri, bool add);
|
|
|
|
|
|
2019-03-07 09:10:43 +02:00
|
|
|
|
/// Projects a "big" matrix onto an irrep.
|
|
|
|
|
/** TODO doc */
|
2019-03-07 12:15:46 +02:00
|
|
|
|
complex double *qpms_scatsys_irrep_pack_matrix(complex double *target_packed,
|
2019-03-07 09:10:43 +02:00
|
|
|
|
const complex double *orig_full, const qpms_scatsys_t *ss,
|
|
|
|
|
qpms_iri_t iri);
|
|
|
|
|
|
|
|
|
|
/// Transforms a big "packed" matrix into the full basis.
|
|
|
|
|
/** TODO doc */
|
2019-03-07 12:15:46 +02:00
|
|
|
|
complex double *qpms_scatsys_irrep_unpack_matrix(complex double *target_full,
|
2019-03-07 09:10:43 +02:00
|
|
|
|
const complex double *orig_packed, const qpms_scatsys_t *ss,
|
2019-03-07 12:15:46 +02:00
|
|
|
|
qpms_iri_t iri, bool add);
|
2019-03-07 09:10:43 +02:00
|
|
|
|
|
|
|
|
|
/// Projects a "big" vector onto an irrep.
|
|
|
|
|
/** TODO doc */
|
2019-03-07 12:15:46 +02:00
|
|
|
|
complex double *qpms_scatsys_irrep_pack_vector(complex double *target_packed,
|
2019-03-07 09:10:43 +02:00
|
|
|
|
const complex double *orig_full, const qpms_scatsys_t *ss,
|
|
|
|
|
qpms_iri_t iri);
|
|
|
|
|
|
|
|
|
|
/// Transforms a big "packed" vector into the full basis.
|
|
|
|
|
/** TODO doc */
|
2019-03-07 12:15:46 +02:00
|
|
|
|
complex double *qpms_scatsys_irrep_unpack_vector(complex double *target_full,
|
2019-03-07 09:10:43 +02:00
|
|
|
|
const complex double *orig_packed, const qpms_scatsys_t *ss,
|
2019-03-07 12:15:46 +02:00
|
|
|
|
qpms_iri_t iri, bool add);
|
2019-03-07 09:10:43 +02:00
|
|
|
|
|
2019-07-22 01:08:41 +03:00
|
|
|
|
/// Global translation matrix.
|
|
|
|
|
/**
|
2019-11-14 13:36:45 +02:00
|
|
|
|
* The diagonal (particle self-) block are filled with zeros (even for regular Bessel waves).
|
2019-07-22 01:08:41 +03:00
|
|
|
|
* This may change in the future.
|
|
|
|
|
*/
|
2019-03-09 14:29:43 +02:00
|
|
|
|
complex double *qpms_scatsys_build_translation_matrix_full(
|
|
|
|
|
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
|
|
|
|
|
complex double *target,
|
|
|
|
|
const qpms_scatsys_t *ss,
|
2019-11-06 18:13:50 +02:00
|
|
|
|
complex double k ///< Wave number to use in the translation matrix.
|
2019-03-09 14:29:43 +02:00
|
|
|
|
);
|
2019-07-21 21:14:11 +03:00
|
|
|
|
|
|
|
|
|
/// As qpms_scatsys_build_translation_full() but with choice of Bessel function type.
|
|
|
|
|
/** Might be useful for evaluation of cross sections and testing.
|
|
|
|
|
*/
|
2019-07-22 01:08:41 +03:00
|
|
|
|
complex double *qpms_scatsys_build_translation_matrix_e_full(
|
|
|
|
|
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
|
|
|
|
|
complex double *target,
|
|
|
|
|
const qpms_scatsys_t *ss,
|
2019-11-06 18:13:50 +02:00
|
|
|
|
complex double k, ///< Wave number to use in the translation matrix.
|
2019-07-22 01:08:41 +03:00
|
|
|
|
qpms_bessel_t J
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/// Global translation matrix with selectable Bessel function, projected on an irrep.
|
|
|
|
|
/**
|
|
|
|
|
* The diagonal (particle self-) blocks are currently filled with zeros.
|
|
|
|
|
* This may change in the future.
|
|
|
|
|
*/
|
|
|
|
|
complex double *qpms_scatsys_build_translation_matrix_e_irrep_packed(
|
2019-07-21 21:14:11 +03:00
|
|
|
|
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
|
|
|
|
|
complex double *target,
|
|
|
|
|
const qpms_scatsys_t *ss,
|
2019-07-22 01:08:41 +03:00
|
|
|
|
qpms_iri_t iri,
|
2019-11-06 18:13:50 +02:00
|
|
|
|
complex double k, ///< Wave number to use in the translation matrix.
|
2019-07-21 21:14:11 +03:00
|
|
|
|
qpms_bessel_t J
|
|
|
|
|
);
|
|
|
|
|
|
2019-07-23 08:43:25 +03:00
|
|
|
|
/// Creates the full \f$ (I - TS) \f$ matrix of the scattering system.
|
2020-01-10 11:43:35 +02:00
|
|
|
|
complex double *qpms_scatsysw_build_modeproblem_matrix_full(
|
2019-03-09 12:55:46 +02:00
|
|
|
|
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
|
|
|
|
|
complex double *target,
|
2020-01-09 16:57:30 +02:00
|
|
|
|
const qpms_scatsys_at_omega_t *ssw
|
2019-03-09 12:55:46 +02:00
|
|
|
|
);
|
2019-07-23 08:43:25 +03:00
|
|
|
|
/// Creates the mode problem matrix \f$ (I - TS) \f$ directly in the irrep-packed form.
|
2020-01-10 12:10:08 +02:00
|
|
|
|
complex double *qpms_scatsysw_build_modeproblem_matrix_irrep_packed(
|
2019-03-09 12:55:46 +02:00
|
|
|
|
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
|
|
|
|
|
complex double *target,
|
2020-01-09 16:57:30 +02:00
|
|
|
|
const qpms_scatsys_at_omega_t *ssw,
|
|
|
|
|
qpms_iri_t iri
|
2019-03-09 12:55:46 +02:00
|
|
|
|
);
|
2020-01-10 12:10:08 +02:00
|
|
|
|
/// Alternative implementation of qpms_scatsysw_build_modeproblem_matrix_irrep_packed().
|
|
|
|
|
complex double *qpms_scatsysw_build_modeproblem_matrix_irrep_packed_orbitorderR(
|
2019-03-17 23:49:10 +02:00
|
|
|
|
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
|
|
|
|
|
complex double *target,
|
2020-01-09 16:57:30 +02:00
|
|
|
|
const qpms_scatsys_at_omega_t *ssw,
|
|
|
|
|
qpms_iri_t iri
|
2019-03-17 23:49:10 +02:00
|
|
|
|
);
|
2020-01-10 12:10:08 +02:00
|
|
|
|
/// Alternative (serial reference) implementation of qpms_scatsysw_build_modeproblem_matrix_irrep_packed().
|
|
|
|
|
complex double *qpms_scatsysw_build_modeproblem_matrix_irrep_packed_orbitorder_serial(
|
2019-03-18 03:06:04 +02:00
|
|
|
|
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
|
|
|
|
|
complex double *target,
|
2020-01-09 16:57:30 +02:00
|
|
|
|
const qpms_scatsys_at_omega_t *ssw,
|
|
|
|
|
qpms_iri_t iri
|
2019-03-18 03:06:04 +02:00
|
|
|
|
);
|
2019-03-09 12:55:46 +02:00
|
|
|
|
|
2019-07-23 08:43:25 +03:00
|
|
|
|
/// LU factorisation (LAPACKE_zgetrf) result holder.
|
|
|
|
|
typedef struct qpms_ss_LU {
|
2020-01-09 16:57:30 +02:00
|
|
|
|
const qpms_scatsys_at_omega_t *ssw;
|
2019-07-23 15:50:31 +03:00
|
|
|
|
bool full; ///< true if full matrix; false if irrep-packed.
|
|
|
|
|
qpms_iri_t iri; ///< Irrep index if `full == false`.
|
2019-07-23 08:43:25 +03:00
|
|
|
|
/// LU decomposition array.
|
|
|
|
|
complex double *a;
|
|
|
|
|
/// Pivot index array, size at least max(1,min(m, n)).
|
2019-07-23 15:50:31 +03:00
|
|
|
|
int *ipiv;
|
2019-07-23 08:43:25 +03:00
|
|
|
|
} qpms_ss_LU;
|
2019-07-23 15:50:31 +03:00
|
|
|
|
void qpms_ss_LU_free(qpms_ss_LU);
|
|
|
|
|
|
|
|
|
|
/// Builds an LU-factorised mode/scattering problem \f$ (I - TS) \f$ matrix from scratch.
|
2020-01-10 11:43:35 +02:00
|
|
|
|
qpms_ss_LU qpms_scatsysw_build_modeproblem_matrix_full_LU(
|
2019-07-23 15:50:31 +03:00
|
|
|
|
complex double *target, ///< Pre-allocated target array. Optional (if NULL, new one is allocated).
|
|
|
|
|
int *target_piv, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
|
2020-01-09 16:57:30 +02:00
|
|
|
|
const qpms_scatsys_at_omega_t *ssw
|
2019-07-23 15:50:31 +03:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/// Builds an irrep-packed LU-factorised mode/scattering problem matrix from scratch.
|
2020-01-10 12:10:08 +02:00
|
|
|
|
qpms_ss_LU qpms_scatsysw_build_modeproblem_matrix_irrep_packed_LU(
|
2019-07-23 15:50:31 +03:00
|
|
|
|
complex double *target, ///< Pre-allocated target array. Optional (if NULL, new one is allocated).
|
|
|
|
|
int *target_piv, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
|
2020-01-09 16:57:30 +02:00
|
|
|
|
const qpms_scatsys_at_omega_t *ssw,
|
|
|
|
|
qpms_iri_t iri
|
2019-07-23 15:50:31 +03:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/// Computes LU factorisation of a pre-calculated mode/scattering problem matrix, replacing its contents.
|
2020-01-10 11:43:35 +02:00
|
|
|
|
qpms_ss_LU qpms_scatsysw_modeproblem_matrix_full_factorise(
|
2019-07-23 15:50:31 +03:00
|
|
|
|
complex double *modeproblem_matrix_full, ///< Pre-calculated mode problem matrix (I-TS). Mandatory.
|
|
|
|
|
int *target_piv, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
|
2020-01-09 16:57:30 +02:00
|
|
|
|
const qpms_scatsys_at_omega_t *ssw
|
2019-07-23 15:50:31 +03:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/// Computes LU factorisation of a pre-calculated irrep-packed mode/scattering problem matrix, replacing its contents.
|
2020-01-10 12:10:08 +02:00
|
|
|
|
qpms_ss_LU qpms_scatsysw_modeproblem_matrix_irrep_packed_factorise(
|
2019-07-23 15:50:31 +03:00
|
|
|
|
complex double *modeproblem_matrix_irrep_packed, ///< Pre-calculated mode problem matrix (I-TS). Mandatory.
|
|
|
|
|
int *target_piv, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
|
2020-01-09 16:57:30 +02:00
|
|
|
|
const qpms_scatsys_at_omega_t *ssw,
|
|
|
|
|
qpms_iri_t iri
|
2019-07-23 15:50:31 +03:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/// Solves a (possibly partial, irrep-packed) scattering problem \f$ (I-TS)f = Ta_\mathrm{inc} \f$ using a pre-factorised \f$ (I-TS) \f$.
|
|
|
|
|
complex double *qpms_scatsys_scatter_solve(
|
|
|
|
|
complex double *target_f, ///< Target (full or irrep-packed, depending on `ludata.full`) array for \a f. If NULL, a new one is allocated.
|
|
|
|
|
const complex double *a_inc, ///< Incident field expansion coefficient vector \a a (full or irrep-packed, depending on `ludata.full`).
|
|
|
|
|
qpms_ss_LU ludata ///< Pre-factorised \f$ I - TS \f$ matrix data.
|
|
|
|
|
);
|
2019-07-23 08:43:25 +03:00
|
|
|
|
|
|
|
|
|
|
2019-03-01 12:36:11 +02:00
|
|
|
|
/// NOT IMPLEMENTED Dumps a qpms_scatsys_t structure to a file.
|
|
|
|
|
qpms_errno_t qpms_scatsys_dump(qpms_scatsys_t *ss, char *path);
|
|
|
|
|
|
|
|
|
|
/// NOT IMPLEMENTED Reads a qpms_scatsys_t structure from a file.
|
|
|
|
|
qpms_scatsys_t *qpms_scatsys_load(char *path);
|
|
|
|
|
|
2019-03-04 00:57:54 +02:00
|
|
|
|
struct qpms_finite_group_t;
|
|
|
|
|
|
|
|
|
|
/// Constructs a "full matrix action" of a point group element for an orbit type.
|
|
|
|
|
/** TODO detailed doc */
|
|
|
|
|
complex double *qpms_orbit_action_matrix(
|
|
|
|
|
/// Target array. If NULL, a new one is allocated.
|
|
|
|
|
/** The size of the array is (orbit->size * bspec->n)**2
|
|
|
|
|
* (it makes sense to assume all the T-matrices share their spec).
|
|
|
|
|
*/
|
|
|
|
|
complex double *target,
|
|
|
|
|
/// The orbit (type).
|
|
|
|
|
const qpms_ss_orbit_type_t *orbit,
|
|
|
|
|
/// Base spec of the t-matrices (we don't know it from orbit, as it has
|
|
|
|
|
/// only T-matrix indices.
|
|
|
|
|
const qpms_vswf_set_spec_t *bspec,
|
|
|
|
|
/// The symmetry group used to generate the orbit (must have rep3d filled).
|
|
|
|
|
const struct qpms_finite_group_t *sym,
|
|
|
|
|
/// The index of the operation in sym to represent.
|
|
|
|
|
const qpms_gmi_t g);
|
|
|
|
|
|
2019-03-04 01:35:06 +02:00
|
|
|
|
/// Constructs a dense matrix representation of a irrep projector for an orbit type.
|
|
|
|
|
/** TODO detailed doc */
|
|
|
|
|
complex double *qpms_orbit_irrep_projector_matrix(
|
|
|
|
|
/// Target array. If NULL, a new one is allocated.
|
|
|
|
|
/** The size of the array is (orbit->size * bspec->n)**2
|
|
|
|
|
* (it makes sense to assume all the T-matrices share their spec).
|
|
|
|
|
*/
|
|
|
|
|
complex double *target,
|
|
|
|
|
/// The orbit (type).
|
|
|
|
|
const qpms_ss_orbit_type_t *orbit,
|
|
|
|
|
/// Base spec of the t-matrices (we don't know it from orbit, as it has
|
|
|
|
|
/// only T-matrix indices.
|
|
|
|
|
const qpms_vswf_set_spec_t *bspec,
|
|
|
|
|
/// The symmetry group used to generate the orbit (must have rep3d filled).
|
|
|
|
|
const struct qpms_finite_group_t *sym,
|
|
|
|
|
/// The index of the irreducible representation of sym.
|
|
|
|
|
const qpms_iri_t iri);
|
2019-03-02 06:42:34 +02:00
|
|
|
|
|
2019-03-07 06:46:19 +02:00
|
|
|
|
/// TODO DOC!!!!!
|
|
|
|
|
complex double *qpms_orbit_irrep_basis(
|
|
|
|
|
/// Here theh size of theh basis shall be saved,
|
|
|
|
|
size_t *basis_size,
|
|
|
|
|
/// Target array. If NULL, a new one is allocated.
|
|
|
|
|
/** The size of the array is basis_size * (orbit->size * bspec->n)
|
|
|
|
|
* (it makes sense to assume all the T-matrices share their spec).
|
|
|
|
|
*/
|
|
|
|
|
complex double *target,
|
|
|
|
|
/// The orbit (type).
|
|
|
|
|
const qpms_ss_orbit_type_t *orbit,
|
|
|
|
|
/// Base spec of the t-matrices (we don't know it from orbit, as it has
|
|
|
|
|
/// only T-matrix indices.
|
|
|
|
|
const qpms_vswf_set_spec_t *bspec,
|
|
|
|
|
/// The symmetry group used to generate the orbit (must have rep3d filled).
|
|
|
|
|
const struct qpms_finite_group_t *sym,
|
|
|
|
|
/// The index of the irreducible representation of sym.
|
|
|
|
|
const qpms_iri_t iri);
|
|
|
|
|
|
2019-07-14 23:00:43 +03:00
|
|
|
|
|
|
|
|
|
/// Creates an incident field vector in the full basis, given a function that evaluates the field expansions at points.
|
|
|
|
|
/** TODO detailed doc!
|
|
|
|
|
* \returns target_full if target_full was not NULL, otherwise the newly allocated array. */
|
|
|
|
|
complex double *qpms_scatsys_incident_field_vector_full(
|
|
|
|
|
/// Target array. If NULL, a new one is allocated.
|
|
|
|
|
/** The length of the array is ss->fecv_size. */
|
|
|
|
|
complex double *target_full,
|
|
|
|
|
const qpms_scatsys_t *ss,
|
|
|
|
|
qpms_incfield_t field_at_point,
|
|
|
|
|
const void *args, ///< Pointer passed as the last argument to (*field_at_point)()
|
|
|
|
|
bool add ///< If true, add to target_full; rewrite target_full if false.
|
|
|
|
|
);
|
|
|
|
|
|
2019-07-22 16:56:03 +03:00
|
|
|
|
/// Applies T-matrices onto an incident field vector in the full basis.
|
2020-01-10 12:10:08 +02:00
|
|
|
|
complex double *qpms_scatsysw_apply_Tmatrices_full(
|
2019-07-22 16:56:03 +03:00
|
|
|
|
complex double *target_full, /// Target vector array. If NULL, a new one is allocated.
|
|
|
|
|
const complex double *inc_full, /// Incident field coefficient vector. Must not be NULL.
|
2020-01-09 16:57:30 +02:00
|
|
|
|
const qpms_scatsys_at_omega_t *ssw
|
2019-07-22 16:56:03 +03:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
2019-07-15 14:39:08 +03:00
|
|
|
|
#if 0
|
2019-07-14 23:00:43 +03:00
|
|
|
|
/// Creates a (partial) incident field vector in the symmetry-adapted basis, given a function that evaluates the field expansions at points.
|
|
|
|
|
/** TODO detailed doc! */
|
|
|
|
|
complex double *qpms_scatsys_incident_field_vector_irrep_packed(
|
|
|
|
|
/// Target array. If NULL, a new one is allocated.
|
|
|
|
|
/** The length of the array is ss->fecv_size. */
|
|
|
|
|
complex double *target_full,
|
|
|
|
|
const qpms_scatsys_t *ss,
|
|
|
|
|
const qpms_iri_t iri, ///< The index of given irreducible representation of ss->sym.
|
|
|
|
|
qpms_incfield_t field_at_point,
|
|
|
|
|
const void *args, ///< Pointer passed as the last argument to (*field_at_point)()
|
|
|
|
|
bool add ///< If true, add to target_full; rewrite target_full if false.
|
|
|
|
|
);
|
2019-07-15 14:39:08 +03:00
|
|
|
|
#endif
|
2019-07-14 23:00:43 +03:00
|
|
|
|
|
2019-06-24 15:12:06 +03:00
|
|
|
|
/// Evaluates scattered fields (corresponding to a given excitation vector) at a given point.
|
|
|
|
|
/**
|
|
|
|
|
* By scattered field, one assumes a linear combination of positive-Hankel-type
|
|
|
|
|
* spherical waves.
|
2019-06-20 07:39:43 +03:00
|
|
|
|
*
|
|
|
|
|
* \return Complex electric field at the point defined by \a where.
|
|
|
|
|
*/
|
2019-06-24 15:12:06 +03:00
|
|
|
|
ccart3_t qpms_scatsys_eval_E(const qpms_scatsys_t *ss,
|
2019-07-14 23:00:43 +03:00
|
|
|
|
const complex double *coeff_vector, ///< A full-length excitation vector (outgoing wave coefficients).
|
2019-06-24 14:03:45 +03:00
|
|
|
|
cart3_t where, ///< Evaluation point.
|
|
|
|
|
complex double k ///< Wave number.
|
2019-06-20 07:39:43 +03:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
2019-06-24 15:12:06 +03:00
|
|
|
|
#if 0
|
2019-06-20 07:39:43 +03:00
|
|
|
|
/** Evaluates partial scattered fields (corresponding to a given irrep-reduced excitation vector)
|
|
|
|
|
* at a given point.
|
|
|
|
|
*
|
|
|
|
|
* \return Complex electric field at the point defined by \a where.
|
|
|
|
|
*/
|
2019-06-24 15:12:06 +03:00
|
|
|
|
ccart3_t qpms_scatsys_eval_E_irrep(const qpms_scatsys_t *ss,
|
2019-06-24 14:03:45 +03:00
|
|
|
|
qpms_iri_t iri, ///< Irreducible representation
|
|
|
|
|
const complex double *coeff_vector, ///< A reduced excitation vector, corresponding to \a iri.
|
|
|
|
|
cart3_t where, ///< Evaluation point.
|
|
|
|
|
complex double k ///< Wave number.
|
2019-06-20 07:39:43 +03:00
|
|
|
|
);
|
2019-06-24 15:12:06 +03:00
|
|
|
|
#endif
|
2019-07-23 08:43:25 +03:00
|
|
|
|
|
2019-02-20 09:57:36 +02:00
|
|
|
|
#endif //QPMS_SCATSYSTEM_H
|