WIP Rewriting scatsystem.

Former-commit-id: 17f0f48ab54b84c4701b17846f941dd0142eb668
This commit is contained in:
Marek Nečada 2020-01-09 16:57:30 +02:00
parent 5dd93235f0
commit 541af5a984
5 changed files with 104 additions and 91 deletions

View File

@ -410,7 +410,7 @@ typedef struct qpms_epsmu_t {
complex double mu; ///< Relative permeability. complex double mu; ///< Relative permeability.
} qpms_epsmu_t; } qpms_epsmu_t;
struct qpms_tolerance_spec_t; // See tolerances.c struct qpms_tolerance_spec_t; // See tolerances.h
#define lmcheck(l,m) assert((l) >= 1 && abs(m) <= (l)) #define lmcheck(l,m) assert((l) >= 1 && abs(m) <= (l))
#endif // QPMS_TYPES #endif // QPMS_TYPES

View File

@ -21,6 +21,7 @@
#include "tmatrices.h" #include "tmatrices.h"
#include <pthread.h> #include <pthread.h>
#include "kahansum.h" #include "kahansum.h"
#include "tolerances.h"
#ifdef QPMS_SCATSYSTEM_USE_OWN_BLAS #ifdef QPMS_SCATSYSTEM_USE_OWN_BLAS
#include "qpmsblas.h" #include "qpmsblas.h"
@ -143,7 +144,7 @@ static void add_orbit_type(qpms_scatsys_t *ss, const qpms_ss_orbit_type_t *ot_cu
// Almost 200 lines. This whole thing deserves a rewrite! // Almost 200 lines. This whole thing deserves a rewrite!
qpms_scatsys_t *qpms_scatsys_apply_symmetry(const qpms_scatsys_t *orig, qpms_scatsys_at_omega_t *qpms_scatsys_apply_symmetry(const qpms_scatsys_t *orig,
const qpms_finite_group_t *sym, complex double omega, const qpms_finite_group_t *sym, complex double omega,
const qpms_tolerance_spec_t *tol) { const qpms_tolerance_spec_t *tol) {
// TODO check data sanity // TODO check data sanity
@ -174,17 +175,17 @@ qpms_scatsys_t *qpms_scatsys_apply_symmetry(const qpms_scatsys_t *orig,
assert(!cart3_isclose(orig->p[i].pos, orig->p[j].pos, 0, QPMS_SCATSYS_LEN_RTOL * lenscale)); assert(!cart3_isclose(orig->p[i].pos, orig->p[j].pos, 0, QPMS_SCATSYS_LEN_RTOL * lenscale));
// Allocate T-matrix, particle and particle orbit info arrays
qpms_scatsys_t *ss;
QPMS_CRASHING_MALLOC(ss, sizeof(qpms_scatsys_t));
ss->lenscale = lenscale;
ss->sym = sym;
// Copy the qpms_tmatrix_fuction_t from orig // Copy the qpms_tmatrix_fuction_t from orig
ss->tmg_count = orig->tmg_count; ss->tmg_count = orig->tmg_count;
QPMS_CRASHING_MALLOC(ss->tmg, ss->tmg_count * sizeof(*(ss->tmg))); QPMS_CRASHING_MALLOC(ss->tmg, ss->tmg_count * sizeof(*(ss->tmg)));
memcpy(ss->tmg, orig->tmg, ss->tmg_count * sizeof(*(ss->tmg))); memcpy(ss->tmg, orig->tmg, ss->tmg_count * sizeof(*(ss->tmg)));
// Allocate T-matrix, particle and particle orbit info arrays
qpms_scatsys_t *ss;
ss = QPMS_CRASHING_MALLOC(ss, sizeof(qpms_scatsys_t));
ss->lenscale = lenscale;
ss->sym = sym;
ss->tm_capacity = sym->order * orig->tm_count; ss->tm_capacity = sym->order * orig->tm_count;
QPMS_CRASHING_MALLOC(ss->tm, ss->tm_capacity * sizeof(*(ss->tm))); QPMS_CRASHING_MALLOC(ss->tm, ss->tm_capacity * sizeof(*(ss->tm)));
@ -226,11 +227,11 @@ qpms_scatsys_t *qpms_scatsys_apply_symmetry(const qpms_scatsys_t *orig,
break; break;
} }
if (j == ss->tm_count) { // duplicity not found, save both the "abstract" and "at omega" T-matrices if (j == ss->tm_count) { // duplicity not found, save both the "abstract" and "at omega" T-matrices
ss->tm[j].op = qpms_tmatrix_operation_copy(orig->tm[j].op); qpms_tmatrix_operation_copy(&(ss->tm[j].op), orig->tm[j].op);
ss->tm[j].tmgi = orig->tm[j].tmgi; // T-matrix functions are preserved. ss->tm[j].tmgi = orig->tm[j].tmgi; // T-matrix functions are preserved.
ssw->tm[j] = ti; ssw->tm[j] = ti;
ss->max_bspecn = MAX(ssw->tm[j]->spec->n, ss->max_bspecn); ss->max_bspecn = MAX(ssw->tm[j]->spec->n, ss->max_bspecn);
lMax = MAX(lMax, ss->tm[j]->spec->lMax); lMax = MAX(lMax, ss->tm[j].spec->lMax);
++(ss->tm_count); ++(ss->tm_count);
} }
else qpms_tmatrix_free(ti); else qpms_tmatrix_free(ti);
@ -1049,13 +1050,14 @@ complex double *qpms_scatsys_build_translation_matrix_e_full(
complex double *qpms_scatsys_build_modeproblem_matrix_full( complex double *qpms_scatsys_at_omega_build_modeproblem_matrix_full(
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated. /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
complex double *target, complex double *target,
const qpms_scatsys_t *ss, const qpms_scatsys_at_omega_t *ssw,
complex double k ///< Wave number to use in the translation matrix.
) )
{ {
const complex double k = ssw->wavenumber;
const qpms_scatsys_t *ss = ssw->ss;
const size_t full_len = ss->fecv_size; const size_t full_len = ss->fecv_size;
if(!target) if(!target)
QPMS_CRASHING_MALLOC(target, SQ(full_len) * sizeof(complex double)); QPMS_CRASHING_MALLOC(target, SQ(full_len) * sizeof(complex double));
@ -1066,13 +1068,13 @@ complex double *qpms_scatsys_build_modeproblem_matrix_full(
{ // Non-diagonal part; M[piR, piC] = -T[piR] S(piR<-piC) { // Non-diagonal part; M[piR, piC] = -T[piR] S(piR<-piC)
size_t fullvec_offsetR = 0; size_t fullvec_offsetR = 0;
for(qpms_ss_pi_t piR = 0; piR < ss->p_count; ++piR) { for(qpms_ss_pi_t piR = 0; piR < ss->p_count; ++piR) {
const qpms_vswf_set_spec_t *bspecR = ss->tm[ss->p[piR].tmatrix_id]->spec; const qpms_vswf_set_spec_t *bspecR = ssw->tm[ss->p[piR].tmatrix_id]->spec;
const cart3_t posR = ss->p[piR].pos; const cart3_t posR = ss->p[piR].pos;
size_t fullvec_offsetC = 0; size_t fullvec_offsetC = 0;
// dest particle T-matrix // dest particle T-matrix
const complex double *tmmR = ss->tm[ss->p[piR].tmatrix_id]->m; const complex double *tmmR = ssw->tm[ss->p[piR].tmatrix_id]->m;
for(qpms_ss_pi_t piC = 0; piC < ss->p_count; ++piC) { for(qpms_ss_pi_t piC = 0; piC < ss->p_count; ++piC) {
const qpms_vswf_set_spec_t *bspecC = ss->tm[ss->p[piC].tmatrix_id]->spec; const qpms_vswf_set_spec_t *bspecC = ssw->tm[ss->p[piC].tmatrix_id]->spec;
if(piC != piR) { // The diagonal will be dealt with later. if(piC != piR) { // The diagonal will be dealt with later.
const cart3_t posC = ss->p[piC].pos; const cart3_t posC = ss->p[piC].pos;
QPMS_ENSURE_SUCCESS(qpms_trans_calculator_get_trans_array_lc3p(ss->c, QPMS_ENSURE_SUCCESS(qpms_trans_calculator_get_trans_array_lc3p(ss->c,
@ -1102,10 +1104,12 @@ complex double *qpms_scatsys_build_modeproblem_matrix_full(
complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_serial( complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_serial(
/// Target memory with capacity for ss->saecv_sizes[iri]**2 elements. If NULL, new will be allocated. /// Target memory with capacity for ss->saecv_sizes[iri]**2 elements. If NULL, new will be allocated.
complex double *target_packed, complex double *target_packed,
const qpms_scatsys_t *ss, qpms_iri_t iri, const qpms_scatsys_at_omega_t *ssw,
complex double k ///< Wave number to use in the translation matrix. qpms_iri_t iri,
) )
{ {
const qpms_scatsys_t *ss = ssw->ss;
const complex double k = ssw->wavenumber;
const size_t packedlen = ss->saecv_sizes[iri]; const size_t packedlen = ss->saecv_sizes[iri];
if (!packedlen) // THIS IS A BIT PROBLEMATIC, TODO how to deal with empty irreps? if (!packedlen) // THIS IS A BIT PROBLEMATIC, TODO how to deal with empty irreps?
return target_packed; return target_packed;
@ -1136,7 +1140,7 @@ complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_serial(
const size_t packed_orbit_offsetR = const size_t packed_orbit_offsetR =
ss->saecv_ot_offsets[iri*ss->orbit_type_count + otiR] ss->saecv_ot_offsets[iri*ss->orbit_type_count + otiR]
+ osnR * otR->irbase_sizes[iri]; + osnR * otR->irbase_sizes[iri];
const qpms_vswf_set_spec_t *bspecR = ss->tm[ss->p[piR].tmatrix_id]->spec; const qpms_vswf_set_spec_t *bspecR = ssw->tm[ss->p[piR].tmatrix_id]->spec;
// Orbit coeff vector's full size: // Orbit coeff vector's full size:
const size_t orbit_fullsizeR = otR->size * otR->bspecn; const size_t orbit_fullsizeR = otR->size * otR->bspecn;
const size_t particle_fullsizeR = otR->bspecn; // == bspecR->n const size_t particle_fullsizeR = otR->bspecn; // == bspecR->n
@ -1146,7 +1150,7 @@ complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_serial(
const cart3_t posR = ss->p[piR].pos; const cart3_t posR = ss->p[piR].pos;
if(orbit_packedsizeR) { // avoid zgemm crash on empty irrep if(orbit_packedsizeR) { // avoid zgemm crash on empty irrep
// dest particle T-matrix // dest particle T-matrix
const complex double *tmmR = ss->tm[ss->p[piR].tmatrix_id]->m; const complex double *tmmR = ssw->tm[ss->p[piR].tmatrix_id]->m;
for(qpms_ss_pi_t piC = 0; piC < ss->p_count; ++piC) { //Column loop for(qpms_ss_pi_t piC = 0; piC < ss->p_count; ++piC) { //Column loop
const qpms_ss_oti_t otiC = ss->p_orbitinfo[piC].t; const qpms_ss_oti_t otiC = ss->p_orbitinfo[piC].t;
const qpms_ss_orbit_type_t *const otC = ss->orbit_types + otiC; const qpms_ss_orbit_type_t *const otC = ss->orbit_types + otiC;
@ -1156,7 +1160,7 @@ complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_serial(
const size_t packed_orbit_offsetC = const size_t packed_orbit_offsetC =
ss->saecv_ot_offsets[iri*ss->orbit_type_count + otiC] ss->saecv_ot_offsets[iri*ss->orbit_type_count + otiC]
+ osnC * otC->irbase_sizes[iri]; + osnC * otC->irbase_sizes[iri];
const qpms_vswf_set_spec_t *bspecC = ss->tm[ss->p[piC].tmatrix_id]->spec; const qpms_vswf_set_spec_t *bspecC = ssw->tm[ss->p[piC].tmatrix_id]->spec;
// Orbit coeff vector's full size: // Orbit coeff vector's full size:
const size_t orbit_fullsizeC = otC->size * otC->bspecn; const size_t orbit_fullsizeC = otC->size * otC->bspecn;
const size_t particle_fullsizeC = otC->bspecn; // == bspecC->n const size_t particle_fullsizeC = otC->bspecn; // == bspecC->n
@ -1211,10 +1215,11 @@ complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_serial(
complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorderR( complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorderR(
/// Target memory with capacity for ss->saecv_sizes[iri]**2 elements. If NULL, new will be allocated. /// Target memory with capacity for ss->saecv_sizes[iri]**2 elements. If NULL, new will be allocated.
complex double *target_packed, complex double *target_packed,
const qpms_scatsys_t *ss, qpms_iri_t iri, const qpms_scatsys_at_omega_t *ssw, qpms_iri_t iri
complex double k ///< Wave number to use in the translation matrix.
) )
{ {
const qpms_scatsys_t *ss = ssw->ss;
const complex double k = ssw->wavenumber;
const size_t packedlen = ss->saecv_sizes[iri]; const size_t packedlen = ss->saecv_sizes[iri];
if (!packedlen) // THIS IS A BIT PROBLEMATIC, TODO how to deal with empty irreps? if (!packedlen) // THIS IS A BIT PROBLEMATIC, TODO how to deal with empty irreps?
return target_packed; return target_packed;
@ -1248,7 +1253,7 @@ complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorderR(
if(orbit_packedsizeR) { // avoid zgemm crash on empty irrep if(orbit_packedsizeR) { // avoid zgemm crash on empty irrep
const size_t particle_fullsizeR = otR->bspecn; // == bspecR->n const size_t particle_fullsizeR = otR->bspecn; // == bspecR->n
const qpms_vswf_set_spec_t *bspecR = ss->tm[ss->p[orbitstartpiR].tmatrix_id]->spec; const qpms_vswf_set_spec_t *bspecR = ssw->tm[ss->p[orbitstartpiR].tmatrix_id]->spec;
// This is the orbit-level matrix projecting the whole orbit onto the irrep. // This is the orbit-level matrix projecting the whole orbit onto the irrep.
const complex double *omR = otR->irbases + otR->irbase_offsets[iri]; const complex double *omR = otR->irbases + otR->irbase_offsets[iri];
// Orbit coeff vector's full size: // Orbit coeff vector's full size:
@ -1264,7 +1269,7 @@ complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorderR(
assert(ss->p_orbitinfo[piR].osn == osnR); assert(ss->p_orbitinfo[piR].osn == osnR);
const cart3_t posR = ss->p[piR].pos; const cart3_t posR = ss->p[piR].pos;
// dest particle T-matrix // dest particle T-matrix
const complex double *tmmR = ss->tm[ss->p[piR].tmatrix_id]->m; const complex double *tmmR = ssw->tm[ss->p[piR].tmatrix_id]->m;
for(qpms_ss_pi_t piC = 0; piC < ss->p_count; ++piC) { //Column loop for(qpms_ss_pi_t piC = 0; piC < ss->p_count; ++piC) { //Column loop
const qpms_ss_oti_t otiC = ss->p_orbitinfo[piC].t; const qpms_ss_oti_t otiC = ss->p_orbitinfo[piC].t;
const qpms_ss_orbit_type_t *const otC = ss->orbit_types + otiC; const qpms_ss_orbit_type_t *const otC = ss->orbit_types + otiC;
@ -1274,7 +1279,7 @@ complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorderR(
const size_t packed_orbit_offsetC = const size_t packed_orbit_offsetC =
ss->saecv_ot_offsets[iri*ss->orbit_type_count + otiC] ss->saecv_ot_offsets[iri*ss->orbit_type_count + otiC]
+ osnC * otC->irbase_sizes[iri]; + osnC * otC->irbase_sizes[iri];
const qpms_vswf_set_spec_t *bspecC = ss->tm[ss->p[piC].tmatrix_id]->spec; const qpms_vswf_set_spec_t *bspecC = ssw->tm[ss->p[piC].tmatrix_id]->spec;
// Orbit coeff vector's full size: // Orbit coeff vector's full size:
const size_t orbit_fullsizeC = otC->size * otC->bspecn; const size_t orbit_fullsizeC = otC->size * otC->bspecn;
const size_t particle_fullsizeC = otC->bspecn; // == bspecC->n const size_t particle_fullsizeC = otC->bspecn; // == bspecC->n
@ -1328,19 +1333,20 @@ complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorderR(
} }
struct qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread_arg{ struct qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread_arg{
const qpms_scatsys_t *ss; const qpms_scatsys_at_omega_t *ssw;
qpms_ss_pi_t *opistartR_ptr; qpms_ss_pi_t *opistartR_ptr;
pthread_mutex_t *opistartR_mutex; pthread_mutex_t *opistartR_mutex;
qpms_iri_t iri; qpms_iri_t iri;
complex double *target_packed; complex double *target_packed;
complex double k;
}; };
static void *qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread(void *arg) static void *qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread(void *arg)
{ {
const struct qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread_arg const struct qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread_arg
*a = arg; *a = arg;
const qpms_scatsys_t *ss = a->ss; const qpms_scatsys_at_omega_t *ssw = a->ssw;
const complex double k = ssw->wavenumber;
const qpms_scatsys_t *ss = ssw->ss;
const qpms_iri_t iri = a->iri; const qpms_iri_t iri = a->iri;
const size_t packedlen = ss->saecv_sizes[iri]; const size_t packedlen = ss->saecv_sizes[iri];
@ -1380,7 +1386,7 @@ static void *qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread
if(orbit_packedsizeR) { // avoid zgemm crash on empty irrep if(orbit_packedsizeR) { // avoid zgemm crash on empty irrep
const size_t particle_fullsizeR = otR->bspecn; // == bspecR->n const size_t particle_fullsizeR = otR->bspecn; // == bspecR->n
const qpms_vswf_set_spec_t *bspecR = ss->tm[ss->p[orbitstartpiR].tmatrix_id]->spec; const qpms_vswf_set_spec_t *bspecR = ssw->tm[ss->p[orbitstartpiR].tmatrix_id]->spec;
// This is the orbit-level matrix projecting the whole orbit onto the irrep. // This is the orbit-level matrix projecting the whole orbit onto the irrep.
const complex double *omR = otR->irbases + otR->irbase_offsets[iri]; const complex double *omR = otR->irbases + otR->irbase_offsets[iri];
// Orbit coeff vector's full size: // Orbit coeff vector's full size:
@ -1396,7 +1402,7 @@ static void *qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread
assert(ss->p_orbitinfo[piR].osn == osnR); assert(ss->p_orbitinfo[piR].osn == osnR);
const cart3_t posR = ss->p[piR].pos; const cart3_t posR = ss->p[piR].pos;
// dest particle T-matrix // dest particle T-matrix
const complex double *tmmR = ss->tm[ss->p[piR].tmatrix_id]->m; const complex double *tmmR = ssw->tm[ss->p[piR].tmatrix_id]->m;
for(qpms_ss_pi_t piC = 0; piC < ss->p_count; ++piC) { //Column loop for(qpms_ss_pi_t piC = 0; piC < ss->p_count; ++piC) { //Column loop
const qpms_ss_oti_t otiC = ss->p_orbitinfo[piC].t; const qpms_ss_oti_t otiC = ss->p_orbitinfo[piC].t;
const qpms_ss_orbit_type_t *const otC = ss->orbit_types + otiC; const qpms_ss_orbit_type_t *const otC = ss->orbit_types + otiC;
@ -1406,7 +1412,7 @@ static void *qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread
const size_t packed_orbit_offsetC = const size_t packed_orbit_offsetC =
ss->saecv_ot_offsets[iri*ss->orbit_type_count + otiC] ss->saecv_ot_offsets[iri*ss->orbit_type_count + otiC]
+ osnC * otC->irbase_sizes[iri]; + osnC * otC->irbase_sizes[iri];
const qpms_vswf_set_spec_t *bspecC = ss->tm[ss->p[piC].tmatrix_id]->spec; const qpms_vswf_set_spec_t *bspecC = ssw->tm[ss->p[piC].tmatrix_id]->spec;
// Orbit coeff vector's full size: // Orbit coeff vector's full size:
const size_t orbit_fullsizeC = otC->size * otC->bspecn; const size_t orbit_fullsizeC = otC->size * otC->bspecn;
const size_t particle_fullsizeC = otC->bspecn; // == bspecC->n const size_t particle_fullsizeC = otC->bspecn; // == bspecC->n
@ -1465,12 +1471,11 @@ static void *qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread
// this differs from the ...build_modeproblem_matrix... only by the `J` // this differs from the ...build_modeproblem_matrix... only by the `J`
// maybe I should use this one there as well to save lines... TODO // maybe I should use this one there as well to save lines... TODO
struct qpms_scatsys_build_translation_matrix_e_irrep_packed_parallelR_thread_arg{ struct qpms_scatsys_build_translation_matrix_e_irrep_packed_parallelR_thread_arg{
const qpms_scatsys_t *ss; const qpms_scatsys_at_omega_t *ssw;
qpms_ss_pi_t *opistartR_ptr; qpms_ss_pi_t *opistartR_ptr;
pthread_mutex_t *opistartR_mutex; pthread_mutex_t *opistartR_mutex;
qpms_iri_t iri; qpms_iri_t iri;
complex double *target_packed; complex double *target_packed;
complex double k;
qpms_bessel_t J; qpms_bessel_t J;
}; };
@ -1478,7 +1483,9 @@ static void *qpms_scatsys_build_translation_matrix_e_irrep_packed_parallelR_thre
{ {
const struct qpms_scatsys_build_translation_matrix_e_irrep_packed_parallelR_thread_arg const struct qpms_scatsys_build_translation_matrix_e_irrep_packed_parallelR_thread_arg
*a = arg; *a = arg;
const qpms_scatsys_t *ss = a->ss; const qpms_scatsys_at_omega_t *ssw = a->ssw;
const qpms_scatsys_t *ss = ssw->ss;
const complex double k = ssw->wavenumber;
const qpms_iri_t iri = a->iri; const qpms_iri_t iri = a->iri;
const size_t packedlen = ss->saecv_sizes[iri]; const size_t packedlen = ss->saecv_sizes[iri];
const qpms_bessel_t J = a->J; const qpms_bessel_t J = a->J;
@ -1517,7 +1524,7 @@ static void *qpms_scatsys_build_translation_matrix_e_irrep_packed_parallelR_thre
if(orbit_packedsizeR) { // avoid zgemm crash on empty irrep if(orbit_packedsizeR) { // avoid zgemm crash on empty irrep
const size_t particle_fullsizeR = otR->bspecn; // == bspecR->n const size_t particle_fullsizeR = otR->bspecn; // == bspecR->n
const qpms_vswf_set_spec_t *bspecR = ss->tm[ss->p[orbitstartpiR].tmatrix_id]->spec; const qpms_vswf_set_spec_t *bspecR = ssw->tm[ss->p[orbitstartpiR].tmatrix_id]->spec;
// This is the orbit-level matrix projecting the whole orbit onto the irrep. // This is the orbit-level matrix projecting the whole orbit onto the irrep.
const complex double *omR = otR->irbases + otR->irbase_offsets[iri]; const complex double *omR = otR->irbases + otR->irbase_offsets[iri];
// Orbit coeff vector's full size: // Orbit coeff vector's full size:
@ -1541,7 +1548,7 @@ static void *qpms_scatsys_build_translation_matrix_e_irrep_packed_parallelR_thre
const size_t packed_orbit_offsetC = const size_t packed_orbit_offsetC =
ss->saecv_ot_offsets[iri*ss->orbit_type_count + otiC] ss->saecv_ot_offsets[iri*ss->orbit_type_count + otiC]
+ osnC * otC->irbase_sizes[iri]; + osnC * otC->irbase_sizes[iri];
const qpms_vswf_set_spec_t *bspecC = ss->tm[ss->p[piC].tmatrix_id]->spec; const qpms_vswf_set_spec_t *bspecC = ssw->tm[ss->p[piC].tmatrix_id]->spec;
// Orbit coeff vector's full size: // Orbit coeff vector's full size:
const size_t orbit_fullsizeC = otC->size * otC->bspecn; const size_t orbit_fullsizeC = otC->size * otC->bspecn;
const size_t particle_fullsizeC = otC->bspecn; // == bspecC->n const size_t particle_fullsizeC = otC->bspecn; // == bspecC->n
@ -1600,7 +1607,7 @@ complex double *qpms_scatsys_build_translation_matrix_e_irrep_packed(
complex double *target_packed, complex double *target_packed,
const qpms_scatsys_t *ss, const qpms_scatsys_t *ss,
qpms_iri_t iri, qpms_iri_t iri,
complex double k, ///< Wave number to use in the translation matrix. const complex double k;
qpms_bessel_t J qpms_bessel_t J
) )
{ {
@ -1616,7 +1623,7 @@ complex double *qpms_scatsys_build_translation_matrix_e_irrep_packed(
pthread_mutex_t opistartR_mutex; pthread_mutex_t opistartR_mutex;
QPMS_ENSURE_SUCCESS(pthread_mutex_init(&opistartR_mutex, NULL)); QPMS_ENSURE_SUCCESS(pthread_mutex_init(&opistartR_mutex, NULL));
const struct qpms_scatsys_build_translation_matrix_e_irrep_packed_parallelR_thread_arg const struct qpms_scatsys_build_translation_matrix_e_irrep_packed_parallelR_thread_arg
arg = {ss, &opistartR, &opistartR_mutex, iri, target_packed, k, J}; arg = {ssw, &opistartR, &opistartR_mutex, iri, target_packed, J};
// FIXME THIS IS NOT PORTABLE: // FIXME THIS IS NOT PORTABLE:
long nthreads; long nthreads;
@ -1653,11 +1660,10 @@ complex double *qpms_scatsys_build_translation_matrix_e_irrep_packed(
complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed( complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed(
/// Target memory with capacity for ss->saecv_sizes[iri]**2 elements. If NULL, new will be allocated. /// Target memory with capacity for ss->saecv_sizes[iri]**2 elements. If NULL, new will be allocated.
complex double *target_packed, complex double *target_packed,
const qpms_scatsys_t *ss, qpms_iri_t iri, const qpms_scatsys_at_omega_t *ssw, qpms_iri_t iri
complex double k ///< Wave number to use in the translation matrix.
) )
{ {
const size_t packedlen = ss->saecv_sizes[iri]; const size_t packedlen = ssw->ss->saecv_sizes[iri];
if (!packedlen) // THIS IS A BIT PROBLEMATIC, TODO how to deal with empty irreps? if (!packedlen) // THIS IS A BIT PROBLEMATIC, TODO how to deal with empty irreps?
return target_packed; return target_packed;
if (target_packed == NULL) if (target_packed == NULL)
@ -1668,7 +1674,7 @@ complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed(
pthread_mutex_t opistartR_mutex; pthread_mutex_t opistartR_mutex;
QPMS_ENSURE_SUCCESS(pthread_mutex_init(&opistartR_mutex, NULL)); QPMS_ENSURE_SUCCESS(pthread_mutex_init(&opistartR_mutex, NULL));
const struct qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread_arg const struct qpms_scatsys_build_modeproblem_matrix_irrep_packed_parallelR_thread_arg
arg = {ss, &opistartR, &opistartR_mutex, iri, target_packed, k}; arg = {ssw, &opistartR, &opistartR_mutex, iri, target_packed};
// FIXME THIS IS NOT PORTABLE: // FIXME THIS IS NOT PORTABLE:
long nthreads; long nthreads;
@ -1784,7 +1790,8 @@ void qpms_ss_LU_free(qpms_ss_LU lu) {
} }
qpms_ss_LU qpms_scatsys_modeproblem_matrix_full_factorise(complex double *mpmatrix_full, qpms_ss_LU qpms_scatsys_modeproblem_matrix_full_factorise(complex double *mpmatrix_full,
int *target_piv, const qpms_scatsys_t *ss) { int *target_piv, const qpms_scatsys_at_omega_t *ssw) {
const qpms_scatsys_t *ss = ssw->ss;
QPMS_ENSURE(mpmatrix_full, "A non-NULL pointer to the pre-calculated mode matrix is required"); QPMS_ENSURE(mpmatrix_full, "A non-NULL pointer to the pre-calculated mode matrix is required");
if (!target_piv) QPMS_CRASHING_MALLOC(target_piv, ss->fecv_size * sizeof(int)); if (!target_piv) QPMS_CRASHING_MALLOC(target_piv, ss->fecv_size * sizeof(int));
QPMS_ENSURE_SUCCESS(LAPACKE_zgetrf(LAPACK_ROW_MAJOR, ss->fecv_size, ss->fecv_size, QPMS_ENSURE_SUCCESS(LAPACKE_zgetrf(LAPACK_ROW_MAJOR, ss->fecv_size, ss->fecv_size,
@ -1792,23 +1799,23 @@ qpms_ss_LU qpms_scatsys_modeproblem_matrix_full_factorise(complex double *mpmatr
qpms_ss_LU lu; qpms_ss_LU lu;
lu.a = mpmatrix_full; lu.a = mpmatrix_full;
lu.ipiv = target_piv; lu.ipiv = target_piv;
lu.ss = ss; lu.ssw = ssw;
lu.full = true; lu.full = true;
lu.iri = -1; lu.iri = -1;
return lu; return lu;
} }
qpms_ss_LU qpms_scatsys_modeproblem_matrix_irrep_packed_factorise(complex double *mpmatrix_packed, qpms_ss_LU qpms_scatsys_modeproblem_matrix_irrep_packed_factorise(complex double *mpmatrix_packed,
int *target_piv, const qpms_scatsys_t *ss, qpms_iri_t iri) { int *target_piv, const qpms_scatsys_at_omega_t *ssw, qpms_iri_t iri) {
QPMS_ENSURE(mpmatrix_packed, "A non-NULL pointer to the pre-calculated mode matrix is required"); QPMS_ENSURE(mpmatrix_packed, "A non-NULL pointer to the pre-calculated mode matrix is required");
size_t n = ss->saecv_sizes[iri]; size_t n = ssw->ss->saecv_sizes[iri];
if (!target_piv) QPMS_CRASHING_MALLOC(target_piv, n * sizeof(int)); if (!target_piv) QPMS_CRASHING_MALLOC(target_piv, n * sizeof(int));
QPMS_ENSURE_SUCCESS(LAPACKE_zgetrf(LAPACK_ROW_MAJOR, n, n, QPMS_ENSURE_SUCCESS(LAPACKE_zgetrf(LAPACK_ROW_MAJOR, n, n,
mpmatrix_packed, n, target_piv)); mpmatrix_packed, n, target_piv));
qpms_ss_LU lu; qpms_ss_LU lu;
lu.a = mpmatrix_packed; lu.a = mpmatrix_packed;
lu.ipiv = target_piv; lu.ipiv = target_piv;
lu.ss = ss; lu.ssw = ssw;
lu.full = false; lu.full = false;
lu.iri = iri; lu.iri = iri;
return lu; return lu;
@ -1816,21 +1823,21 @@ qpms_ss_LU qpms_scatsys_modeproblem_matrix_irrep_packed_factorise(complex double
qpms_ss_LU qpms_scatsys_build_modeproblem_matrix_full_LU( qpms_ss_LU qpms_scatsys_build_modeproblem_matrix_full_LU(
complex double *target, int *target_piv, complex double *target, int *target_piv,
const qpms_scatsys_t *ss, complex double k){ const qpms_scatsys_at_omega_t *ssw){
target = qpms_scatsys_build_modeproblem_matrix_full(target, ss, k); target = qpms_scatsys_build_modeproblem_matrix_full(target, ssw);
return qpms_scatsys_modeproblem_matrix_full_factorise(target, target_piv, ss); return qpms_scatsys_modeproblem_matrix_full_factorise(target, target_piv, ssw);
} }
qpms_ss_LU qpms_scatsys_build_modeproblem_matrix_irrep_packed_LU( qpms_ss_LU qpms_scatsys_build_modeproblem_matrix_irrep_packed_LU(
complex double *target, int *target_piv, complex double *target, int *target_piv,
const qpms_scatsys_t *ss, qpms_iri_t iri, complex double k){ const qpms_scatsys_at_omega_t *ssw, qpms_iri_t iri){
target = qpms_scatsys_build_modeproblem_matrix_irrep_packed(target, ss, iri, k); target = qpms_scatsys_build_modeproblem_matrix_irrep_packed(target, ssw, iri);
return qpms_scatsys_modeproblem_matrix_irrep_packed_factorise(target, target_piv, ss, iri); return qpms_scatsys_modeproblem_matrix_irrep_packed_factorise(target, target_piv, ssw, iri);
} }
complex double *qpms_scatsys_scatter_solve( complex double *qpms_scatsys_scatter_solve(
complex double *f, const complex double *a_inc, qpms_ss_LU lu) { complex double *f, const complex double *a_inc, qpms_ss_LU lu) {
const size_t n = lu.full ? lu.ss->fecv_size : lu.ss->saecv_sizes[lu.iri]; const size_t n = lu.full ? lu.ssw->ss->fecv_size : lu.ssw->ss->saecv_sizes[lu.iri];
if (!f) QPMS_CRASHING_MALLOC(f, n * sizeof(complex double)); if (!f) QPMS_CRASHING_MALLOC(f, n * sizeof(complex double));
memcpy(f, a_inc, n*sizeof(complex double)); // It will be rewritten by zgetrs memcpy(f, a_inc, n*sizeof(complex double)); // It will be rewritten by zgetrs
QPMS_ENSURE_SUCCESS(LAPACKE_zgetrs(LAPACK_ROW_MAJOR, 'N' /*trans*/, n /*n*/, 1 /*nrhs number of right hand sides*/, QPMS_ENSURE_SUCCESS(LAPACKE_zgetrs(LAPACK_ROW_MAJOR, 'N' /*trans*/, n /*n*/, 1 /*nrhs number of right hand sides*/,

View File

@ -12,6 +12,7 @@
#define QPMS_SCATSYSTEM_H #define QPMS_SCATSYSTEM_H
#include "qpms_types.h" #include "qpms_types.h"
#include "vswf.h" #include "vswf.h"
#include "tmatrices.h"
#include <stdbool.h> #include <stdbool.h>
/// Overrides the number of threads spawned by the paralellized functions. /// Overrides the number of threads spawned by the paralellized functions.
@ -124,7 +125,7 @@ typedef struct qpms_ss_particle_orbitinfo {
/// Auxillary type used in qpms_scatsys_t: A recepy to create another T-matrices by symmetry operations. /// Auxillary type used in qpms_scatsys_t: A recepy to create another T-matrices by symmetry operations.
typedef struct qpms_ss_derived_tmatrix { typedef struct qpms_ss_derived_tmatrix {
qpms_ss_tmgi_t tmgi; ///< Index of the corresponding qpms_scatsys_t::tm element. qpms_ss_tmgi_t tmgi; ///< Index of the corresponding qpms_scatsys_t::tm element.
qpms_tmatrix_operation_t *op; ///< Operation to derive this particular T-matrix. struct qpms_tmatrix_operation_t *op; ///< Operation to derive this particular T-matrix.
} qpms_ss_derived_tmatrix_t; } qpms_ss_derived_tmatrix_t;
@ -132,7 +133,7 @@ struct qpms_trans_calculator;
struct qpms_epsmu_generator_t; struct qpms_epsmu_generator_t;
typedef struct qpms_scatsys_t { typedef struct qpms_scatsys_t {
struct qpms_epsmu_generator_t *medium; ///< Optical properties of the background medium. struct qpms_epsmu_generator_t medium; ///< Optical properties of the background medium.
/// (Template) T-matrix functions in the system. /// (Template) T-matrix functions in the system.
/** The qpms_abstract_tmatrix_t objects (onto which this array member point) /** The qpms_abstract_tmatrix_t objects (onto which this array member point)
@ -187,8 +188,13 @@ typedef struct qpms_scatsys_t {
} qpms_scatsys_t; } qpms_scatsys_t;
/// Retrieve the bspec of \a tmi'th element of \a ss->tm. /// Retrieve the bspec of \a tmi'th element of \a ss->tm.
static inline const qpms_vswf_set_spec_t *qpms_ss_bspec_tmi(qpms_scatsys_t *ss, qpms_ss_tmi_t *tmi) { static inline const qpms_vswf_set_spec_t *qpms_ss_bspec_tmi(qpms_scatsys_t *ss, qpms_ss_tmi_t tmi) {
return ss->tmg[ss->tm[tmi].tmgi]->spec; return ss->tmg[ss->tm[tmi].tmgi].spec;
}
/// Retrieve the bspec of \a pi'th particle in \a ss->p.
static inline const qpms_vswf_set_spec_t *qpms_ss_bspec_pi(qpms_scatsys_t *ss, qpms_ss_pi_t pi) {
return ss->tmg[ss->tm[ss->p[pi].tmatrix_id].tmgi].spec;
} }
typedef struct qpms_scatsys_at_omega_t { typedef struct qpms_scatsys_at_omega_t {
@ -205,11 +211,6 @@ typedef struct qpms_scatsys_at_omega_t {
void qpms_scatsys_at_omega_free(qpms_scatsys_at_omega_t *); void qpms_scatsys_at_omega_free(qpms_scatsys_at_omega_t *);
/// Convenience function to access pi'th particle's bspec.
static inline const qpms_vswf_set_spec_t *qpms_ss_bspec_pi(const qpms_scatsys_t *ss, qpms_ss_pi_t pi) {
return ss->tm[ss->p[pi].tmatrix_id]->spec;
}
/// Creates a new scatsys by applying a symmetry group onto a "proto-scatsys", copying particles if needed. /// 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, /** In fact, it copies everything except the vswf set specs and qpms_abstract_tmatrix_t instances,
* so keep them alive until scatsys is destroyed. * so keep them alive until scatsys is destroyed.
@ -239,13 +240,13 @@ static inline const qpms_vswf_set_spec_t *qpms_ss_bspec_pi(const qpms_scatsys_t
* qpms_scatsys_free() when not needed anymore. * qpms_scatsys_free() when not needed anymore.
*/ */
qpms_scatsys_at_omega_t *qpms_scatsys_apply_symmetry(const qpms_scatsys_t *orig, const struct qpms_finite_group_t *sym, qpms_scatsys_at_omega_t *qpms_scatsys_apply_symmetry(const qpms_scatsys_t *orig, const struct qpms_finite_group_t *sym,
complex double omega, const qpms_tolerance_spec_t *tol); complex double omega, const struct qpms_tolerance_spec_t *tol);
/// Destroys the result of qpms_scatsys_apply_symmetry or qpms_scatsys_load. /// Destroys the result of qpms_scatsys_apply_symmetry or qpms_scatsys_load.
void qpms_scatsys_free(qpms_scatsys_t *s); void qpms_scatsys_free(qpms_scatsys_t *s);
/// Destroys the result of qpms_scatsys_eval_at_omega() /// Destroys the result of qpms_scatsys_eval_at_omega()
void qpms_scatsys_at_omega_free(qpms_scatsys_at_omega *so); void qpms_scatsys_at_omega_free(qpms_scatsys_at_omega_t *ssw);
/// Creates a "full" transformation matrix U that takes a full vector and projects it onto an symmetry adapted basis. /// 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. /** Mostly as a reference and a debugging tool, as multiplicating these big matrices would be inefficient.
@ -329,37 +330,36 @@ complex double *qpms_scatsys_build_translation_matrix_e_irrep_packed(
); );
/// Creates the full \f$ (I - TS) \f$ matrix of the scattering system. /// Creates the full \f$ (I - TS) \f$ matrix of the scattering system.
complex double *qpms_scatsys_build_modeproblem_matrix_full( complex double *qpms_scatsys_at_omega_build_modeproblem_matrix_full(
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated. /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
complex double *target, complex double *target,
const qpms_scatsys_t *ss, const qpms_scatsys_at_omega_t *ssw
complex double k ///< Wave number to use in the translation matrix.
); );
/// Creates the mode problem matrix \f$ (I - TS) \f$ directly in the irrep-packed form. /// Creates the mode problem matrix \f$ (I - TS) \f$ directly in the irrep-packed form.
complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed( complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed(
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated. /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
complex double *target, complex double *target,
const qpms_scatsys_t *ss, qpms_iri_t iri, const qpms_scatsys_at_omega_t *ssw,
complex double k ///< Wave number to use in the translation matrix. qpms_iri_t iri
); );
/// Alternative implementation of qpms_scatsys_build_modeproblem_matrix_irrep_packed(). /// Alternative implementation of qpms_scatsys_build_modeproblem_matrix_irrep_packed().
complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorderR( complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorderR(
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated. /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
complex double *target, complex double *target,
const qpms_scatsys_t *ss, qpms_iri_t iri, const qpms_scatsys_at_omega_t *ssw,
complex double k ///< Wave number to use in the translation matrix. qpms_iri_t iri
); );
/// Alternative (serial reference) implementation of qpms_scatsys_build_modeproblem_matrix_irrep_packed(). /// Alternative (serial reference) implementation of qpms_scatsys_build_modeproblem_matrix_irrep_packed().
complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorder_serial( complex double *qpms_scatsys_build_modeproblem_matrix_irrep_packed_orbitorder_serial(
/// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated. /// Target memory with capacity for ss->fecv_size**2 elements. If NULL, new will be allocated.
complex double *target, complex double *target,
const qpms_scatsys_t *ss, qpms_iri_t iri, const qpms_scatsys_at_omega_t *ssw,
complex double k ///< Wave number to use in the translation matrix. qpms_iri_t iri
); );
/// LU factorisation (LAPACKE_zgetrf) result holder. /// LU factorisation (LAPACKE_zgetrf) result holder.
typedef struct qpms_ss_LU { typedef struct qpms_ss_LU {
const qpms_scatsys_t *ss; const qpms_scatsys_at_omega_t *ssw;
bool full; ///< true if full matrix; false if irrep-packed. bool full; ///< true if full matrix; false if irrep-packed.
qpms_iri_t iri; ///< Irrep index if `full == false`. qpms_iri_t iri; ///< Irrep index if `full == false`.
/// LU decomposition array. /// LU decomposition array.
@ -373,30 +373,30 @@ void qpms_ss_LU_free(qpms_ss_LU);
qpms_ss_LU qpms_scatsys_build_modeproblem_matrix_full_LU( qpms_ss_LU qpms_scatsys_build_modeproblem_matrix_full_LU(
complex double *target, ///< Pre-allocated target array. Optional (if NULL, new one is allocated). 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). int *target_piv, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
const qpms_scatsys_t *ss, const qpms_scatsys_at_omega_t *ssw
complex double k ///< Wave number to use in the translation matrix.
); );
/// Builds an irrep-packed LU-factorised mode/scattering problem matrix from scratch. /// Builds an irrep-packed LU-factorised mode/scattering problem matrix from scratch.
qpms_ss_LU qpms_scatsys_build_modeproblem_matrix_irrep_packed_LU( qpms_ss_LU qpms_scatsys_build_modeproblem_matrix_irrep_packed_LU(
complex double *target, ///< Pre-allocated target array. Optional (if NULL, new one is allocated). 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). int *target_piv, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
const qpms_scatsys_t *ss, qpms_iri_t iri, const qpms_scatsys_at_omega_t *ssw,
complex double k ///< Wave number to use in the translation matrix. qpms_iri_t iri
); );
/// Computes LU factorisation of a pre-calculated mode/scattering problem matrix, replacing its contents. /// Computes LU factorisation of a pre-calculated mode/scattering problem matrix, replacing its contents.
qpms_ss_LU qpms_scatsys_modeproblem_matrix_full_factorise( qpms_ss_LU qpms_scatsys_modeproblem_matrix_full_factorise(
complex double *modeproblem_matrix_full, ///< Pre-calculated mode problem matrix (I-TS). Mandatory. 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). int *target_piv, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
const qpms_scatsys_t *ss const qpms_scatsys_at_omega_t *ssw
); );
/// Computes LU factorisation of a pre-calculated irrep-packed mode/scattering problem matrix, replacing its contents. /// Computes LU factorisation of a pre-calculated irrep-packed mode/scattering problem matrix, replacing its contents.
qpms_ss_LU qpms_scatsys_modeproblem_matrix_irrep_packed_factorise( qpms_ss_LU qpms_scatsys_modeproblem_matrix_irrep_packed_factorise(
complex double *modeproblem_matrix_irrep_packed, ///< Pre-calculated mode problem matrix (I-TS). Mandatory. 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). int *target_piv, ///< Pre-allocated pivot array. Optional (if NULL, new one is allocated).
const qpms_scatsys_t *ss, qpms_iri_t iri const qpms_scatsys_at_omega_t *ssw,
qpms_iri_t iri
); );
/// Solves a (possibly partial, irrep-packed) scattering problem \f$ (I-TS)f = Ta_\mathrm{inc} \f$ using a pre-factorised \f$ (I-TS) \f$. /// Solves a (possibly partial, irrep-packed) scattering problem \f$ (I-TS)f = Ta_\mathrm{inc} \f$ using a pre-factorised \f$ (I-TS) \f$.
@ -488,7 +488,7 @@ complex double *qpms_scatsys_incident_field_vector_full(
complex double *qpms_scatsys_apply_Tmatrices_full( complex double *qpms_scatsys_apply_Tmatrices_full(
complex double *target_full, /// Target vector array. If NULL, a new one is allocated. 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. const complex double *inc_full, /// Incident field coefficient vector. Must not be NULL.
const qpms_scatsys_t *ss const qpms_scatsys_at_omega_t *ssw
); );

View File

@ -53,6 +53,15 @@ qpms_tmatrix_t *qpms_tmatrix_init(const qpms_vswf_set_spec_t *bspec) {
return t; return t;
} }
qpms_tmatrix_t *qpms_tmatrix_init_from_generator(
const qpms_vswf_set_spec_t *bspec,
qpms_tmatrix_generator_t gen,
complex double omega) {
qpms_tmatrix_t *t = qpms_tmatrix_init(bspec);
QPMS_ENSURE_SUCCESS(gen.function(t, omega, gen.params));
return t;
}
qpms_tmatrix_t *qpms_tmatrix_copy(const qpms_tmatrix_t *T) { qpms_tmatrix_t *qpms_tmatrix_copy(const qpms_tmatrix_t *T) {
qpms_tmatrix_t *t = qpms_tmatrix_init(T->spec); qpms_tmatrix_t *t = qpms_tmatrix_init(T->spec);
size_t n = T->spec->n; size_t n = T->spec->n;
@ -1107,7 +1116,7 @@ void qpms_tmatrix_operation_compose_chain_init(qpms_tmatrix_operation_t *dest,
if (nops < opmem_size) if (nops < opmem_size)
QPMS_WARN("Allocating buffer for %zu operations, in a chained operation of" QPMS_WARN("Allocating buffer for %zu operations, in a chained operation of"
" only %zu elemens, that does not seem to make sense.", opmem_size, nops); " only %zu elemens, that does not seem to make sense.", opmem_size, nops);
dest.typ = QPMS_TMATRIX_OPERATION_COMPOSE_CHAIN; dest->typ = QPMS_TMATRIX_OPERATION_COMPOSE_CHAIN;
struct qpms_tmatrix_operation_compose_chain * const o = struct qpms_tmatrix_operation_compose_chain * const o =
&(dest->op.compose_chain); &(dest->op.compose_chain);
o->n = nops; o->n = nops;

View File

@ -257,14 +257,11 @@ typedef struct qpms_tmatrix_generator_t {
} qpms_tmatrix_generator_t; } qpms_tmatrix_generator_t;
/// Initialises and evaluates a new T-matrix using a generator. /// Initialises and evaluates a new T-matrix using a generator.
static inline qpms_tmatrix_t *qpms_tmatrix_init_from_generator( qpms_tmatrix_t *qpms_tmatrix_init_from_generator(
const qpms_vswf_set_spec_t *bspec, const qpms_vswf_set_spec_t *bspec,
qpms_tmatrix_generator_t gen, qpms_tmatrix_generator_t gen,
complex double omega) { complex double omega);
qpms_tmatrix_t *t = qpms_tmatrix_init(bspec);
QPMS_ENSURE_SUCCESS(gen.function(t, omega, gen.params));
return t;
}
/// Implementation of qpms_matrix_generator_t that just copies a constant matrix. /// Implementation of qpms_matrix_generator_t that just copies a constant matrix.
/** N.B. this does almost no checks at all, so use it only for t-matrices with /** N.B. this does almost no checks at all, so use it only for t-matrices with
@ -534,7 +531,7 @@ typedef struct qpms_tmatrix_function_t {
/// Convenience function to create a new T-matrix from qpms_tmatrix_function_t. /// Convenience function to create a new T-matrix from qpms_tmatrix_function_t.
// FIXME the name is not very intuitive. // FIXME the name is not very intuitive.
static inline qpms_tmatrix_t *qpms_tmatrix_init_from_function(qpms_tmatrix_function_t f, complex double omega) { static inline qpms_tmatrix_t *qpms_tmatrix_init_from_function(qpms_tmatrix_function_t f, complex double omega) {
return qpms_tmatrix_init_from_generator(f.spec, omega, f.gen); return qpms_tmatrix_init_from_generator(f.spec, *f.gen, omega);
} }
/// Specifies different kinds of operations done on T-matrices /// Specifies different kinds of operations done on T-matrices