CASM  1.1.0
A Clusters Approach to Statistical Mechanics
Tensor.hh
Go to the documentation of this file.
1 #ifndef TENSOR_HH
2 #define TENSOR_HH
3 
4 #include <cmath>
5 #include <iostream>
6 
12 
13 namespace CASM {
14 
15 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 template <class T>
18 
19 template <class T>
20 class ReturnTensor;
21 
22 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 
31 template <class T>
32 class Tensor : public Array<T> {
35 
36  public:
37  using Array<T>::resize;
38  using Array<T>::size;
39  using Array<T>::at;
40 
41  // These constructors take two arguments even though they really just need
42  // one, since rank==dim.size() if you're doing it right.
43  Tensor(Index tNrank, Array<Index> tNdim) : Nrank(tNrank), Ndim(tNdim) {
44  Index N = 1;
45  idim.resize(Nrank);
47  for (Index i = 0; i < Nrank; i++) {
48  max_ind[i] = Ndim[i] - 1;
49  idim[i] = N;
50  N *= Ndim[i];
51  }
52 
53  resize(N);
54  };
55 
56  Tensor(Index tNrank, Array<Index> tNdim, T init_val)
57  : Nrank(tNrank), Ndim(tNdim) {
58  Index N = 1;
59  idim.resize(Nrank);
61  for (Index i = 0; i < Nrank; i++) {
62  max_ind[i] = Ndim[i] - 1;
63  idim[i] = N;
64  N *= Ndim[i];
65  }
66 
67  resize(N, init_val);
68  };
69 
70  Tensor(Index tNrank = 0) : Nrank(tNrank), Ndim(tNrank, 3) {
71  Index N = 1;
72  idim.resize(Nrank);
74  for (Index i = 0; i < Nrank; i++) {
75  max_ind[i] = Ndim[i] - 1;
76  idim[i] = N;
77  N *= Ndim[i];
78  }
79  resize(N);
80  };
81 
82  Tensor(const Eigen::Matrix<T, 3, 3> &mat_init) : Nrank(2), Ndim(2, 3) {
83  Index N = 1;
84  idim.resize(Nrank);
86  for (Index i = 0; i < Nrank; i++) {
87  max_ind[i] = Ndim[i] - 1;
88  idim[i] = N;
89  N *= Ndim[i];
90  }
91  resize(N);
92  for (int i = 0; i < 3; i++)
93  for (int j = 0; j < 3; j++) (*this)(i, j) = mat_init(i, j);
94  }
95 
96  Tensor(ReturnTensor<T> &init_cont) { swap(init_cont); };
97 
99  swap(RHS);
100  return *this;
101  };
102 
103  Tensor &operator=(const T &RHS) {
104  for (Index i = 0; i < size(); i++) at(i) = RHS;
105  return *this;
106  }
107 
108  template <int dim1, int dim2, int flag1>
109  Tensor &operator=(const Eigen::Matrix<T, dim1, dim2, flag1> &LHS);
110 
111  static ReturnTensor<T> identity(Index trank, Index tdim);
112 
113  void swap(Tensor &RHS);
114  void redefine(Array<Index> _Ndim);
115  void redefine(Array<Index> _Ndim, T fill_val);
116 
117  Tensor &dim_permute(const Array<Index> &iperm);
118  Tensor &dim_permute(const Permutation &perm);
119 
120  Tensor &dim_ipermute(const Array<Index> &perm);
121  Tensor &dim_ipermute(const Permutation &perm);
122 
124  bool next_permute();
126  void permute_symmetrize();
130  void permute_symmetrize(const Array<Array<Index> > &unique_dim);
131  void reset_idim();
132 
134 
135  Index rank() const;
136  const Array<Index> &ind_max() const;
137  const Array<Index> &dim() const;
138  Index dim(Index i) const;
139 
140  const Array<Index> &mult_array() const;
141 
142  const T &get(const Array<Index> &inds) const;
143  T &at(const Array<Index> &inds);
144  const T &at(const Array<Index> &inds) const;
145  T &operator()(const Array<Index> &inds);
146  const T &operator()(const Array<Index> &inds) const;
147  T &operator()(Index i, Index j);
148  const T &operator()(Index i, Index j) const;
149 
150  Tensor &operator+=(const Tensor &RHS);
151  Tensor &operator-=(const Tensor &RHS);
152  Tensor &operator*=(T RHS);
153  Tensor &operator/=(T RHS);
154 
156  ReturnTensor<T> operator+(const Tensor &RHS);
157  ReturnTensor<T> operator-(const Tensor &RHS);
158 
159  // We should find a way to do tensor contraction/multiplication
160 
161  T scalar_prod(const Tensor &RHS) const;
162  ReturnTensor<T> tensor_prod(const Tensor &RHS);
163  Tensor &normalize();
164 
165  Tensor &transform(const Eigen::MatrixXd &op);
166 
167  // rep_IDs specify the representations that transform each dimension of tensor
168  Tensor &transform(const SymOp &op, Array<SymGroupRepID> rep_IDs);
169 
170  Tensor &apply_sym(const SymOp &op);
171 
173  Array<Index> inner_ind);
174 
175  Tensor slice(Array<Index> slice_Ndim, Array<Index> slice_ind);
176 
177  void read(std::istream &stream); // Added by Ivy -- TODO: Make more general
178  // for not just rank 2 tensors
179 
180  // Tensor<T> matrix_multiply(Vector3<T> &tvec);
181 
182  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> convert_to_Eigen() const;
183 };
184 
185 template <class T>
186 Tensor<T> operator*(const T &LHS, const Tensor<T> &RHS);
187 
188 template <class T>
189 Tensor<T> operator*(const SymOp &LHS, const Tensor<T> &RHS);
190 
191 template <class T>
192 std::ostream &operator<<(std::ostream &stream, const Tensor<T> &RHS);
193 
194 template <class T>
195 std::istream &operator>>(std::istream &stream, Tensor<T> &RHS);
196 
197 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
198 
199 template <class T>
200 class ReturnTensor : public Tensor<T> {
201  public:
202  using Tensor<T>::swap;
203 
204  ReturnTensor(Tensor<T> &init_tens) { swap(init_tens); }
205 
207  swap(RHS);
208  return *this;
209  };
210 };
211 
212 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
213 
214 template <class T>
215 class TensorBasis : public Array<Tensor<T> > {
216  public:
217  using Array<Tensor<T> >::size;
218  using Array<Tensor<T> >::at;
219  using Array<Tensor<T> >::clear;
220 
222 
223  double eci(Index i) const { return coeffs[i]; };
224  double &eci(Index i) { return coeffs[i]; }; // Added by Ivy 09/25/2012
225 
226  void generate_basis(Index Nrank, const SymGroup &sym_group);
227  void generate_basis(Index Nrank, const SymGroup &sym_group, Index Rep_ID);
228  void generate_basis(Index Nrank, const SymGroup &sym_group,
229  const SymGroupRep &perm_group);
230 
231  void make_orthogonal_to(const TensorBasis &ortho_basis);
232  TensorBasis &apply_sym(const SymOp &op);
233  void normalize();
234  void idealize();
235  bool read(std::istream &stream); // Added by Ivy
236 };
237 
238 //************************************************************
239 
240 template <class T>
242  Index trank(Nrank);
243  Nrank = RHS.Nrank;
244  RHS.Nrank = trank;
245  Ndim.swap(RHS.Ndim);
246  idim.swap(RHS.idim);
247  max_ind.swap(RHS.max_ind);
248  Array<T>::swap(RHS);
249  return;
250 }
251 
252 //************************************************************
253 template <class T>
254 template <int dim1, int dim2, int flag1>
256  const Eigen::Matrix<T, dim1, dim2, flag1> &LHS) {
257  Array<Index> tdim(2);
258  if (rank() != 2 || dim(0) != LHS.rows() || dim(1) != LHS.cols()) {
259  tdim[0] = LHS.rows();
260  tdim[1] = LHS.cols();
261  redefine(tdim);
262  }
263  for (int i = 0; i < LHS.rows(); i++) {
264  tdim[0] = i;
265  for (int j = 0; j < LHS.rows(); j++) {
266  tdim[1] = j;
267  at(tdim) = LHS(i, j);
268  }
269  }
270  return (*this);
271 }
272 
273 //************************************************************
274 
275 template <class T>
277  Nrank = _Ndim.size();
278  Ndim = _Ndim;
279  Index N = 1;
280  idim.resize(Nrank);
281  max_ind.resize(Nrank);
282  for (Index i = 0; i < Nrank; i++) {
283  max_ind[i] = Ndim[i] - 1;
284  idim[i] = N;
285  N *= Ndim[i];
286  }
287 
288  resize(N);
289 }
290 
291 //************************************************************
292 
293 template <class T>
294 void Tensor<T>::redefine(Array<Index> _Ndim, T fill_val) {
295  Nrank = _Ndim.size();
296  Ndim = _Ndim;
297  Index N = 1;
298  idim.resize(Nrank);
299  max_ind.resize(Nrank);
300  for (Index i = 0; i < Nrank; i++) {
301  max_ind[i] = Ndim[i] - 1;
302  idim[i] = N;
303  N *= Ndim[i];
304  }
305 
306  resize(N, fill_val);
307 }
308 
309 //************************************************************
310 
311 template <class T>
313  if (iperm.size() != Nrank) {
314  // temporarily changed this to cout
315  throw std::runtime_error(
316  "Tensor<T>::dim_permute, permutation array is incompatible with tensor "
317  "rank!");
318  return *this;
319  }
320 
321  idim.permute(iperm);
322  Ndim.permute(iperm);
323  max_ind.permute(iperm);
324 
325  return *this;
326 }
327 
328 //************************************************************
329 
330 template <class T>
332  return dim_permute(perm.perm_array());
333 }
334 //************************************************************
335 
336 template <class T>
338  if (iperm.size() != Nrank) {
339  std::cerr << "WARNING: In Tensor<T>::dim_permute, permutation array is "
340  "incompatible with tensor rank! Continuing without permuting "
341  "indeces...\n";
342  return *this;
343  }
344 
345  idim.ipermute(iperm);
346  Ndim.ipermute(iperm);
347  max_ind.ipermute(iperm);
348 
349  return *this;
350 }
351 
352 //************************************************************
353 
354 template <class T>
356  return dim_ipermute(perm.perm_array());
357 }
358 //************************************************************
359 
360 template <class T>
362  Array<Index> tperm;
363 
364  idim.sort(tperm);
365  Ndim.permute(tperm);
366  max_ind.permute(tperm);
367 
368  return *this;
369 }
370 
371 //************************************************************
372 
373 template <class T>
375  Index i = Nrank - 2;
376  bool is_valid = true;
377  Array<Index> iperm;
378  for (Index k = 0; k < Nrank; k++) iperm[k] = k;
379 
380  while (valid_index(i) && idim[i + 1] <= idim[i]) i--;
381 
382  Index j = Nrank - 1;
383 
384  if (valid_index(i)) {
385  while (idim[j] <= idim[i]) j--;
386 
387  idim.swap_elem(i, j);
388  Ndim.swap_elem(i, j);
389  max_ind.swap_elem(i, j);
390 
391  i++;
392  j = Nrank - 1;
393  }
394 
395  else {
396  is_valid = false;
397  i = 0;
398  }
399 
400  while (i < j && valid_index(j)) {
401  idim.swap_elem(i, j);
402  Ndim.swap_elem(i, j);
403  max_ind.swap_elem(i, j);
404 
405  i++;
406  j--;
407  }
408 
409  return is_valid;
410 }
411 
412 //************************************************************
413 
414 template <class T>
416  if (idim.is_ascending()) return;
417 
418  Tensor ttens(Nrank, Ndim);
419  Counter<Array<Index> > icount(ttens.element_counter());
420 
421  do {
422  ttens(icount()) = at(icount());
423  } while ((++icount).valid());
424 
425  swap(ttens);
426 
427  return;
428 }
429 
430 //************************************************************
431 
432 template <class T>
434  reset_idim();
435  Tensor<T> ttens(*this);
436  Index nperm = 1;
437  while (ttens.next_permute()) {
438  (*this) += ttens;
439  nperm++;
440  }
441  (*this) /= nperm;
442  return;
443 }
444 
445 //************************************************************
446 
447 template <class T>
449  reset_idim();
450  Array<Array<Index> > tunique(unique_dim);
451  for (Index i = 0; i < tunique.size(); i++) tunique[i].sort();
452  Array<Index> tperm = Ndim;
453  Tensor<T> ttens(*this);
454  Index iset(0), i(0), j(0), nperm(1);
455  (*this) = 0;
456  while (iset < tunique.size()) {
457  for (i = 0; i < tunique.size(); i++)
458  for (j = 0; j < tunique[i].size(); j++)
459  tperm[unique_dim[i][j]] = tunique[i][j];
460  (*this) += ttens.dim_permute(tperm);
461  ttens.dim_unpermute();
462  nperm++;
463  iset = 0;
464  while (iset < tunique.size() && !tunique[iset].next_permute()) iset++;
465  }
466  (*this) /= double(nperm);
467 }
468 
469 //************************************************************
470 
471 template <class T>
473  return Counter<Array<Index> >(Array<Index>(Nrank, 0), max_ind,
474  Array<Index>(Nrank, 1));
475 }
476 
477 //************************************************************
478 
479 template <class T>
481  return max_ind;
482 }
483 
484 //************************************************************
485 
486 template <class T>
487 const Array<Index> &Tensor<T>::dim() const {
488  return Ndim;
489 }
490 
491 //************************************************************
492 
493 template <class T>
495  return Ndim[i];
496 }
497 
498 //************************************************************
499 
500 template <class T>
502  return idim;
503 }
504 
505 //************************************************************
506 
507 template <class T>
509  return Nrank;
510 }
511 
512 //************************************************************
513 
514 template <class T>
515 const T &Tensor<T>::get(const Array<Index> &inds) const {
516  Index lin_index = 0;
517  for (Index i = 0; i < Nrank; i++) lin_index += inds[i] * idim[i];
518 
519  return at(lin_index);
520 };
521 
522 //************************************************************
523 
524 template <class T>
525 T &Tensor<T>::at(const Array<Index> &inds) {
526  Index lin_index = 0;
527  for (Index i = 0; i < Nrank; i++) lin_index += inds[i] * idim[i];
528 
529  return at(lin_index);
530 };
531 
532 //************************************************************
533 
534 template <class T>
535 const T &Tensor<T>::at(const Array<Index> &inds) const {
536  Index lin_index = 0;
537  for (Index i = 0; i < Nrank; i++) lin_index += inds[i] * idim[i];
538 
539  return at(lin_index);
540 };
541 
542 //************************************************************
543 
544 template <class T>
546  Index lin_index = 0;
547  for (Index i = 0; i < Nrank; i++) lin_index += inds[i] * idim[i];
548 
549  return at(lin_index);
550 };
551 
552 //************************************************************
553 
554 template <class T>
555 const T &Tensor<T>::operator()(const Array<Index> &inds) const {
556  Index lin_index = 0;
557  for (Index i = 0; i < Nrank; i++) lin_index += inds[i] * idim[i];
558 
559  return at(lin_index);
560 };
561 //************************************************************
562 
563 template <class T>
565  return at(i * idim[0] + j * idim[1]);
566 };
567 
568 //************************************************************
569 
570 template <class T>
571 const T &Tensor<T>::operator()(Index i, Index j) const {
572  return at(i * idim[0] + j * idim[1]);
573 };
574 
575 //************************************************************
576 
577 template <class T>
579  if (Ndim != RHS.Ndim) {
580  std::cerr << "Attempting to add two incompatible tensors!\n";
581  exit(1);
582  }
583 
584  if (idim == RHS.idim) {
585  for (Index i = 0; i < size(); i++) at(i) += RHS[i];
586 
587  return *this;
588  }
589 
590  Counter<Array<Index> > icount(Array<Index>(Nrank, 0), max_ind,
591  Array<Index>(Nrank, 1));
592  do {
593  at(icount()) += RHS(icount());
594 
595  } while ((++icount).valid());
596 
597  return *this;
598 }
599 
600 //************************************************************
601 
602 template <class T>
604  if (Ndim != RHS.Ndim) {
605  std::cerr << "Attempting to add two incompatible tensors!\n";
606  exit(1);
607  }
608 
609  if (idim == RHS.idim) {
610  for (Index i = 0; i < size(); i++) at(i) -= RHS[i];
611 
612  return *this;
613  }
614 
615  Counter<Array<Index> > icount(Array<Index>(Nrank, 0), max_ind,
616  Array<Index>(Nrank, 1));
617  do {
618  at(icount()) -= RHS(icount());
619  } while ((++icount).valid());
620 
621  return *this;
622 }
623 
624 //************************************************************
625 
626 template <class T>
628  for (Index i = 0; i < size(); i++) at(i) *= RHS;
629 
630  return *this;
631 }
632 
633 //************************************************************
634 
635 template <class T>
637  for (Index i = 0; i < size(); i++) at(i) /= RHS;
638 
639  return *this;
640 }
641 
642 //************************************************************
643 
644 template <class T>
646  Tensor<T> ttens(*this);
647  for (Index i = 0; i < ttens.size(); i++) ttens[i] = -at(i);
648  return ReturnTensor<T>(ttens);
649 }
650 
651 //************************************************************
652 
653 template <class T>
655  return ReturnTensor<T>(Tensor<T>(*this) += RHS);
656 }
657 
658 //************************************************************
659 
660 template <class T>
662  return ReturnTensor<T>(Tensor<T>(*this) -= RHS);
663 }
664 
665 //************************************************************
666 
667 template <class T>
668 T Tensor<T>::scalar_prod(const Tensor &RHS) const {
669  if (Ndim != RHS.Ndim) {
670  std::cerr
671  << "Attempting to take scalar product of two incompatible tensors!\n";
672  assert(0);
673  // exit(1);
674  }
675 
676  T tprod = 0;
677 
678  if (idim == RHS.idim) {
679  for (Index i = 0; i < size(); i++) tprod += at(i) * RHS[i];
680  }
681 
682  else {
683  Counter<Array<Index> > icount(Array<Index>(Nrank, 0), max_ind,
684  Array<Index>(Nrank, 1));
685  do {
686  tprod += at(icount()) * RHS(icount());
687  } while ((++icount).valid());
688  }
689 
690  return tprod;
691 }
692 
693 //************************************************************
694 
695 template <class T>
697  Tensor<T> ttens(rank() + RHS.rank(), array_cat(dim(), RHS.dim()), 0);
698 
699  Counter<Array<Index> > icount(element_counter()),
700  jcount(RHS.element_counter());
701 
702  Index i, j, tot_ind;
703  do {
704  jcount.reset();
705  do {
706  tot_ind = 0;
707  for (i = 0; i < icount().size(); i++)
708  tot_ind += icount[i] * ttens.idim[i];
709 
710  for (j = 0; j < jcount().size(); j++)
711  tot_ind += jcount[j] * ttens.idim[i + j];
712 
713  ttens[tot_ind] = at(icount()) * RHS(jcount());
714 
715  } while ((++jcount).valid());
716  } while ((++icount).valid());
717 
718  return ReturnTensor<T>(ttens);
719 }
720 
721 //************************************************************
722 
723 template <class T>
725  return (*this) /= sqrt(scalar_prod(*this));
726 }
727 
728 //************************************************************
729 
730 template <class T>
732  Tensor<T> ttens(trank, Array<Index>(trank, tdim), 0);
733  for (Index i = 0; i < tdim; i++) ttens(Array<Index>(trank, i)) = 1;
734 
735  return ReturnTensor<T>(ttens);
736 }
737 
738 //************************************************************
739 template <class T>
741  if (!rank()) return *this;
742  Array<Eigen::MatrixXd const *> rep_mats(op.get_matrix_reps(rep_IDs));
743 
744  Tensor<T> ttens(Nrank, Ndim);
745  Index nd;
746 
747  T tval;
748  Counter<Array<Index> > icount(element_counter());
749  Counter<Array<Index> > jcount(icount);
750  do {
751  ttens(icount()) = 0;
752  jcount.reset();
753  do {
754  tval = at(jcount());
755  for (nd = 0; nd < Nrank; nd++)
756  tval *= (*rep_mats[nd])(icount[nd], jcount[nd]);
757  ttens(icount()) += tval;
758 
759  } while ((++jcount).valid());
760 
761  } while ((++icount).valid());
762  swap(ttens);
763  return *this;
764 }
765 
766 //************************************************************
767 template <class T>
769  Array<SymGroupRepID> rep_IDs,
770  Array<Index> inner_ind) {
771  if (!rank()) return *this;
772  Array<Eigen::MatrixXd const *> rep_mats(op.get_matrix_reps(rep_IDs));
773 
774  Index nd;
775 
776  T tval;
777  Counter<Array<Index> > icount(element_counter());
778  do {
779  tval = 1.0;
780  for (nd = 0; nd < Nrank; nd++)
781  tval *= (*rep_mats[nd])(icount[nd], inner_ind[nd]);
782  at(icount()) += tval;
783 
784  } while ((++icount).valid());
785  return *this;
786 }
787 
788 //************************************************************
789 template <class T>
791  if (!rank()) return *this;
792 
793  Tensor<T> ttens(Nrank, Ndim);
794  Index nd;
795 
796  T tval;
797  Counter<Array<Index> > icount(element_counter());
798  Counter<Array<Index> > jcount(icount);
799  do {
800  ttens(icount()) = 0;
801  jcount.reset();
802  do {
803  tval = at(jcount());
804  for (nd = 0; nd < Nrank; nd++)
805  tval *= op.matrix()(icount[nd], jcount[nd]);
806  ttens(icount()) += tval;
807 
808  } while ((++jcount).valid());
809 
810  } while ((++icount).valid());
811  swap(ttens);
812  return *this;
813 }
814 
815 //************************************************************
816 //************************************************************
817 template <class T>
818 void Tensor<T>::read(std::istream &stream) {
819  double val;
820  Array<Index> min(rank(), 0), max(ind_max()), inc(rank(), 1);
821  Counter<Array<Index> > icount(min, max, inc);
822 
823  do {
824  stream >> val;
825  at(icount()) = val;
826  } while ((++icount).valid());
827 
828  return;
829 };
830 
831 //************************************************************
837 //************************************************************
838 /*template<class T>
839 Tensor<T> Tensor<T>::matrix_multiply(Vector3<T> &tvec) {
840 
841  Index j = 0;
842  Array<Index> tensordim(2, 0);
843  tensordim[0] = 3;
844  tensordim[1] = 1;
845  Tensor<T> result(2, tensordim, 0);
846 
847  for(Index i = 0; i < size(); i++) {
848  if(i % 3 == 0) {
849  j++;
850  }
851  result.at(j - 1) += at(i) * tvec.at(i % 3);
852  }
853 
854  return result;
855 
856 };
857 */
858 //************************************************************
859 
860 template <class T>
862  if (!rank()) return *this;
863 
864  Tensor<T> ttens(Nrank, Ndim);
865  Index nd;
866 
867  T tval;
868  Counter<Array<Index> > icount(element_counter());
869  Counter<Array<Index> > jcount(icount);
870  do {
871  ttens(icount()) = 0;
872  jcount.reset();
873  do {
874  tval = at(jcount());
875  for (nd = 0; nd < Nrank; nd++) tval *= mat(icount[nd], jcount[nd]);
876  ttens(icount()) += tval;
877 
878  } while ((++jcount).valid());
879 
880  } while ((++icount).valid());
881  swap(ttens);
882  return *this;
883 }
884 
885 //************************************************************
886 
887 template <class T>
888 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> Tensor<T>::convert_to_Eigen()
889  const {
890  if (rank() != 2) {
891  std::cerr << "WARNING: Attempting to assign Eigen::Matrix object using a "
892  "Tensor of rank "
893  << rank()
894  << "!\nTensor must have rank=2 for assignment to be valid. "
895  "Exiting...\n";
896  exit(1);
897  }
898  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> tmat(dim(0), dim(1));
899  tmat.setZero();
900  for (Index i = 0; i < tmat.rows(); i++) {
901  for (Index j = 0; j < tmat.rows(); j++) {
902  tmat(i, j) = (*this)(i, j);
903  }
904  }
905  return tmat;
906 }
907 
908 //************************************************************
909 
910 template <class T>
911 Tensor<T> operator*(const T &LHS, const Tensor<T> &RHS) {
912  return Tensor<T>(RHS) *= LHS;
913 }
914 
915 //************************************************************
916 
917 template <class T>
918 Tensor<T> operator*(const SymOp &LHS, const Tensor<T> &RHS) {
919  return Tensor<T>(RHS).apply_sym(LHS);
920 }
921 
922 //************************************************************
923 
924 template <class T>
925 T dot(const Tensor<T> &LHS, const Tensor<T> &RHS) {
926  return LHS.scalar_prod(RHS);
927 }
928 
929 //************************************************************
930 
931 template <class T>
932 T norm(const Tensor<T> &ttens) {
933  return sqrt(ttens.scalar_prod(ttens));
934 }
935 
936 //************************************************************
937 
938 template <class T>
939 std::ostream &operator<<(std::ostream &stream, const Tensor<T> &RHS) {
940  std::ios::fmtflags old_flags = stream.flags();
941  stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
942  int twide = stream.width();
943 
944  if (!RHS.rank()) {
945  stream << RHS[0] << '\n';
946  stream.flags(old_flags);
947  return stream;
948  }
949 
950  Array<Index> min(RHS.rank(), 0), max(RHS.ind_max()), inc(RHS.rank(), 1);
951  Counter<Array<Index> > icount(min, max, inc);
952  do {
953  if (RHS.rank() > 2 && icount[0] == 0 && icount[1] == 0) {
954  stream << "Block (:,:," << icount[2];
955  for (Index j = 3; j < RHS.rank(); j++) stream << "," << icount[j];
956  stream << ") :\n";
957  }
958 
959  stream << std::setw(0) << " " << std::setw(twide) << RHS(icount());
960  if (icount[0] == RHS.ind_max()[0]) {
961  stream << '\n';
962 
963  // if(RHS.rank() > 1 && icount[1] == RHS.ind_max()[1])
964  // stream << "\n"; //commented out by Ivy 07/01/13 so that an extra new
965  // line isn't printed.
966  }
967 
968  } while ((++icount).valid());
969  stream.flags(old_flags);
970  return stream;
971 }
972 
973 //************************************************************
974 
975 template <class T>
976 std::istream &operator>>(std::istream &stream, Tensor<T> &RHS) {
977  std::cerr << "WARNING: Input stream operator has not been implemented for "
978  "Tensor class! Exiting...\n";
979  exit(1);
980 }
981 
982 //************************************************************
983 
984 template <class T>
985 void TensorBasis<T>::generate_basis(Index Nrank, const SymGroup &sym_group) {
986  Index i, ns;
987  clear();
988 
989  Tensor<T> ttens(Nrank, Array<Index>(Nrank, 3), 0);
990 
991  for (i = 0; i < ttens.size(); i++) {
992  Tensor<T> avtens(Nrank, Array<Index>(Nrank, 3), 0);
993  ttens[i] = 1;
994  for (ns = 0; ns < sym_group.size(); ns++) avtens += sym_group[ns] * ttens;
995  if (!this->contains(avtens)) this->push_back(avtens);
996  ttens[i] = 0;
997  }
998  idealize();
999 
1000  coeffs.resize(size(), NAN); // Changed by Ivy 09/25/2012
1001 }
1002 
1003 //************************************************************
1004 
1005 template <class T>
1006 void TensorBasis<T>::generate_basis(Index Nrank, const SymGroup &sym_group,
1007  Index Rep_ID) {
1008  if (!sym_group.size()) {
1009  std::cerr << "WARNING: Attempting to generate tensor basis from an invalid "
1010  "symmetry group. Exiting...";
1011  exit(0);
1012  }
1013  Index i, ns;
1014  clear();
1015 
1016  Tensor<T> ttens(Nrank, Array<Index>(Nrank, 3), 0);
1017 
1018  for (i = 0; i < ttens.size(); i++) {
1019  Tensor<T> avtens(Nrank, Array<Index>(Nrank, 3), 0);
1020  ttens[i] = 1;
1021  for (ns = 0; ns < sym_group.size(); ns++) avtens += sym_group[ns] * ttens;
1022  if (!contains(avtens)) push_back(avtens);
1023  ttens[i] = 0;
1024  }
1025  idealize();
1026 
1027  coeffs.resize(size(), NAN); // Changed by Ivy 09/25/2012
1028 }
1029 
1030 //************************************************************
1031 
1032 template <class T>
1033 void TensorBasis<T>::generate_basis(Index Nrank, const SymGroup &sym_group,
1034  const SymGroupRep &perm_group) {
1035  Index i, ns;
1036  clear();
1037 
1038  if (sym_group.size() != perm_group.size()) {
1039  std::cerr << "WARNING: Attempting to generate tensor basis, but symmetry "
1040  "group and permutation group are not compatible!\n";
1041  }
1042 
1043  Tensor<T> ttens(Nrank, Array<Index>(Nrank, 3), 0);
1044 
1045  for (i = 0; i < ttens.size(); i++) {
1046  Tensor<T> avtens(Nrank, Array<Index>(Nrank, 3), 0);
1047  ttens[i] = 1;
1048  for (ns = 0; ns < sym_group.size(); ns++)
1049  avtens += (sym_group[ns] * ttens)
1050  .dim_permute(*(perm_group[ns]->get_permutation()));
1051  if (!this->contains(avtens)) this->push_back(avtens);
1052  ttens[i] = 0;
1053  }
1054  idealize();
1055 
1056  coeffs.resize(size(), NAN); // Changed by Ivy 09/25/2012
1057  return;
1058 }
1059 
1060 //************************************************************
1061 
1062 template <class T>
1064  Index i, j;
1065  for (i = 0; i < size(); i++) {
1066  for (j = 0; j < ortho_basis.size(); j++) {
1067  at(i) -= (at(i).scalar_prod(ortho_basis[j]) / norm(ortho_basis[j])) *
1068  ortho_basis[j];
1069  }
1070  }
1071  return;
1072 }
1073 
1074 //************************************************************
1075 
1076 template <class T>
1078  for (Index i = 0; i < size(); i++) {
1079  at(i).apply_sym(op);
1080  }
1081  return *this;
1082 }
1083 
1084 //************************************************************
1085 
1086 template <class T>
1088  for (Index i = 0; i < size(); i++) at(i).normalize();
1089  return;
1090 }
1091 
1092 //************************************************************
1093 
1094 template <class T>
1096  // GaussJordan<Tensor<T>, T>::eliminate(*this);
1097 
1098  // for(Index i=0; i<size(); i++)
1099  // std::cout << "Basis Tensor " << i << ": \n" << at(i);
1100 
1101  GramSchmidt<Tensor<T>, T>::orthogonalize(*this);
1102  return;
1103 }
1104 
1105 //************************************************************
1106 template <class T>
1107 bool TensorBasis<T>::read(std::istream &stream) {
1108  char ch;
1109  Index num_elem, rank;
1110  Array<Index> dim;
1111  double tcoeff;
1112 
1113  ch = stream.peek();
1114  while (ch < '0' || ch > '9') {
1115  stream.ignore(256, '\n');
1116  ch = stream.peek();
1117  }
1118  stream >> num_elem;
1119  if (!num_elem) {
1120  stream.ignore(256, '\n');
1121  return false;
1122  }
1123  stream >> rank;
1124 
1125  dim.resize(rank);
1126 
1127  for (Index i = 0; i < rank; i++) {
1128  stream >> dim[i];
1129  }
1130 
1131  stream.ignore(1000, '\n');
1132 
1133  coeffs.resize(num_elem, NAN);
1134 
1135  Tensor<T> ttensor(rank, dim);
1136 
1137  for (Index j = 0; j < num_elem; j++) {
1138  ttensor.redefine(dim);
1139 
1140  // Check for "<" to find "<ECI>"
1141  ch = stream.peek();
1142  while (ch != char(60)) {
1143  if (((ch < '0') || (ch > '9')) && (ch != '-')) {
1144  stream.ignore(1000, '\n');
1145  } else {
1146  break;
1147  }
1148  ch = stream.peek();
1149  }
1150 
1151  // Reading in coefficient
1152  if (((ch != char(60)) && ((ch >= '0') || (ch <= '9'))) || (ch == '-')) {
1153  stream >> tcoeff;
1154  eci(j) = tcoeff;
1155  }
1156 
1157  stream.ignore(1000, '\n');
1158 
1159  ttensor.read(stream);
1160  this->push_back(ttensor);
1161  }
1162 
1163  return true;
1164 }
1165 
1167 }; // namespace CASM
1168 
1169 #endif
Basic std::vector like container (deprecated)
Definition: Array.hh:45
Tensor< T > & at(Index ind)
Definition: Array.hh:140
Index size() const
Definition: Array.hh:131
void swap_elem(Index i, Index j)
Definition: Array.hh:197
Index N
Definition: Array.hh:53
size_type size() const
Definition: BaseCounter.hh:178
A Counter allows looping over many incrementing variables in one loop.
Definition: Counter.hh:109
void reset()
Reset the current value of the Counter to the initial value.
Definition: Counter.hh:184
const std::vector< Index > & perm_array() const
Definition: Permutation.hh:62
ReturnTensor(Tensor< T > &init_tens)
Definition: Tensor.hh:204
ReturnTensor & operator=(Tensor< T > &RHS)
Definition: Tensor.hh:206
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Definition: SymGroup.hh:42
SymGroupRep is an alternative representation of a SymGroup for something other than real space....
Definition: SymGroupRep.hh:31
SymOp is the Coordinate representation of a symmetry operation it keeps fraction (FRAC) and Cartesian...
Definition: SymOp.hh:28
const matrix_type & matrix() const
Const access of entire cartesian symmetry matrix.
Definition: SymOp.hh:60
Array< Eigen::MatrixXd const * > get_matrix_reps(Array< SymGroupRepID > _rep_IDs) const
double eci(Index i) const
Definition: Tensor.hh:223
Array< double > coeffs
Definition: Tensor.hh:221
double & eci(Index i)
Definition: Tensor.hh:224
Array< Index > Ndim
Definition: Tensor.hh:34
Tensor(const Eigen::Matrix< T, 3, 3 > &mat_init)
Definition: Tensor.hh:82
Tensor slice(Array< Index > slice_Ndim, Array< Index > slice_ind)
Tensor & operator=(ReturnTensor< T > &RHS)
Definition: Tensor.hh:98
Tensor(Index tNrank, Array< Index > tNdim, T init_val)
Definition: Tensor.hh:56
Tensor(Index tNrank=0)
Definition: Tensor.hh:70
Tensor(Index tNrank, Array< Index > tNdim)
Definition: Tensor.hh:43
Index Nrank
Definition: Tensor.hh:33
Tensor & operator=(const T &RHS)
Definition: Tensor.hh:103
Tensor & operator=(const Eigen::Matrix< T, dim1, dim2, flag1 > &LHS)
Array< Index > max_ind
Definition: Tensor.hh:34
Tensor(ReturnTensor< T > &init_cont)
Definition: Tensor.hh:96
Array< Index > idim
Definition: Tensor.hh:34
void resize(Index new_N)
Definition: Array.hh:390
void swap(Array< T > &RHS)
Definition: Array.hh:371
Array< T > array_cat(const Array< T > &A1, const Array< T > &A2)
Definition: Array.hh:974
Array & ipermute(const Array< Index > &perm_array)
Definition: Array.hh:849
void sort(const CompareType &comp)
Definition: Array.hh:677
bool next_permute()
Definition: Array.hh:865
void generate_basis(Index Nrank, const SymGroup &sym_group)
Definition: Tensor.hh:985
void redefine(Array< Index > _Ndim)
Definition: Tensor.hh:276
Tensor & symmetrize_index(const SymOp &op, Array< SymGroupRepID > rep_IDs, Array< Index > inner_ind)
Definition: Tensor.hh:768
const Array< Index > & dim() const
Definition: Tensor.hh:487
T scalar_prod(const Tensor &RHS) const
Definition: Tensor.hh:668
ReturnTensor< T > operator+(const Tensor &RHS)
Definition: Tensor.hh:654
Tensor & operator+=(const Tensor &RHS)
Definition: Tensor.hh:578
T & operator()(const Array< Index > &inds)
Definition: Tensor.hh:545
Tensor & operator/=(T RHS)
Definition: Tensor.hh:636
Tensor & transform(const Eigen::MatrixXd &op)
Definition: Tensor.hh:861
Index rank() const
Definition: Tensor.hh:508
Counter< Array< Index > > element_counter() const
Definition: Tensor.hh:472
T dot(const Tensor< T > &LHS, const Tensor< T > &RHS)
Definition: Tensor.hh:925
Tensor & dim_unpermute()
Definition: Tensor.hh:361
bool next_permute()
Definition: Tensor.hh:374
static ReturnTensor< T > identity(Index trank, Index tdim)
Definition: Tensor.hh:731
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > convert_to_Eigen() const
Definition: Tensor.hh:888
const Array< Index > & ind_max() const
Definition: Tensor.hh:480
ReturnTensor< T > tensor_prod(const Tensor &RHS)
Definition: Tensor.hh:696
const Array< Index > & mult_array() const
Definition: Tensor.hh:501
void make_orthogonal_to(const TensorBasis &ortho_basis)
Definition: Tensor.hh:1063
void read(std::istream &stream)
Definition: Tensor.hh:818
Tensor & normalize()
Definition: Tensor.hh:724
Tensor & apply_sym(const SymOp &op)
Definition: Tensor.hh:790
Tensor & operator*=(T RHS)
Definition: Tensor.hh:627
void permute_symmetrize()
Symmetrize tensor with respect to index permutation.
Definition: Tensor.hh:433
Tensor & operator-=(const Tensor &RHS)
Definition: Tensor.hh:603
ReturnTensor< T > operator-()
Definition: Tensor.hh:645
T & at(const Array< Index > &inds)
Definition: Tensor.hh:525
void reset_idim()
Definition: Tensor.hh:415
Tensor & dim_ipermute(const Array< Index > &perm)
Definition: Tensor.hh:337
Tensor & dim_permute(const Array< Index > &iperm)
Definition: Tensor.hh:312
bool read(std::istream &stream)
Definition: Tensor.hh:1107
void swap(Tensor &RHS)
Definition: Tensor.hh:241
const T & get(const Array< Index > &inds) const
Definition: Tensor.hh:515
TensorBasis & apply_sym(const SymOp &op)
Definition: Tensor.hh:1077
void normalize()
Definition: Tensor.hh:1087
T norm(const Tensor< T > &ttens)
Definition: Tensor.hh:932
Main CASM namespace.
Definition: APICommand.hh:8
Eigen::MatrixXd MatrixXd
std::ostream & operator<<(std::ostream &_stream, const FormattedPrintable &_formatted)
std::istream & operator>>(std::istream &_in, std::vector< T > &vec)
Definition: stream_io.hh:10
void swap(ConfigDoF &A, ConfigDoF &B)
Definition: ConfigDoF.cc:260
BasisSet operator*(const SymOp &LHS, const BasisSet &RHS)
Definition: BasisSet.cc:1408
T min(const T &A, const T &B)
Definition: CASM_math.hh:88
bool contains(const Container &container, const T &value)
Equivalent to container.end() != std::find(container.begin(), container.end(), value)
Definition: algorithm.hh:83
bool valid_index(Index i)
Definition: definitions.cc:5
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
T max(const T &A, const T &B)
Definition: CASM_math.hh:95
pair_type eci
Definition: settings.cc:146