CASM  1.1.0
A Clusters Approach to Statistical Mechanics
HasCanonicalForm_impl.hh
Go to the documentation of this file.
1 #ifndef CASM_HasCanonicalForm_impl
2 #define CASM_HasCanonicalForm_impl
3 
6 #include "casm/clex/Supercell.hh"
13 #include "casm/symmetry/SymOp.hh"
14 
15 namespace CASM {
16 
17 // --- template<typename _Base> class CanonicalForm ---
18 
19 template <typename _Base>
20 template <typename SymCompareType>
22  const std::vector<SymOp> &g, const SymCompareType &sym_compare) const {
23  IsCanonical<Orbit<SymCompareType>> f(g, sym_compare);
24  return f(derived());
25 }
26 
27 template <typename _Base>
28 template <typename SymCompareType>
30  const std::vector<SymOp> &g, const SymCompareType &sym_compare) const {
32  return f(derived());
33 }
34 
35 template <typename _Base>
36 template <typename SymCompareType>
38  const MostDerived &other, const std::vector<SymOp> &g,
39  const SymCompareType &sym_compare) const {
41  return sym_compare.equal(f(derived()), f(other));
42 }
43 
44 template <typename _Base>
45 template <typename ObjIterator, typename SymCompareType>
47  ObjIterator begin, ObjIterator end, const std::vector<SymOp> &g,
48  const SymCompareType &sym_compare) const {
50  auto canon = f(derived());
51  auto is_sym_equiv = [&](const MostDerived &test) {
52  return sym_compare.equal(canon, f(test));
53  };
54  return std::find_if(begin, end, is_sym_equiv);
55 }
56 
57 template <typename _Base>
58 template <typename SymCompareType>
60  const std::vector<SymOp> &g, const SymCompareType &sym_compare) const {
62  f(derived());
63  return f.to_canonical();
64 }
65 
66 template <typename _Base>
67 template <typename SymCompareType>
69  const std::vector<SymOp> &g, const SymCompareType &sym_compare) const {
70  return to_canonical(g, sym_compare).inverse();
71 }
72 
73 template <typename _Base>
74 template <typename SymCompareType>
76  const SymGroup &super_grp, const SymCompareType &sym_compare) const {
77  return make_invariant_subgroup(derived(), super_grp, sym_compare);
78 }
79 
80 template <typename _Base>
82  return is_canonical(scel, scel.sym_info().permute_begin(),
83  scel.sym_info().permute_end());
84 }
85 
86 template <typename _Base>
88  const Supercell &scel) const {
89  return canonical_form(scel, scel.sym_info().permute_begin(),
90  scel.sym_info().permute_end());
91 }
92 
94 template <typename _Base>
96  const Supercell &scel) const {
97  return is_sym_equivalent(scel, scel.sym_info().permute_begin(),
98  scel.sym_info().permute_end());
99 }
100 
101 template <typename _Base>
103  return to_canonical(scel, scel.sym_info().permute_begin(),
104  scel.sym_info().permute_end());
105 }
106 
107 template <typename _Base>
109  return from_canonical(scel, scel.sym_info().permute_begin(),
110  scel.sym_info().permute_end());
111 }
112 
113 template <typename _Base>
114 std::vector<PermuteIterator> CanonicalForm<_Base>::invariant_subgroup(
115  const Supercell &scel) const {
116  return invariant_subgroup(scel, scel.sym_info().permute_begin(),
117  scel.sym_info().permute_end());
118 }
119 
120 template <typename _Base>
121 template <typename PermuteIteratorIt>
123  PermuteIteratorIt begin,
124  PermuteIteratorIt end) const {
126  return f(derived(), begin, end);
127 }
128 
129 template <typename _Base>
130 template <typename PermuteIteratorIt>
132  const Supercell &scel, PermuteIteratorIt begin,
133  PermuteIteratorIt end) const {
135  return f(derived());
136 }
137 
139 template <typename _Base>
140 template <typename PermuteIteratorIt>
142  const Supercell &scel,
143  PermuteIteratorIt begin,
144  PermuteIteratorIt end) const {
146  return f.sym_compare.equal(f(derived(), begin, end), f(B, begin, end));
147 }
148 
150 template <typename _Base>
151 template <typename ObjIterator, typename PermuteIteratorIt>
153  ObjIterator obj_begin, ObjIterator obj_end, const Supercell &scel,
154  PermuteIteratorIt begin, PermuteIteratorIt end) const {
156  auto canon = f(derived(), begin, end);
157  auto is_sym_equiv = [&](const MostDerived &test) {
158  return f.sym_compare.equal(canon, f(test, begin, end));
159  };
160  return std::find_if(obj_begin, obj_end, is_sym_equiv);
161 }
162 
163 template <typename _Base>
164 template <typename PermuteIteratorIt>
166  PermuteIteratorIt begin,
167  PermuteIteratorIt end) const {
169  f(derived());
170  return f.to_canonical();
171 }
172 
173 template <typename _Base>
174 template <typename PermuteIteratorIt>
176  PermuteIteratorIt begin,
177  PermuteIteratorIt end) const {
178  // Please use -Werror=return-type in your compiler flags
179  return to_canonical(scel, begin, end).inverse();
180 }
181 
182 template <typename _Base>
183 template <typename PermuteIteratorIt>
184 std::vector<PermuteIterator> CanonicalForm<_Base>::invariant_subgroup(
185  const Supercell &scel, PermuteIteratorIt begin,
186  PermuteIteratorIt end) const {
187  return make_invariant_subgroup(derived(), scel, begin, end);
188 }
189 
190 // --- template<typename Base> class ConfigCanonicalForm<Base>
191 
192 template <typename Base>
194  return this->canonical_form() == B.canonical_form();
195 }
196 
197 template <typename Base>
198 template <typename ConfigIterator>
200  const MostDerived &B, ConfigIterator obj_begin,
201  ConfigIterator obj_end) const {
202  auto canon = this->canonical_form();
203  auto is_sym_equiv = [&](const MostDerived &test) {
204  return canon == test.canonical_form();
205  };
206  return std::find_if(obj_begin, obj_end, is_sym_equiv);
207 }
208 
209 template <typename Base>
211  return is_canonical(derived().supercell().sym_info().permute_begin(),
212  derived().supercell().sym_info().permute_end());
213 }
214 
215 template <typename Base>
218  return canonical_form(derived().supercell().sym_info().permute_begin(),
219  derived().supercell().sym_info().permute_end());
220 }
221 
222 template <typename Base>
224  return to_canonical(derived().supercell().sym_info().permute_begin(),
225  derived().supercell().sym_info().permute_end());
226 }
227 
228 template <typename Base>
230  return from_canonical(derived().supercell().sym_info().permute_begin(),
231  derived().supercell().sym_info().permute_end());
232 }
233 
234 template <typename Base>
235 std::vector<PermuteIterator> ConfigCanonicalForm<Base>::invariant_subgroup()
236  const {
237  return invariant_subgroup(derived().supercell().sym_info().permute_begin(),
238  derived().supercell().sym_info().permute_end());
239 }
240 
241 template <typename Base>
242 template <typename PermuteIteratorIt>
243 bool ConfigCanonicalForm<Base>::is_canonical(PermuteIteratorIt begin,
244  PermuteIteratorIt end) const {
245  return std::none_of(begin, end, derived().less());
246 }
247 
249 template <typename Base>
250 template <typename PermuteIteratorIt>
252  PermuteIteratorIt begin,
253  PermuteIteratorIt end) const {
254  return this->canonical_form(begin, end) == B.canonical_form(begin, end);
255 }
256 
257 template <typename Base>
258 template <typename ConfigIterator, typename PermuteIteratorIt>
260  ConfigIterator obj_begin, ConfigIterator obj_end, PermuteIteratorIt begin,
261  PermuteIteratorIt end) const {
262  auto canon = this->canonical_form(begin, end);
263  auto is_sym_equiv = [&](const MostDerived &test) {
264  return canon == test.canonical_form(begin, end);
265  };
266  return std::find_if(obj_begin, obj_end, is_sym_equiv);
267 }
268 
269 template <typename Base>
270 template <typename PermuteIteratorIt>
273  PermuteIteratorIt end) const {
274  return copy_apply(to_canonical(begin, end), derived());
275 }
276 
277 template <typename Base>
278 template <typename PermuteIteratorIt>
280  PermuteIteratorIt begin, PermuteIteratorIt end) const {
281  return *std::max_element(begin, end, derived().less());
282 }
283 
284 template <typename Base>
285 template <typename PermuteIteratorIt>
287  PermuteIteratorIt begin, PermuteIteratorIt end) const {
288  // simplest version: use the inverse of the first element that results in the
289  // canonical form return to_canonical(begin, end).inverse();
290 
291  // alternate version: the lowest index element that transforms canonical form
292  // to this
293  auto less = derived().less();
294  auto _to_canonical = begin;
295  auto _from_canonical = _to_canonical.inverse();
296  for (auto it = begin; it < end; ++it) {
297  if (less(_to_canonical, it)) {
298  _to_canonical = it;
299  _from_canonical = _to_canonical.inverse();
300  }
301  // other permutations that result in canonical config may have a lower index
302  // inverse
303  else if (!less(it, _to_canonical)) {
304  auto it_inv = it.inverse();
305  if (it_inv < _from_canonical) {
306  _from_canonical = it_inv;
307  }
308  }
309  }
310  return _from_canonical;
311 }
312 
313 template <typename Base>
314 template <typename PermuteIteratorIt>
316  PermuteIteratorIt begin, PermuteIteratorIt end) const {
317  // std::cout << "INSIDE invariant_subgroup()" << std::endl;
318  std::vector<PermuteIterator> sub_grp;
319  // std::cout << "begin: " << begin->factor_group_index() << std::endl;
320  std::copy_if(begin, end, std::back_inserter(sub_grp), derived().equal_to());
321  // std::cout << "Complete!\n";
322  return sub_grp;
323 }
324 
325 // --- template<typename Base> class SupercellCanonicalForm
326 
327 template <typename Base>
329  return xtal::canonical::check(derived().lattice(),
330  derived().prim().point_group());
331 }
332 
333 template <typename Base>
335  auto to_canonical_ix = xtal::canonical::operation_index(
336  derived().lattice(), derived().prim().point_group());
337  return derived().prim().point_group()[to_canonical_ix];
338 }
339 
340 template <typename Base>
342  return to_canonical().inverse();
343 }
344 
345 template <typename Base>
347  return xtal::canonical::equivalent(derived().lattice(),
348  derived().prim().point_group(),
349  derived().crystallography_tol());
350 }
351 
352 template <typename Base>
354  if (!m_canonical) {
355  m_canonical = &*derived().insert().first;
356  }
357  return *m_canonical;
358 }
359 
367 template <typename Base>
368 template <typename PermuteIteratorIt>
370  const Supercell &scel_B, PermuteIteratorIt begin, PermuteIteratorIt end) {
371  return make_invariant_subgroup(derived(), scel_B, begin, end);
372 }
373 
374 } // namespace CASM
375 
376 #endif
MostDerived canonical_form(const std::vector< SymOp > &g, const SymCompareType &sym_compare) const
Return canonical form.
bool is_canonical(const std::vector< SymOp > &g, const SymCompareType &sym_compare) const
Check if canonical.
SymOp to_canonical(const std::vector< SymOp > &g, const SymCompareType &sym_compare) const
Return op that transforms this into canonical form.
SymOp from_canonical(const std::vector< SymOp > &g, const SymCompareType &sym_compare) const
Return op that transforms the canonical form into this.
bool is_sym_equivalent(const MostDerived &other, const std::vector< SymOp > &g, const SymCompareType &sym_compare) const
Check if two elements have the same canonical form.
ObjIterator find_sym_equivalent(ObjIterator begin, ObjIterator end, const std::vector< SymOp > &g, const SymCompareType &sym_compare) const
Find element that has the same canonical form.
SymGroup invariant_subgroup(const SymGroup &super_grp, const SymCompareType &sym_compare) const
Return subgroup of super_grp that leaves this invariant.
Base::MostDerived MostDerived
PermuteIterator to_canonical() const
PermuteIterator from_canonical() const
Base::MostDerived MostDerived
std::vector< PermuteIterator > invariant_subgroup() const
bool is_sym_equivalent(const MostDerived &B) const
True if this and B have same canonical form.
ConfigIterator find_sym_equivalent(const MostDerived &B, ConfigIterator obj_begin, ConfigIterator obj_end) const
Find Config that has same canonical form.
MostDerived canonical_form() const
Functor to find the canonical generating element for an orbit in a Supercell.
const SymCompareType & sym_compare() const
PermuteIterator to_canonical() const
After using call operator, this can be checked.
const Supercell & canonical_form() const
Return canonical equivalent Supercell.
SymOp from_canonical() const
The inverse of to_canonical()
std::vector< PermuteIterator > invariant_subgroup(const Supercell &scel_B, PermuteIteratorIt begin, PermuteIteratorIt end)
Construct the subgroup of permutations that leaves a Supercell unchanged.
xtal::Lattice canonical_lattice() const
Return canonical equivalent lattice.
bool is_canonical() const
True if lattice().is_canonical(g), where g is the prim().point_group()
Represents a supercell of the primitive parent crystal structure.
Definition: Supercell.hh:51
std::pair< DB::DatabaseIterator< Supercell >, bool > insert() const
Insert the canonical form of this into the database.
Definition: Supercell.cc:283
const SupercellSymInfo & sym_info() const
Definition: Supercell.cc:265
permute_const_iterator permute_end() const
permute_const_iterator permute_begin() const
bool equal(const Element &A, const Element &B) const
Check equivalence of 'prepared' elements.
Definition: SymCompare.hh:183
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Definition: SymGroup.hh:42
SymOp is the Coordinate representation of a symmetry operation it keeps fraction (FRAC) and Cartesian...
Definition: SymOp.hh:28
SymOp inverse() const
get the inverse of this SymOp
Definition: SymOp.cc:87
bool is_canonical(const Configuration &_config)
returns true if no symmetry transformation applied to _config will increase its lexicographic order
std::vector< PermuteIterator > make_invariant_subgroup(ConfigEnumInput const &config_enum_input)
GenericVectorXdScelFormatter lattice()
Definition: SupercellIO.cc:266
SymGroup invariant_subgroup(const SymGroup &super_group, const xtal::Lattice &lat)
Returns the subgroup of the given group that keeps the lattice invariant.
Definition: SymTools.cc:34
Lattice equivalent(Lattice const &in_lat, SymOpVector const &point_grp, double compare_tol)
Index operation_index(const Lattice &lat, SymOpVector const &g)
bool check(const Lattice &lat)
bool less(LatticeNode const &A, LatticeNode const &B, double cost_tol)
Compare two LatticeMap objects, based on their mapping cost first, followed by PrimGrid transformatio...
Main CASM namespace.
Definition: APICommand.hh:8
MappingNode copy_apply(PermuteIterator const &_it, MappingNode const &_node, bool transform_cost_mat=true)
Reorders the permutation and compounds the spatial isometry (rotation.
Functor to find the canonical generating element for an orbit.
const SymOp & to_canonical() const
After using call operator, this can be checked.
Functor to find to check if element is in canonical form.
Functor to find to check if element is in canonical form.