CASM  1.1.0
A Clusters Approach to Statistical Mechanics
BasicStructureTools.cc
Go to the documentation of this file.
2 
3 #include <algorithm>
4 #include <atomic>
5 #include <tuple>
6 #include <unordered_set>
7 #include <utility>
8 #include <vector>
9 
26 #include "casm/external/Eigen/Core"
27 #include "casm/external/Eigen/src/Core/Matrix.h"
30 #include "casm/symmetry/SymOp.hh"
31 #include "casm/external/Eigen/src/Core/PermutationMatrix.h"
32 #include "casm/external/Eigen/src/Core/util/Constants.h"
33 namespace {
34 using namespace CASM;
35 
42 bool global_dofs_are_compatible_with_operation(
43  const xtal::SymOp &operation,
44  const std::map<DoFKey, xtal::DoFSet> &global_dof_map) {
45  for (const auto &name_dof_pr : global_dof_map) {
46  const xtal::DoFSet &dof = name_dof_pr.second;
47  xtal::DoFSet transformed_dof = sym::copy_apply(operation, dof);
48  if (!xtal::DoFSetIsEquivalent_f(dof, TOL)(transformed_dof)) {
49  return false;
50  }
51  }
52  return true;
53 }
54 
57 void expand_with_time_reversal(xtal::SymOpVector *growing_point_group) {
58  int size = growing_point_group->size();
59  for (int ix = 0; ix < size; ++ix) {
60  growing_point_group->emplace_back(growing_point_group->at(ix) *
62  }
63  return;
64 }
65 
70 std::pair<bool, xtal::Coordinate> map_translated_basis_and_calc_drift(
71  const std::vector<xtal::Site> &basis,
72  const std::vector<xtal::Site> &translatable_basis,
73  const xtal::Coordinate &translation, double tol) {
74  xtal::Coordinate drift = xtal::Coordinate::origin(translation.lattice());
75 
76  if (basis.size() != translatable_basis.size()) return {false, drift};
77 
78  for (const xtal::Site &s_tb : translatable_basis) {
79  Index ix = xtal::find_index(basis, s_tb + translation, tol);
80  if (ix >= basis.size())
81  return {false, xtal::Coordinate::origin(translation.lattice())};
82  // (basis[ix]-s_tb) is exact_translation for mapping pair, translation is
83  // proposed translation translation.min_translation(exact_translation) is
84  // vector FROM nearest periodic image of exact_translation TO proposed
85  // translation. Average of this vector is CoM drift due to proposed
86  // translation
87  drift += translation.min_translation(basis[ix] - s_tb);
88  }
89 
90  drift.cart() /= double(basis.size());
91  return {true, drift};
92 }
93 
95 void bring_within(std::vector<xtal::SymOp> *symmetry_group,
96  const xtal::Lattice &tiling_unit) {
97  for (xtal::SymOp &operation : *symmetry_group) {
98  xtal::Coordinate translation_coord(operation.translation, tiling_unit,
99  CART);
100  translation_coord.within();
101  operation.translation = translation_coord.const_cart();
102  }
103  return;
104 }
105 
112 xtal::SymOpVector make_factor_group_from_point_group(
113  const xtal::BasicStructure &struc, const xtal::SymOpVector &point_group,
114  bool is_primitive, double tol) {
115  if (struc.basis().size() == 0) {
116  return point_group;
117  }
118 
120  Index i = 0;
121  for (const xtal::SymOp &point_group_operation : point_group) {
122  ++i;
123 
124  if (!::global_dofs_are_compatible_with_operation(point_group_operation,
125  struc.global_dofs())) {
126  continue;
127  }
128 
129  // apply the point group operation to tall the sites
130  std::vector<xtal::Site> transformed_basis;
131  for (const xtal::Site &s : struc.basis()) {
132  transformed_basis.emplace_back(point_group_operation * s);
133  }
134 
135  // Using the symmetrically transformed basis, find all possible
136  // translations that MIGHT map the symmetrically transformed basis onto
137  // the original basis
138  const xtal::Site &reference_site = struc.basis()[0];
139  for (const xtal::Site &transformed_site : transformed_basis) {
140  // If the types don't match don't even bother with anything else
141  if (!reference_site.compare_type(transformed_site)) {
142  continue;
143  }
144 
145  xtal::Coordinate translation = reference_site - transformed_site;
146  translation.within();
147 
148  xtal::Coordinate drift(struc.lattice());
149  bool success = false;
150  // By construction, the current transformed_site matches the first
151  // basis site, do the rest of them match too?
152  // Determine if mapping is successful, and calculate center-of-mass drift
153  std::tie(success, drift) = map_translated_basis_and_calc_drift(
154  struc.basis(), transformed_basis, translation, tol);
155 
156  // The mapping failed, continue to the next site for a new translation
157  if (!success) {
158  continue;
159  }
160 
161  // You found a valid translation! BUT, before you construct the
162  // symmetry operation, remove some bias from the translation. We want
163  // the average mapping error to be zero, but we arbitrarily
164  // constructed the translation by taking the first basis site of the
165  // structure as a reference. Here we use the average mapping error to
166  // correct this.
167  translation -= drift;
168 
169  // Now that the translation has been adjusted, create the symmetry
170  // operation and add it if we don't have an equivalent one already
171  xtal::SymOp translation_operation =
173  xtal::SymOp new_factor_group_operation(translation_operation *
174  point_group_operation);
176  equals_new_factor_group_operation(new_factor_group_operation,
177  struc.lattice(), tol);
178 
179  if (std::find_if(factor_group.begin(), factor_group.end(),
180  equals_new_factor_group_operation) ==
181  factor_group.end()) {
182  factor_group.push_back(new_factor_group_operation);
183  }
184 
185  if (is_primitive) {
186  // If structure is primitive, there is no need to attempt other
187  // translations
188  break;
189  }
190  }
191  }
192 
193  xtal::close_group<xtal::SymOpPeriodicCompare_f>(&factor_group,
194  struc.lattice(), tol);
195  bring_within(&factor_group, struc.lattice());
196 
197  return factor_group;
198 }
199 
200 xtal::SymOpVector make_translation_group(const xtal::BasicStructure &struc,
201  double tol) {
202  xtal::SymOpVector identity_group{xtal::SymOp::identity()};
203  xtal::SymOpVector translation_group =
204  make_factor_group_from_point_group(struc, identity_group, false, tol);
205  return translation_group;
206 }
207 
210 std::pair<xtal::BasicStructure, xtal::SymOpVector> make_primitive_factor_group(
211  const xtal::BasicStructure &non_primitive_struc, double tol) {
212  xtal::BasicStructure primitive_struc =
213  xtal::make_primitive(non_primitive_struc);
214 
215  xtal::SymOpVector primitive_point_group =
216  xtal::make_point_group(primitive_struc.lattice());
217  if (primitive_struc.is_time_reversal_active()) {
218  // Duplicate each symmetry operation so that the second version has time
219  // reversal enabled
220  ::expand_with_time_reversal(&primitive_point_group);
221  }
222 
223  xtal::SymOpVector primitive_factor_group =
224  ::make_factor_group_from_point_group(primitive_struc,
225  primitive_point_group, true, tol);
226  return std::make_pair(primitive_struc, primitive_factor_group);
227 }
228 
229 } // namespace
230 
231 namespace CASM {
232 namespace xtal {
233 Index find_index(const std::vector<Site> &basis, const Site &test_site,
234  double tol) {
235  for (Index i = 0; i < basis.size(); i++) {
236  if (basis[i].compare_type(test_site) &&
237  basis[i].min_dist(test_site) < tol) {
238  return i;
239  }
240  }
241  return basis.size();
242 }
243 
244 bool is_primitive(const BasicStructure &struc, double tol) {
245  SymOpVector translation_group = ::make_translation_group(struc, tol);
246  // For a primitive structure, the only possible translation is no translation
247  return translation_group.size() == 1;
248 }
249 
250 BasicStructure make_primitive(const BasicStructure &non_primitive_struc,
251  double tol) {
252  if (non_primitive_struc.basis().size() == 0) {
253  return non_primitive_struc;
254  }
255  SymOpVector translation_group =
256  ::make_translation_group(non_primitive_struc, tol);
257  double minimum_possible_volume =
258  std::abs(0.5 * non_primitive_struc.lattice().volume() /
259  non_primitive_struc.basis().size());
260 
261  // The candidate lattice vectors are the original lattice vectors, plus all
262  // the possible translations that map the basis of the non primitive structure
263  // onto itself
264  std::vector<Eigen::Vector3d> possible_lattice_vectors{
265  non_primitive_struc.lattice()[0], non_primitive_struc.lattice()[1],
266  non_primitive_struc.lattice()[2]};
267 
268  for (const SymOp &trans_op : translation_group) {
269  Coordinate debug(trans_op.translation, non_primitive_struc.lattice(), CART);
270  possible_lattice_vectors.push_back(trans_op.translation);
271  }
272 
273  // Attempt every combination of vectors, picking one that doesn't have
274  // colinearity (minimum volume check), but results in the smallest lattice
275  // possible (running lattice volume check)
276  double minimum_volume = std::abs(2 * non_primitive_struc.lattice().volume());
277  Eigen::Vector3d a_vector_primitive, b_vector_primitive, c_vector_primitive;
278  for (const Eigen::Vector3d a_vector_candidate : possible_lattice_vectors) {
279  for (const Eigen::Vector3d b_vector_candidate : possible_lattice_vectors) {
280  for (const Eigen::Vector3d c_vector_candidate :
281  possible_lattice_vectors) {
282  double possible_volume = std::abs(triple_product(
283  a_vector_candidate, b_vector_candidate, c_vector_candidate));
284  if (possible_volume < minimum_volume &&
285  possible_volume > minimum_possible_volume) {
286  minimum_volume = possible_volume;
287  a_vector_primitive = a_vector_candidate;
288  b_vector_primitive = b_vector_candidate;
289  c_vector_primitive = c_vector_candidate;
290  }
291  }
292  }
293  }
294  Lattice non_reduced_form_primitive_lattice(
295  a_vector_primitive, b_vector_primitive, c_vector_primitive);
296  Lattice primitive_lattice = niggli(non_reduced_form_primitive_lattice,
297  non_primitive_struc.lattice().tol());
298 
299  // The primitive lattice could be noisy, so we smoothen it out to match an
300  // integer transformation to the original lattice exactly
301  Superlattice prim_to_original = Superlattice::smooth_prim(
302  primitive_lattice, non_primitive_struc.lattice());
303  primitive_lattice = prim_to_original.prim_lattice();
304 
305  // Fill up the basis
306  BasicStructure primitive_struc(primitive_lattice);
307  for (Site site_for_prim : non_primitive_struc.basis()) {
308  site_for_prim.set_lattice(primitive_struc.lattice(), CART);
309  if (find_index(primitive_struc.basis(), site_for_prim, tol) ==
310  primitive_struc.basis().size()) {
311  site_for_prim.within();
312  primitive_struc.set_basis().emplace_back(std::move(site_for_prim));
313  }
314  }
315 
316  // TODO: Do we want this?
317  primitive_struc.set_title(non_primitive_struc.title());
318  return primitive_struc;
319 }
320 
323 std::pair<double, Eigen::Vector3d> calc_rotation_angle_and_axis(
324  const SymOp &op, const Lattice &lat) {
325  auto matrix = op.matrix;
326  double angle;
327  Eigen::Vector3d rotation_axis, _axis;
328 
329  // Simplest case is identity: has no axis and no location
330  if (almost_equal(matrix.trace(), 3.) || almost_equal(matrix.trace(), -3.)) {
331  angle = 0;
332  _axis = Eigen::Vector3d::Zero();
333  rotation_axis = Coordinate(_axis, lat, CART).const_frac();
334  return std::make_pair(angle, rotation_axis);
335  }
336 
337  // det is -1 if improper and +1 if proper
338  int det = round(matrix.determinant());
339 
340  // Find eigen decomposition of proper operation (by multiplying by
341  // determinant)
342  Eigen::EigenSolver<Eigen::Matrix3d> t_eig(det * matrix);
343 
344  // 'axis' is eigenvector whose eigenvalue is +1
345  for (Index i = 0; i < 3; i++) {
346  if (almost_equal(t_eig.eigenvalues()(i), std::complex<double>(1, 0))) {
347  _axis = t_eig.eigenvectors().col(i).real();
348  break;
349  }
350  }
351 
352  // Sign convention for 'axis': first non-zero element is positive
353  for (Index i = 0; i < 3; i++) {
354  if (!almost_zero(_axis[i])) {
355  _axis *= float_sgn(_axis[i]);
356  break;
357  }
358  }
359 
360  // get vector orthogonal to axis: ortho,
361  // apply matrix: rot
362  // and check angle between ortho and det*rot,
363  // using determinant to get the correct angle for improper
364  // (i.e. want angle before inversion for rotoinversion)
365  Eigen::Vector3d ortho = _axis.unitOrthogonal();
366  Eigen::Vector3d rot = det * (matrix * ortho);
367  angle = fmod(
368  (180. / M_PI) * atan2(_axis.dot(ortho.cross(rot)), ortho.dot(rot)) + 360.,
369  360.);
370  rotation_axis = Coordinate(_axis, lat, CART).const_frac();
371  return std::make_pair(angle, rotation_axis);
372 }
373 
374 //*******************************************************************************************
383 void sort_factor_group(std::vector<SymOp> &factor_group, const Lattice &lat) {
384  // floating point comparison tolerance
385  double tol = TOL;
386 
387  // COORD_TYPE print_mode = CART;
388 
389  // compare on vector of '-det', '-trace', 'angle', 'axis', 'tau'
390  typedef Eigen::Matrix<double, 10, 1> key_type;
391  auto make_key = [](const SymOp &op, const Lattice &lat) {
392  key_type vec;
393  int offset = 0;
394  double sym_angle;
395  Eigen::Vector3d sym_frac;
396  std::tie(sym_angle, sym_frac) = calc_rotation_angle_and_axis(op, lat);
397 
398  vec[offset] = double(op.is_time_reversal_active);
399  offset++;
400 
401  vec[offset] = -op.matrix.determinant();
402  offset++;
403 
404  vec[offset] = -op.matrix.trace();
405  offset++;
406 
407  vec[offset] = sym_angle;
408  offset++;
409 
410  vec.segment<3>(offset) = sym_frac;
411  offset += 3;
412 
413  vec.segment<3>(offset) = Coordinate(op.translation, lat, CART).const_frac();
414  offset += 3;
415 
416  return vec;
417  };
418 
419  // define symop compare function
420  auto op_compare = [tol](const key_type &A, const key_type &B) {
421  return float_lexicographical_compare(A, B, tol);
422  };
423 
424  typedef std::map<key_type, SymOp,
425  std::reference_wrapper<decltype(op_compare)>>
426  map_type;
427 
428  // first put identity in position 0 in order to calculat multi_table correctly
429  for (int i = 0; i < factor_group.size(); ++i) {
430  if (factor_group[i].matrix.isIdentity() &&
431  factor_group[i].translation.norm() < TOL &&
432  !factor_group[i].is_time_reversal_active) {
434  break;
435  }
436  }
437 
438  // sort conjugacy class using the first symop in the sorted class
439  auto cclass_compare = [tol](const map_type &A, const map_type &B) {
440  return float_lexicographical_compare(A.begin()->first, B.begin()->first,
441  tol);
442  };
443 
444  // sort elements in each conjugracy class (or just put all elements in the
445  // first map)
446  std::set<map_type, std::reference_wrapper<decltype(cclass_compare)>> sorter(
447  cclass_compare);
448 
449  // else just sort element
450  map_type all_op(op_compare);
451  for (auto it = factor_group.begin(); it != factor_group.end(); ++it) {
452  all_op.emplace(make_key(*it, lat), *it);
453  }
454  sorter.emplace(std::move(all_op));
455 
456  // copy symop back into group
457  int j = 0;
458  for (auto const &cclass : sorter) {
459  for (auto it = cclass.begin(); it != cclass.end(); ++it) {
460  factor_group[j] = it->second;
461  ++j;
462  }
463  }
464 }
465 
466 std::vector<SymOp> make_factor_group(const BasicStructure &struc, double tol) {
467  auto prim_factor_group_pair = ::make_primitive_factor_group(struc, tol);
468  const BasicStructure &primitive_struc = prim_factor_group_pair.first;
469  const std::vector<SymOp> &primitive_factor_group =
470  prim_factor_group_pair.second;
471 
472  auto all_lattice_points = make_lattice_points(
473  primitive_struc.lattice(), struc.lattice(), struc.lattice().tol());
474 
475  std::vector<SymOp> point_group = make_point_group(struc.lattice());
476  std::vector<SymOp> factor_group;
477 
478  for (const SymOp &prim_op : primitive_factor_group) {
479  // If the primitive factor group operation with translations removed can't
480  // map the original structure's lattice onto itself, then ditch that
481  // operation.
482  UnaryCompare_f<SymOpMatrixCompare_f> equals_prim_op_ignoring_trans(prim_op,
483  tol);
484  if (std::find_if(point_group.begin(), point_group.end(),
485  equals_prim_op_ignoring_trans) == point_group.end()) {
486  continue;
487  }
488 
489  // Otherwise take that factor operation, and expand it by adding additional
490  // translations within the structure
491  for (const UnitCell &lattice_point : all_lattice_points) {
492  xtal::Coordinate lattice_point_coordinate = make_superlattice_coordinate(
493  lattice_point, primitive_struc.lattice(), struc.lattice());
494  factor_group.emplace_back(
495  SymOp::translation_operation(lattice_point_coordinate.cart()) *
496  prim_op);
497  }
498  }
500  return factor_group;
501 }
502 
522 std::vector<Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic, Index>>
524  const std::vector<SymOp> &factor_group) {
525  std::string clr(100, ' ');
526  if (factor_group.size() <= 0) {
527  std::cout << "ERROR in xtal::make_permutation_representation" << std::endl;
528  std::cout << "Factor group is empty." << std::endl;
529  exit(1);
530  }
531  std::vector<xtal::UnitCellCoord> sitemap;
532 
533  Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic, Index> init_perm_mat;
534  init_perm_mat.setIdentity(struc.basis().size());
535  std::vector<Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic, Index>>
536  perm_rep(factor_group.size(), init_perm_mat);
537 
538  for (Index s = 0; s < factor_group.size(); ++s) {
539  auto const &op = factor_group[s];
540  std::vector<Index> _perm(struc.basis().size(), -1);
541  sitemap = xtal::symop_site_map(op, struc);
542 
543  for (Index b = 0; b < struc.basis().size(); ++b) {
544  auto const &dofref_to =
545  struc.basis()[sitemap[b].sublattice()].occupant_dof();
546  auto const &dofref_from = struc.basis()[b].occupant_dof();
548  // adapter::Adapter<SymOp, CASM::SymOp>()(op)
549  if (eq(op, dofref_to)) {
550  _perm[b] = sitemap[b].sublattice();
551  } else
552  throw std::runtime_error(
553  "In Structure::_generate_basis_symreps(), Sites originally "
554  "identified as equivalent cannot be mapped by symmetry.");
555  }
556  Eigen::Map<Eigen::Matrix<Index, Eigen::Dynamic, 1>> index_matrix(
557  _perm.data(), _perm.size());
558  perm_rep[s].indices() = index_matrix;
559  }
560  return perm_rep;
561 }
562 
573 std::set<std::set<Index>> make_asymmetric_unit(
574  const xtal::BasicStructure &struc, const std::vector<SymOp> &factor_group) {
575  double tol = struc.lattice().tol();
576 
577  auto transformed_site_index = [&](Site const &site, SymOp const &op) {
578  Site transformed_site = op * site;
579  return UnitCellCoord::from_coordinate(struc, transformed_site, tol)
580  .sublattice();
581  };
582 
583  std::set<std::set<Index>> asym_unit;
584  for (Site const &site : struc.basis()) {
585  std::set<Index> equivalent_sites;
586  for (SymOp const &op : factor_group) {
587  equivalent_sites.insert(transformed_site_index(site, op));
588  }
589  asym_unit.insert(equivalent_sites);
590  }
591  return asym_unit;
592 }
593 
602 std::set<std::set<Index>> make_asymmetric_unit(
603  const xtal::BasicStructure &struc) {
604  std::vector<SymOp> factor_group =
605  make_factor_group(struc, struc.lattice().tol());
606  return make_asymmetric_unit(struc, factor_group);
607 }
608 
610  const std::vector<SymOp> &enforced_group) {
611  // All your sites need to be within
612  auto symmetrized_structure = structure;
613 
614  // First make a copy of your current basis
615  // This copy will eventually become the new average basis.
616  auto avg_basis = structure.basis();
617 
618  // Loop through given symmetry group an fill a temporary "operated basis"
619  decltype(avg_basis) operated_basis;
620 
621  // Loop through given symmetry group an fill a temporary "operated basis"
622  for (const SymOp &enforce_group_operation : enforced_group) {
623  operated_basis.clear();
624  for (const auto &symmetrized_structure_site :
625  symmetrized_structure.basis()) {
626  operated_basis.push_back(enforce_group_operation *
627  symmetrized_structure_site);
628  }
629 
630  // Now that you have a transformed basis, find the closest mapping of atoms
631  // Then average the distance and add it to the average basis
632  for (Index b = 0; b < symmetrized_structure.basis().size(); b++) {
633  double smallest = 1000000;
634  Coordinate bshift(symmetrized_structure.lattice());
635  for (const auto &operated_basis_site : operated_basis) {
636  double dist =
637  operated_basis_site.min_dist(symmetrized_structure.basis()[b]);
638  if (dist < smallest) {
639  bshift = operated_basis_site.min_translation(
640  symmetrized_structure.basis()[b]);
641  smallest = dist;
642  }
643  }
644  bshift.cart() *= (1.0 / enforced_group.size());
645  avg_basis[b] += bshift;
646  }
647  }
648  symmetrized_structure.set_basis(avg_basis);
649  return symmetrized_structure;
650 }
651 
652 template <typename IntegralType, int Options>
654  const BasicStructure &tiling_unit,
655  const Eigen::Matrix<IntegralType, 3, 3, Options> &transformation_matrix) {
656  static_assert(std::is_integral<IntegralType>::value,
657  "Transfomration matrix must be integer matrix");
658  Lattice superlat =
659  make_superlattice(tiling_unit.lattice(), transformation_matrix);
660  BasicStructure superstruc(superlat);
661 
662  std::vector<UnitCell> all_lattice_points =
663  make_lattice_points(tiling_unit.lattice(), superlat, superlat.tol());
664 
665  std::vector<Site> superstruc_basis;
666  for (const Site &unit_basis_site : tiling_unit.basis()) {
667  for (const UnitCell &lattice_point : all_lattice_points) {
668  Coordinate lattice_point_coordinate = make_superlattice_coordinate(
669  lattice_point, tiling_unit.lattice(), superlat);
670  superstruc_basis.emplace_back(unit_basis_site + lattice_point_coordinate);
671  }
672  }
673  superstruc.set_basis(superstruc_basis, CART);
674  return superstruc;
675 }
676 
678  const BasicStructure &tiling_unit,
679  const Eigen::Matrix<int, 3, 3, 0> &transformation_matrix);
681  const BasicStructure &tiling_unit,
682  const Eigen::Matrix<long, 3, 3, 0> &transformation_matrix);
683 
684 } // namespace xtal
685 } // namespace CASM
std::set< std::string > & s
Class for checking equivalence of two OccupantDoF objects, with respect to symmetry transformations.
BasicStructure specifies the lattice and atomic basis of a crystal.
std::map< DoFKey, DoFSet > const & global_dofs() const
std::vector< Site > & set_basis()
const std::string & title() const
void set_title(std::string const &_title)
Set the title of the structure.
const Lattice & lattice() const
bool is_time_reversal_active() const
Returns true if structure has attributes affected by time reversal.
const std::vector< Site > & basis() const
Represents cartesian and fractional coordinates.
Definition: Coordinate.hh:34
Coordinate_impl::CartCoordinate cart()
Set Cartesian coordinate vector and update fractional coordinate vector.
Definition: Coordinate.hh:562
const Lattice & lattice() const
Access the home lattice of the coordinate.
Definition: Coordinate.hh:206
const vector_type & const_frac() const
user override to force const Access the fractional coordinate vector
Definition: Coordinate.hh:68
Coordinate min_translation(const Coordinate &neighbor) const
Returns translation coordinate (in Angstr) to nearest periodic image of neighbor.
Definition: Coordinate.cc:156
const vector_type & const_cart() const
user override to force const Access the Cartesian coordinate vector
Definition: Coordinate.hh:90
double tol() const
Definition: Lattice.hh:195
double volume() const
Return signed volume of this lattice.
Definition: Lattice.hh:88
bool compare_type(const Site &test_site) const
Definition: Site.cc:189
const Lattice & prim_lattice() const
Definition: Superlattice.hh:20
static Superlattice smooth_prim(const Lattice &tiling_unit, const Lattice &superlattice)
Definition: Superlattice.cc:22
static UnitCellCoord from_coordinate(const PrimType &, const Coordinate &coord, double tol)
Unit Cell Indices.
bool is_primitive(const Configuration &_config)
returns true if _config describes primitive cell of the configuration it describes
static Coordinate origin(const Lattice &_home)
construct a coordinate describing origin of _home lattice
Definition: Coordinate.hh:284
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
Derived::Scalar triple_product(const Derived &vec0, const Derived &vec1, const Derived &vec2)
double angle(const Eigen::Ref< const Eigen::Vector3d > &a, const Eigen::Ref< const Eigen::Vector3d > &b)
Get angle, in radians, between two vectors on range [0,pi].
Eigen::CwiseUnaryOp< decltype(Local::round_l< typename Derived::Scalar >), const Derived > round(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd.
bool compare_type(AtomPosition const &A, AtomPosition const &B, double tol)
Definition: Molecule.cc:19
std::vector< UnitCellCoord > symop_site_map(SymOp const &_op, BasicStructure const &_struc)
To which site a SymOp transforms each basis site.
ConfigIO::GenericConfigFormatter< jsonParser > structure()
Definition: ConfigIO.cc:766
SharedPrimFormatter< jsonParser > factor_group()
xtal::Coordinate copy_apply(const xtal::SymOp &op, xtal::Coordinate coord)
Copy and apply SymOp to a Coordinate.
Definition: Coordinate.cc:354
std::set< std::set< Index > > make_asymmetric_unit(const xtal::BasicStructure &struc, const std::vector< SymOp > &factor_group)
Return indices of equivalent basis sites.
std::vector< UnitCell > make_lattice_points(const Eigen::Matrix3l &transformation_matrix)
template BasicStructure make_superstructure< long, 0 >(const BasicStructure &tiling_unit, const Eigen::Matrix< long, 3, 3, 0 > &transformation_matrix)
BasicStructure symmetrize(const BasicStructure &structure, const std::vector< SymOp > &enforced_group)
std::vector< SymOp > make_factor_group(const BasicStructure &struc, double tol=TOL)
std::vector< Eigen::PermutationMatrix< Eigen::Dynamic, Eigen::Dynamic, Index > > make_permutation_representation(const xtal::BasicStructure &struc, const std::vector< SymOp > &factor_group)
Create the permutation group of a structure.
void sort_factor_group(std::vector< SymOp > &factor_group, const Lattice &lat)
Sort SymOp in the SymGroup.
std::pair< double, Eigen::Vector3d > calc_rotation_angle_and_axis(const SymOp &op, const Lattice &lat)
Calculates the rotation angle and axis of a symmetry operation. This function is almost exactly ident...
BasicStructure make_primitive(const BasicStructure &non_primitive_struc, double tol=TOL)
Returns the smallest possible tiling unit of the given structure.
bool is_primitive(const BasicStructure &struc, double tol=TOL)
Coordinate make_superlattice_coordinate(const UnitCell &ijk, const Superlattice &superlattice)
Lattice niggli(const Lattice &in_lat, double compare_tol, bool keep_handedness=false)
Definition: Niggli.cc:330
template BasicStructure make_superstructure< int, 0 >(const BasicStructure &tiling_unit, const Eigen::Matrix< int, 3, 3, 0 > &transformation_matrix)
Index find_index(const std::vector< Site > &basis, const Site &test_site, double tol)
BasicStructure make_superstructure(const BasicStructure &tiling_unit, const Eigen::Matrix< IntegralType, 3, 3, Options > &transformation_matrix)
std::vector< SymOp > make_point_group(Lattice const &_lat)
Populate.
Definition: SymTools.cc:113
std::vector< SymOp > SymOpVector
Main CASM namespace.
Definition: APICommand.hh:8
bool almost_equal(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Check if ClusterInvariants are equal.
void swap(ConfigDoF &A, ConfigDoF &B)
Definition: ConfigDoF.cc:260
const double TOL
Definition: definitions.hh:30
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
Definition: CASM_math.hh:104
int float_sgn(T val, double compare_tol=TOL)
Definition: CASM_math.hh:188
bool float_lexicographical_compare(const Eigen::Ref< const Eigen::MatrixXd > &A, const Eigen::Ref< const Eigen::MatrixXd > &B, double tol)
Floating point lexicographical comparison with tol.
const COORD_TYPE CART
Definition: enum.hh:9
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
ProjectSettings & set
Definition: settings.cc:137
static SymOp identity()
Definition: SymType.hh:29
static SymOp translation_operation(const SymOpTranslationType &translation)
Definition: SymType.hh:39
SymOpMatrixType matrix
Definition: SymType.hh:47
SymOpTranslationType translation
Definition: SymType.hh:48
SymOpTimeReversalType is_time_reversal_active
Definition: SymType.hh:49
static SymOp time_reversal()
Definition: SymType.hh:34