CASM  1.1.0
A Clusters Approach to Statistical Mechanics
SuperlatticeEnumerator.cc
Go to the documentation of this file.
2 
4 #include "casm/external/Eigen/Dense"
6 
7 namespace CASM {
8 namespace xtal {
9 
10 //*******************************************************************************************************************//
11 // ScelEnumProps
12 
13 //*******************************************************************************************************************//
14 // SuperlatticeIterator
15 
17  const SuperlatticeEnumerator &enumerator, int volume, int dims)
18  : m_super_updated(false),
19  m_enum(&enumerator),
20  m_current(notstd::make_cloneable<HermiteCounter>(volume, dims)) {
22  throw std::runtime_error(
23  "The beginning volume of the SuperlatticeEnumerator cannot be greater "
24  "than the end volume!");
25  }
26 
27  if (dims < 1) {
28  throw std::runtime_error(
29  "Dimensions to count over must be greater than 0!");
30  }
31 }
32 
34  const SuperlatticeIterator &B) {
35  m_enum = B.m_enum;
36  m_current = B.m_current;
37  m_super_updated = false;
38 
40  return *this;
41 }
42 
44  return (m_enum == B.m_enum) && (matrix() - B.matrix()).isZero();
45 }
46 
48  return !(*this == B);
49 }
50 
52  const {
53  if (!m_super_updated) {
55  m_super_updated = true;
56  }
57  return m_super;
58 }
59 
61  const {
62  if (!m_super_updated) {
64  m_super_updated = true;
65  }
66  return &m_super;
67 }
68 
70  return m_current->determinant();
71 }
72 
74  return *m_enum;
75 }
76 
77 // prefix
79  _increment();
80  return *this;
81 }
82 
84  m_canon_hist.push_back(matrix());
85  HermiteCounter::value_type last_determinant = m_current->determinant();
86  ++(*m_current);
87 
88  if (last_determinant != m_current->determinant()) {
89  m_canon_hist.clear();
90  }
91 
92  while (std::find(m_canon_hist.begin(), m_canon_hist.end(), matrix()) !=
93  m_canon_hist.end()) {
94  ++(*m_current);
95  }
96 
97  m_super_updated = false;
98 }
99 
100 Eigen::Matrix3i SuperlatticeIterator::matrix() const {
101  Eigen::Matrix3i expanded =
103  return canonical_hnf(expanded, m_enum->point_group(), m_enum->unit());
104  /* return canonical_hnf(expanded, m_enum->point_group(), m_enum->lattice());
105  */
106 }
107 
108 //*******************************************************************************************************************//
109 // SuperlatticeEnumerator
110 
112  const SymOpVector &point_grp,
113  const ScelEnumProps &enum_props)
114  : m_unit(unit),
115  m_point_group(point_grp),
116  m_begin_volume(enum_props.begin_volume()),
117  m_end_volume(enum_props.end_volume()),
118  m_gen_mat(enum_props.generating_matrix()),
119  m_dims(enum_props.dims()) {
120  if (m_gen_mat.determinant() < 1) {
121  throw std::runtime_error(
122  "The transformation matrix to expand into a 3x3 matrix must have a "
123  "positive determinant!");
124  }
125 }
126 
127 const Lattice &SuperlatticeEnumerator::unit() const { return m_unit; }
128 
130  return m_point_group;
131 }
132 
133 const Eigen::Matrix3i &SuperlatticeEnumerator::gen_mat() const {
134  return m_gen_mat;
135 }
136 
138 
141  return m_begin_volume;
142 }
143 
145  const {
146  return m_end_volume;
147 }
148 
150  const {
151  return const_iterator(*this, m_begin_volume, dimension());
152 }
153 
155  const {
156  return const_iterator(*this, m_end_volume, dimension());
157 }
158 
160  const {
161  return const_iterator(*this, m_begin_volume, dimension());
162 }
163 
165  const {
166  return const_iterator(*this, m_end_volume, dimension());
167 }
168 
171  return SuperlatticeIterator(*this, volume, dimension());
172 }
173 
174 //*******************************************************************************************************************//
175 // Functions
176 
177 Eigen::Matrix3i enforce_min_volume(const Lattice &unit,
178  const Eigen::Matrix3i &T,
179  const SymOpVector &point_grp, Index volume,
180  bool fix_shape) {
181  if (fix_shape) {
182  auto init_vol = T.determinant();
183  Index m = 1;
184  while (m * m * m * init_vol < volume) {
185  ++m;
186  }
187 
188  return m * Eigen::Matrix3i::Identity();
189  } else {
190  auto init_vol = T.determinant();
191  Index m = 1;
192  while (m * init_vol < volume) {
193  ++m;
194  }
195 
196  auto compactness = [](const Lattice &lat) {
197  Eigen::Matrix3d L = lat.lat_column_mat();
198  return (L.transpose() * L).trace();
199  };
200 
201  auto compare = [&](const Lattice &A, const Lattice &B) {
202  return compactness(A) < compactness(B);
203  };
204 
205  SuperlatticeEnumerator scel(unit, point_grp, ScelEnumProps(m, m + 1));
206  auto best_it = std::min_element(scel.begin(), scel.end(), compare);
207  return best_it.matrix();
208  }
209 }
210 
211 Eigen::Matrix3i canonical_hnf(const Eigen::Matrix3i &T,
212  const SymOpVector &effective_pg,
213  const Lattice &ref_lattice) {
214  Eigen::Matrix3d lat = ref_lattice.lat_column_mat();
215 
216  // get T in hermite normal form
217  // H is the canonical form of the initial T matrix
218  const Eigen::Matrix3i H = hermite_normal_form(T).first;
219 
220  // H_best will be the most canonical version and is returned
221  Eigen::Matrix3i H_best;
222  H_best = H;
223 
224  for (const auto &op : effective_pg) {
225  Eigen::Matrix3i transformed =
226  iround(lat.inverse() * get_matrix(op) * lat) * H;
227  Eigen::Matrix3i H_transformed = hermite_normal_form(transformed).first;
228 
229  // If you fall in here then transformed was greater than H
230  if (HermiteCounter_impl::_canonical_compare(H_best, H_transformed) == 1) {
231  H_best = H_transformed;
232  }
233  }
234 
235  return H_best;
236  // return std::make_pair<Eigen::Matrix3i, Eigen::MatrixXd>(H_best,
237  // effective_pg[i_canon].matrix());
238 }
239 
240 } // namespace xtal
241 } // namespace CASM
Eigen::VectorXi::Scalar value_type
const Eigen::Matrix3d & lat_column_mat() const
3x3 matrix with lattice vectors as its columne
Definition: Lattice.hh:110
Data structure for holding supercell enumeration properties.
A fake container of supercell matrices.
Iterators used with SuperlatticeEnumerator.
bool operator!=(const SuperlatticeIterator &B) const
Iterator comparison.
const_iterator end() const
A const iterator to the past-the-last volume.
const_iterator cend() const
A const iterator to the past-the-last volume.
Lattice m_super
A supercell, stored here so that iterator dereferencing will be OK. Only used when requested.
const Eigen::Matrix3i & gen_mat() const
Get the transformation matrix that's being applied to the unit vectors.
SuperlatticeIterator & operator=(const SuperlatticeIterator &B)
const SuperlatticeEnumerator & enumerator() const
const reference to the SuperlatticeEnumerator this is iterating with
void end_volume(size_type _end_volume)
Set the end volume.
Eigen::Matrix3i matrix() const
constructed supercell matrix
const Lattice m_unit
The unit cell of the supercells.
int dimension() const
Get the dimensions of the enumerator (1D, 2D or 3D)
const int m_dims
The number of lattice directions the enumeration is being done in.
bool operator==(const SuperlatticeIterator &B) const
Iterator comparison.
size_type begin_volume() const
Get the beginning volume.
Eigen::Matrix3i canonical_hnf(const Eigen::Matrix3i &T, const SymOpVector &effective_pg, const Lattice &ref_lattice)
Return canonical hermite normal form of the supercell matrix.
HermiteCounter::value_type volume() const
current volume
const Eigen::Matrix3i m_gen_mat
This matrix (G) specifies new lattice vectors to enumerate over column-wise, such that the resulting ...
std::vector< Eigen::Matrix3i > m_canon_hist
Keep track of the HNF matrices for the current determinant value.
pointer operator->() const
Access the supercell.
Eigen::Matrix3i enforce_min_volume(const Lattice &unit, const Eigen::Matrix3i &T, const SymOpVector &point_grp, Index volume, bool fix_shape=false)
Return a transformation matrix that ensures a supercell of at least some volume.
const int m_end_volume
The past-the-last volume supercells to be iterated over (what cend uses)
const_iterator citerator(size_type volume) const
A const iterator to a specified volume.
const Lattice & unit() const
Access the unit the is being made into superlattices.
const_iterator cbegin() const
A const iterator to the beginning volume.
SuperlatticeIterator & operator++()
Prefix increment operator. Increment to next unique supercell.
bool m_super_updated
Indicates if m_super reflects the current m_current supercell matrix.
SuperlatticeEnumerator(const Lattice &unit, const SymOpVector &point_grp, const ScelEnumProps &enum_props)
Construct a SuperlatticeEnumerator using custom point group operations.
const_iterator begin() const
A const iterator to the beginning volume, specify here how the iterator should jump through the enume...
reference operator*() const
Access the supercell.
size_type end_volume() const
Get the end volume.
const int m_begin_volume
The first volume supercells to be iterated over (what cbegin uses)
notstd::cloneable_ptr< HermiteCounter > m_current
Current supercell matrix in HermitCounter form.
void begin_volume(size_type _begin_volume)
Set the beginning volume.
const SuperlatticeEnumerator * m_enum
Pointer to SuperlatticeEnumerator which holds the unit cell and point group.
SymOpVector m_point_group
The lattice of the unit cell.
const SymOpVector & point_group() const
Access the unit point group.
void _increment()
Postfix increment operator. Increment to next unique supercell.
double volume(const Lattice &lat)
Returns the volume of a Lattice.
Definition: Lattice.hh:281
Lattice make_superlattice(const Lattice &lat, const Eigen::Matrix< IntegralType, 3, 3, Options > &transf_mat)
Returns a super Lattice. Transformation matrix must be integer.
Definition: Lattice.hh:287
std::pair< Eigen::MatrixXi, Eigen::MatrixXi > hermite_normal_form(const Eigen::MatrixXi &M)
Return the hermite normal form, M == H*V.
Eigen::CwiseUnaryOp< decltype(Local::iround_l< typename Derived::Scalar >), const Derived > iround(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd to Eigen::MatrixXi.
IdentitySymRepBuilder Identity()
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....
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<H1.
Eigen::Matrix3d const & get_matrix(MappingNode const &_node)
External accessor for isometry, to provide xtal::SymOp adaptability.
std::vector< SymOp > SymOpVector
Main CASM namespace.
Definition: APICommand.hh:8
bool compare(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Compare ClusterInvariants.
Eigen::Matrix3d Matrix3d
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:16
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
Non-std smart pointer classes and functions.
cloneable_ptr< T > make_cloneable(Args &&... args)
make a cloneable_ptr<T> via T(Args... args)