CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
Orbit_impl.hh
Go to the documentation of this file.
1 #include <climits>
2 
8 namespace CASM {
9  //**************************************************************************************
10 
11  template<typename ClustType>
13  prototype.set_lattice(new_home, mode);
14 
15  for(Index i = 0; i < size(); i++)
16  at(i).set_lattice(new_home, mode);
17 
18  return;
19 
20  }
21 
22 
23  //*******************************************************************************************
24  //void get_equivalent(const Array<SymOp> &sym_group);
25  //Take prototype cluster, find all of the equivalent clusters (fills orbit array)
26  //Also, fill equivalence_map
27 
28  //Apply each SymOp to prototype, check to see if result is already in the orbit array
29  // if(contains(prototype.apply_sym(sym_group.get(i))) do:
30  //If it is not in the orbit array, add it, and record the SymOp in equivalence_map
31  //If it is already in the orbit array, record the SymOp that mapped the prototype onto that cluster
32 
33  template<typename ClustType>
34  void GenericOrbit<ClustType>::get_equivalent(const SymGroup &sym_group, double tol) {
35  if(sym_group.size() == 0) {
36  std::cerr << "WARNING: In Orbit::get_equivalent, sym_group must at least have one element (identity).\n";
37  assert(0);
38  }
39 
40  Index i, j, map_ind;
41  ClustType t_cluster(prototype.home());
42  Coordinate map_shift(Eigen::Vector3d::Zero(), prototype.home(), CART);
43  Coordinate within_shift(map_shift);
44  clear();
45  equivalence_map.clear();
46 
47  prototype.within();
48  prototype.prepare_prototype();
49  // first put prototype into the orbit and preserve open space for sym_op(s) that map prototype onto itself
50  // doing resize, basically erases all work history in the past
51  this->push_back(prototype);
52  equivalence_map.resize(1);
53 
54  // go through all symmetry operation in sym_group
55  for(i = 0; i < sym_group.size(); i++) {
56  t_cluster = sym_group[i] * prototype; // apply current sym_op to prototype, using the overloaded *
57 
58  map_ind = find(t_cluster, map_shift, tol);
59 
60  //Case 1: Cluster already exists in orbit; update equivalence map to record
61  // symmetry operation that maps prototype onto equivalent cluster
62  if(map_ind < size()) {
63  if(map_ind == 0) {
64  equivalence_map[map_ind].push_back(SymOp::translation(map_shift.cart())*sym_group[i]);
65  }
66  }
67 
68  //Case 2: Identified new equivalent cluster; add it to orbit and update equivalence map
69  // to record symmetry operation that maps prototype onto equivalent cluster
70  else {
71  t_cluster.within(0, within_shift); //make sure new equivalent cluster has first site within primitive cell
72  this->push_back(t_cluster); // add it
73  SymOp tsymm(SymOp::translation((map_shift + within_shift).cart())*sym_group[i]);
74  equivalence_map.push_back(Array<SymOp>(1, tsymm));
75  }
76 
77  }
78 
79  // record symmetry info for all equivalent clusters
80  prototype.set_clust_group(equivalence_map[0]);
81  at(0).set_clust_group(equivalence_map[0]);
82  std::vector<Permutation> proto_perms(prototype.clust_group_permutations(tol));
83  SymGroupRepID perm_rep_ID(sym_group.add_empty_representation());
84  prototype.set_permute_rep(perm_rep_ID);
85  at(0).set_permute_rep(perm_rep_ID);
86  for(j = 0; j < prototype.clust_group().size(); j++)
87  prototype.clust_group()[j].set_rep(perm_rep_ID, SymPermutation(proto_perms[j]));
88  for(i = 1; i < size(); i++) {
89  equivalence_map[i][0].set_rep(perm_rep_ID, SymPermutation(proto_perms[0]));
90  for(j = 1; j < prototype.clust_group().size(); j++) {
91  equivalence_map[i].push_back(equivalence_map[i][0]*prototype.clust_group()[j]);
92  equivalence_map[i][j].set_rep(perm_rep_ID, SymPermutation(proto_perms[j]));
93  }
94  SymGroup tclust_group(prototype.clust_group());
95  tclust_group.apply_sym(equivalence_map[i][0]);
96  at(i).set_clust_group(tclust_group);
97  at(i).set_permute_rep(perm_rep_ID);
98  }
99 
100  return;
101  }
102 
103  //****************************************************************************************************
104 
105  template<typename ClustType>
107  prototype.apply_sym(op);
108  for(Index i = 0; i < size(); i++) {
109  at(i).apply_sym(op);
110  if(equivalence_map.size() < size()) continue;
111  for(Index j = 0; j < equivalence_map[i].size(); j++) {
112  equivalence_map[i][j].apply_sym(op);
113  }
114  }
115  return *this;
116  }
117 
118  //****************************************************************************************************
119  //bool contains(const Cluster &test_clust);
120  //go through all cluster in orbit array and see if test_clust is among them, accounting for translation
121  //HINT: only translate if the periodicity flag is on
122 
123  template<typename ClustType>
124  bool GenericOrbit<ClustType>::contains(const ClustType &test_clust, double tol) const {
125  ClustType tclust(test_clust);
126  for(Index i = 0; i < size(); i++) {
127  if(tclust.map_onto(at(i), tol)) {
128  return true;
129  }
130  }
131 
132  return false;
133  }
134 
135  //****************************************************************************************************
136  //bool contains(const Site &test_site);
137  //go through all cluster in orbit array and see if test_site is contained in any of them, accounting for translation
138 
139  template<typename ClustType>
140  bool GenericOrbit<ClustType>::contains(const typename ClustType::WhichCoordType &test_coord, double tol) const {
141 
142  for(Index i = 0; i < size(); i++) {
143  if(at(i).contains_periodic(test_coord, tol))
144  return true;
145  }
146 
147  return false;
148  }
149 
150  //****************************************************************************************************
151  //int find(const ClustType &test_clust);
152  //go through all cluster in orbit array and return the index of test_clust, accounting for translation
153  //HINT: only translate if the periodicity flag is on
154 
155  template<typename ClustType>
156  Index GenericOrbit<ClustType>::find(const ClustType &test_clust, double tol) const {
157  Index i;
158  ClustType tclust(test_clust);
159  for(i = 0; i < size(); i++) {
160  if(tclust.map_onto(at(i), tol))
161  break;
162  }
163  return i;
164  }
165 
166  //****************************************************************************************************
167  //int find(const ClustType &test_clust);
168  //go through all cluster in orbit array and return the index of test_clust, accounting for translation
169  //HINT: only translate if the periodicity flag is on
170 
171  template<typename ClustType>
172  Index GenericOrbit<ClustType>::find(const ClustType &test_clust, Coordinate &trans, double tol) const {
173  Index i;
174  trans.frac() = Eigen::Vector3d::Zero();
175  ClustType tclust(test_clust);
176  for(i = 0; i < size(); i++) {
177  if(tclust.map_onto(at(i), trans, tol)) {
178  break;
179  }
180  }
181  return i;
182  }
183 
184 
185  //********************************************************************
186 
187  template<typename ClustType>
189  prototype.collect_basis_info(basis, shift);
190  for(Index ne = 0; ne < size(); ne++)
191  at(ne).collect_basis_info(basis, shift);
192  }
193 
194  //********************************************************************
195 
196  template<typename ClustType>
198  prototype.collect_basis_info(basis);
199  for(Index ne = 0; ne < size(); ne++)
200  at(ne).collect_basis_info(basis);
201  }
202 
203  //********************************************************************
210  //********************************************************************
211 
212  template<typename ClustType>
213  void GenericOrbit<ClustType>::read(std::istream &stream, COORD_TYPE mode, const SymGroup &sym_group) {
214 
215  int num_clust;
216  char ch;
217 
218  ch = stream.peek();
219  while((ch != 'C') && (ch != 'c') && !stream.eof()) {
220  stream.ignore(1000, '\n');
221  ch = stream.peek();
222  }
223 
224  stream.ignore(1000, ':');
225  ch = stream.peek();
226 #ifdef DEBUG
227  std::cout << "ch in cluster is " << ch << "\n";
228 #endif //DEBUG
229  while(ch < '0' || ch > '9') {
230  stream.ignore(1, '\n');
231  ch = stream.peek();
232  }
233  stream >> num_clust;
234 
235 #ifdef DEBUG
236  std::cout << "num_clust is " << num_clust << "\n";
237 #endif //DEBUG
238 
239  for(int i = 0; i < num_clust; i++) {
240  if(i == 0) {
241  prototype.clear();
242  prototype.read(stream, mode);
243  (*this).push_back(prototype);
244  }
245  else {
246  SiteCluster tclust(prototype.home());
247  (*this).push_back(tclust);
248  (*this).back().read(stream, mode);
249  }
250  }
251  // }
252 
253  //if ( ((*this).back().max_length() > TOL) ||
254  // (((*this).back().max_length() < TOL) && ((*this).back().size() == 1)) ){
255  //This works only when reading in orbitree
256  if((*this).back().size() > 0) {
257 #ifdef DEBUG
258  std::cout << "Inside this loop the cluster is \n";
259  std::cout << (*this).back() << "\n";
260 #endif //DEBUG
261  get_equivalent(sym_group);
262  //}
263  }
264 
265  for(Index t = 0; t < size(); t++) {
266  at(t).within();
267  }
268 
269  //get_cluster_symmetry();
270 
271  return;
272  }
273 
274  //********************************************************************
275 
276  // Divide by multiplicity. Same result as evaluating correlations via orbitree.
277  template<typename ClustType>
279  std::string suffix("");
280  Array<std::string> formulae(prototype.clust_basis.size(), std::string());
281  if(size() > 1) {
282  formulae.resize(prototype.clust_basis.size(), std::string("("));
283  suffix = ")/" + std::to_string(size()) + ".0";
284  }
285 
286  for(Index ne = 0; ne < size(); ne++) {
287  for(Index nl = 0; nl < labelers.size(); nl++)
288  at(ne).clust_basis.accept(*labelers[nl]);
289  }
290 
291  for(Index nf = 0; nf < prototype.clust_basis.size(); nf++) {
292  for(Index ne = 0; ne < size(); ne++) {
293  if(!at(ne).clust_basis[nf] || (at(ne).clust_basis[nf]->formula()) == "0")
294  continue;
295  if(formulae[nf].size() > 1)
296  formulae[nf] += " + ";
297  formulae[nf] += "(" + at(ne).clust_basis[nf]->formula() + ")";
298  }
299 
300  if(formulae[nf].size() <= 1)
301  formulae[nf].clear();
302  else
303  formulae[nf] += suffix;
304  }
305  return formulae;
306  }
307 
308  //********************************************************************
309 
311  template<typename ClustType>
313 
314  Array<std::string> formulae(prototype.clust_basis.size(), std::string());
315  std::string suffix;
316  Index ib;
317 
318  //normalize by multiplicity (by convention)
319  if(size()*prototype.size() > 1) {
320  formulae.resize(prototype.clust_basis.size(), std::string("("));
321  suffix = ")/" + std::to_string(size()) + ".0";
322  }
323 
324  for(Index ne = 0; ne < size(); ne++) {
325  //std::cout << "# of translists: " << at(ne).trans_nlists().size() << "\n";
326  for(Index nt = 0; nt < at(ne).trans_nlists().size(); nt++) {
327  ib = at(ne).trans_nlist(nt).find(nlist_index);
328 
329  //std::cout << "ib is " << ib << " of " << at(ne).size() << "\n";
330  if(ib == at(ne).size())
331  continue;
332 
333  at(ne).set_nlist_inds(at(ne).trans_nlist(nt));
334 
335  for(Index nl = 0; nl < labelers.size(); nl++)
336  at(ne).clust_basis.accept(*labelers[nl]);
337 
338  for(Index nf = 0; nf < at(ne).clust_basis.size(); nf++) {
339  if(!at(ne).clust_basis[nf] || (at(ne).clust_basis[nf]->formula()) == "0")
340  continue;
341 
342  if(formulae[nf].size() > 1)
343  formulae[nf] += " + ";
344  formulae[nf] += "(" + at(ne).clust_basis[nf]->formula() + ")";
345  }
346  }
347  }
348 
349  // Make sure that formulae that evaluate to zero have an empty string.
350  for(Index nf = 0; nf < prototype.clust_basis.size(); nf++) {
351  if(formulae[nf].size() <= 1)
352  formulae[nf].clear();
353  else
354  formulae[nf] += suffix;
355  }
356  return formulae;
357  }
358 
359  //********************************************************************
360 
363  template<typename ClustType>
364  ReturnArray<std::string> GenericOrbit<ClustType>::delta_occfunc_flower_function_cpp_strings(BasisSet site_basis, // passed by value because we use it as a temporary
365  const Array<FunctionVisitor *> &labelers,
366  Index nlist_index,
367  Index b_index,
368  Index f_index) {
369 
370  Array<std::string> formulae(prototype.clust_basis.size(), std::string());
371  std::string suffix;
372  Index ib;
373  Array<Index> old_id(1, b_index), new_id(1, 0);
374  //normalize by multiplicity (by convention)
375  if(size()*prototype.size() > 1) {
376  formulae.resize(prototype.clust_basis.size(), std::string("("));
377  suffix = ")/" + std::to_string(size()) + ".0";
378  }
379 
380  for(Index ne = 0; ne < size(); ne++) {
381  //std::cout << " **** for ne = " << ne << ":\n";
382  for(Index nt = 0; nt < at(ne).trans_nlists().size(); nt++) {
383  ib = at(ne).trans_nlist(nt).find(nlist_index);
384  if(ib == at(ne).size())
385  continue;
386  //std::cout << " **** for translist: " << at(ne).trans_nlist(nt) << ":\n";
387  at(ne).set_nlist_inds(at(ne).trans_nlist(nt));
388 
389  new_id[0] = at(ne)[ib].nlist_ind();
390  site_basis.set_dof_IDs(new_id);
391  old_id = new_id;
392 
393  BasisSet quotient_basis = at(ne).clust_basis.poly_quotient_set(site_basis[f_index]);
394  for(Index nl = 0; nl < labelers.size(); nl++)
395  quotient_basis.accept(*labelers[nl]);
396 
397  for(Index nf = 0; nf < quotient_basis.size(); nf++) {
398 
399  if((quotient_basis[nf]->formula()) == "0")
400  continue;
401 
402  if(formulae[nf].size() > 1)
403  formulae[nf] += " + ";
404  formulae[nf] += "(" + quotient_basis[nf]->formula() + ")";
405  }
406  }
407  }
408 
409  // Make sure that formulae that evaluate to zero have an empty sting.
410  for(Index nf = 0; nf < prototype.clust_basis.size(); nf++) {
411  if(formulae[nf].size() <= 1)
412  formulae[nf].clear();
413  else
414  formulae[nf] += suffix;
415  }
416 
417  return formulae;
418  }
419 
420 
421  //********************************************************************
422 
423  template<typename ClustType>
425 
426  json.put_obj();
427 
428  // template<typename ClustType>
429  // class GenericOrbit : public Array<ClustType >
430  json["clusters"].put_array(size());
431  for(Index i = 0; i < size(); i++) {
432  json["clusters"][i] = at(i);
433  }
434 
435  // mutable int index;
436  json["index"] = index;
437 
438  // int permute_rep_ID, coord_rep_ID;
439  // json["permute_rep_ID"] = permute_rep_ID;
440  // json["coord_rep_ID"] = coord_rep_ID;
441 
442  // Array<GenericOrbit *> sub_cluster;
443  // This doesn't seem used right now?
444 
445  // ClustType prototype;
446  json["prototype"] = prototype;
447 
448  // Array< Array<SymOp> > equivalence_map;
449  //json["equivalence_map"] = equivalence_map;
450 
451  return json;
452  }
453 
454  //********************************************************************
455 
457  template<typename ClustType>
459  try {
460 
461  // template<typename ClustType>
462  // class GenericOrbit : public Array<ClustType >
463  clear();
464  ClustType clust(prototype);
465  // // GOING TO GENERATE THE EQUIVALENT CLUSTERS INSTEAD OF READING
466  // // THEM IN
467  // std::cout<<"Number of clusters:"<<json["clusters"].size()<<std::endl;
468  // this->resize(json["clusters"].size(), clust);
469  // for(int i = 0; i < json["clusters"].size(); i++) {
470  // std::cout<<"Working on:"<<i;
471  // CASM::from_json(at(i), json["clusters"][i]);
472  // }
473 
474  // mutable int index;
475  CASM::from_json(index, json["index"]);
476 
477  // int permute_rep_ID, coord_rep_ID;
478  // CASM::from_json(permute_rep_ID, json["permute_rep_ID"]);
479  // CASM::from_json(coord_rep_ID, json["coord_rep_ID"]);
480 
481  // Array<GenericOrbit *> sub_cluster;
482  // This doesn't seem used right now?
483 
484  // ClustType prototype;
485  //std::cout<<"Reading in the prototype cluster"<<std::endl;
486  CASM::from_json(prototype, json["prototype"]);
487  // std::cout<<"Generating the equivalent clusters"<<std::endl;
488 
489  // // Array< Array<SymOp> > equivalence_map;
490  // SymOp op(prototype.home());
491  // Array<SymOp> equiv;
492  // equivalence_map.clear();
493  // std::cout<<"Reading in the equivalence_map"<<std::endl;
494  // std::cout<<"i<"<<json["equivalence_map"].size()<<std::endl;
495  // for(int i = 0; i < json["equivalence_map"].size(); i++) {
496  // equiv.clear();
497  // std::cout<<" i:"<<i<<std::endl;
498  // std::cout<<"j<"<<json["equivalence_map"][i].size()<<std::endl;
499  // for(int j = 0; j < json["equivalence_map"][i].size(); j++) {
500  // std::cout<<" j:"<<j;
501  // CASM::from_json(op, json["equivalence_map"][i][j]);
502  // equiv.push_back(op);
503  // }
504  // equivalence_map.push_back(equiv);
505  // }
506 
507  //std::cout<<"Done with reading in the Orbit"<<std::endl;
508  }
509  catch(...) {
511  throw;
512  }
513  }
514 
515 
516 }
517 
518 
jsonParser & to_json(jsonParser &json) const
Definition: Orbit_impl.hh:424
ReturnArray< std::string > delta_occfunc_flower_function_cpp_strings(BasisSet site_basis, const Array< FunctionVisitor * > &labelers, Index nlist_index, Index b_index, Index f_index)
Definition: Orbit_impl.hh:364
ReturnArray< std::string > flower_function_cpp_strings(const Array< FunctionVisitor * > &labelers, Index nlist_index)
nlist_index is the index into the nlist for the site the flower centers on
Definition: Orbit_impl.hh:312
void read(std::istream &stream, int num_sites, COORD_TYPE mode)
static SymOp translation(const Eigen::Ref< const vector_type > &_tau)
static method to create operation that describes pure translation
Definition: SymOp.hh:35
GenericOrbit & apply_sym(const SymOp &op)
Apply symmetry to prototype and all the clusters in the orbit.
Definition: Orbit_impl.hh:106
void from_json(ClexDescription &desc, const jsonParser &json)
Index size() const
Definition: Array.hh:145
Type-safe ID object for communicating and accessing Symmetry representation info. ...
SymGroup & apply_sym(const SymOp &op)
Calls 'apply_sym' on all SymOps in the group.
Definition: SymGroup.cc:3413
void resize(Index new_N)
Definition: Array.hh:468
void from_json(const jsonParser &json)
Assumes the prototype lattice is already set.
Definition: Orbit_impl.hh:458
bool contains(const ClustType &test_clust, double tol) const
Definition: Orbit_impl.hh:124
Main CASM namespace.
Definition: complete.cpp:8
std::string to_string(ENUM val)
Return string representation of enum class.
Definition: EnumIO.hh:83
void push_back(const Site &new_site)
Definition: SiteCluster.cc:11
BasisSet poly_quotient_set(const Function *divisor) const
Definition: BasisSet.cc:163
SymPermutation describes how a symmetry operation permutes a list of 'things' For example...
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Definition: SymGroup.hh:33
double tol
SymOp is the Coordinate representation of a symmetry operation it keeps fraction (FRAC) and Cartesian...
Definition: SymOp.hh:28
Represents cartesian and fractional coordinates.
Definition: Coordinate.hh:34
EigenIndex Index
For long integer indexing:
bool accept(const FunctionVisitor &visitor)
Definition: BasisSet.cc:202
Index find(const ClustType &test_clust, double tol) const
Same as contains, but returns index of equivalent cluster that maps onto test_clust.
Definition: Orbit_impl.hh:156
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:10
ReturnArray< std::string > orbit_function_cpp_strings(const Array< FunctionVisitor * > &labelers)
returns Array of std::string, each of which is
Definition: Orbit_impl.hh:278
void get_equivalent(const SymGroup &sym_group, double tol)
Definition: Orbit_impl.hh:34
jsonParser & put_obj()
Puts new empty JSON object.
Definition: jsonParser.hh:276
void collect_basis_info(const Array< typename ClustType::WhichCoordType > &basis, const Coordinate &shift)
calls collect_basis_info on all clusters in orbit
Definition: Orbit_impl.hh:188
Coordinate_impl::FracCoordinate frac()
Set the fractional coordinate vector.
Definition: Coordinate.hh:581
void set_dof_IDs(const Array< Index > &new_IDs)
Definition: BasisSet.cc:304
void set_lattice(const Lattice &new_home, COORD_TYPE mode)
calls set_lattice on prototype, and all equivalent clusters
Definition: Orbit_impl.hh:12
SymGroupRepID add_empty_representation() const
Add a new empty representation.
Definition: SymGroup.cc:3109
jsonParser & put_array()
Puts new empty JSON array.
Definition: jsonParser.hh:285