28 m_basis_symrep_ID(init_basis.basis_symrep_ID()),
29 m_name(init_basis.name()),
30 m_basis_ID(init_basis.m_basis_ID),
31 m_min_poly_order(init_basis.m_min_poly_order),
32 m_max_poly_order(init_basis.m_max_poly_order),
36 m_dof_IDs(init_basis.m_dof_IDs),
37 m_dof_subbases(init_basis.m_dof_subbases),
38 m_min_poly_constraints(init_basis.min_poly_constraints()),
39 m_max_poly_constraints(init_basis.max_poly_constraints()) {
45 for(
Index i = 0; i < init_basis.
size(); i++) {
117 assert(0 &&
"In BasisSet::append(), it is unsafe to append a BasisSet whose dependencies differ from (this).");
194 exp_sum = expons.
sum();
203 bool is_changed(
false), tchanged;
207 is_changed = tchanged || is_changed;
215 tchanged =
at(i)->
accept(visitor,
this);
216 is_changed = tchanged || is_changed;
261 if(!(
at(i)->shallow_compare(RHS[i])))
293 for(
Index i = 0; i < tvar_compon.
size(); i++) {
294 if(!tvar_compon[i].is_locked() && !tdof_IDs.
contains(tvar_compon[i].ID()))
298 for(
Index i = 0; i < tvar_compon.
size(); i++) {
311 if(before_IDs.
size() != after_IDs.
size() &&
size() > 0) {
312 std::cerr <<
"CRITICAL ERROR: In BasisSet::update_dof_IDs(), new IDs are incompatible with current IDs.\n"
327 if(m == before_IDs.
size()) {
328 std::cerr <<
"CRITICAL ERROR: In BasisSet::update_dof_IDs(), new IDs are incompatible with current IDs.\n"
352 std::vector< std::set<Index> > result;
353 std::vector<bool> unclaimed(
size(),
true);
358 for(j = 0; j < result.size(); j++) {
363 if(j == result.size())
364 result.emplace_back();
370 bool has_unclaimed =
false;
371 for(
Index i = 0; i < unclaimed.size(); i++) {
374 result.emplace_back();
375 has_unclaimed =
true;
377 result.back().insert(i);
409 for(
int i = 0; i < exp_count.
size(); i++) {
411 curr_expon[i] = exp_count()[i];
414 new_trie(curr_expon) = 1.0;
429 for(
Index i = 0; i < tsubs.
size(); ++i) {
431 tsubs[i]->get_symmetry_representation(head_group);
453 SubBasis big_sub_basis;
455 for(
Index j = 0; j < tsubs.
size(); j++) {
458 if(ID_ind == (tsubs[j]->
dof_IDs()).size())
461 for(
Index b = 0; b < sub_basis.
size(); b++) {
462 big_sub_basis.
push_back(sub_basis[b] + offset);
464 offset += tsubs[j]->
size();
471 OrderCount::Container initial_order(tsubs.
size(), 0), final_order(tsubs.
size(), order);
472 for(
Index i = 0; i < tsubs.
size(); i++) {
479 OrderCount order_count(initial_order, final_order, 1, order);
482 for(
Index i = 0; i < tsubs.
size(); i++) {
484 curr_exp.
append(exp_count.back());
487 for(; order_count.valid(); ++order_count) {
488 for(
Index i = 0; i < exp_count.size(); i++)
489 exp_count[i].set_sum_constraint(order_count[i]);
490 for(; exp_count.valid(); ++exp_count) {
491 bool valid_expon =
true;
492 for(
Index i = 0; i < exp_count.size() && valid_expon; i++)
499 ExpCount::const_value_iterator it(exp_count.value_begin()), it_end(exp_count.value_end());
500 for(; it != it_end; ++it) {
501 curr_exp[ne++] = *it;
509 for(
Index i = 0; i < head_group.
size(); i++) {
562 std::cerr <<
"CRITICAL ERROR: Passed a Gram Matrix to BasisSet::construct_orthonormal_discrete_functions that is not symmetric.\n"
563 <<
" Gram Matrix is:\n" << gram_mat <<
"\nExiting...\n";
571 std::cerr <<
"CRITICAL ERROR: Passed ill-conditioned Gram Matrix to BasisSet::construct_orthonormal_discrete_functions.\n"
572 <<
" The sum of the elements of the Gram matrix must be equal to 1.\n"
573 <<
" Gram Matrix is:\n" << gram_mat <<
"\nExiting...\n";
581 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> teig(gram_mat, Eigen::ComputeEigenvectors);
582 if(teig.eigenvalues().minCoeff() <
TOL) {
584 std::cerr <<
"CRITICAL ERROR: Passed a Gram Matrix to BasisSet::construct_orthonormal_discrete_functions that is not positive-definite.\n"
585 <<
" Gram Matrix is:\n" << gram_mat <<
"\nSmallest Eigenvalue = " << teig.eigenvalues().minCoeff() <<
"; Exiting...\n";
594 Eigen::MatrixXd B = teig.eigenvectors() * (teig.eigenvalues().array().cwiseInverse().cwiseSqrt().matrix().asDiagonal()) * teig.eigenvectors().inverse();
600 if(conc_vec.maxCoeff(&max_ind) < 0.75) {
604 for(
Index i = 0; i <
N; i++) {
605 tcos_table(i, 0) = 1.0;
606 double x = -cos(M_PI * (i + 0.5) /
double(N));
607 for(
Index j = 1; j <
N; j++) {
608 tcos_table(i, j) = x * tcos_table(i, j - 1);
613 tseed = tcos_table.householderQr().householderQ();
633 Eigen::MatrixXd Q = (B.inverse() * tseed).householderQr().householderQ();
641 for(
Index i = 1; i <
N; i++) {
653 for(
Index j = 0; j < B.rows(); j++) {
654 if(std::abs(B(j, i)) > (max_abs -
TOL)) {
655 max_abs = std::abs(B(j, i));
693 if(allowed_occs.
size() != occ_probs.
size()) {
694 std::cerr <<
"CRITICAL ERROR: In BasiSet::construct_orthonormal_discrete_functions(), occ_probs and allowed_occs are incompatible!\nExiting...\n";
700 std::cerr <<
"CRITICAL ERROR: In BasiSet::construct_orthonormal_discrete_functions(), occ_probs must sum to 1 (they specify a probability distributation).\n"
701 <<
" occ_probs is: " << occ_probs <<
"\nExiting...\n";
710 for(
Index i = 0; i <
N; i++) {
711 gram_mat(i, i) += occ_probs[i] - occ_probs[i] * occ_probs[i];
712 for(
Index j = 0; j <
N; j++) {
715 gram_mat(i, i) += (occ_probs[i] - occ_probs[j]) * (occ_probs[i] - occ_probs[j]);
717 gram_mat(i, j) -= occ_probs[i] * occ_probs[j] + (occ_probs[i] - occ_probs[j]) * (occ_probs[i] - occ_probs[j]);
724 for(
Index i = 0; i <
N; i++) {
725 for(
Index j = 0; j <
N; j++) {
726 gram_mat(i, j) += occ_probs[i] * occ_probs[j];
742 for(
Index ng = 0; ng < head_group.
size(); ng++) {
766 std::cerr <<
"CRITICAL ERROR: Inside BasisSet::is_normal_basis_for() and cannot calculate a valid SymGroup representation. Exiting...\n";
769 if(!head_group.
size())
786 std::cerr <<
"CRITICAL ERROR: Inside BasisSet::calc_normal_basis() and cannot calculate a valid SymGroup representation. Exiting...\n";
789 if(!head_group.
size()) {
790 std::cerr <<
"CRITICAL ERROR: Inside BasisSet::calc_normal_basis() and and passed empty SymGroup. Exiting...\n";
807 if(
m_argument.size() == 0 && new_func !=
nullptr) {
815 if(!
size())
return nullptr;
816 if(
size() != coeffs.size()) {
817 std::cerr <<
"FATAL ERROR: In BasisSet::_linear_combination, the number of basis functions \n"
818 <<
"does not match the size of the coefficient vector. Exiting...\n";
822 Function *combfunc(
nullptr), *tfunc(
nullptr);
824 for(
EigenIndex i = 0; i < coeffs.size(); i++) {
828 combfunc->
scale(coeffs[i]);
832 tfunc->
scale(coeffs[i]);
833 combfunc->plus_in_place(tfunc);
838 combfunc->
scale(0.0);
851 if(trans_mat.cols() !=
size()) {
852 std::cerr <<
"In BasisSet::transform_copy(), attempting to transform basis with a transformation\n"
853 <<
"matrix that has incompatible number of columns (has " << trans_mat.cols() <<
" and needs " <<
size() <<
").\n"
857 for(
EigenIndex nc = 0; nc < trans_mat.rows(); nc++) {
870 if(this_dep_layer == _dependency_layer) {
876 m_argument[i]->apply_sym(op, _dependency_layer);
886 std::cerr <<
"CRITICAL ERROR: In BasisSet::_set_arguments(), cannot reset arguments of already-initialized BasisSet.\n"
891 for(
Index i = 0; i < new_args.
size(); i++)
892 m_argument.push_back(new_args[i]->shared_copy());
906 bool is_unchanged(
true);
912 for(i = 0; i <
size(); i++) {
915 tcoeff = sqrt(
at(i)->
dot(
at(i)));
918 is_unchanged =
false;
925 is_unchanged =
false;
930 for(j = i + 1; j <
size(); j++) {
936 is_unchanged =
false;
942 tfunc->
scale(tcoeff);
959 bool is_unchanged(
true);
961 Index j_min, i_min, i_temp;
962 double tcoeff, min_coeff;
966 for(i_temp = i; i_temp <
size(); i_temp++) {
972 is_unchanged =
false;
975 if(!
valid_index(j_min) || j < j_min || (j == j_min && std::abs(tcoeff) > std::abs(min_coeff))) {
981 if(i >=
size())
break;
985 is_unchanged =
false;
992 for(i_temp = 0; i_temp <
size(); i_temp++) {
993 if(i_temp == i)
continue;
996 is_unchanged =
false;
1002 tfunc->
scale(tcoeff);
1008 for(i = 0; i <
size(); i++) {
1014 return is_unchanged;
1019 if(!head_group.
size() || !head_group[0].has_valid_master())
return;
1025 for(
Index ng = 0; ng < head_group.
size(); ng++) {
1028 for(
Index nb1 = 0; nb1 <
size(); nb1++) {
1031 for(
Index nb2 = 0; nb2 <
size(); nb2++) {
1032 tRep(nb2, nb1) = tfunct->
dot(
at(nb2));
1047 bool ortho_flag(
true);
1048 for(
Index i = 0; i < ortho_basis.
size(); i++) {
1059 bool ortho_flag(
true);
1068 tcoeff = tfunc->
dot(tfunc);
1077 tfunc->scale(1.0 / sqrt(tcoeff));
1081 tcoeff = (
at(i)->
dot(tfunc));
1090 tfunc->scale(tcoeff);
1092 tfunc->
scale(1.0 / tcoeff);
bool make_orthogonal_to(Function const *ortho_func)
void _set_arguments(const Array< BasisSet const * > &new_args)
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
std::pair< SubBasis, Index > PolyConstraint
void get_symmetry_representation(const SymGroup &head_sym_group) const
bool update_dof_IDs(const Array< Index > &before_IDs, const Array< Index > &after_IDs)
bool contains(const T &test_elem) const
void _deval_to_cache(const DoF::RemoteHandle &_dvar) const
Remotely evaluate each basis function and add it to the respective value in cumulant.
const MasterSymGroup & master_group() const
Type-safe ID object for communicating and accessing Symmetry representation info. ...
bool empty() const
Returns true if SymGroupRepID has not been initialized with valid group_index or rep_index.
bool accept(const FunctionVisitor &visitor, BasisSet const *home_basis_ptr=NULL)
void construct_polynomials_by_order(const Array< BasisSet const * > &tsubs, Index order)
virtual Function * apply_sym_coeffs(const SymOp &op, int dependency_layer=1)
void calc_invariant_functions(const SymGroup &head_sym_group)
void push_back(const T &toPush)
SymGroupRepID add_transformed_rep(SymGroupRepID orig_ID, const Eigen::MatrixXd &trans_mat) const
const Array< PolyConstraint > & max_poly_constraints() const
jsonParser & to_json(const ClexDescription &desc, jsonParser &json)
Function * minus_in_place(Function const *RHS)
bool is_identity() const
Returns true if SymGroupRepID corresponds to an Identity representation.
BasisSet transform_copy(const Eigen::MatrixXd &trans_mat) const
virtual int register_remotes(const std::string &dof_name, const Array< DoF::RemoteHandle > &remote_handles)
void construct_invariant_polynomials(const Array< BasisSet const * > &tsubs, const SymGroup &head_sym_group, Index order, Index min_dof_order=1)
void add_min_poly_constraint(const Array< Index > &expons, Index expon_sum)
void push_back(Function *new_func)
const std::string & name() const
Array< PolyConstraint > & _min_poly_constraints()
bool compare(const BasisSet &RHS) const
virtual double get_coefficient(Index i) const =0
void set_arguments(const ArgumentContainer &new_arg)
void remote_eval_and_add_to(Array< double > &cumulant) const
Remotely evaluate each basis function and add it to the respective value in cumulant.
static ReturnArray< T > sequence(const T &initial, const T &final)
Returns an array with the sequence (initial, ++initial, ..., final), inclusive.
BasisSet poly_quotient_set(const Function *divisor) const
Eigen::MatrixXd get_irrep_trans_mat(const SymGroup &head_group) const
BasisSet calc_normal_basis(const SymGroup &head_sym_group, Eigen::MatrixXd &trans_mat) const
std::vector< double > m_deval_cache
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Array< SubBasis > m_dof_subbases
void append(const BasisSet &RHS)
virtual void scale(double scale_factor)=0
jsonParser & to_json(jsonParser &json) const
SymGroupRepID sym_rep_ID() const
Eigen::MatrixXd::Index EigenIndex
For integer indexing:
SymOp is the Coordinate representation of a symmetry operation it keeps fraction (FRAC) and Cartesian...
BasisSet operator*(const SymOp &LHS, const BasisSet &RHS)
virtual void small_to_zero(double tol=TOL)=0
virtual Function * copy() const =0
int dependency_layer() const
std::vector< std::shared_ptr< BasisSet > > m_argument
EigenIndex Index
For long integer indexing:
void construct_orthonormal_discrete_functions(const DiscreteDoF &allowed_occs, const Eigen::MatrixXd &gram_mat, Index basis_ind, const SymGroup &symgroup)
bool accept(const FunctionVisitor &visitor)
const PolyTrie< double > & poly_coeffs() const
int float_sgn(T val, double compare_tol=TOL)
SymGroupRepID m_basis_symrep_ID
const Array< PolyConstraint > & min_poly_constraints() const
bool is_normal_basis_for(const SymGroup &head_sym_group)
std::vector< double > m_eval_cache
virtual Index size() const =0
Function * transform_monomial_and_add(double prefactor, const Array< Index > &ind, const SymOp &op)
T max(const T &A, const T &B)
Function * sym_copy_coeffs(const SymOp &op, int dependency_layer=1) const
Function *& at(Index ind)
T dot(const Tensor< T > &LHS, const Tensor< T > &RHS)
void swap_elem(Index i, Index j)
BasisSet(const std::string &name="")
Index find(const T &test_elem) const
int register_remotes(const std::string &dof_name, const Array< DoF::RemoteHandle > &remote_handles)
Array & append(const Array &new_tail)
Generalized symmetry matrix representation for arbitrary dimension Can be used to describe applicatio...
A IsoCounter allows looping over many incrementing variables in one loop.
double dot(Function const *RHS) const
void remote_eval_to(IteratorType result_begin, IteratorType result_end) const
Remotely evaluate each basis function and add it to the respective value in cumulant.
SymGroupRepID basis_symrep_ID() const
ReturnArray< Index > num_each_real_irrep(const SymGroup &subgroup, bool verbose=false) const
jsonParser & put_obj()
Puts new empty JSON object.
void reserve(Index new_max)
void _update_dof_IDs(const Array< Index > before_IDs, const Array< Index > &after_IDs)
jsonParser & push_back(const T &value)
Puts new valued element at end of array of any type T for which 'jsonParser& to_json( const T &value...
BasisSet & apply_sym(const SymOp &op, int dependency_layer=1)
SymGroupRep coord_transformed_copy(const Eigen::MatrixXd &trans_mat) const
Function * _linear_combination(const Eigen::VectorXd &coeffs) const
SymGroupRep is an alternative representation of a SymGroup for something other than real space...
void set_variable_basis(const Array< ContinuousDoF > &tvar_compon, SymGroupRepID _sym_rep_ID)
Define the basis set to contain only variables (e.g., x,y,z)
const SubBasis & dof_sub_basis(Index i) const
void remote_deval_to(IteratorType result_begin, IteratorType result_end, const DoF::RemoteHandle &dvar) const
Remotely evaluate derivative of each basis function (w.r.t. dvar) and add it to the respective value ...
virtual double leading_coefficient() const =0
Function * plus_in_place(Function const *RHS)
void set_dof_IDs(const Array< Index > &new_IDs)
virtual double cache_deval(const DoF::RemoteHandle &dvar) const =0
Index max_poly_order() const
const ArgumentContainer & argument_bases() const
void remote_deval_and_add_to(Array< double > &cumulant, const DoF::RemoteHandle &dvar) const
Remotely evaluate derivative of each basis function (w.r.t. dvar) and add it to the respective value ...
const BasisSet & operator=(const BasisSet &RHS)
Index min_poly_order() const
Array< PolyConstraint > & _max_poly_constraints()
bool satisfies_exponent_constraints(const Array< Index > &expons) const
std::vector< std::set< Index > > independent_sub_bases() const
SymGroupRepID add_empty_representation() const
Add a new empty representation.
Basic std::vector like container (deprecated)
virtual double cache_eval() const =0
jsonParser & put_array()
Puts new empty JSON array.
bool almost_equal(const GenericCluster< CoordType > &LHS, const GenericCluster< CoordType > &RHS, double tol)
void _eval_to_cache() const
Remotely evaluate each basis function and add it to the respective value in cumulant.
const Array< SubBasis > & dof_sub_bases() const
const Array< Index > & dof_IDs() const
static SymGroupRepID identity(Index dim)
Static function to construct an ID for identity representations.
bool valid_index(Index i)