26 namespace BasisSet_impl {
29 for (
auto const &B : BB) push_back(&B);
33 for (
auto B : BB) push_back(B);
37 for (
auto const &B : BB) push_back(&B);
41 for (
auto B : BB) push_back(B);
49 m_basis_symrep_ID(init_basis.basis_symrep_ID()),
50 m_name(init_basis.
name()),
51 m_basis_ID(init_basis.m_basis_ID),
52 m_min_poly_order(init_basis.m_min_poly_order),
53 m_max_poly_order(init_basis.m_max_poly_order),
57 m_dof_IDs(init_basis.m_dof_IDs),
58 m_dof_subbases(init_basis.m_dof_subbases),
59 m_min_poly_constraints(init_basis.min_poly_constraints()),
60 m_max_poly_constraints(init_basis.max_poly_constraints()) {
68 for (
Index i = 0; i < init_basis.
size(); i++) {
126 if (
at(i))
delete at(i);
141 throw std::runtime_error(
142 "In BasisSet::append(), it is unsafe to append a BasisSet whose "
143 "dependencies differ from (this).");
228 exp_sum = expons.
sum();
235 bool is_changed(
false), tchanged;
240 is_changed = tchanged || is_changed;
248 tchanged =
at(i)->
accept(visitor,
this);
249 is_changed = tchanged || is_changed;
293 if (!(
at(i)->shallow_compare(RHS[i])))
return false;
327 for (
Index i = 0; i < _dof_set.
size(); i++) {
328 if (!_dof_set[i].is_locked()) {
338 for (
Index i = 0; i < _dof_set.
size(); i++) {
351 const std::vector<Index> &after_IDs) {
352 bool changed =
false;
357 if (before_IDs.size() != after_IDs.size() &&
size() > 0) {
358 throw std::runtime_error(
359 "In BasisSet::update_dof_IDs(), new IDs are incompatible with current "
372 if (m == before_IDs.size())
373 throw std::runtime_error(
374 "In BasisSet::update_dof_IDs(), new IDs are incompatible with "
392 if (changed &&
at(i)) {
409 std::vector<std::set<Index> > result;
410 std::vector<bool> unclaimed(
size(),
true);
414 for (j = 0; j < result.size(); j++) {
419 if (j == result.size()) result.emplace_back();
425 bool has_unclaimed =
false;
426 for (
Index i = 0; i < unclaimed.size(); i++) {
428 if (!has_unclaimed) {
429 result.emplace_back();
430 has_unclaimed =
true;
432 result.back().insert(i);
441 const std::vector<DoF::RemoteHandle> &remote_handles) {
466 for (
int i = 0; i < exp_count.
size(); i++) {
468 curr_expon[i] = exp_count()[i];
471 new_trie(curr_expon) = 1.0;
474 }
while (++exp_count);
482 Index min_dof_order) {
487 for (
Index i = 0; i < tsubs.size(); ++i) {
489 tsubs[i]->get_symmetry_representation(head_group);
519 for (
Index i = 0; i <
dof_IDs().size() && min_dof_order >= 0; i++) {
522 for (
Index j = 0; j < tsubs.size(); offset += tsubs[j]->size(), j++) {
526 if (ID_ind == (tsubs[j]->
dof_IDs()).
size())
continue;
530 for (
Index b = 0; b < sub_basis.
size(); b++) {
531 big_sub_basis.
push_back(sub_basis[b] + offset);
540 OrderCount::Container initial_order(tsubs.size(), 0),
541 final_order(tsubs.size(), order);
542 for (
Index i = 0; i < tsubs.size(); i++) {
544 initial_order[i] = tsubs[i]->min_poly_order();
546 final_order[i] = tsubs[i]->max_poly_order();
550 OrderCount order_count(initial_order, final_order, 1, order);
553 for (
Index i = 0; i < tsubs.size(); i++) {
557 curr_exp.
append(exp_count.back());
560 for (; order_count.valid(); ++order_count) {
562 for (
Index i = 0; i < exp_count.size(); i++) {
563 exp_count[i].set_sum_constraint(order_count[i]);
569 for (; exp_count.valid(); ++exp_count) {
570 bool valid_expon =
true;
571 for (
Index i = 0; i < exp_count.size() && valid_expon; i++) {
574 valid_expon = tsubs[i]->satisfies_exponent_constraints(exp_count[i]());
578 if (!valid_expon)
continue;
581 ExpCount::const_value_iterator it(exp_count.value_begin()),
582 it_end(exp_count.value_end());
584 for (; it != it_end; ++it) {
585 curr_exp[ne++] = *it;
596 for (
Index i = 0; i < head_group.size(); i++) {
653 throw std::runtime_error(
654 "Passed a Gram Matrix to "
655 "BasisSet::construct_orthonormal_discrete_functions that is not "
662 std::stringstream ss;
665 ss <<
"Passed ill-conditioned Gram Matrix to "
666 "BasisSet::construct_orthonormal_discrete_functions."
667 <<
"The sum of the elements of the Gram matrix must be equal to 1."
668 <<
"Gram Matrix is:\n"
670 throw std::runtime_error(ss.str());
677 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> teig(
678 gram_mat, Eigen::ComputeEigenvectors);
679 if (teig.eigenvalues().minCoeff() <
TOL) {
680 std::stringstream ss;
683 ss <<
"Gram Matrix in BasisSet::construct_orthonormal_discrete_functions "
684 "is not positive-definite."
685 <<
"Gram Matrix is:\n"
687 <<
"\nSmallest Eigenvalue = " << teig.eigenvalues().minCoeff();
688 throw std::runtime_error(ss.str());
705 teig.eigenvectors().inverse();
711 if (conc_vec.maxCoeff(&max_ind) < 0.75) {
715 for (
Index i = 0; i <
N; i++) {
716 tcos_table(i, 0) = 1.0;
717 double x = -cos(M_PI * (i + 0.5) /
double(
N));
718 for (
Index j = 1; j <
N; j++) {
719 tcos_table(i, j) = x * tcos_table(i, j - 1);
724 tseed = tcos_table.householderQr().householderQ();
731 if (i == max_ind)
continue;
733 if (curr_i + 1 == j) tseed(i, j) = 1;
742 Eigen::MatrixXd Q = (B.inverse() * tseed).householderQr().householderQ();
750 for (
Index i = 1; i <
N; i++) {
764 for (
Index j = 0; j < B.rows(); j++) {
765 if (std::abs(B(j, i)) > (max_abs -
TOL)) {
766 max_abs = std::abs(B(j, i));
771 B.col(i) *= double(sign_change);
808 const DiscreteDoF &allowed_occs,
const std::vector<double> &occ_probs,
811 if (allowed_occs.
size() != occ_probs.size()) {
812 std::stringstream ss;
813 ss <<
"Error in BasiSet::construct_orthonormal_discrete_functions(): "
815 for (
Index i = 0; i < occ_probs.size(); ++i) {
816 if (i != 0) ss <<
",";
823 throw std::runtime_error(ss.str());
827 for (
double dub : occ_probs) prob_sum += dub;
830 throw std::runtime_error(
831 "In BasiSet::construct_orthonormal_discrete_functions(), occ_probs "
832 "must sum to 1 (they specify a probability distributation).\n");
840 for (
Index i = 0; i <
N; i++) {
841 gram_mat(i, i) += occ_probs[i] - occ_probs[i] * occ_probs[i];
842 for (
Index j = 0; j <
N; j++) {
843 if (i == j)
continue;
846 (occ_probs[i] - occ_probs[j]) * (occ_probs[i] - occ_probs[j]);
849 occ_probs[i] * occ_probs[j] +
850 (occ_probs[i] - occ_probs[j]) * (occ_probs[i] - occ_probs[j]);
856 for (
Index i = 0; i <
N; i++) {
857 for (
Index j = 0; j <
N; j++) {
858 gram_mat(i, j) += occ_probs[i] * occ_probs[j];
883 for (
Index i = 0; i < expon.
size(); i++) {
899 if (min_order <= 0)
append(even_basis);
902 if (!even_only && min_order <= 1)
append(odd_basis);
904 for (
Index i = 2; i <= order; i++) {
906 if (even_only && i % 2 != 0)
continue;
909 BasisSet &orthog_basis(i % 2 == 0 ? even_basis : odd_basis);
912 for (
Index j = 0; j < orthog_basis.
size(); j++) {
930 orthog_basis.
append(curr_order_basis);
932 if (min_order <= i)
append(curr_order_basis);
955 for (
Index ng = 0; ng < head_group.size(); ng++) {
978 <<
"CRITICAL ERROR: Inside BasisSet::calc_normal_basis() and cannot "
979 "calculate a valid SymGroup representation. Exiting...\n";
982 if (!head_group.size()) {
983 std::cerr <<
"CRITICAL ERROR: Inside BasisSet::calc_normal_basis() and and "
984 "passed empty SymGroup. Exiting...\n";
1005 if (new_func !=
nullptr) {
1015 if (!
size())
return nullptr;
1016 if (
size() != coeffs.size()) {
1018 <<
"FATAL ERROR: In BasisSet::_linear_combination, the number of basis "
1020 <<
"does not match the size of the coefficient vector. Exiting...\n";
1024 Function *combfunc(
nullptr), *tfunc(
nullptr);
1026 for (
EigenIndex i = 0; i < coeffs.size(); i++) {
1029 combfunc =
at(i)->
copy();
1030 combfunc->
scale(coeffs[i]);
1034 tfunc->
scale(coeffs[i]);
1035 combfunc->plus_in_place(tfunc);
1039 combfunc =
at(0)->
copy();
1040 combfunc->
scale(0.0);
1053 if (trans_mat.cols() !=
size()) {
1054 std::cerr <<
"In BasisSet::transform_copy(), attempting to transform basis "
1055 "with a transformation\n"
1056 <<
"matrix that has incompatible number of columns (has "
1057 << trans_mat.cols() <<
" and needs " <<
size() <<
").\n"
1061 for (
EigenIndex nc = 0; nc < trans_mat.rows(); nc++) {
1074 int _dependency_layer ) {
1076 if (this_dep_layer == _dependency_layer) {
1082 else if (!ptr->isIdentity()) {
1090 m_argument[i]->apply_sym(op, _dependency_layer);
1100 throw std::runtime_error(
1101 "In BasisSet::_set_arguments(), cannot reset arguments of "
1102 "already-initialized BasisSet.");
1106 for (
Index i = 0; i < new_args.size(); i++) {
1134 bool is_unchanged(
true);
1140 for (i = 0; i <
size(); i++) {
1143 tcoeff = sqrt(
at(i)->
dot(
at(i)));
1146 is_unchanged =
false;
1152 is_unchanged =
false;
1158 for (j = i + 1; j <
size(); j++) {
1164 is_unchanged =
false;
1169 tfunc->
scale(tcoeff);
1178 return is_unchanged;
1184 bool is_unchanged(
true);
1186 Index j_min(0), i_min(0), i_temp;
1187 double tcoeff, min_coeff(1e10);
1189 while (i <
size()) {
1191 for (i_temp = i; i_temp <
size(); i_temp++) {
1197 is_unchanged =
false;
1201 (j == j_min && std::abs(tcoeff) > std::abs(min_coeff))) {
1207 if (i >=
size())
break;
1211 is_unchanged =
false;
1215 at(i)->
scale(1.0 / min_coeff);
1218 for (i_temp = 0; i_temp <
size(); i_temp++) {
1219 if (i_temp == i)
continue;
1222 is_unchanged =
false;
1228 tfunc->
scale(tcoeff);
1234 for (i = 0; i <
size(); i++) {
1240 return is_unchanged;
1244 if (!head_group.size() || !head_group[0].has_valid_master())
return;
1250 for (
Index ng = 0; ng < head_group.size(); ng++) {
1253 for (
Index nb1 = 0; nb1 <
size(); nb1++) {
1255 for (
Index nb2 = 0; nb2 <
size(); nb2++) {
1256 tRep(nb2, nb1) = tfunct->
dot(
at(nb2));
1270 bool ortho_flag(
true);
1271 for (
Index i = 0; i < ortho_basis.
size(); i++) {
1280 bool ortho_flag(
true);
1289 tcoeff = tfunc->
dot(tfunc);
1298 tfunc->
scale(1.0 / sqrt(tcoeff));
1302 tcoeff = (
at(i)->
dot(tfunc));
1311 tfunc->
scale(tcoeff);
1313 tfunc->
scale(1.0 / tcoeff);
1325 if (tsubs.empty())
return BasisSet();
1327 compat_maps.reserve(tsubs.size());
1329 std::set<Index> dof_ids;
1330 std::string new_name = tsubs.size() ? tsubs[0]->name() :
"";
1332 for (
auto const &sub : tsubs) {
1333 if ((sub->name()).find(new_name) == std::string::npos)
1334 new_name += (
"+" + sub->name());
1335 dof_ids.insert(sub->dof_IDs().begin(), sub->dof_IDs().end());
1336 compat_maps.push_back({});
1337 for (
auto const &arg : sub->arguments()) {
1339 for (; i < tot_args.size(); ++i) {
1340 if (tot_args[i]->
compare(*arg))
break;
1342 if (i == tot_args.size()) tot_args.
add(*arg);
1343 compat_maps.back().push_back(i);
1347 std::vector<Index> dof_ids_vec(dof_ids.begin(), dof_ids.end());
1348 BasisSet result(new_name, tot_args);
1350 for (
Index i = 0; i < tsubs.size(); ++i) {
1396 return bset.to_json(json);
Basic std::vector like container (deprecated)
Function * & at(Index ind)
void swap_elem(Index i, Index j)
void add(BasisSet const &B)
void construct_invariant_polynomials(ArgList const &tsubs, const SymGroup &head_sym_group, Index order, Index min_dof_order=1)
void _deval_to_cache(const DoF::RemoteHandle &_dvar) const
void construct_polynomials_by_order(ArgList const &tsubs, Index order)
std::vector< std::shared_ptr< BasisSet > > m_argument
void remote_eval_and_add_to(Array< double > &cumulant) const
SymGroupRepID basis_symrep_ID() const
std::vector< Index > m_dof_IDs
const Array< SubBasis > & dof_sub_bases() const
bool compare(const BasisSet &RHS) const
bool _update_dof_IDs(const std::vector< Index > before_IDs, const std::vector< Index > &after_IDs)
BasisSet calc_normal_basis(const SymGroup &head_sym_group, Eigen::MatrixXd &trans_mat) const
void append(const BasisSet &RHS, std::function< Function *(Function *)> const &transform=CASM_TMP::UnaryIdentity< Function * >())
Append contents of.
bool satisfies_exponent_constraints(const Array< Index > &expons) const
void remote_eval_to(IteratorType result_begin, IteratorType result_end) const
void construct_harmonic_polynomials(const ArgList &tsubs, Index order, Index min_order, bool even_only)
void set_variable_basis(const DoFSet &_dof_set)
Define the basis set to contain only variables (e.g., x,y,z)
void set_dof_IDs(const std::vector< Index > &new_IDs)
std::vector< std::set< Index > > independent_sub_bases() const
void calc_invariant_functions(const SymGroup &head_sym_group)
void _eval_to_cache() const
const Array< PolyConstraint > & max_poly_constraints() const
void remote_deval_and_add_to(Array< double > &cumulant, const DoF::RemoteHandle &dvar) const
BasisSet(const std::string &name="", ArgList const &_args=ArgList())
std::pair< SubBasis, Index > PolyConstraint
Array< PolyConstraint > & _min_poly_constraints()
const std::vector< Index > & dof_IDs() const
std::vector< double > m_deval_cache
int dependency_layer() const
jsonParser & to_json(jsonParser &json) const
void set_name(const std::string &new_name)
Function * _linear_combination(const Eigen::VectorXd &coeffs) const
bool accept(const FunctionVisitor &visitor)
void push_back(Function *new_func)
void add_min_poly_constraint(const Array< Index > &expons, Index expon_sum)
void construct_orthonormal_discrete_functions(const DiscreteDoF &allowed_occs, const Eigen::MatrixXd &gram_mat, Index basis_ind, const SymGroup &symgroup)
const SubBasis & dof_sub_basis(Index i) const
Index min_poly_order() const
const std::string & name() const
BasisSet poly_quotient_set(const Function *divisor) const
Array< SubBasis > m_dof_subbases
void get_symmetry_representation(const SymGroup &head_sym_group) const
BasisSet transform_copy(const Eigen::MatrixXd &trans_mat) const
Index max_poly_order() const
int register_remotes(const std::vector< DoF::RemoteHandle > &remote_handles)
bool make_orthogonal_to(Function const *ortho_func)
Array< PolyConstraint > & _max_poly_constraints()
SymGroupRepID m_basis_symrep_ID
std::vector< std::shared_ptr< BasisSet > > const & arguments() const
std::shared_ptr< BasisSet > shared_copy() const
void _set_arguments(const ArgList &new_args)
BasisSet & apply_sym(const SymOp &op, int dependency_layer=1)
const BasisSet & operator=(const BasisSet &RHS)
std::vector< double > m_eval_cache
const Array< PolyConstraint > & min_poly_constraints() const
void remote_deval_to(IteratorType result_begin, IteratorType result_end, const DoF::RemoteHandle &dvar) const
virtual Index size() const =0
SymGroupRepID symrep_ID() const
Index ID() const
Const access of integer ID.
bool is_locked() const
true if ID is locked
std::string type_name() const
Const access of DoF type name.
SymGroupRepID const & symrep_ID() const
Index size() const
Returns the number of components in this DoFSet.
std::string const & type_name() const
Function * plus_in_place(Function const *RHS)
virtual double leading_coefficient() const =0
std::string identifier(char _key) const
virtual double cache_eval() const =0
virtual void scale(double scale_factor)=0
Function * minus_in_place(Function const *RHS)
virtual Function * copy() const =0
virtual int register_remotes(const std::vector< DoF::RemoteHandle > &remote_handles)
bool accept(const FunctionVisitor &visitor, BasisSet const *home_basis_ptr=nullptr)
virtual Function * apply_sym_coeffs(const SymOp &op, int dependency_layer=1)
virtual double get_coefficient(Index i) const =0
const ArgumentContainer & argument_bases() const
void set_identifier(char _key, std::string const &_value)
bool update_dof_IDs(const std::vector< Index > &before_IDs, const std::vector< Index > &after_IDs)
Function * poly_quotient(Function const *RHS) const
double dot(Function const *RHS) const
Function * sym_copy_coeffs(const SymOp &op, int dependency_layer=1) const
virtual void small_to_zero(double tol=TOL)=0
void set_arguments(const ArgumentContainer &new_arg)
change arguments of this function
virtual double cache_deval(const DoF::RemoteHandle &dvar) const =0
Function * multiply(Function const *RHS) const
A IsoCounter allows looping over many incrementing variables in one loop.
SymGroupRepID add_representation(const SymGroupRep &new_rep) const
SymGroupRepID add_transformed_rep(SymGroupRepID orig_ID, const Eigen::MatrixXd &trans_mat) const
Function * copy() const override
Function * copy() const override
const PolyTrie< double > & poly_coeffs() const
Function * transform_monomial_and_add(double prefactor, const Array< Index > &ind, const SymOp &op)
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
const MasterSymGroup & master_group() const
SymGroupRepID allocate_representation() const
Add a new empty representation.
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 ...
Type-safe ID object for communicating and accessing Symmetry representation info.
static SymGroupRepID identity(Index dim)
Static function to construct an ID for identity representations.
bool empty() const
Returns true if SymGroupRepID has not been initialized with valid group_index or rep_index.
bool is_identity() const
Returns true if SymGroupRepID corresponds to an Identity representation.
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...
const MasterSymGroup & master_group() const
const access of head group
Eigen::MatrixXd const * get_matrix_rep(SymGroupRepID _rep_ID) const
get pointer to matrix representation corresponding to rep_ID
bool has_valid_master() const
check if this representation is registered with a MasterSymGroup
jsonParser & put_obj()
Puts new empty JSON object.
jsonParser & put_array()
Puts new empty JSON array.
void reserve(Index new_max)
static ReturnArray< T > sequence(const T &initial, const T &final)
void push_back(const T &toPush)
Array & append(const Array &new_tail)
Index find(const Function * &test_elem) const
std::string to_string(ENUM val)
Return string representation of enum class.
T dot(const Tensor< T > &LHS, const Tensor< T > &RHS)
jsonParser & push_back(const T &value, Args &&... args)
bool almost_equal(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Check if ClusterInvariants are equal.
jsonParser & to_json(const ClexDescription &desc, jsonParser &json)
bool compare(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Compare ClusterInvariants.
Index find_index(Iterator begin, Iterator end, const T &value)
Equivalent to std::distance(begin, std::find(begin, end, value))
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...
BasisSet direct_sum(BasisSet::ArgList const &_subs)
BasisSet operator*(const SymOp &LHS, const BasisSet &RHS)
GenericDatumFormatter< std::string, DataObject > name()
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
int float_sgn(T val, double compare_tol=TOL)
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 ...
Eigen::MatrixXd::Index EigenIndex
bool valid_index(Index i)
INDEX_TYPE Index
For long integer indexing:
T max(const T &A, const T &B)
Shortcut for multidimensional vector (std::vector< std::vector< ...)