CASM  1.1.0
A Clusters Approach to Statistical Mechanics
SupercellSymInfo.cc
Go to the documentation of this file.
2 
3 #include <boost/algorithm/string/classification.hpp>
4 #include <boost/algorithm/string/split.hpp>
5 
13 #include "casm/misc/CASM_math.hh"
21 
22 namespace CASM {
23 
24 std::vector<Permutation> make_translation_permutations(
25  const Eigen::Matrix3l &transformation_matrix, int basis_sites_in_prim) {
26  xtal::UnitCellCoordIndexConverter bijk_index_converter(transformation_matrix,
27  basis_sites_in_prim);
28  xtal::UnitCellIndexConverter ijk_index_converter(transformation_matrix);
29  std::vector<Permutation> translation_permutations;
30 
31  // Loops over lattice points
32  for (Index translation_ix = 0;
33  translation_ix < ijk_index_converter.total_sites(); ++translation_ix) {
34  std::vector<Index> single_translation_permutation(
35  bijk_index_converter.total_sites(), -1);
36  UnitCell translation_uc = ijk_index_converter(translation_ix);
37 
38  // Loops over all the sites
39  for (Index old_site_ix = 0;
40  old_site_ix < bijk_index_converter.total_sites(); ++old_site_ix) {
41  UnitCellCoord old_site_ucc = bijk_index_converter(old_site_ix);
42  Index new_site_ix = bijk_index_converter(old_site_ucc + translation_uc);
43 
44  single_translation_permutation[new_site_ix] = old_site_ix;
45  }
46  // You should have given a permutation value to every single site
47  assert(std::find(single_translation_permutation.begin(),
48  single_translation_permutation.end(),
49  -1) == single_translation_permutation.end());
50  translation_permutations.push_back(
51  Permutation(single_translation_permutation));
52  }
54 }
55 
57  Lattice const &_prim_lat, Lattice const &_super_lat,
58  Index num_sites_in_prim, SymGroup const &_prim_factor_group,
59  SymGroupRepID basis_permutation_symrep_ID,
60  std::map<DoFKey, SymGroupRepID> const &global_dof_symrep_IDs,
61  std::vector<SymGroupRepID> const &occ_symrep_IDs,
62  std::map<DoFKey, std::vector<SymGroupRepID> > const &local_dof_symrep_IDs)
63  : m_supercell_superlattice(_prim_lat, _super_lat),
64  m_unitcell_to_index_converter(
65  m_supercell_superlattice.transformation_matrix_to_super()),
66  m_unitcellcoord_to_index_converter(
67  m_supercell_superlattice.transformation_matrix_to_super(),
68  num_sites_in_prim),
69  m_translation_permutations(make_translation_permutations(
70  this->superlattice().transformation_matrix_to_super(),
71  num_sites_in_prim)),
72  m_factor_group(sym::invariant_subgroup(_prim_factor_group, _super_lat)),
73  m_basis_perm_symrep(factor_group(), basis_permutation_symrep_ID),
74  m_has_aniso_occs(false),
75  m_has_occupation_dofs(false) {
76  for (auto const &dofID : global_dof_symrep_IDs)
77  m_global_dof_symreps.emplace(std::make_pair(
78  dofID.first, SymGroupRep::RemoteHandle(factor_group(), dofID.second)));
79 
80  for (auto const &dofID : local_dof_symrep_IDs) {
81  SublatSymReps treps(num_sites_in_prim);
82  for (Index b = 0; b < num_sites_in_prim; ++b) {
83  if (!dofID.second[b].empty())
84  treps[b] = SymGroupRep::RemoteHandle(factor_group(), dofID.second[b]);
85  }
86  m_local_dof_symreps.emplace(std::make_pair(dofID.first, std::move(treps)));
87  }
88 
89  m_occ_symreps.resize(num_sites_in_prim);
90  for (Index b = 0; b < num_sites_in_prim; ++b) {
91  if (!occ_symrep_IDs[b].is_identity()) {
92  m_has_aniso_occs = true;
93  m_has_occupation_dofs = true;
94  } else if (occ_symrep_IDs[b].rep_index() > 1) {
95  m_has_occupation_dofs = true;
96  }
97 
98  m_occ_symreps[b] =
99  SymGroupRep::RemoteHandle(factor_group(), occ_symrep_IDs[b]);
100  }
101 }
102 
104  const SymGroup &group,
105  const xtal::UnitCellCoordIndexConverter &bijk_index_converter,
106  const Lattice &prim_lattice, const SymGroupRepID &prim_symrep_ID) {
107  SymGroupRepID perm_rep_ID = group.allocate_representation();
108  long total_sites = bijk_index_converter.total_sites();
109  for (Index operation_ix = 0; operation_ix < group.size(); ++operation_ix) {
110  const auto &operation = group[operation_ix];
111  std::vector<Index> permutation(total_sites);
112  for (Index old_l = 0; old_l < total_sites; ++old_l) {
113  const UnitCellCoord &old_ucc = bijk_index_converter(old_l);
114  UnitCellCoord new_ucc =
115  sym::copy_apply(operation, old_ucc, prim_lattice, prim_symrep_ID);
116  Index new_l = bijk_index_converter(new_ucc);
117  permutation[new_l] = old_l;
118  }
119 
120  group[operation_ix].set_rep(perm_rep_ID, SymPermutation(permutation));
121  }
122  return perm_rep_ID;
123 }
124 
131  const {
132  return m_basis_perm_symrep;
133 }
134 
165  const {
166  if (m_site_perm_symrep.empty()) {
168  this->factor_group(),
171  this->prim_lattice(),
172  this->basis_permutation_symrep().symrep_ID()));
173  }
174 
175  return m_site_perm_symrep;
176 }
177 
180  Index supercell_factor_group_index) const {
181  return *(
182  site_permutation_symrep()[supercell_factor_group_index]->permutation());
183 }
184 
187  const {
188  return permute_begin();
189 }
190 
193  const {
194  return permute_begin().begin_next_fg_op();
195 }
196 
198  const {
199  return permute_it(0, 0); // starting indices
200 }
201 
203  return permute_it(factor_group().size(), 0); // one past final indices
204 }
205 
207  Index fg_index, Index trans_index) const {
208  return permute_const_iterator(*this, fg_index, trans_index);
209 }
210 
212  Index fg_index, UnitCell trans) const {
213  Index trans_index = this->unitcell_index_converter()(trans);
214  return permute_it(fg_index, trans_index);
215 }
216 
217 std::string hermite_normal_form_name(const Eigen::Matrix3l &matrix) {
218  std::string name_str;
219 
220  Eigen::Matrix3i H = hermite_normal_form(matrix.cast<int>()).first;
221  name_str = "SCEL";
222  std::stringstream tname;
223  // Consider using a for loop with HermiteCounter_impl::_canonical_unroll here
224  tname << H(0, 0) * H(1, 1) * H(2, 2) << "_" << H(0, 0) << "_" << H(1, 1)
225  << "_" << H(2, 2) << "_" << H(1, 2) << "_" << H(0, 2) << "_" << H(0, 1);
226  name_str.append(tname.str());
227 
228  return name_str;
229 }
230 
232  std::vector<std::string> tmp, tokens;
233  try {
234  // else construct transf_mat from name (make sure to remove any empty
235  // tokens)
236  boost::split(tmp, hermite_normal_form_name, boost::is_any_of("SCEL_"),
237  boost::token_compress_on);
238  std::copy_if(tmp.begin(), tmp.end(), std::back_inserter(tokens),
239  [](const std::string &val) { return !val.empty(); });
240  if (tokens.size() != 7) {
241  throw std::invalid_argument(
242  "Error in make_supercell: supercell name format error");
243  }
244  Eigen::Matrix3l T;
245  auto cast = [](std::string val) { return std::stol(val); };
246  T << cast(tokens[1]), cast(tokens[6]), cast(tokens[5]), 0, cast(tokens[2]),
247  cast(tokens[4]), 0, 0, cast(tokens[3]);
248  return T;
249  } catch (std::exception &e) {
250  std::string format = "SCELV_T00_T11_T22_T12_T02_T01";
251  std::stringstream ss;
252  ss << "Error in make_hermite_normal_form: "
253  << "expected format: " << format << ", "
254  << "name: |" << hermite_normal_form_name << "|"
255  << ", "
256  << "tokens: " << tokens << ", "
257  << "tokens.size(): " << tokens.size() << ", "
258  << "error: " << e.what();
259  throw std::runtime_error(ss.str());
260  }
261 }
262 
278 std::string make_supercell_name(SymGroup const &point_group,
279  Lattice const &prim_lattice,
280  Lattice const &supercell_lattice) {
281  xtal::Superlattice canon_superlattice{
282  prim_lattice,
284  std::string supercell_name = hermite_normal_form_name(
285  canon_superlattice.transformation_matrix_to_super());
287  canon_superlattice.superlattice())) {
288  double tol = prim_lattice.tol();
289  auto from_canonical_index =
291  canon_superlattice.superlattice(),
292  point_group.begin(), point_group.end(), tol)
293  .first->index();
294  supercell_name += ("." + std::to_string(from_canonical_index));
295  }
296  return supercell_name;
297 }
298 
300 std::string make_canonical_supercell_name(SymGroup const &point_group,
301  Lattice const &prim_lattice,
302  Lattice const &supercell_lattice) {
303  xtal::Superlattice canon_superlattice{
304  prim_lattice,
307  canon_superlattice.transformation_matrix_to_super());
308 }
309 
312  SymGroup const &factor_group, Lattice const &prim_lattice,
313  std::string supercell_name) {
314  try {
315  // tokenize name: check if non-canonical
316  std::vector<std::string> tokens;
317  boost::split(tokens, supercell_name, boost::is_any_of("."),
318  boost::token_compress_on);
319 
320  // validate name
321  if (tokens.size() == 0 || tokens.size() > 2) {
322  throw std::invalid_argument("supercell_name format error");
323  }
324 
326  xtal::Lattice super_lattice = make_superlattice(prim_lattice, T);
327 
328  if (tokens.size() == 2) {
329  Index fg_op_index = std::stol(tokens[1]);
330  if (fg_op_index >= factor_group.size()) {
331  std::stringstream ss;
332  ss << "Error in make_superlattice_from_supercell_name: "
333  << "found prim factor group index: " << fg_op_index
334  << ", which is out of range [0, " << factor_group.size() << ").";
335  throw std::invalid_argument(ss.str());
336  }
337  super_lattice = sym::copy_apply(factor_group[fg_op_index], super_lattice);
338  // ** uses super_lattice point group **
339  super_lattice = xtal::canonical::equivalent(super_lattice);
340  } else {
341  // ** uses point group of provided factor group (typically from prim) **
342  SymGroup point_group = factor_group.copy_no_trans();
343  super_lattice = xtal::canonical::equivalent(super_lattice, point_group);
344  }
345  return xtal::Superlattice{prim_lattice, super_lattice};
346 
347  } catch (std::exception &e) {
348  std::string format = "$CANON_SCEL_NAME[.$PRIM_FG_OP]";
349  std::stringstream ss;
350  ss << "Error in make_superlattice_from_supercell_name: "
351  << "expected format: " << format << ", name: " << supercell_name
352  << ", error: " << e.what();
353  throw std::runtime_error(ss.str());
354  }
355 }
356 
372 std::pair<MasterSymGroup, SymGroupRepID> make_collective_dof_symrep(
373  std::set<Index> const &site_indices, SupercellSymInfo const &_syminfo,
374  DoFKey const &_key, std::vector<PermuteIterator> const &_group) {
375  // To build the collective DoF symrep matrices, we need to know the
376  // conventions for permutations among sites, and the conventions for storing
377  // site DoF symmetry representations.
378  //
379  // For permutation among sites, by convention:
380  // after[i] = before[perm.permute_ind(i)],
381  // where:
382  // - perm is a PermuteIterator
383  //
384  // For transforming site DoF values, by convention:
385  // op.matrix() * B_from = B_to * U(from_b, op.index()),
386  // where:
387  // - op.matrix(), factor group operation symmetry matrix
388  // - B_from: site dof basis on "before" site
389  // - B_to: site dof basis on "after" site
390  // - U(from_b, op.index()): symmetry representation matrix, stored in
391  // `_syminfo.local_dof_symreps(_key)[from_b][op.index()]`
392  //
393  // Relationships between the site DoF on the "from" site before symmetry
394  // application, to the site DoF value on the "to" site after symmetry
395  // application:
396  //
397  // v_standard_after = op.matrix() * v_standard_before
398  // = op.matrix() * B_from * v_prim_from_before
399  // = B_to * v_prim_to_after
400  // v_prim_to_after = B_to^-1 * op.matrix() * B_from * v_prim_from_before
401  // v_prim_to_after = U(from_b, op.index()) * v_prim_from_before
402 
403  std::pair<MasterSymGroup, SymGroupRepID> result;
404  if (_group.empty())
405  throw std::runtime_error("Empty group passed to collective_dof_symrep()");
406  result.first.set_lattice(_syminfo.supercell_lattice());
407  for (PermuteIterator const &perm : _group) {
408  result.first.push_back(perm.sym_op());
409  }
410 
411  result.second = result.first.allocate_representation();
412  SupercellSymInfo::SublatSymReps const &subreps =
413  _key == "occ" ? _syminfo.occ_symreps() : _syminfo.local_dof_symreps(_key);
414 
415  // make map of site_index -> beginning row in basis for that site
416  // (number of rows per site == dof dimension on that site)
417  std::map<Index, Index> site_index_to_basis_index;
418  Index total_dim = 0;
419  for (Index site_index : site_indices) {
420  Index b = _syminfo.unitcellcoord_index_converter()(site_index).sublattice();
421  Index site_dof_dim = subreps[b].dim();
422  site_index_to_basis_index[site_index] = total_dim;
423  total_dim += site_dof_dim;
424  }
425 
426  // make matrix rep, by filling in blocks with site dof symreps
427  Eigen::MatrixXd trep(total_dim, total_dim);
428  Index g = 0;
429  for (PermuteIterator const &perm : _group) {
430  trep.setZero();
431  for (Index site_index : site_indices) {
432  // "to_site" (after applying symmetry) determines row of block
433  // can't fail, because it was built from [begin, end)
434  Index to_site_index = site_index;
435  Index row = site_index_to_basis_index.find(to_site_index)->second;
436 
437  // "from_site" (before applying symmetry) determines col of block
438  // could fail, if mismatch between [begin, end) and group
439  Index from_site_index = perm.permute_ind(site_index);
440  auto col_it = site_index_to_basis_index.find(from_site_index);
441  if (col_it == site_index_to_basis_index.end()) {
442  throw std::runtime_error(
443  "Error in collective_dof_symrep: Input group includes permutations "
444  "between selected and unselected sites.");
445  }
446  Index col = col_it->second;
447 
448  // "from_site" sublattice and factor group op index
449  // are used to lookup the site dof rep matrix
450  Index from_site_b =
451  _syminfo.unitcellcoord_index_converter()(from_site_index)
452  .sublattice();
453  Eigen::MatrixXd U =
454  *(subreps[from_site_b][perm.factor_group_index()]->MatrixXd());
455 
456  // insert matrix as block in collective dof symrep
457  trep.block(row, col, U.rows(), U.cols()) = U;
458  }
459  result.first[g++].set_rep(result.second, SymMatrixXd(trep));
460  }
461  result.first.sort();
462  return result;
463 }
464 
465 } // namespace CASM
PermuteIterator begin_next_fg_op() const
A class that collects all symmetry information for for performing symmetry transformations on the sit...
SymGroupRep::RemoteHandle m_basis_perm_symrep
const Permutation & factor_group_permute(Index supercell_factor_group_index) const
Site permutation corresponding to supercell factor group operation.
const xtal::UnitCellCoordIndexConverter & unitcellcoord_index_converter() const
UnitCellCoordIndexConverter for this superstructure/primstructure pair Used to convert from lattice t...
SupercellSymInfo(Lattice const &_prim_lat, Lattice const &_super_lat, Index number_of_sublats, SymGroup const &_prim_factor_group, SymGroupRepID basis_permutation_symrep_ID, std::map< DoFKey, SymGroupRepID > const &global_dof_symrep_IDs, std::vector< SymGroupRepID > const &occ_symrep_IDs, std::map< DoFKey, std::vector< SymGroupRepID > > const &local_dof_symrep_IDs)
Construct with primitive and super lattice, number of sublattice and all relevant representation IDs.
permute_const_iterator translate_end() const
End PermuteIterator over pure translational permutations.
const xtal::Lattice & prim_lattice() const
const reference to primitive lattice
SymGroup const & factor_group() const
Subgroup of primitive-cell factor group operations that leave supercell lattice invariant.
permute_const_iterator permute_end() const
const xtal::UnitCellIndexConverter & unitcell_index_converter() const
UnitCellIndexConverter for this superlattice/primlattice pair Used to convert from lattice translatio...
SymGroupRep::RemoteHandle const & site_permutation_symrep() const
const xtal::Lattice & supercell_lattice() const
const reference to supercell lattice
PermuteIterator permute_const_iterator
std::vector< SymGroupRep::RemoteHandle > SublatSymReps
permute_const_iterator permute_begin() const
permute_const_iterator permute_it(Index supercell_factor_group_index, Index translation_index) const
std::map< DoFKey, SymGroupRep::RemoteHandle > m_global_dof_symreps
SymGroupRep::RemoteHandle const & basis_permutation_symrep() const
permute_const_iterator translate_begin() const
Begin PermuteIterator over pure translational permutations / Equivalent to permute_begin()
std::map< DoFKey, SublatSymReps > m_local_dof_symreps
SymGroupRep::RemoteHandle m_site_perm_symrep
std::map< DoFKey, SublatSymReps > const & local_dof_symreps() const
Const reference local DoF matrix representations of the supercell's factor group.
SublatSymReps const & occ_symreps() const
SymGroupRep handle for occupant permutation representation of supercell's factor group An occupant pe...
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Definition: SymGroup.hh:42
SymGroupRepID allocate_representation() const
Add a new empty representation.
Definition: SymGroup.cc:1601
SymGroupRepHandle RemoteHandle
Definition: SymGroupRep.hh:35
Permutation const * permutation(Index i) const
pointer to Permutation corresponding to SymOpRepresentation at entry 'i' of this SymGroupRep Returns ...
Definition: SymGroupRep.cc:157
Type-safe ID object for communicating and accessing Symmetry representation info.
Generalized symmetry matrix representation for arbitrary dimension Can be used to describe applicatio...
Definition: SymMatrixXd.hh:26
SymPermutation describes how a symmetry operation permutes a list of 'things' For example,...
double tol() const
Definition: Lattice.hh:195
Unit Cell Coordinates.
Index total_sites() const
Returns the total number of sites within the superlattice.
Unit Cell Indices.
Index total_sites() const
Returns the total number of sites within the superlattice.
std::string to_string(ENUM val)
Return string representation of enum class.
Definition: io_traits.hh:172
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.
xtal::Superlattice make_superlattice_from_supercell_name(Structure const &prim, std::string supercell_name)
Construct a Superlattice from the supercell name.
Definition: Supercell.cc:350
std::string make_canonical_supercell_name(Structure const &prim, xtal::Superlattice const &superlattice)
Make the canonical supercell name from a Superlattice.
Definition: Supercell.cc:343
std::string make_supercell_name(Structure const &prim, xtal::Superlattice const &superlattice)
Make the supercell name from a Superlattice.
Definition: Supercell.cc:336
SharedPrimFormatter< jsonParser > factor_group()
VectorXdSupercellSymInfoFormatter supercell_lattice()
MatrixXiSupercellSymInfoFormatter transformation_matrix_to_super()
SupercellSymInfoFormatter< jsonParser > translation_permutations()
xtal::Coordinate copy_apply(const xtal::SymOp &op, xtal::Coordinate coord)
Copy and apply SymOp to a Coordinate.
Definition: Coordinate.cc:354
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)
bool is_equivalent(const Lattice &ref_lattice, const Lattice &other)
Check if ref_lattice = other*U, where U is unimodular.
std::pair< OpIterator, Eigen::Matrix3d > is_equivalent_superlattice(const Object &scel, const Object &unit, OpIterator begin, OpIterator end, double tol)
Definition: SymTools.hh:110
Main CASM namespace.
Definition: APICommand.hh:8
Eigen::MatrixXd MatrixXd
std::vector< Permutation > make_translation_permutations(const Eigen::Matrix3l &transformation_matrix, int basis_sites_in_prim)
std::pair< MasterSymGroup, SymGroupRepID > make_collective_dof_symrep(std::set< Index > const &site_indices, SupercellSymInfo const &_syminfo, DoFKey const &_key, std::vector< PermuteIterator > const &_group)
Make the matrix representation for group '_group' describing the transformation of DoF '_key' among a...
SymGroupRepID make_permutation_representation(const SymGroup &group, const xtal::UnitCellCoordIndexConverter &bijk_index_converter, const Lattice &prim_lattice, const SymGroupRepID &prim_symrep_ID)
std::string DoFKey
Definition: DoFDecl.hh:7
Eigen::Matrix3l make_hermite_normal_form(std::string hermite_normal_form_name)
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
std::string hermite_normal_form_name(const Eigen::Matrix3l &matrix)
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
Matrix< long int, 3, 3 > Matrix3l
Definition: eigen.hh:12