2 * \brief Modern interface for finite lattice calculations, including symmetries.
4 * N.B. Only "reasonably normalised" waves are supported now in most of the
5 * functions defined here, i.e. those that can be rotated by the usual
6 * Wigner matrices, i.e. the "power" or "spharm" -normalised ones.
8 * TODO FIXME check whether Condon-Shortley phase can have some nasty influence
9 * here; I fear that yes.
11 #ifndef QPMS_SCATSYSTEM_H
12 #define QPMS_SCATSYSTEM_H
13 #include "qpms_types.h"
15 #include "tmatrices.h"
18 /// Overrides the number of threads spawned by the paralellized functions.
19 /** TODO MORE DOC which are those? */
20 void qpms_scatsystem_set_nthreads(long n
);
22 /// A particle, defined by its T-matrix and position.
23 typedef struct qpms_particle_t
{
24 // Does it make sense to ever use other than cartesian coords for this?
25 cart3_t pos
; ///< Particle position in cartesian coordinates.
26 const qpms_tmatrix_t
*tmatrix
; ///< T-matrix; not owned by qpms_particle_t.
29 struct qpms_finite_group_t
;
30 typedef struct qpms_finite_group_t qpms_finite_group_t
;
32 /// A particle, defined by its T-matrix INDEX and position, to be used in qpms_scatsys_t.
33 typedef struct qpms_particle_tid_t
{
34 // Does it make sense to ever use other than cartesian coords for this?
35 cart3_t pos
; ///< Particle position in cartesian coordinates.
36 qpms_ss_tmi_t tmatrix_id
; ///< T-matrix index
37 } qpms_particle_tid_t
;
40 typedef qpms_gmi_t qpms_ss_orbit_pi_t
; ///< Auxilliary type used in qpms_ss_orbit_type_t for labeling particles inside orbits.
41 typedef qpms_ss_tmi_t qpms_ss_oti_t
; ///< Auxilliary type used for labeling orbit types.
43 /// Structure describing a particle's "orbit type" under symmetry group actions in a system.
45 * Each particle has its orbit with respect to a symmetry group of the system in which the particle lies,
46 * i.e. a set of particles onto which the group operations map the original particle.
48 * (TODO DOC improve the following explanation:)
49 * Typically, there will be only a small number of different (T-matrix, particle
50 * <a href="https://en.wikipedia.org/wiki/Group_action#Fixed_points_and_stabilizer_subgroups">stabiliser</a>)
51 * pairs in the system. We can group the particles accordingly, into the same "orbit types"
52 * that will allow to do certain operations only once for each "orbit type", saving memory and (perhaps) time.
54 * Each particle will then have assigned:
56 * 2. an ID inside that orbit.
59 * TODO DOC how the process of assigning the particle IDs actually work, orbit type (non-)uniqueness.
62 * Memory is managed by qpms_scatspec_t; qpms_ss_orbit_type_t does not own anything.
65 typedef struct qpms_ss_orbit_type_t
{
66 qpms_ss_orbit_pi_t size
; ///< Size of the orbit (a divisor of the group order), i.e. number of particles on the orbit.
67 size_t bspecn
; ///< Individual particle's coefficient vector length. The same as ss->tm[this.tmatrices[0]]->spec->n.
68 /// Action of the group elements onto the elements in this orbit.
69 /** Its size is sym->order * this.size
70 * and its values lie between 0 and \a this.size − 1.
72 * Action of the group element g onto the pi-th particle
73 * is given by action[g + pi*sym->order].
76 qpms_ss_orbit_pi_t
*action
;
77 /// T-matrix IDs of the particles on this orbit (type).
79 * We save all the tmi's of the particles on the orbit here to make the number of array lookups
80 * and pointer dereferences constant.
82 * The size of this array is \a size.
84 qpms_ss_tmi_t
*tmatrices
;
85 /// Sizes of the per-orbit irrep bases.
87 * The order of the irreps corresponds to the order in \a ss->sym->irreps.
88 * The size of this array is (obviously) \a ss->sym->nirreps.
90 * TODO different type?
94 //The following are pretty redundant, TODO reduce them at some point.
95 /// Cumulative sums of irbase_sizes.
96 size_t *irbase_cumsizes
;
98 size_t *irbase_offsets
;
99 /// Per-orbit irreducible representation orthonormal bases.
100 /** This also defines the unitary operator that transforms the orbital excitation coefficients
101 * in the symmetry-adapted basis.
103 * The size is (\a this->size * \a this->tmatrices[0].spec->n)**2.
107 complex double *irbases
;
109 size_t instance_count
;
110 /// Cumulative sum of the preceding ot->siza * ot->instance_count;
111 qpms_ss_pi_t p_offset
;
112 } qpms_ss_orbit_type_t
;
115 typedef ptrdiff_t qpms_ss_osn_t
; ///< "serial number" of av orbit in a given type.
117 /// Auxillary type used in qpms_scatsys_t that identifies the particle's orbit and its id inside that orbit.
118 typedef struct qpms_ss_particle_orbitinfo
{
119 qpms_ss_oti_t t
; ///< Orbit type.
120 #define QPMS_SS_P_ORBITINFO_UNDEF (-1) ///< This labels that the particle has not yet been assigned to an orbit.
121 qpms_ss_osn_t osn
; ///< "Serial number" of the orbit in the given type. TODO type and more doc.
122 qpms_ss_orbit_pi_t p
; ///< Order (sija, ei rankki) of the particle inside that orbit type.
123 } qpms_ss_particle_orbitinfo_t
;
125 /// Auxillary type used in qpms_scatsys_t: A recepy to create another T-matrices by symmetry operations.
126 typedef struct qpms_ss_derived_tmatrix
{
127 qpms_ss_tmgi_t tmgi
; ///< Index of the corresponding qpms_scatsys_t::tm element.
128 struct qpms_tmatrix_operation_t op
; ///< Operation to derive this particular T-matrix.
129 } qpms_ss_derived_tmatrix_t
;
132 struct qpms_trans_calculator
;
133 struct qpms_epsmu_generator_t
;
135 typedef struct qpms_scatsys_t
{
136 struct qpms_epsmu_generator_t medium
; ///< Optical properties of the background medium.
138 /// (Template) T-matrix functions in the system.
139 /** The qpms_abstract_tmatrix_t objects (onto which this array member point)
140 * are NOT owned by this and must be kept alive for the whole lifetime
141 * of all qpms_scatsys_t objects that are built upon them.
143 qpms_tmatrix_function_t
*tmg
;
144 qpms_ss_tmgi_t tmg_count
; ///< Number of all different original T-matrix generators in the system.
146 /// All the different T-matrix functions in the system, including those derived from \a tmg elements by symmetries.
147 qpms_ss_derived_tmatrix_t
*tm
;
148 qpms_ss_tmi_t tm_count
; ///< Number of all different T-matrices in the system (length of tm[]).
149 qpms_ss_tmi_t tm_capacity
; ///< Capacity of tm[].
151 qpms_particle_tid_t
*p
; ///< Particles.
152 qpms_ss_pi_t p_count
; ///< Size of particles array.
153 qpms_ss_pi_t p_capacity
; ///< Capacity of p[].
155 //TODO the index types do not need to be so big.
156 const struct qpms_finite_group_t
*sym
; ///< Symmetry group of the array
157 qpms_ss_pi_t
*p_sym_map
; ///< Which particles map onto which by the symmetry ops.
158 ///< p_sym_map[idi + pi * sym->order] gives the index of pi-th particle under the idi'th sym op.
159 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].
161 qpms_ss_oti_t orbit_type_count
;
162 qpms_ss_orbit_type_t
*orbit_types
; ///< (Array length is \a orbit_type_count.)
164 qpms_ss_particle_orbitinfo_t
*p_orbitinfo
; ///< Orbit type identification of each particle. (Array length is \a p_count.)
166 size_t fecv_size
; ///< Number of elements of a full excitation coefficient vector size.
167 size_t *saecv_sizes
; ///< Number of elements of symmetry-adjusted coefficient vector sizes (order as in sym->irreps).
169 size_t *fecv_pstarts
; ///< Indices of where pi'th particle's excitation coeffs start in a full excitation coefficient vector.
170 size_t *saecv_ot_offsets
; ///< TODO DOC. In the packed vector, saecv_ot_offsets[iri * orbit_type_count + oti] indicates start of ot
171 /**< TODO maybe move it to qpms_ss_orbit_type_t, ffs. */
172 //size_t **saecv_pstarts; ///< NI. Indices of where pi'th particle's excitation coeff start in a symmetry-adjusted e.c.v.
173 ///**< First index is irrep index as in sym->irreps, second index is particle index. */
175 // TODO shifted origin of the symmetry group etc.
176 // TODO some indices for fast operations here.
178 size_t max_bspecn
; ///< Maximum tm[...]->spec->n. Mainly for workspace allocation.
180 /// Particles grouped by orbit (in the order corresponding to the packed memory layout).
181 qpms_ss_pi_t
*p_by_orbit
;
183 // We keep the p_orbitinfo arrays in this chunk in order to avoid memory fragmentation
186 double lenscale
; // radius of the array, used as a relative tolerance measure
187 struct qpms_trans_calculator
*c
;
190 /// Retrieve the bspec of \a tmi'th element of \a ss->tm.
191 static inline const qpms_vswf_set_spec_t
*qpms_ss_bspec_tmi(const qpms_scatsys_t
*ss
, qpms_ss_tmi_t tmi
) {
192 return ss
->tmg
[ss
->tm
[tmi
].tmgi
].spec
;
195 /// Retrieve the bspec of \a pi'th particle in \a ss->p.
196 static inline const qpms_vswf_set_spec_t
*qpms_ss_bspec_pi(const qpms_scatsys_t
*ss
, qpms_ss_pi_t pi
) {
197 return ss
->tmg
[ss
->tm
[ss
->p
[pi
].tmatrix_id
].tmgi
].spec
;
200 typedef struct qpms_scatsys_at_omega_t
{
201 const qpms_scatsys_t
*ss
; ///< Parent scattering system.
202 /// T-matrices from \a ss, evaluated at \a omega.
203 /** The T-matrices are in the same order as in \a ss,
204 * i.e in the order corresponding to \a ss->tm.
207 complex double omega
; ///< Angular frequency
208 qpms_epsmu_t medium
; ///< Background medium optical properties at the given frequency
209 complex double wavenumber
; ///< Background medium wavenumber
210 } qpms_scatsys_at_omega_t
;
212 void qpms_scatsys_at_omega_free(qpms_scatsys_at_omega_t
*);
214 /// Creates a new scatsys by applying a symmetry group onto a "proto-scatsys", copying particles if needed.
215 /** In fact, it copies everything except the vswf set specs and qpms_abstract_tmatrix_t instances,
216 * so keep them alive until scatsys is destroyed.
218 * The following fields must be filled in the "proto- scattering system" \a orig:
219 * * orig->medium – The pointer is copied to the new qpms_scatsys_t instance;
220 * the target qpms_abstract_tmatrix_t objects must be kept alive before all the resulting
221 * * orig->tmg – The pointers are copied to the new qpms_scatsys_t instance;
222 * the target qpms_abstract_tmatrix_t objects must be kept alive before all the resulting
223 * qpms_scatsys_t instances are properly destroyed. The pointers from orig->tmg, however, are copied.
225 * * orig->tm – Must be filled, although the operations will typically be identities
226 * (QPMS_TMATRIX_OPERATION_NOOP). N.B. these NOOPs might be replaced with some symmetrisation operation
227 * in the resulting "full" qpms_scatsys_t instance.
232 * The resulting qpms_scatsys_t is obtained by actually evaluating the T-matrices
233 * at the given frequency \a omega and where applicable, these are compared
234 * by their values with given tolerances. The T-matrix generators are expected
235 * to preserve the point group symmetries for all frequencies.
237 * \returns An instance \a sso of qpms_scatsys_omega_t. Note that \a sso->ss
238 * must be saved by the caller before destroying \a sso
239 * (with qpms_scatsys_at_omega_free(), and destroyed only afterwards with
240 * qpms_scatsys_free() when not needed anymore.
242 qpms_scatsys_at_omega_t
*qpms_scatsys_apply_symmetry(const qpms_scatsys_t
*orig
, const struct qpms_finite_group_t
*sym
,
243 complex double omega
, const struct qpms_tolerance_spec_t
*tol
);
245 /// Destroys the result of qpms_scatsys_apply_symmetry or qpms_scatsys_load.
246 void qpms_scatsys_free(qpms_scatsys_t
*s
);
248 /// Destroys the result of qpms_scatsys_eval_at_omega()
249 void qpms_scatsys_at_omega_free(qpms_scatsys_at_omega_t
*ssw
);
251 /// Creates a "full" transformation matrix U that takes a full vector and projects it onto an symmetry adapted basis.
252 /** Mostly as a reference and a debugging tool, as multiplicating these big matrices would be inefficient.
254 * TODO doc about shape etc.
256 complex double *qpms_scatsys_irrep_transform_matrix(complex double *target_U
,
257 const qpms_scatsys_t
*ss
, qpms_iri_t iri
);
259 /// Projects a "big" matrix onto an irrep (slow reference implementation).
261 complex double *qpms_scatsys_irrep_pack_matrix_stupid(complex double *target_packed
,
262 const complex double *orig_full
, const qpms_scatsys_t
*ss
,
265 /// Transforms a big "packed" matrix into the full basis (slow reference implementation).
267 complex double *qpms_scatsys_irrep_unpack_matrix_stupid(complex double *target_full
,
268 const complex double *orig_packed
, const qpms_scatsys_t
*ss
,
269 qpms_iri_t iri
, bool add
);
271 /// Projects a "big" matrix onto an irrep.
273 complex double *qpms_scatsys_irrep_pack_matrix(complex double *target_packed
,
274 const complex double *orig_full
, const qpms_scatsys_t
*ss
,
277 /// Transforms a big "packed" matrix into the full basis.
279 complex double *qpms_scatsys_irrep_unpack_matrix(complex double *target_full
,
280 const complex double *orig_packed
, const qpms_scatsys_t
*ss
,
281 qpms_iri_t iri
, bool add
);
283 /// Projects a "big" vector onto an irrep.
285 complex double *qpms_scatsys_irrep_pack_vector(complex double *target_packed
,
286 const complex double *orig_full
, const qpms_scatsys_t
*ss
,
289 /// Transforms a big "packed" vector into the full basis.
291 complex double *qpms_scatsys_irrep_unpack_vector(complex double *target_full
,
292 const complex double *orig_packed
, const qpms_scatsys_t
*ss
,
293 qpms_iri_t iri
, bool add
);
295 /// Global translation matrix.
297 * The diagonal (particle self-) block are filled with zeros (even for regular Bessel waves).
298 * This may change in the future.
300 complex double *qpms_scatsys_build_translation_matrix_full(
301 /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
302 complex double *target
,
303 const qpms_scatsys_t
*ss
,
304 complex double k
///< Wave number to use in the translation matrix.
307 /// As qpms_scatsys_build_translation_full() but with choice of Bessel function type.
308 /** Might be useful for evaluation of cross sections and testing.
310 complex double *qpms_scatsys_build_translation_matrix_e_full(
311 /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
312 complex double *target
,
313 const qpms_scatsys_t
*ss
,
314 complex double k
, ///< Wave number to use in the translation matrix.
318 /// Global translation matrix with selectable Bessel function, projected on an irrep.
320 * The diagonal (particle self-) blocks are currently filled with zeros.
321 * This may change in the future.
323 complex double *qpms_scatsys_build_translation_matrix_e_irrep_packed(
324 /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
325 complex double *target
,
326 const qpms_scatsys_t
*ss
,
328 complex double k
, ///< Wave number to use in the translation matrix.
332 /// Creates the full \f$ (I - TS) \f$ matrix of the scattering system.
333 complex double *qpms_scatsysw_build_modeproblem_matrix_full(
334 /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
335 complex double *target
,
336 const qpms_scatsys_at_omega_t
*ssw
338 /// Creates the mode problem matrix \f$ (I - TS) \f$ directly in the irrep-packed form.
339 complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed(
340 /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
341 complex double *target
,
342 const qpms_scatsys_at_omega_t
*ssw
,
345 /// Alternative implementation of qpms_scatsys_build_modeproblem_matrix_irrep_packed().
346 complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorderR(
347 /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
348 complex double *target
,
349 const qpms_scatsys_at_omega_t
*ssw
,
352 /// Alternative (serial reference) implementation of qpms_scatsys_build_modeproblem_matrix_irrep_packed().
353 complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorder_serial(
354 /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
355 complex double *target
,
356 const qpms_scatsys_at_omega_t
*ssw
,
360 /// LU factorisation (LAPACKE_zgetrf) result holder.
361 typedef struct qpms_ss_LU
{
362 const qpms_scatsys_at_omega_t
*ssw
;
363 bool full
; ///< true if full matrix; false if irrep-packed.
364 qpms_iri_t iri
; ///< Irrep index if `full == false`.
365 /// LU decomposition array.
367 /// Pivot index array, size at least max(1,min(m, n)).
370 void qpms_ss_LU_free(qpms_ss_LU
);
372 /// Builds an LU-factorised mode/scattering problem \f$ (I - TS) \f$ matrix from scratch.
373 qpms_ss_LU
qpms_scatsysw_build_modeproblem_matrix_full_LU(
374 complex double *target
, ///< Pre-allocated target array. Optional (if NULL, new one is allocated).
375 int *target_piv
, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
376 const qpms_scatsys_at_omega_t
*ssw
379 /// Builds an irrep-packed LU-factorised mode/scattering problem matrix from scratch.
380 qpms_ss_LU
qpms_scatsys_build_modeproblem_matrix_irrep_packed_LU(
381 complex double *target
, ///< Pre-allocated target array. Optional (if NULL, new one is allocated).
382 int *target_piv
, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
383 const qpms_scatsys_at_omega_t
*ssw
,
387 /// Computes LU factorisation of a pre-calculated mode/scattering problem matrix, replacing its contents.
388 qpms_ss_LU
qpms_scatsysw_modeproblem_matrix_full_factorise(
389 complex double *modeproblem_matrix_full
, ///< Pre-calculated mode problem matrix (I-TS). Mandatory.
390 int *target_piv
, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
391 const qpms_scatsys_at_omega_t
*ssw
394 /// Computes LU factorisation of a pre-calculated irrep-packed mode/scattering problem matrix, replacing its contents.
395 qpms_ss_LU
qpms_scatsys_modeproblem_matrix_irrep_packed_factorise(
396 complex double *modeproblem_matrix_irrep_packed
, ///< Pre-calculated mode problem matrix (I-TS). Mandatory.
397 int *target_piv
, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
398 const qpms_scatsys_at_omega_t
*ssw
,
402 /// Solves a (possibly partial, irrep-packed) scattering problem \f$ (I-TS)f = Ta_\mathrm{inc} \f$ using a pre-factorised \f$ (I-TS) \f$.
403 complex double *qpms_scatsys_scatter_solve(
404 complex double *target_f
, ///< Target (full or irrep-packed, depending on `ludata.full`) array for \a f. If NULL, a new one is allocated.
405 const complex double *a_inc
, ///< Incident field expansion coefficient vector \a a (full or irrep-packed, depending on `ludata.full`).
406 qpms_ss_LU ludata
///< Pre-factorised \f$ I - TS \f$ matrix data.
410 /// NOT IMPLEMENTED Dumps a qpms_scatsys_t structure to a file.
411 qpms_errno_t
qpms_scatsys_dump(qpms_scatsys_t
*ss
, char *path
);
413 /// NOT IMPLEMENTED Reads a qpms_scatsys_t structure from a file.
414 qpms_scatsys_t
*qpms_scatsys_load(char *path
);
416 struct qpms_finite_group_t
;
418 /// Constructs a "full matrix action" of a point group element for an orbit type.
419 /** TODO detailed doc */
420 complex double *qpms_orbit_action_matrix(
421 /// Target array. If NULL, a new one is allocated.
422 /** The size of the array is (orbit->size * bspec->n)**2
423 * (it makes sense to assume all the T-matrices share their spec).
425 complex double *target
,
426 /// The orbit (type).
427 const qpms_ss_orbit_type_t
*orbit
,
428 /// Base spec of the t-matrices (we don't know it from orbit, as it has
429 /// only T-matrix indices.
430 const qpms_vswf_set_spec_t
*bspec
,
431 /// The symmetry group used to generate the orbit (must have rep3d filled).
432 const struct qpms_finite_group_t
*sym
,
433 /// The index of the operation in sym to represent.
436 /// Constructs a dense matrix representation of a irrep projector for an orbit type.
437 /** TODO detailed doc */
438 complex double *qpms_orbit_irrep_projector_matrix(
439 /// Target array. If NULL, a new one is allocated.
440 /** The size of the array is (orbit->size * bspec->n)**2
441 * (it makes sense to assume all the T-matrices share their spec).
443 complex double *target
,
444 /// The orbit (type).
445 const qpms_ss_orbit_type_t
*orbit
,
446 /// Base spec of the t-matrices (we don't know it from orbit, as it has
447 /// only T-matrix indices.
448 const qpms_vswf_set_spec_t
*bspec
,
449 /// The symmetry group used to generate the orbit (must have rep3d filled).
450 const struct qpms_finite_group_t
*sym
,
451 /// The index of the irreducible representation of sym.
452 const qpms_iri_t iri
);
455 complex double *qpms_orbit_irrep_basis(
456 /// Here theh size of theh basis shall be saved,
458 /// Target array. If NULL, a new one is allocated.
459 /** The size of the array is basis_size * (orbit->size * bspec->n)
460 * (it makes sense to assume all the T-matrices share their spec).
462 complex double *target
,
463 /// The orbit (type).
464 const qpms_ss_orbit_type_t
*orbit
,
465 /// Base spec of the t-matrices (we don't know it from orbit, as it has
466 /// only T-matrix indices.
467 const qpms_vswf_set_spec_t
*bspec
,
468 /// The symmetry group used to generate the orbit (must have rep3d filled).
469 const struct qpms_finite_group_t
*sym
,
470 /// The index of the irreducible representation of sym.
471 const qpms_iri_t iri
);
474 /// Creates an incident field vector in the full basis, given a function that evaluates the field expansions at points.
475 /** TODO detailed doc!
476 * \returns target_full if target_full was not NULL, otherwise the newly allocated array. */
477 complex double *qpms_scatsys_incident_field_vector_full(
478 /// Target array. If NULL, a new one is allocated.
479 /** The length of the array is ss->fecv_size. */
480 complex double *target_full
,
481 const qpms_scatsys_t
*ss
,
482 qpms_incfield_t field_at_point
,
483 const void *args
, ///< Pointer passed as the last argument to (*field_at_point)()
484 bool add
///< If true, add to target_full; rewrite target_full if false.
487 /// Applies T-matrices onto an incident field vector in the full basis.
488 complex double *qpms_scatsys_apply_Tmatrices_full(
489 complex double *target_full
, /// Target vector array. If NULL, a new one is allocated.
490 const complex double *inc_full
, /// Incident field coefficient vector. Must not be NULL.
491 const qpms_scatsys_at_omega_t
*ssw
496 /// Creates a (partial) incident field vector in the symmetry-adapted basis, given a function that evaluates the field expansions at points.
497 /** TODO detailed doc! */
498 complex double *qpms_scatsys_incident_field_vector_irrep_packed(
499 /// Target array. If NULL, a new one is allocated.
500 /** The length of the array is ss->fecv_size. */
501 complex double *target_full
,
502 const qpms_scatsys_t
*ss
,
503 const qpms_iri_t iri
, ///< The index of given irreducible representation of ss->sym.
504 qpms_incfield_t field_at_point
,
505 const void *args
, ///< Pointer passed as the last argument to (*field_at_point)()
506 bool add
///< If true, add to target_full; rewrite target_full if false.
510 /// Evaluates scattered fields (corresponding to a given excitation vector) at a given point.
512 * By scattered field, one assumes a linear combination of positive-Hankel-type
515 * \return Complex electric field at the point defined by \a where.
517 ccart3_t
qpms_scatsys_eval_E(const qpms_scatsys_t
*ss
,
518 const complex double *coeff_vector
, ///< A full-length excitation vector (outgoing wave coefficients).
519 cart3_t where
, ///< Evaluation point.
520 complex double k
///< Wave number.
525 /** Evaluates partial scattered fields (corresponding to a given irrep-reduced excitation vector)
528 * \return Complex electric field at the point defined by \a where.
530 ccart3_t
qpms_scatsys_eval_E_irrep(const qpms_scatsys_t
*ss
,
531 qpms_iri_t iri
, ///< Irreducible representation
532 const complex double *coeff_vector
, ///< A reduced excitation vector, corresponding to \a iri.
533 cart3_t where
, ///< Evaluation point.
534 complex double k
///< Wave number.
538 #endif //QPMS_SCATSYSTEM_H