22 Eigen::MatrixXcd
prettyc(
const Eigen::MatrixXcd &M) {
24 Eigen::MatrixXcd Mp(M);
25 for (
int i = 0; i < M.rows(); i++) {
26 for (
int j = 0; j < M.cols(); j++) {
27 if (std::abs(
std::round(M(i, j).real()) - M(i, j).real()) < tol) {
30 if (std::abs(
std::round(M(i, j).imag()) - M(i, j).imag()) < tol) {
43 for (
int i = 0; i < M.rows(); i++) {
44 for (
int j = 0; j < M.cols(); j++) {
45 if (std::abs(
std::round(M(i, j)) - M(i, j)) < tol) {
61 Eigen::VectorXcd
const &a = irrep_a.
characters;
62 Eigen::VectorXcd
const &b = irrep_b.
characters;
64 typedef std::complex<double> C;
81 if (!
almost_equal(a[0], b[0]))
return a[0].real() < b[0].real();
88 if (a_g != b_g)
return a_g;
91 for (
Index i = 0; i < a.size(); ++i) {
93 return a[i].real() > b[i].real();
97 for (
Index i = 0; i < a.size(); ++i) {
99 return a[i].imag() > b[i].imag();
109 template <
typename T>
112 template <
typename T>
115 template <
typename T>
117 using Type = std::vector<_Real<T>>;
120 template <
typename Scalar,
int RowsAtCompileTime,
int ColsAtCompileTime>
122 using Type = Eigen::Matrix<double, RowsAtCompileTime, ColsAtCompileTime>;
125 template <
typename Derived>
127 return mat.real().template cast<double>();
130 template <
typename T>
132 std::vector<_Real<T>> result;
133 result.reserve(vec.size());
134 for (T
const &el : vec) {
135 result.emplace_back(
_real(el));
148 if (!_rep.size() || !head_group.size() || !_rep.
MatrixXd(head_group[0]))
153 ->cwiseProduct(*_rep.
MatrixXd(head_group[0])));
155 for (
Index i = 1; i < head_group.size(); i++) {
156 block_shape += _rep.
MatrixXd(head_group[i])
157 ->cwiseProduct(*_rep.
MatrixXd(head_group[i]));
168 Eigen::Ref<const Eigen::MatrixXcd>
const &_subspace,
169 double vec_compare_tol) {
176 Eigen::MatrixXcd result;
177 Index dim = _subspace.cols();
178 Index min_mult = 10000;
179 bool orb_orthog =
false;
180 bool tot_orthog =
false;
182 Eigen::MatrixXcd axes, orb_axes, tot_axes;
184 tot_axes.setZero(_subspace.rows(), dim);
186 for (
auto const &orbit : special_directions) {
188 if ((orb_orthog && orbit.size() < min_mult) || !orb_orthog) {
189 orb_axes.setZero(_subspace.rows(), dim);
191 for (
auto const &el : orbit) {
192 if (
almost_zero((el.adjoint() * orb_axes).eval(), vec_compare_tol)) {
193 if (col < orb_axes.cols())
194 orb_axes.col(col++) = el;
196 std::stringstream errstr;
198 <<
"Error in irrep_symmtrizer_from_directions(). Constructing "
199 "coordinate axes from special directions of space spanned "
201 << _subspace.transpose()
202 <<
"\nAxes collected thus far are the row vectors:\n"
203 << orb_axes.transpose()
204 <<
"\nBut an additional orthogonal row vector has been found:\n"
206 <<
"\nindicating that subspace matrix is malformed.";
207 throw std::runtime_error(errstr.str());
217 min_mult = orbit.size();
224 if (!orb_orthog && !tot_orthog) {
225 for (
auto const &el : orbit) {
226 if (
almost_zero((el.adjoint() * tot_axes).eval(), vec_compare_tol)) {
227 if (tot_col < tot_axes.cols())
228 tot_axes.col(tot_col++) = el;
230 std::stringstream errstr;
232 <<
"Error in irrep_symmtrizer_from_directions(). Constructing "
233 "coordinate axes from special directions of space spanned "
235 << _subspace.transpose()
236 <<
"\nAxes collected thus far are the row vectors:\n"
237 << tot_axes.transpose()
238 <<
"\nBut an additional orthogonal row vector has been found:\n"
240 <<
"\nindicating that subspace matrix is malformed.";
241 throw std::runtime_error(errstr.str());
245 if (tot_col == dim) {
256 if (!orb_orthog && !tot_orthog && orbit.size() < min_mult) {
257 orb_axes.setZero(_subspace.rows(), orbit.size());
258 for (
Index col = 0; col < orbit.size(); ++col) {
259 orb_axes.col(col) = orbit[col];
263 min_mult = orbit.size();
264 axes = Eigen::MatrixXcd(orb_axes.colPivHouseholderQr().matrixQ())
270 if (axes.cols() == 0) {
273 result = _subspace.colPivHouseholderQr().solve(
277 result = _subspace.colPivHouseholderQr().solve(axes);
299 for (
Index i = 1; i < axes.cols(); ++i) {
300 double bestproj = -1;
301 for (
SymOp const &op : head_group) {
302 v = (*_rep.
MatrixXd(op)) * axes.col(0);
304 bool skip_op =
false;
305 for (
Index j = 0; j < i; ++j) {
311 if (skip_op)
continue;
315 if (bestproj < (v.transpose() * axes).sum()) {
316 bestproj = (v.transpose() * axes).
sum();
330 for (
Index ns = 0; ns < head_group.size(); ns++) {
332 if (!almost_equal<double>((tmat * tmat.transpose()).trace(), tmat.cols())) {
335 std::cout <<
" Representation failed full-rank/orthogonality check!\n"
336 <<
" ns: " << ns <<
"\n"
339 <<
" Matrix*transpose: \n"
340 << tmat.transpose() * tmat <<
"\n\n";
342 for (
Index ns2 = ns; ns2 < head_group.size(); ns2++) {
343 auto prod = (*(_rep.
MatrixXd(head_group[ns]))) *
344 (*(_rep.
MatrixXd(head_group[ns2])));
350 std::cout <<
" Representation failed multiplication check!\n"
351 <<
" ns: " << ns <<
" ns2: " << ns2 <<
" iprod: " << iprod
360 << *(_rep.
MatrixXd(iprod)) <<
"\n\n";
367 template <
typename T>
372 subspace.adjoint().template cast<std::complex<double>>();
375 for (
const auto &direction_orbit : irrep.
directions) {
376 std::vector<Eigen::VectorXd> new_orbit;
377 new_orbit.reserve(direction_orbit.size());
378 for (
const auto &directions : direction_orbit) {
379 new_orbit.push_back(subspace * directions);
381 result.
directions.push_back(std::move(new_orbit));
390 namespace SymRepTools {
393 trans_mat(
std::move(_trans_mat)),
394 characters(
std::move(_characters)) {
405 if (bmat.cols() == 0)
return 0;
410 for (
EigenIndex i = 0; i + 1 < bmat.rows(); i++) {
422 double vec_compare_tol) {
433 Eigen::Ref<const Eigen::MatrixXcd>
const &_subspace,
434 double vec_compare_tol) {
441 sdirs, _subspace, vec_compare_tol),
448 std::vector<SymRepTools::IrrepInfo>
const &irreps) {
451 for (
auto const &irrep : irreps) {
452 col = irrep.vector_dim();
453 row += irrep.irrep_dim();
457 for (
auto const &irrep : irreps) {
458 trans_mat.block(row, 0, irrep.irrep_dim(), irrep.vector_dim()) =
459 irrep.trans_mat.real();
460 row += irrep.irrep_dim();
469 std::vector<SymRepTools::IrrepInfo> irreps =
473 result.reserve(irreps.size());
475 for (
auto const &irrep : irreps) {
490 double vec_compare_tol) {
505 Eigen::Ref<const Eigen::MatrixXcd>
const &_subspace,
double vec_compare_tol,
506 bool all_subgroups) {
510 std::vector<Eigen::VectorXcd> tdirs;
516 for (
auto const &orbit : sgroups) {
520 for (
Index op : *(orbit.begin())) {
521 R += *(_rep.
MatrixXd(head_group[op]));
524 if ((R * _subspace).norm() <
TOL)
continue;
528 auto QR = (R * _subspace).colPivHouseholderQr();
529 QR.setThreshold(
TOL);
537 if (QR.rank() > 1)
continue;
538 Eigen::MatrixXcd Q = QR.matrixQ();
547 tdirs.push_back(Q.col(0));
548 tdirs.push_back(-Q.col(0));
574 using SymCompareType =
577 std::set<VectorOrbit> orbit_result;
578 make_orbits(tdirs.begin(), tdirs.end(), head_group,
579 SymCompareType(vec_compare_tol, _rep),
580 std::inserter(orbit_result, orbit_result.begin()));
585 for (VectorOrbit
const &orbit : orbit_result) {
588 result.emplace_back(orbit.begin(), orbit.end());
591 if (all_subgroups || result.size() >= _subspace.cols()) {
599 vec_compare_tol,
true);
612 if (!_rep.size() || !_rep.
MatrixXd(0)) {
613 err_log() <<
"CRITICAL ERROR: In special_subspaces() called on "
614 "imcompatible SymGroupRep.\n Exiting...\n";
620 std::vector<std::vector<Eigen::MatrixXd>>
626 auto const &sg_op_inds(head_group.
subgroups());
628 Eigen::ColPivHouseholderQR<Eigen::MatrixXd> QR(*(_rep.
MatrixXd(0)));
630 QR.setThreshold(
TOL);
636 for (i = 0; i < sg_op_inds.size(); i++) {
637 if (sg_op_inds[i].size() == 0 || sg_op_inds[i].begin()->size() == 0) {
638 err_log() <<
"CRITICAL ERROR: In special_subspaces(), attempting to use "
639 "a zero-size subgroup.\n Exiting...\n";
646 for (
Index op : *(sg_op_inds[i].begin())) {
647 Reynolds += *(_rep.
MatrixXd(head_group[op]));
650 Reynolds /= double(sg_op_inds[i].begin()->size());
653 QR.compute(Reynolds);
656 if (QR.rank() < 1)
continue;
666 for (j = 0; j < ssubs.size(); j++) {
667 if (ssubs[j][0].cols() != tsub.cols())
continue;
669 for (k = 0; k < ssubs[j].size(); k++) {
670 double tdet = (tsub.transpose() * ssubs[j][k]).determinant();
673 if (k < ssubs[j].size())
break;
675 if (j < ssubs.size())
continue;
678 ssubs.push_back(std::vector<Eigen::MatrixXd>());
679 for (j = 0; j < head_group.size(); j++) {
680 ttrans = (*(_rep.
MatrixXd(head_group[j]))) * tsub;
681 for (k = 0; k < ssubs.back().size(); k++) {
682 double tdet = (ttrans.transpose() * ssubs.back()[k]).determinant();
685 if (k == ssubs.back().size()) ssubs.back().push_back(ttrans);
695 for (i = 0; i < ssubs.size(); i++) {
696 for (j = i + 1; j < ssubs.size(); j++) {
697 if (ssubs[i][0].cols() > ssubs[j][0].cols()) ssubs[i].
swap(ssubs[j]);
698 if (ssubs[i][0].cols() == ssubs[j][0].cols() &&
699 ssubs[i].size() > ssubs[j].size())
700 ssubs[i].
swap(ssubs[j]);
711 for (
Index i = 0; i < head_group.size(); i++) {
712 tvalue += (_rep[head_group[i].index()]->character()) *
713 (_rep[head_group[i].index()]->character());
716 if (
Index(
round(tvalue)) == head_group.size()) {
727 Eigen::Ref<const Eigen::MatrixXd>
const &_subspace,
bool calc_wedge) {
737 result.
irreps.push_back(wedge.irrep_info);
753 for (
SymOp const &op : head_group) {
772 Eigen::Ref<const Eigen::MatrixXd>
const &_subspace,
bool allow_complex) {
775 [&](Eigen::Ref<const Eigen::MatrixXcd>
const &f_subspace) {
778 _subspace, allow_complex);
791 if (_rep.
dim() != subspace.rows()) {
792 throw std::runtime_error(
793 "In irrep_decomposition, subspace matrix does not have proper number "
794 "of rows (should have " +
800 subspace.cols() * head_group.size());
802 if (!subspace.isIdentity()) {
804 for (
auto const &op : head_group) {
805 symspace.block(0, l, subspace.rows(), subspace.cols()) =
806 (*(_rep[op.index()]->
MatrixXd())) * subspace;
807 l += subspace.cols();
809 Eigen::ColPivHouseholderQR<Eigen::MatrixXd> qr(symspace);
810 qr.setThreshold(
TOL);
818 auto subspace_symmetrizer =
819 [&](
const Eigen::Ref<const Eigen::MatrixXcd> &_subspace) {
824 sub_rep, head_group, subspace_symmetrizer, allow_complex);
826 std::vector<SymRepTools::IrrepInfo> result;
827 result.reserve(irreps.size());
829 for (
auto const &irrep : irreps) {
845 bool allow_complex) {
846 std::set<SymRepTools::IrrepInfo, Local::IrrepCompare> result{
848 if (!_rep.size() || !head_group.size() || !_rep.
MatrixXd(head_group[0])) {
850 <<
"WARNING: In irrep_decomposition(), size of representation is "
851 << _rep.size() <<
" and MatrixXd address is "
852 << _rep.
MatrixXd(head_group[0]) << std::endl
853 <<
" No valid irreps will be returned.\n";
857 "REPRESENTATION IS ILL-DEFINED!!");
859 std::vector<Eigen::MatrixXcd> commuters;
868 typedef std::complex<double> cplx;
869 std::vector<cplx> phase;
870 phase.push_back(cplx(1.0, 0.0));
871 phase.push_back(cplx(0.0, 1.0));
873 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXcd> esolve;
874 Eigen::HouseholderQR<Eigen::MatrixXcd> qr;
875 Eigen::ColPivHouseholderQR<Eigen::MatrixXcd> colqr;
876 colqr.setThreshold(0.001);
878 Eigen::MatrixXcd tmat(Eigen::MatrixXcd::Zero(dim, dim)),
879 tcommute(Eigen::MatrixXcd::Zero(dim, dim));
880 Eigen::MatrixXcd adapted_subspace(Eigen::MatrixXcd::Zero(dim, dim));
883 Eigen::MatrixXcd kernel(((1000 * Eigen::MatrixXcd::Random(dim, dim)) / 1000.)
886 kernel.setIdentity(dim, dim);
891 for (
Index nph = 0; nph < 2; nph++) {
892 for (
Index kci = 0; kci < kernel.cols(); kci++) {
893 bool found_new_irreps(
false);
894 for (
Index kcj = kernel.cols() - 1; kci <= kcj; kcj--) {
897 if (kci == kcj && nph > 0)
continue;
903 tmat = phase[nph] * kernel.col(kci) *
904 kernel.col(kcj).adjoint()
905 + std::conj(phase[nph]) * kernel.col(kcj) *
906 kernel.col(kci).adjoint();
910 for (
SymOp const &op : head_group) {
913 tcommute += (*(_rep.
MatrixXd(op))) * tmat *
921 for (
Index nc = 0; nc < commuters.size(); nc++) {
922 cplx tproj((commuters[nc].array() * tcommute.array().conjugate())
925 tcommute -= tproj * commuters[nc];
935 (tcommute.array().conjugate() * tcommute.array()).sum().real());
940 commuters.push_back(tcommute / sqrt(tnorm));
949 Index nc = commuters.size() - 1;
953 esolve.compute(
double(dim) * sqrt(
double(dim)) * kernel.adjoint() *
954 commuters[nc] * kernel);
956 std::vector<Index> subspace_dims =
969 tmat = kernel * esolve.eigenvectors();
992 std::vector<Eigen::MatrixXcd> trans_rep(head_group.size());
994 for (
Index i = 0; i < head_group.size(); i++) {
996 tmat.adjoint() * (*_rep.
MatrixXd(head_group[i])) * tmat;
1002 for (
Index ns = 0; ns < subspace_dims.size(); ns++) {
1004 Eigen::VectorXcd char_vec(head_group.size());
1011 for (
Index ng = 0; ng < trans_rep.size(); ng++) {
1012 char_vec[ng] = cplx(0, 0);
1013 for (
Index i = last_i; i < last_i + subspace_dims[ns]; i++)
1014 char_vec[ng] += trans_rep[ng](i, i);
1021 double(head_group.size()))) {
1023 Eigen::MatrixXcd t_irrep_subspace;
1025 if (allow_complex) {
1026 t_irrep_subspace = tmat.block(0, last_i, dim, subspace_dims[ns]);
1028 t_irrep_subspace.resize(dim, 2 * subspace_dims[ns]);
1030 t_irrep_subspace.leftCols(subspace_dims[ns]) =
1031 sqrt(2.0) * tmat.block(0, last_i, dim, subspace_dims[ns])
1033 .cast<std::complex<double>>();
1034 t_irrep_subspace.rightCols(subspace_dims[ns]) =
1035 sqrt(2.0) * tmat.block(0, last_i, dim, subspace_dims[ns])
1037 .cast<std::complex<double>>();
1043 (t_irrep_subspace.adjoint() * adapted_subspace).norm(),
1050 qr.compute(t_irrep_subspace);
1055 colqr.compute(t_irrep_subspace);
1056 Index rnk = colqr.rank();
1060 Eigen::MatrixXcd(qr.householderQ()).leftCols(rnk);
1062 auto symmetrizer = symmetrizer_func(t_irrep_subspace);
1064 (t_irrep_subspace * symmetrizer.first).adjoint(), char_vec);
1067 if (rnk == 2 * subspace_dims[ns])
1073 adapted_subspace.block(0, Nfound, dim, rnk) =
1076 auto it = result.find(t_irrep);
1077 if (it != result.end()) {
1082 while (it != result.end() && it->index > 0) {
1087 result.emplace_hint(it, std::move(t_irrep));
1090 found_new_irreps =
true;
1104 last_i += subspace_dims[ns];
1106 if (found_new_irreps) {
1107 qr.compute(adapted_subspace);
1108 kernel = Eigen::MatrixXcd(qr.householderQ()).rightCols(dim - Nfound);
1117 return std::vector<SymRepTools::IrrepInfo>(
1118 std::make_move_iterator(result.begin()),
1119 std::make_move_iterator(result.end()));
1132 [&](Eigen::Ref<const Eigen::MatrixXcd>
const &_subspace) {
1143 const std::vector<std::set<Index>> &subsets) {
1148 std::vector<Index> tperm(subsets.size());
1149 for (
Index np = 0; np < permute_rep.size(); ++np) {
1151 if (perm_ptr == NULL) {
1154 err_log() <<
"CRITICAL ERROR: In "
1155 "subset_permutation_rep(SymGroupRep,std::vector<Index>::X2),"
1156 " permute_rep is missing at least one permutation!\n"
1162 for (
Index ns = 0; ns < subsets.size(); ++ns) {
1163 std::set<Index> perm_sub;
1165 for (
Index i : subsets[ns]) {
1166 perm_sub.insert(iperm[i]);
1170 for (ns2 = 0; ns2 < subsets.size(); ++ns2) {
1171 if (subsets[ns] == perm_sub) {
1177 if (ns2 >= subsets.size()) {
1179 <<
"CRITICAL ERROR: In "
1180 "subset_permutation_rep(SymGroupRep,std::vector<Index>::X2), "
1181 "subsets are not closed under permute_rep permutations!\n"
1196 const std::vector<SymGroupRep const *> &sum_reps) {
1201 std::vector<Index> rep_dims(sum_reps.size(), 0);
1203 err_log() <<
"CRITICAL ERROR: In "
1204 "permuted_direct_sum_rep(SymGroupRep,std::vector<SymGroupRep "
1205 "const*>), permute_rep does not contain permutations!\n"
1211 for (
Index i = 0; i < sum_reps.size(); i++) {
1212 if (sum_reps[i] == NULL) {
1217 &(permute_rep.
master_group()) != &(sum_reps[i]->master_group())) ||
1218 sum_reps[i]->MatrixXd(0) == NULL) {
1219 err_log() <<
"CRITICAL ERROR: In "
1220 "permuted_direct_sum_rep(SymGroupRep,std::vector<"
1221 "SymGroupRep const*>), found incompatible SymGroupReps!\n"
1226 rep_dims[i] = sum_reps[i]->dim();
1229 std::vector<Index> sum_inds(1, 0);
1230 std::partial_sum(rep_dims.begin(), rep_dims.end(),
1231 std::back_inserter(sum_inds));
1232 auto tot = std::accumulate(rep_dims.begin(), rep_dims.end(), 0);
1236 for (
Index g = 0; g < permute_rep.size(); g++) {
1237 if (permute_rep[g] == NULL) {
1242 for (
Index r = 0; r < perm_ptr->
size(); r++) {
1243 if (rep_dims[r] == 0)
continue;
1244 Index new_r = (*perm_ptr)[r];
1245 rep_mat_ptr = sum_reps[new_r]->MatrixXd(g);
1246 sum_mat.block(sum_inds[r], sum_inds[new_r], rep_dims[new_r],
1247 rep_dims[new_r]) = *rep_mat_ptr;
1259 err_log() <<
"CRITICAL ERROR: In kron_rep(SymGroupRep,SymGroupRep), taking "
1260 "product of two incompatible SymGroupReps!\n"
1268 for (
Index i = 0; i < LHS.size(); i++) {
1281 namespace SymRepTools {
1285 irrep_wedge.
mult.reserve(
axes.cols());
1286 for (
Index i = 0; i <
axes.cols(); ++i) {
1287 irrep_wedge.
mult.push_back(1);
1297 std::vector<IrrepWedge>
const &_iwedges) {
1299 Eigen::MatrixXd result(_iwedges[0].axes.rows(), _iwedges[0].axes.rows());
1301 for (
Index w = 0; w < _iwedges.size(); ++w) {
1302 result.block(0, i, _iwedges[w].axes.rows(), _iwedges[w].axes.cols()) =
1304 i += _iwedges[w].axes.cols();
1306 if (i < result.cols()) result.conservativeResize(Eigen::NoChange, i);
1314 Eigen::Ref<const Eigen::MatrixXd>
const &_subspace) {
1323 Eigen::Ref<const Eigen::MatrixXd>
const &_subspace) {
1324 std::vector<SymRepTools::IrrepInfo> irreps =
1326 std::vector<IrrepWedge> wedges;
1327 wedges.reserve(irreps.size());
1328 double best_proj, tproj;
1341 wedges.emplace_back(
1342 irrep, Eigen::MatrixXd::Zero(irrep.vector_dim(), irrep.irrep_dim()));
1346 if (irrep.directions.empty()) {
1354 wedges.back().axes.col(0) = irrep.directions[0][0];
1355 wedges.back().mult.push_back(irrep.directions[0].size());
1356 for (
Index i = 1; i < irrep.irrep_dim(); i++) {
1362 (wedges.back().axes.transpose() * irrep.directions[i][0]).
sum();
1363 for (
Index j = 1; j < irrep.directions[i].size(); j++) {
1364 tproj = (wedges.back().axes.transpose() * irrep.directions[i][j]).
sum();
1365 if (tproj > best_proj) {
1371 wedges.back().axes.col(i) = irrep.directions[i][j_best];
1372 wedges.back().mult.push_back(irrep.directions[i].size());
1392 Eigen::Ref<const Eigen::MatrixXd>
const &_subspace) {
1394 head_group, _subspace);
1408 Eigen::Ref<const Eigen::MatrixXd>
const &_subspace) {
1409 auto irrep_wedge_compare = [](
const IrrepWedge &a,
1414 auto tot_wedge_compare = [irrep_wedge_compare](
1415 const std::vector<IrrepWedge> &a,
1416 const std::vector<IrrepWedge> &b) ->
bool {
1417 if (a.size() != b.size())
return false;
1418 for (
auto ita = a.begin(), itb = b.begin(); ita != a.end(); ++ita, ++itb)
1419 if (!irrep_wedge_compare(*ita, *itb))
return false;
1426 throw std::runtime_error(
1427 "In symrep_subwedges, SymGroupRep does not describe matrix "
1430 std::vector<IrrepWedge> init_wedges =
1433 std::vector<SubWedge> result;
1437 irrep_wedge_orbits.reserve(init_wedges.size());
1439 std::vector<Index> max_equiv;
1440 max_equiv.reserve(init_wedges.size());
1445 for (
IrrepWedge const &wedge : init_wedges) {
1448 irrep_wedge_orbits.push_back({wedge});
1451 subgroups.push_back({});
1452 for (
SymOp const &op : head_group) {
1454 test_wedge.
axes = (*(_rep[op.index()]->
MatrixXd())) * wedge.axes;
1456 for (; o < irrep_wedge_orbits.back().size(); ++o) {
1457 if (irrep_wedge_compare(irrep_wedge_orbits.back()[o], test_wedge)) {
1459 subgroups.back().push_back(op.index());
1464 if (o < irrep_wedge_orbits.back().size())
continue;
1465 irrep_wedge_orbits.back().push_back(test_wedge);
1471 max_equiv.push_back(irrep_wedge_orbits.back().size() - 1);
1472 if (max_equiv.back() > max_equiv[imax]) imax = max_equiv.size() - 1;
1474 max_equiv[imax] = 0;
1479 std::vector<Index>(init_wedges.size(), 1));
1485 for (; wcount; ++wcount) {
1486 std::vector<IrrepWedge> twedge = init_wedges;
1487 for (
Index i = 0; i < init_wedges.size(); i++)
1488 twedge[i].axes = irrep_wedge_orbits[i][wcount[i]].axes;
1492 [tot_wedge_compare, &twedge](
1494 return contains(wedge_orbit, twedge, tot_wedge_compare);
1498 tot_wedge_orbits.push_back({twedge});
1499 result.emplace_back(twedge);
1500 for (
Index p : subgroups[imax]) {
1501 for (
Index i = 0; i < twedge.size(); i++)
1503 (*(_rep[p]->
MatrixXd())) * result.back().irrep_wedges()[i].axes;
1504 if (!
contains(tot_wedge_orbits.back(), twedge, tot_wedge_compare)) {
1505 tot_wedge_orbits.back().push_back(twedge);
A Counter allows looping over many incrementing variables in one loop.
SymGroupRep const & representation(SymGroupRepID i) const
Const access of alternate Representations of a SymGroup.
Permutation inverse() const
Construct permutation that undoes the permutation performed by 'this'.
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
const std::vector< std::set< std::set< Index > > > & subgroups() const
std::vector< std::set< std::set< Index > > > small_subgroups() const
Index ind_prod(Index i, Index j) const
Get index of operation that is result of multiplication of at(i)*at(j)
const MasterSymGroup & master_group() const
SymGroupRep is an alternative representation of a SymGroup for something other than real space....
const MasterSymGroup & master_group() const
Reference to MasterSymGroup for which this SymGroupRep is a group representation If a MasterSymGroup ...
void set_rep(Index op_index, const SymOpRepresentation &new_rep)
Sets the representation of operation at entry 'op_index' of this group representation Throws if this ...
bool has_valid_master() const
Returns true if this SymGroupRep has valid pointer to a MasterSymGroup.
Eigen::MatrixXd const * MatrixXd(Index i) const
pointer to MatrixXd corresponding to SymOpRepresentation at entry 'i' of this SymGroupRep Returns nul...
Permutation const * permutation(Index i) const
pointer to Permutation corresponding to SymOpRepresentation at entry 'i' of this SymGroupRep Returns ...
Index dim() const
Matrix dimension of representation.
Type-safe ID object for communicating and accessing Symmetry representation info.
Generalized symmetry matrix representation for arbitrary dimension Can be used to describe applicatio...
SymOp is the Coordinate representation of a symmetry operation it keeps fraction (FRAC) and Cartesian...
SymPermutation describes how a symmetry operation permutes a list of 'things' For example,...
std::string to_string(ENUM val)
Return string representation of enum class.
Eigen::MatrixXd pretty(const Eigen::MatrixXd &M, double tol)
Round entries that are within tol of being integer to that integer value.
Eigen::CwiseUnaryOp< decltype(Local::round_l< typename Derived::Scalar >), const Derived > round(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd.
T norm(const Tensor< T > &ttens)
SymRepTools::IrrepInfo _subspace_to_full_space(SymRepTools::IrrepInfo const &irrep, Eigen::MatrixBase< T > const &subspace)
static SymRepTools::IrrepWedge _wedge_from_pseudo_irrep(SymRepTools::IrrepInfo const &irrep, SymGroupRep const &_rep, SymGroup const &head_group)
bool _rep_check(SymGroupRep const &_rep, SymGroup const &head_group, bool verbose)
static Eigen::MatrixXd _block_shape_matrix(SymGroupRep const &_rep, SymGroup const &head_group)
Matrix such that result(i,j) is sum of squares over 'p' of op_rep[p].matrix(i,j). 'p' only spans oper...
static Eigen::MatrixXcd _irrep_symmetrizer_from_directions(multivector< Eigen::VectorXcd >::X< 2 > const &special_directions, Eigen::Ref< const Eigen::MatrixXcd > const &_subspace, double vec_compare_tol)
typename _RealType< T >::Type _Real
_Real< Derived > _real(Eigen::MatrixBase< Derived > const &mat)
IdentitySymRepBuilder Identity()
bool almost_equal(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Check if ClusterInvariants are equal.
SymGroupRep permuted_direct_sum_rep(const SymGroupRep &permute_rep, const std::vector< SymGroupRep const * > &sum_reps)
VectorSpaceSymReport vector_space_sym_report(DoFSpace const &dof_space, SupercellSymInfo const &sym_info, std::vector< PermuteIterator > const &group, bool calc_wedges=false)
Make VectorSpaceSymReport.
OrbitOutputIterator make_orbits(OrbitBranchSpecsIterator begin, OrbitBranchSpecsIterator end, const std::vector< IntegralClusterOrbitGenerator > &custom_generators, OrbitOutputIterator result, std::ostream &status)
Generate orbits of IntegralCluster using OrbitBranchSpecs.
bool is_irrep(SymGroupRep const &_rep, const SymGroup &head_group)
Returns true if _rep is irreducible wrt head_group (does not use character table information)
Eigen::MatrixXd full_trans_mat(std::vector< SymRepTools::IrrepInfo > const &irreps)
Assumes that irreps are real, and concatenates their individual trans_mats to form larger trans_mat.
SymRepTools::Symmetrizer irrep_symmetrizer(SymGroupRep const &_rep, const SymGroup &head_group, double vec_compare_tol)
std::vector< SymRepTools::IrrepInfo > irrep_decomposition(SymGroupRep const &_rep, SymGroup const &head_group, bool allow_complex)
Finds irreducible subspaces that comprise an underlying subspace It does not rely on the character ta...
SymGroupRep subset_permutation_rep(const SymGroupRep &permute_rep, const std::vector< std::set< Index >> &subsets)
void swap(ConfigDoF &A, ConfigDoF &B)
SymGroupRep coord_transformed_copy(SymGroupRep const &_rep, const Eigen::MatrixXd &trans_mat)
Make a copy of representation on vector space 'V' that is transformed into a representation on vector...
std::vector< std::vector< Eigen::MatrixXd > > special_subspaces(SymGroupRep const &_rep, const SymGroup &head_group)
finds high-symmetry subspaces within vector space supporting _rep, wrt symmetry of head_group High-sy...
SymGroupRep kron_rep(const SymGroupRep &LHS, const SymGroupRep &RHS)
Container::value_type sum(const Container &container, typename Container::value_type init_val=0)
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
multivector< Eigen::VectorXd >::X< 3 > special_total_directions(SymGroupRep const &_rep, const SymGroup &head_group)
finds high-symmetry directions within vector space supporting _rep, wrt symmetry of head_group
ReturnArray< Index > partition_distinct_values(const Eigen::MatrixBase< Derived > &value, double tol=TOL)
bool contains(const Container &container, const T &value)
Equivalent to container.end() != std::find(container.begin(), container.end(), value)
Eigen::MatrixXd irrep_trans_mat(SymGroupRep const &_rep, const SymGroup &head_group)
Finds the transformation matrix that block-diagonalizes this representation of head_group into irrep ...
multivector< Eigen::VectorXcd >::X< 2 > special_irrep_directions(SymGroupRep const &_rep, SymGroup const &head_group, double vec_compare_tol)
Assuming that _rep is an irrep of head_group, find high-symmetry directions throws if _rep is not an ...
Eigen::MatrixXd::Index EigenIndex
bool contains_if(const Container &container, UnaryPredicate p)
Equivalent to container.end() != std::find_if(container.begin(), container.end(), p)
Index num_blocks(SymGroupRep const &_rep, const SymGroup &head_group)
counts number of nonzero blocks in matrix representation of head_group as specified by _rep Reveals n...
INDEX_TYPE Index
For long integer indexing:
bool almost_equal(const Eigen::MatrixBase< Derived1 > &val1, const Eigen::MatrixBase< Derived2 > &val2, double tol=CASM::TOL)
Derived::PlainObject representation_prepare_impl(Eigen::MatrixBase< Derived > const &obj, double _tol)
Prepare an element for comparison.
Eigen::Matrix< double, RowsAtCompileTime, ColsAtCompileTime > Type
std::vector< _Real< T > > Type
bool operator()(SymRepTools::IrrepInfo const &irrep_a, SymRepTools::IrrepInfo const &irrep_b) const
Summary of data associated with the action of a symmetry group on a vector space.
std::vector< Eigen::MatrixXd > symgroup_rep
Matrix representation for each operation in the group – defines action of group on vector space.
std::vector< std::string > axis_glossary
Names given to individual axes in initial (un-adapted) vector space, corresponding to rows of symmetr...
Eigen::MatrixXd symmetry_adapted_dof_subspace
Symmetry-oriented subspace of the vector space (columns are the basis vectors)
std::vector< SymRepTools::SubWedge > irreducible_wedge
Irreducible wedge in the vector space encoded as a vector of symmetrically distinct SubWedges.
std::vector< SymRepTools::IrrepInfo > irreps
A list of all irreducible representation that make up the full representation.
Shortcut for multidimensional vector (std::vector< std::vector< ...)
typename multivector_impl::multivector_tmp< T, N >::type X