CASM  1.1.0
A Clusters Approach to Statistical Mechanics
ParamComposition.cc
Go to the documentation of this file.
2 
3 #include <unistd.h>
4 
5 #include <cmath>
6 #include <map>
7 #include <set>
8 
9 #include "casm/casm_io/Log.hh"
11 #include "casm/misc/algorithm.hh"
12 
13 namespace CASM {
14 
15 //*************************************************************
16 // GENERATE Routines
17 
18 namespace Local {
19 // Takes set of subsystem compomponents, given as [set of indices], and set of
20 // sublattices, given as the pairs {allowed components [set of indeces],
21 // multiplicity [index]}, and total number of components in the larger system.
22 // Returns the set of extreme integer compositions for the subsystem
23 static std::vector<Eigen::VectorXi> _sub_extremes(
24  std::set<Index> const &subcomponents,
25  std::map<std::set<Index>, Index> const &sublats, Index dim) {
26  std::vector<Eigen::VectorXi> result;
27 
28  std::vector<Index> compon(subcomponents.begin(), subcomponents.end());
29 
30  // Count over k-combinations of subsystem components, where k is number of
31  // sublattices
32  Index k = sublats.size();
33  Index n = compon.size();
34  Index ncomb = nchoosek(n, k);
35 
36  // Combination is stored in 'combo' vector
37  for (Index ic = 0; ic < ncomb; ++ic) {
38  std::vector<Index> tcombo = index_to_kcombination(ic, k);
39 
40  std::vector<Index> combo(tcombo.rbegin(), tcombo.rend());
41 
42  // Consider each permutation of the k-combination elements, which specifies
43  // the 'direction' in which to maximize the composition
44  std::vector<Index> priority;
45  for (Index c : combo) priority.push_back(compon[c]);
46 
47  // std::cout << "combo: " << combo << "\n";
48  do {
49  // std::cout << " priority: " << priority << "\n";
50  // Maximize composition in direction specified by the current 'priority'
51  Eigen::VectorXi tend(Eigen::VectorXi::Zero(dim));
52  bool success = false;
53  for (auto const &sublat : sublats) {
54  success = false;
55  for (Index i : priority) {
56  if (sublat.first.count(i)) {
57  tend[i] +=
58  sublat.second; // increment by multiplicity of the sublattice
59  success = true;
60  break;
61  }
62  }
63  if (!success) break;
64  }
65  // Keep unique extrema
66  if (success && !contains(result, tend)) result.push_back(tend);
67 
68  // std::cout << "tend_members.size(): " << tend_members.size() << "\n";
69 
70  } while (next_permutation(
71  priority.begin(),
72  priority.end())); // repeat the above for all permutations of priority
73  }
74 
75  // std::cout << "sub_max:\n";
76  // for(auto const & el : result)
77  // std::cout << el.transpose() << "\n";
78  // std::cout << "\n";
79  return result;
80 }
81 
82 //*************************************************************
83 
84 static std::map<std::set<Index>, std::map<std::set<Index>, Index> >
86  std::map<std::set<Index>, std::map<std::set<Index>, Index> > result;
87 
88  std::vector<std::string> compon =
90 
91  // Convert _allowed_occs to occ_map, which has a pair for each unique
92  // sublattice, consisting of the indices of its allowed components and its
93  // multiplicity
94  std::map<std::set<Index>, Index> occ_map;
95  for (auto const &list : _allowed_occs) {
96  std::set<Index> tocc;
97  for (auto const &occ : list) tocc.insert(find_index(compon, occ));
98  auto it = occ_map.find(tocc);
99  if (it != occ_map.end())
100  ++(it->second);
101  else
102  occ_map[tocc] = 1;
103  }
104 
105  // std::cout << "occ_map: \n";
106  // for(auto const& occ : occ_map){
107  // for(Index i : occ.first){
108  // std::cout << " " << i;
109  //}
110  // std::cout << ": " << occ.second << "\n";
111  //}
112 
113  // Use flooding algorithm to partition unique sublattices into chemically
114  // independent subsystems
115 
116  // sublattices that have been partitioned
117  std::set<Index> visited;
118 
119  // A chemical subsystem is a graph with species as nodes. Each sublattice is a
120  // fully connected subgraph. Traverse the edges implied by this assumption to
121  // find the nodes belong to the connected subgraph associated with each
122  // species. Loop over all species and record the sublattices that generate
123  // each subgraph thus obtained
124  for (Index i = 0; i < compon.size() && visited.size() < compon.size(); ++i) {
125  // Queue of nodes from which to continue search
126  std::set<Index> q({i});
127 
128  // Set of nodes in the current subgraph
129  std::set<Index> s;
130 
131  if (visited.count(i)) continue;
132 
133  // tmap will hold the sublattices for the independent subsystem
134  std::map<std::set<Index>, Index> tmap;
135 
136  while (!q.empty()) {
137  Index j = *q.begin();
138  q.erase(q.begin());
139  if (!visited.count(j)) {
140  visited.insert(j);
141  // Loop over sublattices
142  for (auto const &list : occ_map) {
143  // If searched species 'j' is allowed at this sublattice, add its
144  // allowed species to the queue and to the set of connected nodes Add
145  // the sublattice to the independent subsystem
146  if (list.first.count(j)) {
147  q.insert(list.first.begin(), list.first.end());
148  s.insert(list.first.begin(), list.first.end());
149  tmap.emplace(list);
150  }
151  }
152  }
153  }
154  result[s] = tmap;
155  }
156 
157  // std::cout << "subsystems result: \n";
158  // for(auto const& sub : result){
159  // for(Index i : sub.first){
160  // std::cout << " " << i;
161  //}
162  // std::cout << " ::\n";
163  // for(auto const& occ : sub.second){
164  // for(Index i : occ.first){
165  // std::cout << " " << i;
166  // }
167  // std::cout << ": " << occ.second << "\n";
168  //}
169  // std::cout << "\n";
170  //}
171 
172  return result;
173 }
174 
175 } // namespace Local
176 
177 //*************************************************************
178 
179 std::vector<std::string> ParamComposition::string_components(
180  ParamComposition::AllowedOccupants const &_allowed_occs) {
181  std::vector<std::string> result;
182  for (auto const &site : _allowed_occs) {
183  for (auto const &occ : site) {
184  if (!contains(result, occ)) {
185  result.push_back(occ);
186  }
187  }
188  }
189  return result;
190 }
191 
192 //---------------------------------------------------------------------------
193 
196  : m_allowed_occs(std::move(_allowed_occs)), m_prim_end_members(0, 0) {
198  m_comp.resize(2);
199  m_comp[0].resize(0, 0);
200  m_comp[1].resize(0, 0);
201  m_origin.resize(0);
202  m_rank_of_space = -1;
203 }
204 
207  const Eigen::MatrixXd &transf_mat, const Eigen::VectorXd &_origin,
208  const int &_rank_of_space, const int &COMP_TYPE)
209  : m_allowed_occs(std::move(_allowed_occs)) {
211  m_rank_of_space = _rank_of_space;
212  m_origin = _origin;
213  m_comp.resize(2);
214  if (COMP_TYPE == PARAM_COMP) {
216  m_comp[NUMBER_ATOMS] = m_comp[PARAM_COMP].inverse();
217  } else if (COMP_TYPE == NUMBER_ATOMS) {
219  m_comp[PARAM_COMP] = m_comp[NUMBER_ATOMS].inverse();
220  }
222 };
223 
224 //*************************************************************
225 /* GENERATE_END_MEMBERS
226 
227  End members are generated by assigning priority values to each
228  component. Based on the priority value, the number of atoms for
229  every component is maximized. The routine then iterates thorough
230  all possible permutations of the priority values to generate all
231  possible end members
232 */
233 //*************************************************************
234 
236  std::map<std::set<Index>, std::map<std::set<Index>, Index> > subsystems =
238 
239  std::vector<Eigen::VectorXi> tresult(
240  1, Eigen::VectorXi::Zero(components().size()));
241 
242  for (auto const &subsystem : subsystems) {
243  std::vector<Eigen::VectorXi> tsubs = Local::_sub_extremes(
244  subsystem.first, subsystem.second, components().size());
245  std::vector<Eigen::VectorXi> tresult2;
246  tresult2.reserve(tresult.size() * tsubs.size());
247  for (auto const &v1 : tresult) {
248  for (auto const &v2 : tsubs) {
249  tresult2.push_back(v1 + v2);
250  }
251  }
252  std::swap(tresult, tresult2);
253  }
254 
255  std::map<Index, std::vector<Eigen::VectorXi> > tsort;
256  for (auto const &v : tresult) {
257  tsort[v.squaredNorm()].push_back(v);
258  }
259 
260  // Store tsort as an Eigen::MatrixXd
261  // makes it easier to find the rank of the space
262  m_prim_end_members.resize(tresult.size(), components().size());
263  Index l = 0;
264  for (auto it = tsort.rbegin(); it != tsort.rend(); ++it) {
265  // std::cout << "sqnorm " << it->first << " has " << it->second.size() <<
266  // "\n";
267  for (auto const &el : it->second) {
268  m_prim_end_members.row(l++) = el.cast<double>().transpose();
269  }
270  }
271 }
272 
273 //---------------------------------------------------------------------------
274 
275 //*********************************************************************
276 /* GENERATE_COMPOSITION_SPACE
277 
278  generates all possible composition axes that result in positive
279  values of the parametric composition.
280  ALGORITHM:
281  - start by finding the rank of the space that user has defined
282  in the PRIM
283  - pick one of the end_members as the origin. To enumerate all
284  possible axes, we loop through all possible end_members
285  - (rank-1) number of end_members are picked as spanning end
286  members from the remaining list of end_members that we get
287  from the PRIM
288  - A composition object is calculated that is then used to
289  calculated the parametric Composition given the current
290  choice of end members and origin. If it results in positive
291  numbers for all the end members that are listed for the PRIM,
292  this set of (origin,spanning end members) is pushed back onto
293  the allowed list of composition axes
294  - The process is repeated for all such unique combinations of
295  (origin, spanning end members)
296  */
297 //*********************************************************************
298 
300  // Eigen object to do the QR decomposition of the list of prim_end_members
301  Eigen::FullPivHouseholderQR<Eigen::MatrixXd> qr(m_prim_end_members);
302  Eigen::VectorXd torigin; // temp origin
303  Eigen::VectorXd test_comp;
304 
305  // If there is already a set of enumerated spaces for this
306  // Composition object
307  if (m_allowed_list.size() != 0) {
308  std::cerr << "WARNING in ParamComposition::generate_composition_space, "
309  "your allowed_list is non-empty. If you are not careful,you "
310  "may end up with repeats of allowed composition axes"
311  << std::endl;
312  }
313 
314  // calculate the rank of the space.
315  // NOTE to the wise: # of spanning members = rank-1
316  m_rank_of_space = qr.rank();
317  if (verbose) log() << "Rank of space : " << m_rank_of_space << std::endl;
318 
319  // Count over K-combinations of end members, for each K-combination, select
320  // one as origin and the rest as axes
322  Index N = m_prim_end_members.rows();
323  Index ncomb = nchoosek(N, K);
324  Eigen::MatrixXd tmembers(m_prim_end_members.cols(), K);
325 
326  // Combination is stored in 'combo' vector
327  std::vector<Index> combo;
328 
329  // set of spanning end members
330  std::vector<Eigen::VectorXd> tspanning;
331  for (Index c = 0; c < ncomb; ++c) {
332  combo = index_to_kcombination(c, K);
333  for (Index i = 0; i < K; ++i) {
334  tmembers.col(i) = m_prim_end_members.row(combo[i]).transpose();
335  }
336  if (c > 100000 && m_allowed_list.size() > 0) break;
337  if (qr.compute(tmembers).rank() < K) continue;
338 
339  if (verbose) {
340  double p = round(1e4 * double(c) / double(ncomb)) / 100.;
341  log() << "combo #" << c << ": " << combo << std::endl;
342  log() << "Found " << m_allowed_list.size() << std::endl;
343  log() << p << "% complete. Considering possible origins for set \n"
344  << tmembers << std::endl;
345  }
346 
347  // loop through all the end members and start them off as the origin
348  for (Index i_o = 0; i_o < K; ++i_o) {
349  torigin = tmembers.col(i_o);
350 
351  if (verbose)
352  log() << "The origin is: " << torigin.transpose() << "\n---"
353  << std::endl;
354 
355  // after picking origin, see if remaining end members span the space
356  // end members to span the space. Only keep those combinations
357  // that result in positive compositions
358  tspanning.clear();
359  for (Index j = 0; j < K; ++j) {
360  if (j != i_o) {
361  tspanning.push_back(tmembers.col(j) - torigin);
362  }
363  }
364 
365  // initialize a ParamComposition object with these spanning vectors and
366  // origin
367  ParamComposition tcomp = calc_composition_object(torigin, tspanning);
368 
369  // loop through end members and see what the values of the compositions
370  // works out to
371  if (verbose) log() << "Calculated compositions:" << std::endl;
372 
373  // flag to test for positive composition axes
374  bool is_positive = true;
375 
376  for (Index j = 0; is_positive && j < m_prim_end_members.rows(); j++) {
377  // Calculates the composition value given the previously
378  // initialized Composition object
379  test_comp = tcomp.calc(m_prim_end_members.row(j), NUMBER_ATOMS);
380  if (verbose)
381  log() << m_prim_end_members.row(j) << " : " << test_comp.transpose()
382  << std::endl;
383 
384  for (Index k = 0; k < test_comp.size(); k++) {
385  // if the calculated parametric composition value is either
386  // less than 0 or is nan(this will occur if the current set
387  // of origin and spanning end members form a subspace in
388  // the composition space for this PRIM)
389  if (test_comp(k) < -TOL) {
390  is_positive = false;
391  break;
392  }
393  }
394  }
395  if (is_positive) {
396  // push back this composition object, its good!
397  m_allowed_list.push_back(tcomp);
398  }
399  }
400  }
401  if (verbose)
402  log() << " "
403  " "
404  << std::endl;
405 }
406 
407 //---------------------------------------------------------------------------
408 
409 //*************************************************************
410 // PRINT Routines
412  std::ostream &stream, const int &stream_width) const {
413  int composition_var = (int)'a';
414  std::stringstream tstr;
415  for (Index i = 0; i < components().size(); i++) {
416  bool first_char = true;
417  tstr << components()[i] << "(";
418  if (!almost_zero(m_origin(i))) {
419  first_char = false;
420  tstr << m_origin(i);
421  }
422  for (int j = 0; j + 1 < (m_rank_of_space); j++) {
423  if (almost_zero(m_comp[PARAM_COMP](i, j))) {
424  continue;
425  }
426  if (almost_zero(m_comp[PARAM_COMP](i, j) - 1)) {
427  if (first_char) {
428  tstr << (char)(composition_var + j);
429  first_char = false;
430  } else {
431  tstr << '+' << (char)(composition_var + j);
432  }
433  } else if (almost_zero(m_comp[PARAM_COMP](i, j) + 1)) {
434  tstr << '-' << (char)(composition_var + j);
435  first_char = false;
436  } else {
437  stream << m_comp[PARAM_COMP](i, j) << (char)(composition_var + j);
438  first_char = false;
439  }
440  }
441  tstr << ")";
442  }
443 
444  stream << tstr.str().c_str();
445 
446  return;
447 }
448 
449 //---------------------------------------------------------------------------
450 
452  std::ostream &stream,
453  const int &stream_width) const {
454  std::stringstream tstr;
455  for (EigenIndex i = 0; i < member.size(); i++) {
456  if (almost_zero(member(i))) {
457  continue;
458  }
459  if (almost_zero(member(i) - 1)) {
460  tstr << components()[i];
461  } else {
462  tstr << components()[i] << int(member(i));
463  }
464  }
465  stream << std::setw(stream_width) << tstr.str().c_str();
466 }
467 
468 //---------------------------------------------------------------------------
469 
470 void ParamComposition::print_origin_formula(std::ostream &stream,
471  const int &stream_width) const {
472  print_member_formula(m_origin, stream, stream_width);
473 }
474 
475 //---------------------------------------------------------------------------
476 
477 void ParamComposition::print_composition_axes(std::ostream &stream) const {
478  stream << "Number of choices of composition axes: " << m_allowed_list.size()
479  << std::endl;
480  // Print Header: ORIGIN, <COMPOUNDS AT THE ENDS OF DIFFERENT AXES> , GENERAL
481  // FORMULA
482 
483  stream << std::setw(10) << "INDEX";
484  stream << std::setw(10) << "ORIGIN";
485  for (int i = 0; i + 1 < m_rank_of_space; i++) {
486  stream << std::setw(10) << (char)((int)'a' + i);
487  }
488  stream << " ";
489  stream << "GENERAL FORMULA";
490  stream << std::endl;
491 
492  stream << std::setw(10) << " ---";
493  stream << std::setw(10) << " ---";
494  for (int i = 0; i < (m_rank_of_space - 1); i++) {
495  stream << std::setw(10) << " ---";
496  }
497  stream << " ";
498  stream << "---" << std::endl;
499 
500  for (Index i = 0; i < m_allowed_list.size(); i++) {
501  stream << std::setw(10) << i;
502  m_allowed_list[i].print_origin_formula(stream, 10);
503  std::vector<Eigen::VectorXd> allowed_spanning_end_members;
504  allowed_spanning_end_members = m_allowed_list[i].spanning_end_members();
505  for (Index j = 0; j < allowed_spanning_end_members.size(); j++) {
506  print_member_formula(allowed_spanning_end_members[j], stream, 10);
507  }
508  stream << " ";
509  m_allowed_list[i].print_composition_formula(stream, 20);
510  stream << std::endl;
511  }
512  // print_end_member_formula(1,log(),10);
513  // for(Index i=0;i<allowed_list.size();i++){
514  // allowed_list[i].print_composition_formula(log());
515  // log()<<std::endl;
516  // }
517 }
518 
519 //---------------------------------------------------------------------------
520 
521 void ParamComposition::print_curr_composition_axes(std::ostream &stream) const {
522  // Print Header: ORIGIN, <COMPOUNDS AT THE ENDS OF DIFFERENT AXES> , GENERAL
523  // FORMULA
524 
525  stream << std::setw(20) << "ORIGIN";
526  for (int i = 0; i < (m_rank_of_space - 1); i++) {
527  stream << std::setw(10) << (char)((int)'a' + i);
528  }
529  stream << " ";
530  stream << "GENERAL FORMULA";
531  stream << std::endl;
532 
533  stream << std::setw(20) << " ---";
534  for (int i = 0; i < (m_rank_of_space - 1); i++) {
535  stream << std::setw(10) << " ---";
536  }
537  stream << " ";
538  stream << "---" << std::endl;
539 
540  print_origin_formula(stream, 20);
541  std::vector<Eigen::VectorXd> allowed_spanning_end_members;
542  allowed_spanning_end_members = spanning_end_members();
543  for (int j = 0; j < allowed_spanning_end_members.size(); j++) {
544  print_member_formula(allowed_spanning_end_members[j], stream, 10);
545  }
546  stream << " ";
547  print_composition_formula(stream, 20);
548  stream << std::endl;
549 }
550 
551 //*************************************************************
552 // CALC ROUTINES
553 
554 //*************************************************************
555 /*
556  CALC
557 
558  To calculate the composition AFTER having set the origin and
559  spanning end members for the class, you need to pass it the
560  "given" values i.e. either the parametric composition or the
561  number of atoms per primClex unit.
562  If you want the PARAM_COMP given NUMBER_ATOMS set the mode to
563  PARAM_COMP.
564  If you eant the NUMBER_ATOMS given PARAM_COMP set the mode to
565  NUMBER_ATOMS.
566  i.e. set the mode to whatever is the quantity that you are giving
567  the class
568  */
569 //*************************************************************
570 
572  const int &MODE) {
573  if (MODE == PARAM_COMP) {
574  return m_origin + m_comp[PARAM_COMP] * tcomp;
575  } else {
576  return (m_comp[NUMBER_ATOMS] * (tcomp - m_origin))
577  .head(m_rank_of_space - 1);
578  }
579 }
580 
581 //*************************************************************
582 
584  const Eigen::VectorXd &num_atoms_per_prim) const {
585  return (m_comp[NUMBER_ATOMS] * (num_atoms_per_prim - m_origin))
586  .head(m_rank_of_space - 1);
587 }
588 
589 //*************************************************************
590 
592  const Eigen::VectorXd &param_composition) const {
593  return m_origin + m_comp[PARAM_COMP] * param_composition;
594 }
595 
596 //*************************************************************
597 
598 // Given an origin and spanning vectors, returns a ParamComposition object that
599 // points to the same Prim as (*this)
601  const Eigen::VectorXd &torigin,
602  const std::vector<Eigen::VectorXd> tspanning) {
603  // holds the temporary transformation matrix that is going to be
604  // used to initialize the new composition object
605  Eigen::MatrixXd tmat;
606  // if(!tspanning.empty() && tspanning[0].size() != components().size()) {
607  // std::cerr << "ERROR in ParamComposition::calc_composition_object the
608  // spanning vectors are not as long as the number of "; std::cerr <<
609  // "components in this system. I'm confused and recommend you quit and try
610  // again. However, not going to force quit\n";
611  //}
612  tmat.setIdentity(components().size(), components().size());
613  // copy the spanning vectors into tmat
614  for (Index i = 0; i < tspanning.size(); i++) {
615  tmat.col(i) = tspanning[i];
616  }
617  // generate an orthogonal set if there aren't as many spanning
618  // vectors as the number of components in the system
619  if (tspanning.size() < (components().size())) {
620  Eigen::FullPivHouseholderQR<Eigen::MatrixXd> qr(
621  tmat.leftCols(tspanning.size()));
622  Eigen::MatrixXd torthogonal = qr.matrixQ();
623  tmat.rightCols((components().size() - tspanning.size())) =
624  torthogonal.rightCols((components().size() - tspanning.size()));
625  // copy the orthogonalized vectors into tmat. We now have a
626  // complete spanning set in this component space
627  }
628  return ParamComposition(allowed_occs(), tmat, torigin, m_rank_of_space,
629  PARAM_COMP);
630 }
631 
632 // assuming that you have filled in the prim_end_members and the
633 // origin. This fills up the transformation matrices
635  Eigen::MatrixXd tmat;
636  tmat.resize(components().size(), components().size());
637  for (Index i = 0; i < m_spanning_end_members.size(); i++) {
638  tmat.col(i) = m_spanning_end_members[i] - m_origin;
639  }
640  if (m_spanning_end_members.size() < components().size()) {
641  Eigen::FullPivHouseholderQR<Eigen::MatrixXd> qr(
642  tmat.leftCols(m_spanning_end_members.size()));
643  Eigen::MatrixXd torthogonal = qr.matrixQ();
644  tmat.rightCols((components().size() - m_spanning_end_members.size())) =
645  torthogonal.rightCols(
646  (components().size() - m_spanning_end_members.size()));
647  // copy the orthogonalized vectors into tmat. We now have a
648  // complete spanning set in this component space
649  }
650  if (m_comp.size() != 2) {
651  m_comp.resize(2);
652  }
653  m_comp[PARAM_COMP] = tmat;
654  m_comp[NUMBER_ATOMS] = m_comp[PARAM_COMP].inverse();
655 }
656 
657 //**************************************************************
658 /*SPANNING END MEMBERS
659 
660  Returns an std::vector< Eigen::VectorXi > that contain the spanning end
661  members listed in the same order as they occur in the
662  transformation matrix.
663 
664 */
666  std::vector<Eigen::VectorXd> tspan_end;
667  if (m_rank_of_space <= 0) {
668  std::cerr << "WARNING something is wrong in "
669  "ParamComposition::spanning_end_members. The rank_of_space in "
670  "the ParamComposition object is <=0. I do not know how to "
671  "calculate the end_members in such a space"
672  << std::endl;
673  m_spanning_end_members = tspan_end;
674  return;
675  }
676  for (int i = 0; i + 1 < m_rank_of_space; i++) {
677  tspan_end.push_back((m_comp[PARAM_COMP].col(i) + m_origin));
678  }
679  m_spanning_end_members = tspan_end;
680 }
681 
682 //*************************************************************
683 // MISCELLANEOUS
684 
686  // printing the data from the 'choice'
687  // log()<<"This is the data from choice: "<<std::endl;
688  // allowed_list[choice].print_composition_matrices(log());
689  if (m_allowed_list.size() < choice + 1) {
690  std::cerr << "ERROR in ParamComposition::select_composition_axes. Your "
691  "value of choice is outside the range of allowed_list"
692  << std::endl;
693  exit(666);
694  }
695  m_comp = m_allowed_list[choice].comp();
696  // components = allowed_list[choice].components();
697  m_origin = m_allowed_list[choice].origin();
698  m_rank_of_space = m_allowed_list[choice].rank_of_space();
699  m_spanning_end_members = m_allowed_list[choice].spanning_end_members();
700  // print_composition_matrices(log());
701 }
702 
703 //*************************************************************
704 // ACCESSORS
705 
707  std::stringstream ss;
709  return ss.str();
710 }
711 
712 } // namespace CASM
std::set< std::string > & s
Eigen::VectorXd calc_num_atoms(const Eigen::VectorXd &param_composition) const
void print_origin_formula(std::ostream &stream, const int &stream_width) const
void select_composition_axes(const Index &choice)
static std::vector< std::string > string_components(ParamComposition::AllowedOccupants const &_allowed_occs)
Eigen::VectorXd m_origin
The origin of the composition space.
std::vector< Eigen::VectorXd > m_spanning_end_members
std::vector< std::string > m_components
The list of all allowed components, based on allowed_occs()
void print_composition_formula(std::ostream &stream, const int &stream_width) const
std::string composition_formula() const
Eigen::MatrixXd m_prim_end_members
std::vector< std::vector< std::string > > AllowedOccupants
const std::vector< std::vector< std::string > > & allowed_occs() const
For each sublattice, a list of occupants allowed on that sublattice.
std::vector< Eigen::MatrixXd > m_comp
void print_member_formula(const Eigen::VectorXd &member, std::ostream &stream, const int &stream_width) const
void print_composition_axes(std::ostream &stream) const
Eigen::VectorXd calc_param_composition(const Eigen::VectorXd &num_atoms_per_prim) const
void generate_composition_space(bool verbose=false)
Eigen::VectorXd calc(const Eigen::VectorXd &tcomp, const int &MODE)
std::vector< ParamComposition > m_allowed_list
void print_curr_composition_axes(std::ostream &stream) const
const std::vector< std::string > & components() const
Components are in order of appearance precedence in allowed_occs()
const std::vector< Eigen::VectorXd > & spanning_end_members() const
ParamComposition calc_composition_object(const Eigen::VectorXd &torigin, const std::vector< Eigen::VectorXd > tspanning)
Eigen::CwiseUnaryOp< decltype(Local::round_l< typename Derived::Scalar >), const Derived > round(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd.
Eigen::Matrix3l transf_mat(const Lattice &prim_lat, const Lattice &super_lat)
static std::vector< Eigen::VectorXi > _sub_extremes(std::set< Index > const &subcomponents, std::map< std::set< Index >, Index > const &sublats, Index dim)
static std::map< std::set< Index >, std::map< std::set< Index >, Index > > _chemical_subsystems(ParamComposition::AllowedOccupants const &_allowed_occs)
Main CASM namespace.
Definition: APICommand.hh:8
Eigen::MatrixXd MatrixXd
IntType nchoosek(IntType n, IntType k)
Definition: CASM_math.hh:207
Log & log()
Definition: Log.hh:424
Index find_index(Iterator begin, Iterator end, const T &value)
Equivalent to std::distance(begin, std::find(begin, end, value))
Definition: algorithm.hh:24
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
bool contains(const Container &container, const T &value)
Equivalent to container.end() != std::find(container.begin(), container.end(), value)
Definition: algorithm.hh:83
Eigen::MatrixXd::Index EigenIndex
Definition: eigen.hh:7
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
Eigen::VectorXd VectorXd
std::vector< IntType > index_to_kcombination(IntType ind, IntType k)
Definition: CASM_math.hh:228
Definition: stream_io.hh:24