48 max_ind[i] = Ndim[i] - 1;
61 max_ind[i] = Ndim[i] - 1;
74 max_ind[i] = Ndim[i] - 1;
81 Tensor(
const Eigen::Matrix<T, 3, 3> &mat_init) : Nrank(2), Ndim(2, 3) {
86 max_ind[i] = Ndim[i] - 1;
91 for(
int i = 0; i < 3; i++)
92 for(
int j = 0; j < 3; j++)
93 (*
this)(i, j) = mat_init(i, j);
111 template<
int dim1,
int dim2,
int flag1>
178 void read(std::istream &stream);
188 Tensor<T>
operator*(
const T &LHS,
const Tensor<T> &RHS);
191 Tensor<T>
operator*(
const SymOp &LHS,
const Tensor<T> &RHS);
194 std::ostream &operator << (std::ostream &stream, const Tensor<T> &RHS);
197 std::istream &
operator >> (std::istream &stream, Tensor<T> &RHS);
202 class ReturnTensor :
public Tensor<T> {
244 bool read(std::istream &stream);
263 template<
int dim1,
int dim2,
int flag1>
266 if(rank() != 2 || dim(0) != LHS.rows() || dim(1) != LHS.cols()) {
267 tdim[0] = LHS.rows();
268 tdim[1] = LHS.cols();
271 for(
int i = 0; i < LHS.rows(); i++) {
273 for(
int j = 0; j < LHS.rows(); j++) {
275 at(tdim) = LHS(i, j);
286 Nrank = _Ndim.
size();
290 max_ind.resize(Nrank);
291 for(
Index i = 0; i < Nrank; i++) {
292 max_ind[i] = Ndim[i] - 1;
304 Nrank = _Ndim.
size();
308 max_ind.resize(Nrank);
309 for(
Index i = 0; i < Nrank; i++) {
310 max_ind[i] = Ndim[i] - 1;
322 if(iperm.
size() != Nrank) {
324 std::cout <<
"WARNING: In Tensor<T>::dim_permute, permutation array is incompatible with tensor rank! Continuing without permuting indeces...\n";
345 if(iperm.
size() != Nrank) {
346 std::cerr <<
"WARNING: In Tensor<T>::dim_permute, permutation array is incompatible with tensor rank! Continuing without permuting indeces...\n";
371 max_ind.permute(tperm);
381 bool is_valid =
true;
383 for(
Index k = 0; k < Nrank; k++)
393 while(idim[j] <= idim[i])
397 Ndim.swap_elem(i, j);
398 max_ind.swap_elem(i, j);
410 idim.swap_elem(i, j);
411 Ndim.swap_elem(i, j);
412 max_ind.swap_elem(i, j);
425 if(idim.is_ascending())
428 Tensor ttens(Nrank, Ndim);
432 ttens(icount()) = at(icount());
434 while((++icount).valid());
462 for(
Index i = 0; i < tunique.
size(); i++)
466 Index iset(0), i(0), j(0), nperm(1);
468 while(iset < tunique.
size()) {
469 for(i = 0; i < tunique.
size(); i++)
470 for(j = 0; j < tunique[i].
size(); j++)
471 tperm[unique_dim[i][j]] = tunique[i][j];
479 (*this) /= double(nperm);
530 for(
Index i = 0; i < Nrank; i++)
531 lin_index += inds[i] * idim[i];
533 return at(lin_index);
541 for(
Index i = 0; i < Nrank; i++)
542 lin_index += inds[i] * idim[i];
544 return at(lin_index);
552 for(
Index i = 0; i < Nrank; i++)
553 lin_index += inds[i] * idim[i];
555 return at(lin_index);
563 for(
Index i = 0; i < Nrank; i++)
564 lin_index += inds[i] * idim[i];
566 return at(lin_index);
574 for(
Index i = 0; i < Nrank; i++)
575 lin_index += inds[i] * idim[i];
577 return at(lin_index);
583 return at(i * idim[0] + j * idim[1]);
590 return at(i * idim[0] + j * idim[1]);
597 if(Ndim != RHS.
Ndim) {
598 std::cerr <<
"Attempting to add two incompatible tensors!\n";
602 if(idim == RHS.
idim) {
603 for(
Index i = 0; i < size(); i++)
612 at(icount()) += RHS(icount());
615 while((++icount).valid());
624 if(Ndim != RHS.
Ndim) {
625 std::cerr <<
"Attempting to add two incompatible tensors!\n";
629 if(idim == RHS.
idim) {
630 for(
Index i = 0; i < size(); i++)
638 at(icount()) -= RHS(icount());
640 while((++icount).valid());
650 for(
Index i = 0; i < size(); i++)
661 for(
Index i = 0; i < size(); i++)
696 if(Ndim != RHS.
Ndim) {
697 std::cerr <<
"Attempting to take scalar product of two incompatible tensors!\n";
704 if(idim == RHS.
idim) {
705 for(
Index i = 0; i < size(); i++)
706 tprod += at(i) * RHS[i];
712 tprod += at(icount()) * RHS(icount());
714 while((++icount).valid());
734 for(i = 0; i < icount().
size(); i++)
735 tot_ind += icount[i] * ttens.
idim[i];
737 for(j = 0; j < jcount().
size(); j++)
738 tot_ind += jcount[j] * ttens.
idim[i + j];
740 ttens[tot_ind] = at(icount()) * RHS(jcount());
743 while((++jcount).valid());
745 while((++icount).valid());
756 return (*
this) /= sqrt(scalar_prod(*
this));
764 for(
Index i = 0; i < tdim; i++)
773 if(!rank())
return *
this;
787 for(nd = 0; nd < Nrank; nd++)
788 tval *= (*rep_mats[nd])(icount[nd], jcount[nd]);
789 ttens(icount()) += tval;
792 while((++jcount).valid());
795 while((++icount).valid());
803 if(!rank())
return *
this;
812 for(nd = 0; nd < Nrank; nd++)
813 tval *= (*rep_mats[nd])(icount[nd], inner_ind[nd]);
814 at(icount()) += tval;
817 while((++icount).valid());
824 if(!rank())
return *
this;
837 for(nd = 0; nd < Nrank; nd++)
838 tval *= op.
matrix()(icount[nd], jcount[nd]);
839 ttens(icount()) += tval;
842 while((++jcount).valid());
845 while((++icount).valid());
863 while((++icount).valid());
899 if(!rank())
return *
this;
912 for(nd = 0; nd < Nrank; nd++)
913 tval *= mat(icount[nd], jcount[nd]);
914 ttens(icount()) += tval;
917 while((++jcount).valid());
920 while((++icount).valid());
930 std::cerr <<
"WARNING: Attempting to assign Eigen::Matrix object using a Tensor of rank " << rank()
931 <<
"!\nTensor must have rank=2 for assignment to be valid. Exiting...\n";
934 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> tmat(dim(0), dim(1));
936 for(
Index i = 0; i < tmat.rows(); i++) {
937 for(
Index j = 0; j < tmat.rows(); j++) {
938 tmat(i, j) = (*this)(i, j);
976 std::ostream &operator<<(std::ostream &stream, const Tensor<T> &RHS) {
977 std::ios::fmtflags old_flags = stream.flags();
978 stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
979 int twide = stream.width();
982 stream << RHS[0] <<
'\n';
983 stream.flags(old_flags);
990 if(RHS.rank() > 2 && icount[0] == 0 && icount[1] == 0) {
991 stream <<
"Block (:,:," << icount[2];
992 for(
Index j = 3; j < RHS.rank(); j++)
993 stream <<
"," << icount[j];
997 stream << std::setw(0) <<
" " << std::setw(twide) << RHS(icount());
998 if(icount[0] == RHS.ind_max()[0]) {
1006 while((++icount).valid());
1007 stream.flags(old_flags);
1017 std::cerr <<
"WARNING: Input stream operator has not been implemented for Tensor class! Exiting...\n";
1032 for(i = 0; i < ttens.
size(); i++) {
1035 for(ns = 0; ns < sym_group.
size(); ns++)
1036 avtens += sym_group[ns] * ttens;
1038 this->push_back(avtens);
1043 coeffs.resize(size(), NAN);
1051 if(!sym_group.
size()) {
1052 std::cerr <<
"WARNING: Attempting to generate tensor basis from an invalid symmetry group. Exiting...";
1060 for(i = 0; i < ttens.
size(); i++) {
1063 for(ns = 0; ns < sym_group.
size(); ns++)
1064 avtens += sym_group[ns] * ttens;
1071 coeffs.resize(size(), NAN);
1083 if(sym_group.
size() != perm_group.
size()) {
1084 std::cerr <<
"WARNING: Attempting to generate tensor basis, but symmetry group and permutation group are not compatible!\n";
1089 for(i = 0; i < ttens.
size(); i++) {
1092 for(ns = 0; ns < sym_group.
size(); ns++)
1093 avtens += (sym_group[ns] * ttens).
dim_permute(*(perm_group[ns]->get_permutation()));
1095 this->push_back(avtens);
1100 coeffs.resize(size(), NAN);
1109 for(i = 0; i < size(); i++) {
1110 for(j = 0; j < ortho_basis.
size(); j++) {
1111 at(i) -= (at(i).scalar_prod(ortho_basis[j]) /
norm(ortho_basis[j])) * ortho_basis[j];
1121 for(
Index i = 0; i < size(); i++) {
1131 for(
Index i = 0; i < size(); i++)
1154 Index num_elem, rank;
1159 while(ch < '0' || ch >
'9') {
1160 stream.ignore(256,
'\n');
1165 stream.ignore(256,
'\n');
1172 for(
Index i = 0; i < rank; i++) {
1177 std::cout <<
"dim is " << dim <<
"\n";
1180 stream.ignore(1000,
'\n');
1182 coeffs.
resize(num_elem, NAN);
1186 for(
Index j = 0; j < num_elem; j++) {
1191 while(ch !=
char(60)) {
1192 if(((ch <
'0') || (ch >
'9')) && (ch !=
'-')) {
1193 stream.ignore(1000,
'\n');
1202 if(((ch !=
char(60)) && ((ch >=
'0') || (ch <=
'9'))) || (ch ==
'-')) {
1205 std::cout <<
"Coefficient is " << tcoeff <<
"\n";
1210 stream.ignore(1000,
'\n');
1212 ttensor.
read(stream);
1213 this->push_back(ttensor);
ReturnTensor & operator=(Tensor< T > &RHS)
Tensor & symmetrize_index(const SymOp &op, Array< SymGroupRepID > rep_IDs, Array< Index > inner_ind)
Tensor & transform(const Eigen::MatrixXd &op)
Tensor & dim_permute(const Array< Index > &iperm)
Tensor & operator=(const T &RHS)
const Array< Index > & ind_max() const
Tensor(const Eigen::Matrix< T, 3, 3 > &mat_init)
Tensor & dim_ipermute(const Array< Index > &perm)
A Counter allows looping over many incrementing variables in one loop.
Counter< Array< Index > > element_counter() const
void generate_basis(Index Nrank, const SymGroup &sym_group)
const Array< Index > & perm_array() const
ReturnTensor< T > operator-()
Tensor(Index tNrank, Array< Index > tNdim, T init_val)
TensorBasis & apply_sym(const SymOp &op)
const Array< Index > & mult_array() const
T & operator()(const Array< Index > &inds)
void swap(Array< T > &RHS)
T scalar_prod(const Tensor &RHS) const
bool read(std::istream &stream)
const T & get(const Array< Index > &inds) const
void swap(ConfigDoF &A, ConfigDoF &B)
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
const matrix_type & matrix() const
Const access of entire cartesian symmetry matrix.
Tensor & operator=(ReturnTensor< T > &RHS)
Tensor(Index tNrank, Array< Index > tNdim)
SymOp is the Coordinate representation of a symmetry operation it keeps fraction (FRAC) and Cartesian...
static ReturnTensor< T > identity(Index trank, Index tdim)
BasisSet operator*(const SymOp &LHS, const BasisSet &RHS)
Tensor & operator+=(const Tensor &RHS)
T norm(const Tensor< T > &ttens)
EigenIndex Index
For long integer indexing:
Tensor & operator-=(const Tensor &RHS)
const Array< Index > & dim() const
void redefine(Array< Index > _Ndim)
Array & ipermute(const Array< Index > &perm_array)
void read(std::istream &stream)
T max(const T &A, const T &B)
T min(const T &A, const T &B)
Tensor< T > & at(Index ind)
T dot(const Tensor< T > &LHS, const Tensor< T > &RHS)
void swap_elem(Index i, Index j)
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > convert_to_Eigen() const
T & at(const Array< Index > &inds)
Tensor & operator*=(T RHS)
std::istream & operator>>(std::istream &_in, std::vector< T > &vec)
void make_orthogonal_to(const TensorBasis &ortho_basis)
ReturnTensor< T > operator+(const Tensor &RHS)
void sort(const CompareType &comp)
ReturnTensor< T > tensor_prod(const Tensor &RHS)
Tensor & operator/=(T RHS)
SymGroupRep is an alternative representation of a SymGroup for something other than real space...
double eci(Index i) const
Array< Eigen::MatrixXd const * > get_matrix_reps(Array< SymGroupRepID > _rep_IDs) const
get array of pointers to matrix representations for representations corresponding to _rep_IDs ...
void permute_symmetrize()
Symmetrize tensor with respect to index permutation.
Tensor & apply_sym(const SymOp &op)
bool contains(const Container &container, const T &value)
Equivalent to container.end() != std::find(container.begin(), container.end(), value) ...
ReturnTensor(Tensor< T > &init_tens)
void reset()
Reset the current value of the Counter to the initial value.
Array< T > array_cat(const Array< T > &A1, const Array< T > &A2)
Basic std::vector like container (deprecated)
Tensor(ReturnTensor< T > &init_cont)
Tensor slice(Array< Index > slice_Ndim, Array< Index > slice_ind)
Array & permute(const Array< Index > &perm_array)
bool valid_index(Index i)