CASM  1.1.0
A Clusters Approach to Statistical Mechanics
Structure.cc
Go to the documentation of this file.
2 
3 #include <sys/stat.h>
4 #include <sys/types.h>
5 
6 #include <boost/filesystem.hpp>
7 #include <boost/filesystem/fstream.hpp>
8 #include <exception>
9 #include <memory>
10 #include <sstream>
11 #include <stdexcept>
12 #include <string>
13 #include <vector>
14 
16 #include "casm/basis_set/DoF.hh"
19 #include "casm/casm_io/Log.hh"
28 #include "casm/external/Eigen/src/Core/Matrix.h"
29 #include "casm/misc/algorithm.hh"
34 #include "casm/symmetry/SymOp.hh"
36 
37 namespace CASM {
38 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40 
41 Structure::Structure(const fs::path &filepath) {
42  if (!fs::exists(filepath)) {
43  err_log() << "Error in Structure::Structure(const fs::path &filepath)."
44  << std::endl;
45  err_log() << " File does not exist at: " << filepath << std::endl;
46  exit(1);
47  }
48  fs::ifstream infile(filepath);
49 
51  m_structure_ptr = std::make_shared<BasicStructure>(read_struc);
52  this->generate_factor_group();
53 }
54 
55 // TODO: This is awful
57  : m_structure_ptr(std::make_shared<BasicStructure>(BasicStructure())) {}
58 
60  : m_structure_ptr(RHS.m_structure_ptr) {
62 };
63 
65  : m_structure_ptr(std::make_shared<BasicStructure>(base)) {
66  this->generate_factor_group();
67 }
68 
72  return *this;
73 }
74 
75 Structure::operator const BasicStructure &() const { return this->structure(); }
76 
77 //***********************************************************
78 
80  m_basis_perm_rep_ID = RHS.m_basis_perm_rep_ID; // this *should* work
81  m_site_dof_symrep_IDs = RHS.m_site_dof_symrep_IDs; // this *should* work
84 }
85 
86 //***********************************************************
87 
91 
92  // Don't copy a MasterSymGroup or you'll have bad luck
93  xtal::SymOpVector factor_group_operations = xtal::make_factor_group(*this);
94  for (const xtal::SymOp &op : factor_group_operations) {
96  }
97 
99 
102 
103  return;
104 }
105 
106 //************************************************************
108 
109 //************************************************************
111  return factor_group().point_group();
112 }
113 
114 //***********************************************************
115 
118 }
119 
120 //***********************************************************
121 
123  return m_basis_perm_rep_ID;
124 }
125 
126 //************************************************************
127 
128 std::vector<SymGroupRepID> Structure::occupant_symrep_IDs() const {
129  return this->m_occupant_symrep_IDs;
130 }
131 
132 std::vector<std::map<DoFKey, SymGroupRepID>> Structure::site_dof_symrep_IDs()
133  const {
134  return this->m_site_dof_symrep_IDs;
135 }
136 
138  const std::string dof_name) const {
139  return this->m_global_dof_symrep_IDs.at(dof_name);
140 }
141 
143  this->m_occupant_symrep_IDs.clear();
144  for (const Site &s : this->basis()) {
145  this->m_occupant_symrep_IDs.emplace_back(
146  SymGroupRepID::identity(s.allowed_occupants().size()));
147  }
148  return;
149 }
150 
152  this->m_site_dof_symrep_IDs =
153  std::vector<std::map<DoFKey, SymGroupRepID>>(this->basis().size());
154 }
155 
156 // This function gets the permutation representation of the
157 // factor group operations of the structure. It first applies
158 // the factor group operation to the structure, and then tries
159 // to map the new position of the basis atom to the various positions
160 // before symmetry was applied. It only checks the positions after
161 // it brings the basis within the crystal.
163  std::string clr(100, ' ');
164  if (factor_group().size() <= 0) {
165  err_log() << "ERROR in generate_basis_permutation_representation"
166  << std::endl;
167  err_log() << "Factor group is empty." << std::endl;
168  ;
169  exit(1);
170  }
171 
172  std::vector<UnitCellCoord> sitemap;
173 
175 
177  for (Index b = 0; b < basis().size(); ++b) {
178  for (auto const &dof : basis()[b].dofs()) {
179  this->m_site_dof_symrep_IDs[b][dof.first] =
181  }
182  }
183 
184  // The sitemap specifies that op*basis(b) -> sitemap[b] (which is a
185  // UnitCellCoord) The new dofs of site specified by UCC sitemap[b] will be
186  // transformations of the dofs that previously resided at basis(b). As such,
187  // for dofs, we use the inverse permutation and
188  // basis()[b].symrep(doftype.name()) =
189  // basis()[b].dof(doftype.name()).basis().transpose()
190  // * doftype.symop_to_matrix(op)
191  // * basis()[sitemap[b].sublattice()].dof(doftype.name().basis())
193  for (Index s = 0; s < m_factor_group.size(); ++s) {
194  auto const &op = m_factor_group[s];
195 
196  sitemap = xtal::symop_site_map(op, *this);
197  op.set_rep(m_basis_perm_rep_ID, SymBasisPermute(op, lattice(), sitemap));
198 
199  for (Index b = 0; b < basis().size(); ++b) {
200  // copy_aply(symop,dofref_from) = P.permute(dofref_to);
201  auto const &dofref_to = basis()[sitemap[b].sublattice()].occupant_dof();
202  auto const &dofref_from = basis()[b].occupant_dof();
203 
204  auto &symrep_from = this->m_occupant_symrep_IDs[b];
206 
207  if (eq(adapter::Adapter<xtal::SymOp, CASM::SymOp>()(op), dofref_to)) {
208  if (symrep_from.is_identity()) {
209  if (!eq.perm().is_identity()) {
210  symrep_from = m_factor_group.allocate_representation();
211  Index s2;
212  for (s2 = 0; s2 < s; ++s2) {
214  symrep_from,
215  SymPermutation(sequence<Index>(0, dofref_from.size() - 1)));
216  }
217  m_factor_group[s2].set_rep(symrep_from,
218  SymPermutation(eq.perm().inverse()));
219  }
220  } else {
221  op.set_rep(symrep_from, SymPermutation(eq.perm().inverse()));
222  }
223  } else
224  throw std::runtime_error(
225  "In Structure::_generate_basis_symreps(), Sites originally "
226  "identified as equivalent cannot be mapped by symmetry.");
227  }
228 
229  for (auto const &dof_key : xtal::continuous_local_dof_types(*this)) {
230  for (Index from_b = 0; from_b < basis().size(); ++from_b) {
231  if (!basis()[from_b].has_dof(dof_key)) continue;
232 
233  xtal::DoFSet const &_dofref_from = basis()[from_b].dof(dof_key);
234 
235  Index to_b = sitemap[from_b].sublattice();
236  xtal::DoFSet const &_dofref_to = basis()[to_b].dof(dof_key);
237 
238  // Transform the xtal::SiteDoFSet to the CASM::DoFSet version
239  CASM::DoFSet dofref_from =
241  _dofref_from, SymGroupRepID(), from_b);
242 
243  CASM::DoFSet dofref_to =
245  _dofref_to, SymGroupRepID(), to_b);
246 
247  DoFIsEquivalent eq(dofref_from);
248  // TODO
249  // Calling the adapter here, because we said we don't want anything
250  // outside of crystallography to invoke crystallography/Adapter.hh
251  if (!eq(adapter::Adapter<xtal::SymOp, CASM::SymOp>()(op), dofref_to)) {
252  throw std::runtime_error(
253  "While generating symmetry representation for local DoF \"" +
254  dof_key +
255  "\", a symmetry operation was identified that invalidates the "
256  "degree of freedom. " +
257  "Degrees of freedom must be fully specified before performing "
258  "symmetry analyses.");
259  }
260 
261  SymGroupRepID from_symrep_ID =
262  this->site_dof_symrep_IDs()[from_b][dof_key];
263  op.set_rep(from_symrep_ID, SymMatrixXd(eq.U()));
264  }
265  }
266  }
267 
268  return;
269 }
270 
271 //***********************************************************
272 
273 // TODO: Simplify the DoF equivalence checks. You can probably completely erase
274 // the comparators in basis_set in favor of the ones in the xtal namespace
276  if (factor_group().size() <= 0) {
277  err_log() << "ERROR in generate_global_dof_representations" << std::endl;
278  err_log() << "Factor group is empty." << std::endl;
279  exit(1);
280  }
281  for (auto const &name_dof_pr : this->structure().global_dofs()) {
282  std::string dof_name = name_dof_pr.first;
283  const xtal::DoFSet &dof = name_dof_pr.second;
284 
285  this->m_global_dof_symrep_IDs[dof_name] =
287 
288  for (auto const &op : m_factor_group) {
289  /* DoFIsEquivalent eq(dof.second); */
290  xtal::DoFSetIsEquivalent_f dof_equals(dof, TOL);
291 
292  xtal::DoFSet transformed_dof = sym::copy_apply(
294  if (!dof_equals(transformed_dof)) {
295  throw std::runtime_error(
296  "While generating symmetry representation for global DoF \"" +
297  dof_name +
298  "\", a symmetry operation was identified that invalidates the "
299  "degree of freedom. " +
300  "Degrees of freedom must be fully specified before performing "
301  "symmetry analyses.");
302  }
303  Eigen::MatrixXd basis_change_representation;
304  try {
305  basis_change_representation = xtal::dofset_transformation_matrix(
306  dof.basis(), transformed_dof.basis(), TOL);
307  } catch (std::runtime_error &e) {
308  throw std::runtime_error(std::string(e.what()) +
309  " Attempted to make representation for " +
310  dof_name + ".");
311  }
312  op.set_rep(this->m_global_dof_symrep_IDs.at(dof_name),
313  SymMatrixXd(basis_change_representation));
314  }
315  }
316 }
317 //***********************************************************
318 
322 std::vector<std::vector<Index>> make_index_converter(
323  const Structure &struc, std::vector<xtal::Molecule> mol_list) {
324  std::vector<std::vector<Index>> converter(struc.basis().size());
325 
326  for (Index i = 0; i < struc.basis().size(); i++) {
327  converter[i].resize(struc.basis()[i].occupant_dof().size());
328 
329  for (Index j = 0; j < struc.basis()[i].occupant_dof().size(); j++) {
330  converter[i][j] =
331  CASM::find_index(mol_list, struc.basis()[i].occupant_dof()[j]);
332  }
333  }
334 
335  return converter;
336 }
337 
341 std::vector<std::vector<Index>> make_index_converter(
342  const Structure &struc, std::vector<std::string> mol_name_list) {
343  std::vector<std::vector<Index>> converter(struc.basis().size());
344 
345  for (Index i = 0; i < struc.basis().size(); i++) {
346  converter[i].resize(struc.basis()[i].occupant_dof().size());
347 
348  for (Index j = 0; j < struc.basis()[i].occupant_dof().size(); j++) {
349  converter[i][j] = CASM::find_index(
350  mol_name_list, struc.basis()[i].occupant_dof()[j].name());
351  }
352  }
353 
354  return converter;
355 }
356 
363 std::vector<std::vector<Index>> make_index_converter_inverse(
364  const Structure &struc, std::vector<std::string> mol_name_list) {
365  std::vector<std::vector<Index>> converter_inv(struc.basis().size());
366 
367  for (Index i = 0; i < struc.basis().size(); i++) {
368  converter_inv[i].resize(mol_name_list.size());
369 
370  std::vector<std::string> site_occ_name_list;
371  for (Index j = 0; j < struc.basis()[i].occupant_dof().size(); j++) {
372  site_occ_name_list.push_back(struc.basis()[i].occupant_dof()[j].name());
373  }
374 
375  for (Index j = 0; j < mol_name_list.size(); j++) {
376  converter_inv[i][j] =
377  CASM::find_index(site_occ_name_list, mol_name_list[j]);
378  }
379  }
380 
381  return converter_inv;
382 }
383 
384 std::map<DoFKey, DoFSetInfo> global_dof_info(Structure const &_struc) {
385  std::map<DoFKey, DoFSetInfo> result;
386  for (auto const &dof : _struc.structure().global_dofs()) {
387  result.emplace(dof.first,
389  dof.second, _struc.global_dof_symrep_ID(dof.first))
390  .info());
391  }
392  return result;
393 }
394 
395 std::map<DoFKey, std::vector<DoFSetInfo>> local_dof_info(
396  Structure const &_struc) {
397  std::map<DoFKey, std::vector<DoFSetInfo>> result;
398 
399  for (DoFKey const &type : xtal::continuous_local_dof_types(_struc)) {
400  std::vector<CASM::DoFSetInfo> tresult(
401  _struc.basis().size(),
403  SymGroupRepID(),
404  Eigen::MatrixXd::Zero(DoF::BasicTraits(type).dim(), 0)));
405 
406  for (Index b = 0; b < _struc.basis().size(); ++b) {
407  if (_struc.basis()[b].has_dof(type)) {
408  const auto &dofset = _struc.basis()[b].dof(type);
410  dofset, _struc.site_dof_symrep_IDs()[b].at(type), b)
411  .info();
412  }
413  }
414  result.emplace(type, std::move(tresult));
415  }
416  return result;
417 }
418 
420  Lattice const &super_lattice) {
421  // Structure data needs to be reorganized for SupercellSymInfo construction
422 
423  // map of global DoFKey -> SymGroupRepID
424  std::map<DoFKey, SymGroupRepID> global_dof_symrep_IDs;
425  for (auto const &key : xtal::global_dof_types(prim)) {
426  global_dof_symrep_IDs.emplace(
427  std::make_pair(key, prim.global_dof_symrep_ID(key)));
428  }
429 
430  // map of site DoFKey -> std::vector<SymGroupRepID>
431  std::map<DoFKey, std::vector<SymGroupRepID>> local_dof_symrep_IDs;
432  for (auto const &key : xtal::continuous_local_dof_types(prim)) {
433  std::vector<SymGroupRepID> treps(prim.basis().size());
434  for (Index b = 0; b < prim.basis().size(); ++b) {
435  if (prim.basis()[b].has_dof(key))
436  treps[b] = prim.site_dof_symrep_IDs()[b][key];
437  }
438  local_dof_symrep_IDs.emplace(std::make_pair(key, std::move(treps)));
439  }
440 
441  return SupercellSymInfo(
442  prim.lattice(), super_lattice, prim.basis().size(), prim.factor_group(),
443  prim.basis_permutation_symrep_ID(), global_dof_symrep_IDs,
444  prim.occupant_symrep_IDs(), local_dof_symrep_IDs);
445 }
446 } // namespace CASM
std::set< std::string > & s
Specifies traits of (possibly) anisotropic crystal properties.
Class for checking equivalence of two DoFSet objects, with respect to symmetry transformations.
Eigen::MatrixXd const & U() const
SymGroupRepID allocate_representation() const
Add a new empty representation.
Definition: SymGroup.cc:694
void sort()
Sort SymOp in the SymGroup.
Definition: SymGroup.cc:737
void set_rep(SymGroupRepID _rep_ID, SymOpRepresentation const &_op_rep, Index op_index) const
Definition: SymGroup.cc:479
const SymGroup & point_group() const
Definition: SymGroup.cc:409
void push_back(const SymOp &op)
Definition: SymGroup.cc:400
SymGroupRep const & representation(SymGroupRepID i) const
Const access of alternate Representations of a SymGroup.
Definition: SymGroup.cc:717
Class for checking equivalence of two OccupantDoF objects, with respect to symmetry transformations.
Permutation const & perm() const
Permutation inverse() const
Construct permutation that undoes the permutation performed by 'this'.
Definition: Permutation.cc:111
bool is_identity() const
Checks whether permutation is identity (i.e., m_perm_aray[i]==i for all i)
Definition: Permutation.cc:89
Structure specifies the lattice and atomic basis of a crystal.
Definition: Structure.hh:30
SymGroupRepID m_basis_perm_rep_ID
This holds the representation id of the permutation representation.
Definition: Structure.hh:43
std::vector< SymGroupRepID > m_occupant_symrep_IDs
Hold the SymRepIDs for the occupant DoF, one for each of the basis sites.
Definition: Structure.hh:46
const xtal::BasicStructure & structure() const
Definition: Structure.hh:92
std::vector< std::map< DoFKey, SymGroupRepID > > site_dof_symrep_IDs() const
Definition: Structure.cc:132
void _generate_global_symreps()
Obtain global dof symreps of factor_group.
Definition: Structure.cc:275
const SymGroup & point_group() const
Definition: Structure.cc:110
const Lattice & lattice() const
Definition: Structure.hh:100
SymGroupRep const * basis_permutation_symrep() const
Definition: Structure.cc:116
std::shared_ptr< const xtal::BasicStructure > m_structure_ptr
Definition: Structure.hh:85
MasterSymGroup m_factor_group
Definition: Structure.hh:40
const std::vector< xtal::Site > & basis() const
Definition: Structure.hh:102
void generate_factor_group()
Definition: Structure.cc:88
void _generate_basis_symreps()
Definition: Structure.cc:162
SymGroupRepID global_dof_symrep_ID(const std::string dof_name) const
Definition: Structure.cc:137
void _reset_site_dof_symrep_IDs()
Definition: Structure.cc:151
std::vector< std::map< DoFKey, SymGroupRepID > > m_site_dof_symrep_IDs
Definition: Structure.hh:50
void copy_attributes_from(const Structure &RHS)
copy all non-derived members
Definition: Structure.cc:79
Structure & operator=(const Structure &RHS)
Definition: Structure.cc:69
const MasterSymGroup & factor_group() const
Definition: Structure.cc:107
SymGroupRepID basis_permutation_symrep_ID() const
Definition: Structure.cc:122
std::unordered_map< std::string, SymGroupRepID > m_global_dof_symrep_IDs
Definition: Structure.hh:54
std::vector< SymGroupRepID > occupant_symrep_IDs() const
Definition: Structure.cc:128
void _reset_occupant_symrep_IDs()
Definition: Structure.cc:142
A class that collects all symmetry information for for performing symmetry transformations on the sit...
SymBasisPermute describes how a symmetry operation permutes atoms in a basis.
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Definition: SymGroup.hh:42
void set_lattice(const Lattice &new_lat)
Lattice used for periodic comparisons (for instance, to generate multiplcation table)
Definition: SymGroup.cc:814
SymGroupRep is an alternative representation of a SymGroup for something other than real space....
Definition: SymGroupRep.hh:31
Type-safe ID object for communicating and accessing Symmetry representation info.
static SymGroupRepID identity(Index dim)
Static function to construct an ID for identity representations.
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,...
BasicStructure specifies the lattice and atomic basis of a crystal.
std::map< DoFKey, DoFSet > const & global_dofs() const
static BasicStructure from_poscar_stream(std::istream &poscar_stream, double tol=TOL)
Eigen::MatrixXd const & basis() const
Matrix that relates DoFSet variables to a conventional coordiante system.
Definition: DoFSet.hh:67
std::vector< DoFKey > continuous_local_dof_types(BasicStructure const &_struc)
std::vector< UnitCellCoord > symop_site_map(SymOp const &_op, BasicStructure const &_struc)
To which site a SymOp transforms each basis site.
std::vector< DoFKey > global_dof_types(BasicStructure const &_struc)
ConfigIO::GenericConfigFormatter< jsonParser > structure()
Definition: ConfigIO.cc:766
xtal::Coordinate copy_apply(const xtal::SymOp &op, xtal::Coordinate coord)
Copy and apply SymOp to a Coordinate.
Definition: Coordinate.cc:354
std::vector< SymOp > make_factor_group(const BasicStructure &struc, double tol=TOL)
Eigen::MatrixXd dofset_transformation_matrix(const Eigen::MatrixXd &from_basis, const Eigen::MatrixXd &to_basis, double tol)
Create the symmtery representation for going from one basis to another.
Definition: DoFSet.cc:52
std::vector< SymOp > SymOpVector
Main CASM namespace.
Definition: APICommand.hh:8
Eigen::MatrixXd MatrixXd
Index find_index(Iterator begin, Iterator end, const T &value)
Equivalent to std::distance(begin, std::find(begin, end, value))
Definition: algorithm.hh:24
const double TOL
Definition: definitions.hh:30
std::string DoFKey
Definition: DoFDecl.hh:7
std::vector< std::vector< Index > > make_index_converter(const Structure &struc, std::vector< xtal::Molecule > mol_list)
Definition: Structure.cc:322
std::vector< std::vector< Index > > make_index_converter_inverse(const Structure &struc, std::vector< std::string > mol_name_list)
Definition: Structure.cc:363
std::map< DoFKey, std::vector< CASM::DoFSetInfo > > local_dof_info(Structure const &_struc)
Definition: Structure.cc:395
SupercellSymInfo make_supercell_sym_info(Structure const &prim, Lattice const &super_lattice)
Definition: Structure.cc:419
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
std::map< DoFKey, CASM::DoFSetInfo > global_dof_info(Structure const &_struc)
Definition: Structure.cc:384
Log & err_log()
Definition: Log.hh:426
Definition: stream_io.hh:24