CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
SupercellEnumerator.hh
Go to the documentation of this file.
1 #ifndef SupercellEnumerator_HH
2 #define SupercellEnumerator_HH
3 
4 #include "casm/external/Eigen/Dense"
5 
11 #include "casm/casm_io/Log.hh"
12 
14 
15 namespace CASM {
16 
17  class PrimClex;
18 
29  class ScelEnumProps {
31 
32  public:
33 
34  typedef long size_type;
35 
50  size_type end_volume,
51  std::string dirs = "abc",
52  Eigen::Matrix3i generating_matrix = Eigen::Matrix3i::Identity()) :
53  m_begin_volume(begin_volume),
54  m_end_volume(end_volume),
55  m_dims(dirs.size()),
56  m_dirs(dirs) {
57 
58  for(int i = 0; i < m_dirs.size(); i++) {
59  if(m_dirs[i] != 'a' && m_dirs[i] != 'b' && m_dirs[i] != 'c') {
60  std::string msg = "Error constructing ScelEnumProps: an element of dirs != 'a', 'b', or 'c'";
61  default_err_log().error("Constructing ScelEnumProps");
62  default_err_log() << msg << "\n" << std::endl;
63  throw std::invalid_argument(msg);
64  }
65  }
66 
67  // add missing directions to 'dirs',
68  // then permute 'G' so that the specified 'dirs' are first
69  while(m_dirs.size() != 3) {
70  if(std::find(m_dirs.begin(), m_dirs.end(), 'a') == m_dirs.end()) {
71  m_dirs.push_back('a');
72  }
73  if(std::find(m_dirs.begin(), m_dirs.end(), 'b') == m_dirs.end()) {
74  m_dirs.push_back('b');
75  }
76  if(std::find(m_dirs.begin(), m_dirs.end(), 'c') == m_dirs.end()) {
77  m_dirs.push_back('c');
78  }
79  }
80  Eigen::Matrix3i P = Eigen::Matrix3i::Zero();
81  P(m_dirs[0] - 'a', 0) = 1;
82  P(m_dirs[1] - 'a', 1) = 1;
83  P(m_dirs[2] - 'a', 2) = 1;
84 
86  }
87 
88 
89  size_type begin_volume() const {
90  return m_begin_volume;
91  }
92 
93  size_type end_volume() const {
94  return m_end_volume;
95  }
96 
97  int dims() const {
98  return m_dims;
99  }
100 
101  std::string dirs() const {
102  return m_dirs;
103  }
104 
105  Eigen::Matrix3i generating_matrix() const {
106  return m_gen_mat;
107  }
108 
109  private:
110 
111  size_type m_begin_volume;
112  size_type m_end_volume;
113  int m_dims;
114  std::string m_dirs;
115  Eigen::Matrix3i m_gen_mat;
116 
117  };
118 
120  Eigen::Matrix3i make_unit_cell(PrimClex &primclex, const jsonParser &json);
121 
124 
156  public:
157  typedef Eigen::VectorXi::Scalar value_type;
159 
161  //HermiteCounter() {};
162 
164  HermiteCounter(int init_determinant, int init_dim);
165 
166  //You probably will never need these. They're just here for testing more than anything.
167  //Either way, they're safe to call.
168  Index position() const;
169  Eigen::VectorXi diagonal() const;
170  //value_type low() const;
171  //value_type high() const;
172 
174  Eigen::MatrixXi current() const;
175 
177  value_type determinant() const;
178 
180  Index dim() const;
181 
183  void reset_current();
184 
186  void next_determinant();
187 
189  void jump_to_determinant(value_type new_det);
190 
193 
195  Eigen::MatrixXi operator()() const;
196 
197 
198  private:
199 
201  Index m_pos;
202 
204  Eigen::VectorXi m_diagonal;
205 
208 
210  Index _increment_diagonal();
211 
212  };
213 
214  namespace HermiteCounter_impl {
217 
219  HermiteCounter::Index next_spill_position(Eigen::VectorXi &diag, HermiteCounter::Index position);
220 
223 
225  EigenVectorXiCounter _upper_tri_counter(const Eigen::VectorXi &current_diag);
226 
228  Eigen::MatrixXi _zip_matrix(const Eigen::VectorXi &current_diag, const Eigen::VectorXi &current_upper_tri);
229 
231  Eigen::MatrixXi _expand_dims_old(const Eigen::MatrixXi &hermit_mat, const Eigen::VectorXi &active_dims);
232 
234  Eigen::MatrixXi _expand_dims(const Eigen::MatrixXi &H, const Eigen::MatrixXi &G);
235 
237  Eigen::VectorXi _canonical_unroll(const Eigen::MatrixXi &hermit_mat);
238 
240  bool _canonical_compare(const Eigen::MatrixXi &H0, const Eigen::MatrixXi &H1);
241  }
242 
243  //******************************************************************************************************************//
244 
245  template <typename UnitType> class SupercellEnumerator;
246 
251  template <typename UnitType>
253 
254  public:
255 
257  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
258 
259  typedef std::forward_iterator_tag iterator_category;
260  typedef int difference_type;
261  typedef UnitType value_type;
262  typedef const UnitType &reference;
263  typedef const UnitType *pointer;
264 
266 
268  int volume,
269  int dims);
270 
271  //required for all iterators
272  //SupercellIterator<UnitType>(const SupercellIterator<UnitType> &B);
273 
274  //required for all iterators?
276 
278  bool operator==(const SupercellIterator<UnitType> &B) const;
279 
281  bool operator!=(const SupercellIterator<UnitType> &B) const;
282 
284  reference operator*() const;
285 
287  pointer operator->() const;
288 
290  Eigen::Matrix3i matrix() const;
291 
294 
297 
300 
302  //SupercellIterator<UnitType> operator++(int); TODO
303 
304 
305  private:
306 
308  void _increment();
309 
311  //bool _is_canonical() const;
312 
314  void _try_increment();
315 
317  void _update_super();
318 
319 
321  mutable bool m_super_updated;
322 
325 
328 
330  mutable UnitType m_super;
331 
333  std::vector<Eigen::Matrix3i> m_canon_hist;
334 
335  };
336 
337 
343  template<typename UnitType>
344  class SupercellEnumerator {
345 
346  public:
347 
348  typedef long int size_type;
349 
351 
360  SupercellEnumerator(UnitType unit,
361  const ScelEnumProps &enum_props,
362  double tol);
363 
372  SupercellEnumerator(UnitType unit,
373  const SymGroup &point_grp,
374  const ScelEnumProps &enum_props);
375 
376 
378  const UnitType &unit() const;
379 
381  const Lattice &lattice() const;
382 
384  const SymGroup &point_group() const;
385 
387  void begin_volume(size_type _begin_volume);
388 
390  size_type begin_volume() const;
391 
393  void end_volume(size_type _end_volume);
394 
396  size_type end_volume() const;
397 
399  const Eigen::Matrix3i &gen_mat() const;
400 
402  int dimension() const;
403 
405  const_iterator begin() const;
406 
408  const_iterator end() const;
409 
411  const_iterator cbegin() const;
412 
414  const_iterator cend() const;
415 
417  const_iterator citerator(size_type volume) const;
418 
419  private:
420 
422  const UnitType m_unit;
423 
426 
428  SymGroup m_point_group; //factor group...?
429 
431  const int m_begin_volume;
432 
434  const int m_end_volume;
435 
438  const Eigen::Matrix3i m_gen_mat;
439 
441  const int m_dims;
442 
443  };
444 
445 
463  template<typename UnitType>
464  Eigen::Matrix3i enforce_min_volume(
465  const UnitType &unit,
466  const Eigen::Matrix3i &T,
467  const SymGroup &point_grp,
468  Index volume,
469  bool fix_shape = false);
470 
471 
472 
473  template<typename UnitType>
475  int volume,
476  int dims):
477  m_super_updated(false),
478  m_enum(&enumerator),
479  m_current(notstd::make_cloneable<HermiteCounter>(volume, dims)) {
480  if(enumerator.begin_volume() > enumerator.end_volume()) {
481  throw std::runtime_error("The beginning volume of the SupercellEnumerator cannot be greater than the end volume!");
482  }
483 
484  if(dims < 1) {
485  throw std::runtime_error("Dimensions to count over must be greater than 0!");
486  }
487  }
488 
489  /*
490  template<typename UnitType>
491  SupercellIterator<UnitType>::SupercellIterator(const SupercellIterator &B)
492  {
493  *this = B;
494  };
495  */
496 
497  template<typename UnitType>
499  m_enum = B.m_enum;
500  m_current = B.m_current;
501  m_super_updated = false;
502 
503  m_canon_hist = B.m_canon_hist;
504  return *this;
505  }
506 
507  template<typename UnitType>
509  return (m_enum == B.m_enum) && (matrix() - B.matrix()).isZero();
510  }
511 
512  template<typename UnitType>
514  return !(*this == B);
515  }
516 
517  template<typename UnitType>
519  if(!m_super_updated) {
520  m_super = make_supercell(m_enum->unit(), matrix());
521  m_super_updated = true;
522  }
523  return m_super;
524  }
525 
526  template<typename UnitType>
528  if(!m_super_updated) {
529  m_super = make_supercell(m_enum->unit(), matrix());
530  m_super_updated = true;
531  }
532  return &m_super;
533  }
534 
535  template<typename UnitType>
537  return m_current->determinant();
538  }
539 
540  template<typename UnitType>
541  Eigen::Matrix3i SupercellIterator<UnitType>::matrix() const {
542  Eigen::Matrix3i expanded = HermiteCounter_impl::_expand_dims((*m_current)(), m_enum->gen_mat());
543  return canonical_hnf(expanded, m_enum->point_group(), m_enum->lattice());
544  }
545 
546  template<typename UnitType>
548  return *m_enum;
549  }
550 
551  // prefix
552  template<typename UnitType>
554  _increment();
555  return *this;
556  }
557 
558  /*
559  // postfix
560  template<typename UnitType>
561  SupercellIterator<UnitType> SupercellIterator<UnitType>::operator++(int)
562  {
563  SupercellIterator result(*this);
564  _increment();
565  return result;
566  }
567  */
568 
569 
570  template<typename UnitType>
572  m_canon_hist.push_back(matrix());
573  HermiteCounter::value_type last_determinant = m_current->determinant();
574  ++(*m_current);
575 
576  if(last_determinant != m_current->determinant()) {
577  m_canon_hist.clear();
578  }
579 
580  while(std::find(m_canon_hist.begin(), m_canon_hist.end(), matrix()) != m_canon_hist.end()) {
581  ++(*m_current);
582  }
583 
584  m_super_updated = false;
585  }
586 
587  //********************************************************************************************************//
588 
589  template<typename UnitType>
590  const UnitType &SupercellEnumerator<UnitType>::unit() const {
591  return m_unit;
592  }
593 
594  template<typename UnitType>
596  return m_lat;
597  }
598 
599  template<typename UnitType>
601  return m_point_group;
602  }
603 
604  template<typename UnitType>
605  const Eigen::Matrix3i &SupercellEnumerator<UnitType>::gen_mat() const {
606  return m_gen_mat;
607  }
608 
609  template<typename UnitType>
611  return m_dims;
612  }
613 
614  /*
615  template<typename UnitType>
616  void SupercellEnumerator<UnitType>::begin_volume(size_type _begin_volume)
617  {
618  m_begin_volume = _begin_volume;
619  }
620  */
621 
622  template<typename UnitType>
624  return m_begin_volume;
625  }
626 
627  /*
628  template<typename UnitType>
629  void SupercellEnumerator<UnitType>::end_volume(size_type _end_volume)
630  {
631  m_end_volume = _end_volume;
632  }
633  */
634 
635  template<typename UnitType>
637  return m_end_volume;
638  }
639 
640  template<typename UnitType>
642  return const_iterator(*this, m_begin_volume, dimension());
643  }
644 
645  template<typename UnitType>
647  return const_iterator(*this, m_end_volume, dimension());
648  }
649 
650  template<typename UnitType>
652  return const_iterator(*this, m_begin_volume, dimension());
653  }
654 
655  template<typename UnitType>
657  return const_iterator(*this, m_end_volume, dimension());
658  }
659 
660  template<typename UnitType>
662  return SupercellIterator<UnitType>(*this, volume, dimension());
663  }
664 
665 
666  // declare specializations for Lattice
667 
668  template<>
670  const ScelEnumProps &enum_props,
671  double tol);
672 
673  template<>
675  const SymGroup &point_grp,
676  const ScelEnumProps &enum_props);
677 
678  template<>
679  Eigen::Matrix3i enforce_min_volume<Lattice>(
680  const Lattice &unit,
681  const Eigen::Matrix3i &T,
682  const SymGroup &point_grp,
683  Index volume,
684  bool fix_shape);
685 
686 
688  Eigen::Matrix3i canonical_hnf(const Eigen::Matrix3i &T, const SymGroup &effective_pg, const Lattice &ref_lattice);
689 
691 }
692 
693 #endif
Index _increment_diagonal()
Go to the next values of diagonal elements that keep the same determinant.
size_type end_volume() const
Get the end volume.
HermiteCounter::Index _spill_factor(Eigen::VectorXi &diag, HermiteCounter::Index position, HermiteCounter::value_type attempt)
Find the next factor of the specified position and share with next element. Use attempt as starting p...
bool operator!=(const SupercellIterator< UnitType > &B) const
Iterator comparison.
value_type determinant() const
Get the current determinant.
Lattice m_lat
The lattice of the unit cell.
Eigen::MatrixXi _expand_dims(const Eigen::MatrixXi &H, const Eigen::MatrixXi &G)
Expand a n x n Hermite normal matrix (H) into a m x m one through a m x m generating matrix (G) (e...
SupercellIterator< UnitType > & operator=(const SupercellIterator< UnitType > &B)
A Counter allows looping over many incrementing variables in one loop.
Definition: Counter.hh:71
reference operator*() const
Access the supercell.
Eigen::VectorXi diagonal() const
void end_volume(size_type _end_volume)
Set the end volume.
const SupercellEnumerator< UnitType > * m_enum
Pointer to SupercellEnumerator which holds the unit cell and point group.
const Eigen::Matrix3i & gen_mat() const
Get the transformation matrix that's being applied to the unit vectors.
Data structure for holding supercell enumeration properties.
Eigen::Matrix3i canonical_hnf(const Eigen::Matrix3i &T, const SymGroup &effective_pg, const Lattice &ref_lattice)
Return canonical hermite normal form of the supercell matrix, and op used to find it...
PrimClex * primclex
Definition: settings.cc:101
Index m_pos
Keeps track of the current diagonal element that needs to be factored.
bool _canonical_compare(const Eigen::MatrixXi &H0, const Eigen::MatrixXi &H1)
Compare two integer matrices and see which one is lexicographically greatest. Returns true if H0
pointer operator->() const
Access the supercell.
SupercellIterator< UnitType > const_iterator
Eigen::MatrixXi _zip_matrix(const Eigen::VectorXi &current_diag, const Eigen::VectorXi &current_upper_tri)
Assemble a matrix diagonal and unrolled upper triangle values into a matrix.
const_iterator end() const
A const iterator to the past-the-last volume.
Eigen::Matrix3i enforce_min_volume(const UnitType &unit, const Eigen::Matrix3i &T, const SymGroup &point_grp, Index volume, bool fix_shape=false)
Return a transformation matrix that ensures a supercell of at least some volume.
std::string dirs() const
Lattice make_supercell(const Lattice &lat, const Eigen::Matrix3i &transf_mat)
Returns a super Lattice.
Definition: Lattice.hh:377
Eigen::MatrixXi _expand_dims_old(const Eigen::MatrixXi &hermit_mat, const Eigen::VectorXi &active_dims)
Expand a n x n Hermite normal matrix into a m x m one (e.g. for 2D supercells)
A fake container of supercell matrices.
Definition: Enumerator.hh:407
void jump_to_determinant(value_type new_det)
Reset the diagonal to the specified determinant and set the other elements to zero.
const int m_end_volume
The past-the-last volume supercells to be iterated over (what cend uses)
const UnitType m_unit
The unit cell of the supercells.
Main CASM namespace.
Definition: complete.cpp:8
Eigen::Matrix3i enforce_min_volume< Lattice >(const Lattice &unit, const Eigen::Matrix3i &T, const SymGroup &point_grp, Index volume, bool fix_shape)
Index dim() const
Get the dimensions of *this.
Eigen::MatrixXi operator()() const
Get the current matrix the counter is on.
const_iterator cend() const
A const iterator to the past-the-last volume.
Eigen::Matrix3i matrix() const
constructed supercell matrix
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Definition: SymGroup.hh:33
double tol
void _update_super()
Update m_super when required.
UnitType m_super
A supercell, stored here so that iterator dereferencing will be OK. Only used when requested...
size_type begin_volume() const
ScelEnumProps(size_type begin_volume, size_type end_volume, std::string dirs="abc", Eigen::Matrix3i generating_matrix=Eigen::Matrix3i::Identity())
Constructor.
const_iterator begin() const
A const iterator to the beginning volume, specify here how the iterator should jump through the enume...
cloneable_ptr< T > make_cloneable(Args &&...args)
make a cloneable_ptr via T(Args... args)
Eigen::VectorXi _canonical_unroll(const Eigen::MatrixXi &hermit_mat)
Unroll a Hermit normal form square matrix into a vector such that it's canonical form is easy to comp...
ScelEnumProps make_scel_enum_props(PrimClex &primclex, const jsonParser &input)
Make a ScelEnumProps object from JSON input.
const int m_begin_volume
The first volume supercells to be iterated over (what cbegin uses)
SymGroup m_point_group
The point group of the unit cell.
EigenIndex Index
For long integer indexing:
HermiteCounter & operator++()
Jump to the next available HNF matrix.
size_type end_volume() const
Eigen::Matrix3i generating_matrix() const
const_iterator cbegin() const
A const iterator to the beginning volume.
Iterator find(Iterator begin, Iterator end, const T &value, BinaryCompare q)
Equivalent to std::find(begin, end, value), but with custom comparison.
Definition: algorithm.hh:10
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:52
size_type begin_volume() const
Get the beginning volume.
HermiteCounter(int init_determinant, int init_dim)
constructor to satisfy iterator requirements. Do not recommend.
HermiteCounter::value_type volume() const
current volume
void _increment()
Postfix increment operator. Increment to next unique supercell.
void _try_increment()
Check if the current supercell matrix hermite normal form is in a canonical form. ...
std::vector< Eigen::Matrix3i > m_canon_hist
Keep track of the HNF matrices for the current determinant value.
EigenVectorXiCounter m_upper_tri
unrolled vector of the upper triangle (does not include diagonal elements)
Non-std smart pointer classes and functions.
void reset_current()
reset the counter to the first iteration of the current determinant
const Lattice & lattice() const
Access the unit lattice.
notstd::cloneable_ptr< HermiteCounter > m_current
Current supercell matrix in HermitCounter form.
SupercellIterator< UnitType > & operator++()
Prefix increment operator. Increment to next unique supercell.
Iterators used with SupercellEnumerator.
const SymGroup & point_group() const
Access the unit point group.
void next_determinant()
Skip the remaining iterations and start at the next determinant value.
Eigen::VectorXi m_diagonal
Vector holding diagonal element values.
void begin_volume(size_type _begin_volume)
Set the beginning volume.
EIGEN_MAKE_ALIGNED_OPERATOR_NEW typedef std::forward_iterator_tag iterator_category
fixes alignment of m_deformation
bool operator==(const SupercellIterator< UnitType > &B) const
Iterator comparison.
const int m_dims
The number of lattice directions the enumeration is being done in.
int dimension() const
Get the dimensions of the enumerator (1D, 2D or 3D)
HermiteCounter::Index upper_size(HermiteCounter::Index init_dim)
Determine the number of elements in the upper triangular matrix (excluding diagonal) ...
Log & default_err_log()
Definition: Log.hh:206
void error(const std::string &what)
Definition: Log.hh:86
double volume(const Lattice &lat)
Returns the volume of a Lattice.
Definition: Lattice.hh:372
A 'cloneable_ptr' can be used in place of 'unique_ptr'.
const UnitType & unit() const
Access the unit the is being made into supercells.
const_iterator citerator(size_type volume) const
A const iterator to a specified volume.
HermiteCounter::Index next_spill_position(Eigen::VectorXi &diag, HermiteCounter::Index position)
Spill the next factor of the specified element with its neighbor, and return new position.
EigenVectorXiCounter _upper_tri_counter(const Eigen::VectorXi &current_diag)
Create a counter for the elements above the diagonal based on the current diagonal value...
bool m_super_updated
Indicates if m_super reflects the current m_current supercell matrix.
Eigen::VectorXi::Scalar value_type
const SupercellEnumerator< UnitType > & enumerator() const
const reference to the SupercellEnumerator this is iterating with
const Eigen::Matrix3i m_gen_mat
This matrix (G) specifies new lattice vectors to enumerate over column-wise, such that the resulting ...
Eigen::MatrixXi current() const
Get the current matrix the counter is on.
SupercellEnumerator(UnitType unit, const ScelEnumProps &enum_props, double tol)
Construct a SupercellEnumerator.
Eigen::Matrix3i make_unit_cell(PrimClex &primclex, const jsonParser &json)
Read unit cell transformation matrix from JSON input.