Scatsystem: excitation coefficient vector irrep packing and unpacking.

Former-commit-id: 5a4b983f43a0e429a8d92eff435d763358a3ad99
This commit is contained in:
Marek Nečada 2019-03-07 12:15:46 +02:00
parent 0053eeb953
commit 519e60a501
2 changed files with 130 additions and 13 deletions

View File

@ -362,6 +362,7 @@ static void add_orbit_type(qpms_scatsys_t *ss, const qpms_ss_orbit_type_t *ot_cu
const qpms_vswf_set_spec_t *bspec = ss->tm[ot_current->tmatrices[0]]->spec;
const size_t bspecn = bspec->n;
ot_new->bspecn = bspecn;
const size_t actionsiz = sizeof(ot_current->action[0]) * ot_current->size
* ss->sym->order;
@ -381,6 +382,8 @@ static void add_orbit_type(qpms_scatsys_t *ss, const qpms_ss_orbit_type_t *ot_cu
ss->otspace_end += irbase_sizes_siz;
ot_new->irbase_cumsizes = (void *) (ss->otspace_end);
ss->otspace_end += irbase_sizes_siz;
ot_new->irbase_offsets = (void *) (ss->otspace_end);
ss->otspace_end += irbase_sizes_siz;
const size_t irbases_siz = sizeof(ot_new->irbases[0]) * SQ(ot_new->size * bspecn);
ot_new->irbases = (void *) (ss->otspace_end);
@ -388,6 +391,7 @@ static void add_orbit_type(qpms_scatsys_t *ss, const qpms_ss_orbit_type_t *ot_cu
size_t lastbs, bs_cumsum = 0;
for(qpms_iri_t iri = 0; iri < ss->sym->nirreps; ++iri) {
ot_new->irbase_offsets[iri] = bs_cumsum * bspecn * ot_new->size;
qpms_orbit_irrep_basis(&lastbs,
ot_new->irbases + bs_cumsum*ot_new->size*bspecn,
ot_new, bspec, ss->sym, iri);
@ -447,7 +451,7 @@ qpms_scatsys_t *qpms_scatsys_apply_symmetry(const qpms_scatsys_t *orig, const qp
// Copy T-matrices; checking for duplicities
size_t max_bspecn = 0; // We'll need it later.for memory alloc estimates.
ss->max_bspecn = 0; // We'll need it later.for memory alloc estimates.
qpms_ss_tmi_t tm_dupl_remap[ss->tm_capacity]; // Auxilliary array to label remapping the indices after ignoring t-matrix duplicities
ss->tm_count = 0;
@ -462,7 +466,7 @@ qpms_scatsys_t *qpms_scatsys_apply_symmetry(const qpms_scatsys_t *orig, const qp
++(ss->tm_count);
}
tm_dupl_remap[i] = j;
max_bspecn = MAX(ss->tm[i]->spec->n, max_bspecn);
ss->max_bspecn = MAX(ss->tm[i]->spec->n, ss->max_bspecn);
}
// Copy particles, remapping the t-matrix indices
@ -508,8 +512,8 @@ qpms_scatsys_t *qpms_scatsys_apply_symmetry(const qpms_scatsys_t *orig, const qp
ss->otspace_end = ss->otspace = malloc( // reallocate later
(sizeof(qpms_ss_orbit_pi_t) * sym->order * sym->order
+ sizeof(qpms_ss_tmi_t) * sym->order
+ 2*sizeof(size_t) * sym->nirreps
+ sizeof(complex double) * SQ(sym->order * max_bspecn)) * ss->p_count
+ 3*sizeof(size_t) * sym->nirreps
+ sizeof(complex double) * SQ(sym->order * ss->max_bspecn)) * ss->p_count
);
// Workspace for the orbit type determination
@ -614,6 +618,18 @@ qpms_scatsys_t *qpms_scatsys_apply_symmetry(const qpms_scatsys_t *orig, const qp
ss->fecv_size += ss->tm[ss->p[pi].tmatrix_id]->spec->n; // That's a lot of dereferencing!
}
ss->saecv_sizes = malloc(sizeof(size_t) * sym->nirreps); if (!ss->saecv_sizes) abort();
ss->saecv_ot_offsets = malloc(sizeof(size_t) * sym->nirreps * ss->orbit_type_count);
if (!ss->saecv_ot_offsets) abort();
for(qpms_iri_t iri = 0; iri < sym->nirreps; ++iri) {
ss->saecv_sizes[iri] = 0;
for(qpms_ss_oti_t oti = 0; oti < ss->orbit_type_count; ++oti) {
ss->saecv_ot_offsets[iri * ss->orbit_type_count + oti] = ss->saecv_sizes[iri];
const qpms_ss_orbit_type_t *ot = &(ss->orbit_types[oti]);
ss->saecv_sizes[iri] += ot->instance_count * ot->irbase_sizes[iri];
}
}
return ss;
}
@ -628,6 +644,7 @@ void qpms_scatsys_free(qpms_scatsys_t *ss) {
free(ss->otspace);
free(ss->p_orbitinfo);
free(ss->orbit_types);
free(ss->saecv_sizes);
}
free(ss);
}
@ -767,4 +784,94 @@ complex double *qpms_orbit_irrep_basis(size_t *basis_size,
}
complex double *qpms_scatsys_irrep_pack_matrix(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.
/** TODO doc */
complex double *qpms_scatsys_irrep_unpack_matrix(complex double *target_full,
const complex double *orig_packed, const qpms_scatsys_t *ss,
qpms_iri_t iri, bool add);
/// Projects a "big" vector onto an irrep.
/** TODO doc */
complex double *qpms_scatsys_irrep_pack_vector(complex double *target_packed,
const complex double *orig_full, const qpms_scatsys_t *ss,
const qpms_iri_t iri) {
const size_t packedlen = ss->saecv_sizes[iri];
if (target_packed == NULL)
target_packed = malloc(packedlen*sizeof(complex double));
if (target_packed == NULL) abort();
memset(target_packed, 0, packedlen*sizeof(complex double));
const complex double one = 1;
size_t fullvec_offset = 0;
for(qpms_ss_pi_t pi = 0; pi < ss->p_count; ++pi) {
const size_t bspecn = ss->tm[ss->p[pi].tmatrix_id]->spec->n;
const qpms_ss_oti_t oti = ss->p_orbitinfo[pi].t;
const qpms_ss_orbit_type_t *const ot = ss->orbit_types + oti;
const qpms_ss_osn_t osn = ss->p_orbitinfo[pi].osn;
const qpms_ss_orbit_pi_t opi = ss->p_orbitinfo[pi].p;
// This is where the particle's orbit starts in the "packed" vector:
const size_t packed_orbit_offset = ss->saecv_ot_offsets[iri*ss->orbit_type_count + oti]
+ osn * ot->irbase_sizes[iri];
// Orbit coeff vector's full size:
const size_t orbit_fullsize = ot->size * ot->bspecn;
const size_t particle_fullsize = ot->bspecn;
const size_t orbit_packedsize = ot->irbase_sizes[iri];
// This is the orbit-level matrix projecting the whole orbit onto the irrep.
const complex double *om = ot->irbases + ot->irbase_offsets[iri];
cblas_zgemv(CblasRowMajor, CblasNoTrans,
orbit_packedsize, particle_fullsize, &one, om + opi*particle_fullsize, orbit_fullsize,
orig_full+fullvec_offset, 1,
&one, target_packed+packed_orbit_offset, 1);
fullvec_offset += bspecn;
}
return target_packed;
}
/// Transforms a big "packed" vector into the full basis.
/** TODO doc */
complex double *qpms_scatsys_irrep_unpack_vector(complex double *target_full,
const complex double *orig_packed, const qpms_scatsys_t *ss,
const qpms_iri_t iri, bool add) {
const size_t full_len = ss->fecv_size;
if (target_full == NULL)
target_full = malloc(full_len*sizeof(complex double));
if (target_full == NULL) abort();
if (!add) memset(target_full, 0, full_len*sizeof(complex double));
const complex double one = 1;
size_t fullvec_offset = 0;
for(qpms_ss_pi_t pi = 0; pi < ss->p_count; ++pi) {
const size_t bspecn = ss->tm[ss->p[pi].tmatrix_id]->spec->n;
const qpms_ss_oti_t oti = ss->p_orbitinfo[pi].t;
const qpms_ss_orbit_type_t *const ot = ss->orbit_types + oti;
const qpms_ss_osn_t osn = ss->p_orbitinfo[pi].osn;
const qpms_ss_orbit_pi_t opi = ss->p_orbitinfo[pi].p;
// This is where the particle's orbit starts in the "packed" vector:
const size_t packed_orbit_offset = ss->saecv_ot_offsets[iri*ss->orbit_type_count + oti]
+ osn * ot->irbase_sizes[iri];
// Orbit coeff vector's full size:
const size_t orbit_fullsize = ot->size * ot->bspecn;
const size_t particle_fullsize = ot->bspecn;
const size_t orbit_packedsize = ot->irbase_sizes[iri];
// This is the orbit-level matrix projecting the whole orbit onto the irrep.
const complex double *om = ot->irbases + ot->irbase_offsets[iri];
cblas_zgemv(CblasRowMajor, CblasConjTrans,
orbit_packedsize, particle_fullsize, &one, om + opi*particle_fullsize, orbit_fullsize,
orig_packed+packed_orbit_offset, 1,
&one, target_full+fullvec_offset, 1);
fullvec_offset += bspecn;
}
return target_full;
}

View File

@ -314,7 +314,8 @@ typedef qpms_ss_tmi_t qpms_ss_oti_t; ///< Auxilliary type used for labeling orbi
*
*/
typedef struct qpms_ss_orbit_type_t {
qpms_ss_orbit_pi_t size; ///< Size of the orbit (a divisor of the group order).
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.
/// 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.
@ -341,8 +342,11 @@ typedef struct qpms_ss_orbit_type_t {
* TODO doc.
*/
size_t *irbase_sizes;
//The following are pretty redundant, TODO reduce them at some point.
/// Cumulative sums of irbase_sizes.
size_t *irbase_cumsizes;
/// TODO doc.
size_t *irbase_offsets;
/// Per-orbit irreducible representation orthonormal bases.
/** This also defines the unitary operator that transforms the orbital excitation coefficients
* in the symmetry-adapted basis.
@ -356,11 +360,13 @@ typedef struct qpms_ss_orbit_type_t {
size_t instance_count;
} qpms_ss_orbit_type_t;
typedef ptrdiff_t qpms_ss_osn_t; ///< "serial number" of av orbit in a given type.
/// 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 {
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.
ptrdiff_t osn; ///< "Serial number" of the orbit in the given type. TODO type and more doc.
qpms_ss_osn_t osn; ///< "Serial number" of the orbit in the given type. TODO type and more doc.
qpms_ss_orbit_pi_t p; ///< Order (sija, ei rankki) of the particle inside that orbit type.
} qpms_ss_particle_orbitinfo_t;
@ -386,15 +392,19 @@ typedef struct qpms_scatsys_t {
qpms_ss_particle_orbitinfo_t *p_orbitinfo; ///< Orbit type identification of each particle. (Array length is \a p_count.)
size_t fecv_size; ///< Number of elements of a full excitation coefficient vector size.
//size_t *saecv_sizes; ///< NI. Number of elements of symmetry-adjusted coefficient vector sizes (order as in sym->irreps).
size_t *saecv_sizes; ///< Number of elements of symmetry-adjusted coefficient vector sizes (order as in sym->irreps).
size_t *fecv_pstarts; ///< Indices of where pi'th particle's excitation coeffs start in a full excitation coefficient vector.
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. */
//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. */
// TODO shifted origin of the symmetry group etc.
// TODO some indices for fast operations here.
// private
size_t max_bspecn; ///< Maximum tm[...]->spec->n. Mainly for workspace allocation.
// We keep the p_orbitinfo arrays in this chunk in order to avoid memory fragmentation
char *otspace;
@ -416,27 +426,27 @@ void qpms_scatsys_free(qpms_scatsys_t *s);
/// Projects a "big" matrix onto an irrep.
/** TODO doc */
qpms_errno_t qpms_scatsys_irrep_pack_matrix(complex double *target_packed,
complex double *qpms_scatsys_irrep_pack_matrix(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.
/** TODO doc */
qpms_errno_t qpms_scatsys_irrep_unpack_matrix(complex double *target_full,
complex double *qpms_scatsys_irrep_unpack_matrix(complex double *target_full,
const complex double *orig_packed, const qpms_scatsys_t *ss,
bool add);
qpms_iri_t iri, bool add);
/// Projects a "big" vector onto an irrep.
/** TODO doc */
qpms_errno_t qpms_scatsys_irrep_pack_vector(complex double *target_packed,
complex double *qpms_scatsys_irrep_pack_vector(complex double *target_packed,
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 */
qpms_errno_t qpms_scatsys_irrep_unpack_vector(complex double *target_full,
complex double *qpms_scatsys_irrep_unpack_vector(complex double *target_full,
const complex double *orig_packed, const qpms_scatsys_t *ss,
bool add);
qpms_iri_t iri, bool add);
/// NOT IMPLEMENTED Dumps a qpms_scatsys_t structure to a file.
qpms_errno_t qpms_scatsys_dump(qpms_scatsys_t *ss, char *path);