CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
ParamComposition.cc
Go to the documentation of this file.
2 
3 #include <cmath>
4 #include <unistd.h>
5 #include "casm/external/boost.hh"
6 
8 #include "casm/clex/PrimClex.hh"
9 
10 namespace CASM {
11 
12 
13  //*************************************************************
14  //GENERATE Routines
15 
16  //*************************************************************
17  /* GENERATE COMPONENTS
18 
19  This routine generates the set ofx unique alloying components
20  that are listed in the prim structure. The unique alloying
21  components are stored as an Array< std::string >
22  */
23  //*************************************************************
24 
26 
27  if(components.size() != 0) {
28  std::cerr << "WARNING in ParamComposition::generate_components(), the components data member in the class";
29  std::cerr << " is not empty. Clearing it anyways.\n";
30  components.clear();
31  }
32 
33  auto struc_molecule = prim_struc->get_struc_molecule();
34  for(auto it = struc_molecule.begin(); it != struc_molecule.end(); ++it) {
35  components.push_back(it->name);
36  }
37 
38  return;
39  }
40 
41  //---------------------------------------------------------------------------
42 
43  //*************************************************************
44  /* GENERATE SUBLATTICE MAP
45 
46  This routine generates a matrix that has sublattice sites on
47  which a specific component is allowed to alloy. Consider the
48  example:
49  species [1] [2] -> sublattice index
50  [Ga] 1 0
51  [As] 1 1
52  [In] 0 1
53 
54  The 1's indicate that that component is allowed on that
55  specific sublattice.
56 
57  */
58  //*************************************************************
60  if(components.size() == 0)
62  //figuring out the number of sublattices on which alloying is happening
65  for(Index i = 0; i < prim_struc->basis.size(); i++) {
66  tlist = prim_struc->basis[i].allowed_occupants();
67  //keep only those sublattices where alloying is allowed
68  // if(tlist.size() == 1) {
69  // continue;
70  // }
71  tocc.push_back(tlist);
72  }
73  //resize the sublattice_map array to <number_components, number_sublattices>
74  sublattice_map.setZero(components.size(), tocc.size());
75  for(Index i = 0; i < tocc.size(); i++) {
76  for(Index j = 0; j < tocc[i].size(); j++) {
77  //If the component is not found in the components array, something is wrong!
78  if(!components.contains(tocc[i][j])) {
79  std::cerr << "ERROR:Your component matrix has been initialized badly. Quitting\n";
80  exit(666);
81  }
82  //Find the position of the component in the components array and increment sublattice_map
83  Index pos = (components.find(tocc[i][j]));
84  sublattice_map(pos, i)++;
85  }
86  }
87  }
88 
89  //---------------------------------------------------------------------------
90 
91  //*************************************************************
92  /* GENERATE_END_MEMBERS
93 
94  End members are generated by assigning priority values to each
95  component. Based on the priority value, the number of atoms for
96  every component is maximized. The routine then iterates thorough
97  all possible permutations of the priority values to generate all
98  possible end members
99  */
100  //*************************************************************
101 
103  if(sublattice_map.rows() == 0 || sublattice_map.cols() == 0)
105 
106  //the number of atoms of components[priority_index[0]] is
107  //maximized first following this the number of atoms of
108  //components[priority_index[1]] is maxed out and so on
109  Array<int> priority_index;
110 
111  //Holds a list of possible end members, this list is appended to
112  //as and when we find an end_member.
113  Array< Eigen::MatrixXi > tend_members;
114  Eigen::MatrixXi tend;
115 
116  //set the size of priority index to the number of components in
117  //the system, following this it is seeded with a starting priority
118  priority_index.resize(components.size());
119  for(Index i = 0; i < priority_index.size(); i++) {
120  priority_index[i] = i;//Initialize the priority_index to [0,1,2,...,(N-1)]
121  }
122  do {
123  //tsublat_comp is meant to keep track of which compositions have
124  //already been maxed out
125  Eigen::MatrixXi tsublat_comp = sublattice_map;
126 
127  //resize and set tend to 0's,we will add to this
128  //array as we loop over the priority indices
129  tend.setZero(1, sublattice_map.rows());
130 
131  //calculate the end_member that corresponds to this
132  //priority_index
133  for(Index i = 0; i < priority_index.size(); i++) {
134  tend(0, priority_index[i]) = tsublat_comp.row(priority_index[i]).sum();
135  //set the value to 0 in those sublattices that have been maxed out
136  max_out(priority_index[i], tsublat_comp);
137  }
138 
139  //figure out if it is already in our list of end members
140  bool is_unique = true;
141  for(Index i = 0; i < tend_members.size(); i++) {
142  if(tend == tend_members[i]) {
143  is_unique = false;
144  break;
145  }
146  }
147  if(is_unique) {
148  tend_members.push_back(tend); //add to the list if it is unique
149  }
150  }
151  while(priority_index.next_permute()); //repeat the above for all permutations of priority_index
152 
153  //Store tend_members as an Eigen::MatrixXi
154  //makes it easier to find the rank of the space
155  prim_end_members.resize(tend_members.size(), sublattice_map.rows());
156  for(Index i = 0; i < tend_members.size(); i++) {
157  for(EigenIndex j = 0; j < sublattice_map.rows(); j++) {
158  prim_end_members(i, j) = double(tend_members[i](0, j));
159  }
160  }
161  }
162 
163  //---------------------------------------------------------------------------
164 
165  //*********************************************************************
166  /* GENERATE_COMPOSITION_SPACE
167 
168  generates all possible composition axes that result in positive
169  values of the parametric composition.
170  ALGORITHM:
171  - start by finding the rank of the space that user has defined
172  in the PRIM
173  - pick one of the end_members as the origin. To enumerate all
174  possible axes, we loop through all possible end_members
175  - (rank-1) number of end_members are picked as spanning end
176  members from the remaining list of end_members that we get
177  from the PRIM
178  - A composition object is calculated that is then used to
179  calculated the parametric Composition given the current
180  choice of end members and origin. If it results in positive
181  numbers for all the end members that are listed for the PRIM,
182  this set of (origin,spanning end members) is pushed back onto
183  the allowed list of composition axes
184  - The process is repeated for all such unique combinations of
185  (origin, spanning end members)
186  */
187  //*********************************************************************
188 
189 
191  //Eigen object to do the QR decomposition of the list of prim_end_members
192  Eigen::FullPivHouseholderQR<Eigen::MatrixXd> qr(prim_end_members);
193  Eigen::VectorXd torigin; //temp origin
194  Eigen::VectorXd test_comp;
195  Array< Eigen::VectorXd > tspanning; //set of spanning end members
196  bool is_positive; //flag to test for positive composition axes
197  Array<int> priority_index;
198 
199  // If there is already a set of enumerated spaces for this
200  // Composition object
201  if(allowed_list.size() != 0) {
202  std::cerr << "WARNING in ParamComposition::generate_composition_space, your allowed_list is non-empty. If you are not careful,you may end up with repeats of allowed composition axes" << std::endl;
203  }
204 
205  // calculate the rank of the space.
206  // NOTE to the wise: # of spanning members = rank-1
207  rank_of_space = qr.rank();
208  if(verbose)
209  std::cout << "Rank of space : " << rank_of_space << std::endl;
210 
211  //This array is used to figure out which of the end members to
212  //select as spanning end members
213  Array<int> binary_choose(prim_end_members.rows() - 1, 0);
214 
215  //the priority index is used to pick a set of origin and end
216  //members to span the space
217  for(EigenIndex i = 0; i < prim_end_members.rows(); i++) {
218  priority_index.push_back(i);
219  }
220 
221  for(int i = 0; i + 1 < (rank_of_space); i++) {
222  binary_choose[binary_choose.size() - 1 - i] = 1;
223  }
224  if(verbose)
225  std::cout << "Binary choose: " << binary_choose << std::endl;
226 
227  if(verbose)
228  std::cout << "Computing the possible composition axes ... " << std::endl;
229 
230  //loop through all the end members and start them off as the origin
231  for(EigenIndex i = 0; i < prim_end_members.rows(); i++) {
232  torigin = prim_end_members.row(i).transpose();
233 
234  if(verbose)
235  std::cout << "The origin is: " << torigin << std::endl;
236 
237  //NOTE: priority seems to be a misnomer here, its really the
238  //list of end members that are in contention to be considered as
239  //the set of spanning end members. Consider changing the name
240  Array<int> tpriority = priority_index;
241  tpriority.remove(i); //remove the 'origin' from contention
242  Array<int> tbinary_choose = binary_choose;
243 
244  //loop over all permutations of priority_index and pick rank-1
245  //end members to span the space. Only keep those combinations
246  //that result in positive compositions
247  do {
248  tspanning.clear();
249  Array< Eigen::VectorXi > tvec; //hold the list of end members that are being considered
250 
251  if(verbose)
252  std::cout << "The end members being considered: " << std::endl;
253 
254  for(Index j = 0; j < tbinary_choose.size(); j++) {
255  if(tbinary_choose[j] == 1) {
256  tspanning.push_back((prim_end_members.row(tpriority[j]).transpose() - torigin));
257  tvec.push_back(prim_end_members.row(tpriority[j]).transpose().cast<int>());
258  }
259  if(verbose)
260  std::cout << prim_end_members.row(tpriority[j]) << std::endl;
261  }
262 
263  if(verbose)
264  std::cout << "---" << std::endl;
265 
266  //initialize a ParamComposition object with these spanning vectors and origin
267  ParamComposition tcomp = calc_composition_object(torigin, tspanning);
268  is_positive = true;
269 
270  //loop through end members and see what the values of the compositions works out to
271  if(verbose)
272  std::cout << "Calculated compositions:" << std::endl;
273 
274  for(EigenIndex j = 0; j < prim_end_members.rows(); j++) {
275  // Calculates the composition value given the previously
276  // initialized Composition object
277  test_comp = tcomp.calc(prim_end_members.row(j), NUMBER_ATOMS);
278  if(verbose)
279  std::cout << prim_end_members.row(j) << " : " << test_comp << std::endl;
280 
281  for(EigenIndex k = 0; k < test_comp.size(); k++) {
282  //if the calculated parametric composition value is either
283  //less than 0 or is nan(this will occur if the current set
284  //of origin and spanning end members form a subspace in
285  //the composition space for this PRIM)
286  if((test_comp(k) < 0 && !almost_zero(test_comp(k))) || std::isnan(test_comp(k))) {
287  is_positive = false;
288  break;
289  }
290  }
291  if(!is_positive) {
292  break;
293  }
294  }
295  if(is_positive) {
296  //push back this composition object, its good!
297  allowed_list.push_back(tcomp);
298  }
299 
300  }
301  while(tbinary_choose.next_permute());
302  fflush(stdout);
303  }
304  std::cout << " \r";
305  fflush(stdout);
306  }
307 
308  //---------------------------------------------------------------------------
309 
310  //*************************************************************
311  //PRINT Routines
312  void ParamComposition::print_composition_formula(std::ostream &stream, const int &stream_width) const {
313  int composition_var = (int)'a';
314  std::stringstream tstr;
315  for(Index i = 0; i < components.size(); i++) {
316  bool first_char = true;
317  tstr << components[i] << "(";
318  if(!almost_zero(origin(i))) {
319  first_char = false;
320  tstr << origin(i);
321  }
322  for(int j = 0; j + 1 < (rank_of_space); j++) {
323  if(almost_zero(comp[PARAM_COMP](i, j))) {
324  continue;
325  }
326  if(almost_zero(comp[PARAM_COMP](i, j) - 1)) {
327  if(first_char) {
328  tstr << (char)(composition_var + j);
329  first_char = false;
330  }
331  else {
332  tstr << '+' << (char)(composition_var + j);
333  }
334  }
335  else if(almost_zero(comp[PARAM_COMP](i, j) + 1)) {
336  tstr << '-' << (char)(composition_var + j);
337  first_char = false;
338  }
339  else {
340  stream << comp[PARAM_COMP](i, j) << (char)(composition_var + j);
341  first_char = false;
342  }
343  }
344  tstr << ")";
345  }
346 
347  stream << tstr.str().c_str();
348 
349  return;
350  }
351 
352  //---------------------------------------------------------------------------
353 
354  void ParamComposition::print_member_formula(const Eigen::VectorXd &member, std::ostream &stream, const int &stream_width) const {
355  std::stringstream tstr;
356  for(EigenIndex i = 0; i < member.size(); i++) {
357  if(almost_zero(member(i))) {
358  continue;
359  }
360  if(almost_zero(member(i) - 1)) {
361  tstr << components[i];
362  }
363  else {
364  tstr << components[i] << int(member(i));
365  }
366  }
367  stream << std::setw(stream_width) << tstr.str().c_str();
368  }
369 
370  //---------------------------------------------------------------------------
371 
372  void ParamComposition::print_origin_formula(std::ostream &stream, const int &stream_width) const {
373  print_member_formula(origin, stream, stream_width);
374  }
375 
376  //---------------------------------------------------------------------------
377 
378  void ParamComposition::print_composition_axes(std::ostream &stream) const {
379  stream << "Number of choices of composition axes: " << allowed_list.size() << std::endl;
380  //Print Header: ORIGIN, <COMPOUNDS AT THE ENDS OF DIFFERENT AXES> , GENERAL FORMULA
381 
382  stream << std::setw(10) << "INDEX";
383  stream << std::setw(10) << "ORIGIN";
384  for(int i = 0; i + 1 < rank_of_space; i++) {
385  stream << std::setw(10) << (char)((int)'a' + i);
386  }
387  stream << " ";
388  stream << "GENERAL FORMULA";
389  stream << std::endl;
390 
391  stream << std::setw(10) << " ---";
392  stream << std::setw(10) << " ---";
393  for(int i = 0; i < (rank_of_space - 1); i++) {
394  stream << std::setw(10) << " ---";
395  }
396  stream << " ";
397  stream << "---" << std::endl;
398 
399  for(Index i = 0; i < allowed_list.size(); i++) {
400  stream << std::setw(10) << i;
401  allowed_list[i].print_origin_formula(stream, 10);
402  Array< Eigen::VectorXd > allowed_spanning_end_members;
403  allowed_spanning_end_members = allowed_list[i].get_spanning_end_members();
404  for(Index j = 0; j < allowed_spanning_end_members.size(); j++) {
405  print_member_formula(allowed_spanning_end_members[j], stream, 10);
406  }
407  stream << " ";
408  allowed_list[i].print_composition_formula(stream, 20);
409  stream << std::endl;
410  }
411  // print_end_member_formula(1,std::cout,10);
412  // for(Index i=0;i<allowed_list.size();i++){
413  // allowed_list[i].print_composition_formula(std::cout);
414  // std::cout<<std::endl;
415  // }
416  }
417 
418  //---------------------------------------------------------------------------
419 
420  void ParamComposition::print_curr_composition_axes(std::ostream &stream) const {
421  //Print Header: ORIGIN, <COMPOUNDS AT THE ENDS OF DIFFERENT AXES> , GENERAL FORMULA
422 
423  stream << std::setw(20) << "ORIGIN";
424  for(int i = 0; i < (rank_of_space - 1); i++) {
425  stream << std::setw(10) << (char)((int)'a' + i);
426  }
427  stream << " ";
428  stream << "GENERAL FORMULA";
429  stream << std::endl;
430 
431  stream << std::setw(20) << " ---";
432  for(int i = 0; i < (rank_of_space - 1); i++) {
433  stream << std::setw(10) << " ---";
434  }
435  stream << " ";
436  stream << "---" << std::endl;
437 
438  print_origin_formula(stream, 20);
439  Array< Eigen::VectorXd > allowed_spanning_end_members;
440  allowed_spanning_end_members = get_spanning_end_members();
441  for(int j = 0; j < allowed_spanning_end_members.size(); j++) {
442  print_member_formula(allowed_spanning_end_members[j], stream, 10);
443  }
444  stream << " ";
445  print_composition_formula(stream, 20);
446  stream << std::endl;
447 
448  }
449 
450 
451  //*************************************************************
452  //CALC ROUTINES
453 
454  //*************************************************************
455  /*
456  CALC
457 
458  To calculate the composition AFTER having set the origin and
459  spanning end members for the class, you need to pass it the
460  "given" values i.e. either the parametric composition or the
461  number of atoms per primClex unit.
462  If you want the PARAM_COMP given NUMBER_ATOMS set the mode to
463  PARAM_COMP.
464  If you eant the NUMBER_ATOMS given PARAM_COMP set the mode to
465  NUMBER_ATOMS.
466  i.e. set the mode to whatever is the quantity that you are giving
467  the class
468  */
469  //*************************************************************
470 
471  Eigen::VectorXd ParamComposition::calc(const Eigen::VectorXd &tcomp, const int &MODE) {
472  if(MODE == PARAM_COMP) {
473  return origin + comp[PARAM_COMP] * tcomp;
474  }
475  else {
476  return (comp[NUMBER_ATOMS] * (tcomp - origin)).head(rank_of_space - 1);
477  }
478  }
479 
480  //*************************************************************
481 
483  return (comp[NUMBER_ATOMS] * (num_atoms_per_prim - origin)).head(rank_of_space - 1);
484  }
485 
486  //*************************************************************
487 
489  return origin + comp[PARAM_COMP] * param_composition;
490  }
491 
492  //*************************************************************
493 
494  std::vector<std::pair<std::string, Index> > ParamComposition::fixed_components() {
495  std::vector<std::pair<std::string, Index> > tcompon;
496  if(prim_end_members.cols() == 0)
499  Eigen::VectorXd sum_vec(Eigen::VectorXd::Zero(end_members.rows()));
500  for(Index i = 1; i < end_members.cols(); i++) {
501  sum_vec += ((end_members.col(i) - end_members.col(0)).array().abs()).matrix();
502  }
503  for(Index i = 0; i < sum_vec.size(); i++) {
504  if(almost_zero(sum_vec[i]))
505  tcompon.push_back(std::pair<std::string, Index> (components[i], round(end_members(i, 0))));
506  }
507  return tcompon;
508  }
509 
510  //*************************************************************
511 
512  //Given an origin and spanning vectors, returns a ParamComposition object that points to the same Prim as (*this)
514  //holds the temporary transformation matrix that is going to be
515  //used to initialize the new composition object
516  Eigen::MatrixXd tmat;
517  if(tspanning[0].size() != components.size()) {
518  std::cerr << "ERROR in ParamComposition::calc_composition_object the spanning vectors are not as long as the number of ";
519  std::cerr << "components in this system. I'm confused and recommend you quit and try again. However, not going to force quit\n";
520  }
521  tmat.resize(components.size(), components.size());
522  //copy the spanning vectors into tmat
523  for(Index i = 0; i < tspanning.size(); i++) {
524  tmat.col(i) = tspanning[i];
525  }
526  //generate an orthogonal set if there aren't as many spanning
527  //vectors as the number of components in the system
528  if(tspanning.size() < (components.size())) {
529  Eigen::FullPivHouseholderQR<Eigen::MatrixXd> qr(tmat.leftCols(tspanning.size()));
530  Eigen::MatrixXd torthogonal = qr.matrixQ();
531  tmat.rightCols((components.size() - tspanning.size())) = torthogonal.rightCols((components.size() - tspanning.size()));
532  //copy the orthogonalized vectors into tmat. We now have a
533  //complete spanning set in this component space
534  }
536  }
537 
538  //assuming that you have filled in the prim_end_members and the
539  //origin. This fills up the transformation matrices
541  Eigen::MatrixXd tmat;
542  tmat.resize(components.size(), components.size());
543  for(Index i = 0; i < spanning_end_members.size(); i++) {
544  tmat.col(i) = spanning_end_members[i] - origin;
545  }
547  Eigen::FullPivHouseholderQR<Eigen::MatrixXd> qr(tmat.leftCols(spanning_end_members.size()));
548  Eigen::MatrixXd torthogonal = qr.matrixQ();
549  tmat.rightCols((components.size() - spanning_end_members.size())) = torthogonal.rightCols((components.size() - spanning_end_members.size()));
550  //copy the orthogonalized vectors into tmat. We now have a
551  //complete spanning set in this component space
552  }
553  if(comp.size() != 2) {
554  comp.resize(2);
555  }
556  comp[PARAM_COMP] = tmat;
557  comp[NUMBER_ATOMS] = comp[PARAM_COMP].inverse();
558  }
559 
560 
561  //use this to write out the composition object into a JSON format
563  ptree comp_ptree;
564  //add the allowed coomposition axes into the ptree
565  if(allowed_list.size() > 0) {
566  std::string root("");
567  // ptree axes_list;
568  //add ptrees that contain information from the allowed composition axes
569  for(Index i = 0; i < allowed_list.size(); i++) {
570  std::stringstream strs;
571  strs << root << "allowed_axes.";
572  strs << i;
573  comp_ptree.put_child(strs.str().c_str(), allowed_list[i].calc_composition_ptree());
574  }
575  }
576 
577  //print the composition members
578  //components
579  if(components.size() > 0) {
580  std::string root("");
581  root.append("components");
582  std::string components_string;
583  for(Index i = 0; i < components.size(); i++) {
584  components_string.append(components[i]);
585  components_string.append(" ");
586  }
587  boost::algorithm::trim(components_string);
588  comp_ptree.put(root, components_string.c_str());
589  }
590 
591  //origin
592  if(origin.size() > 0) {
593  std::string root("");
594  root.append("origin");
595  std::stringstream origin_strs;
596  origin_strs << origin;
597  std::string origin_str;
598  origin_str = origin_strs.str();
599  boost::replace_all(origin_str, "\n", " ");
600  comp_ptree.put(root, origin_str.c_str());
601  }
602 
603  //spanning end members
604  if(rank_of_space > 0 && comp[PARAM_COMP].rows() > 0) {
605  std::string root("");
606  root.append("end_members");
607  //Array< Eigen::VectorXd > tspanning_end_members = spanning_end_members();
608  // ptree end_members_ptree;
609  for(Index i = 0; i < spanning_end_members.size(); i++) {
610  std::stringstream tspan_strs;
611  tspan_strs << spanning_end_members[i];
612  std::string tspan_str = tspan_strs.str();
613  boost::replace_all(tspan_str, "\n", " ");
614  // end_members_ptree.put();
615  std::stringstream tname;
616  tname << root << ".";
617  tname << char('a' + i);
618  comp_ptree.put(tname.str().c_str(), tspan_str.c_str());
619  }
620  }
621 
622  //rank_of_space
623  if(rank_of_space > 0) {
624  std::string root("");
625  root.append("rank_of_space");
626  std::stringstream rank_strs;
627  rank_strs << rank_of_space;
628  comp_ptree.put(root.c_str(), rank_strs.str().c_str());
629  }
630 
631  return comp_ptree;
632 
633  }
634 
635  //**************************************************************
636  /*SPANNING END MEMBERS
637 
638  Returns an Array< Eigen::VectorXi > that contain the spanning end
639  members listed in the same order as they occur in the
640  transformation matrix.
641 
642  */
644  Array< Eigen::VectorXd > tspan_end;
645  if(rank_of_space <= 0) {
646  std::cerr << "WARNING something is wrong in ParamComposition::spanning_end_members. The rank_of_space in the ParamComposition object is <=0. I do not know how to calculate the end_members in such a space" << std::endl;
647  spanning_end_members = tspan_end;
648  return;
649  }
650  for(int i = 0; i + 1 < rank_of_space; i++) {
651  tspan_end.push_back((comp[PARAM_COMP].col(i) + origin));
652  }
653  spanning_end_members = tspan_end;
654  }
655 
656  //*************************************************************
657  //READ
658 
659  void ParamComposition::read(const std::string &comp_filename) {
660  std::ifstream in_comp;
661  in_comp.open(comp_filename.c_str());
662  if(!in_comp) {
663  std::cerr << "ERROR in ParamComposition::read. Could not read the file: " << comp_filename.c_str() << std::endl;
664  std::cerr << "Continuing anyways. However, things could go horribly wrong. I recommend you quit." << std::endl;
665  return;
666  }
667  read(in_comp);
668 
669  }
670 
671  void ParamComposition::read(std::istream &stream) {
672  ptree comp_ptree;
673  read_json(stream, comp_ptree);
674  read(comp_ptree);
675  }
676 
677  void ParamComposition::read(ptree comp_ptree) {
678 
679  //std::cout<<"In ParamComposition::read"<<std::endl;
680  //try to read in the allowed_axes
681  try {
682  const ptree &allowed_axes_ptree = comp_ptree.get_child("allowed_axes");
683  //std::cout<<"Reading the allowed_axes field"<<std::endl;
684  int allowed_axes_num = 0;
685  do {
686  try {
687  std::stringstream tstr;
688  tstr << allowed_axes_num;
689  ParamComposition tc(allowed_axes_ptree.get_child(tstr.str().c_str()) , *prim_struc);
690  allowed_list.push_back(tc);
691  }
692  catch(std::exception const &e) {
693  break;
694  }
695  allowed_axes_num++;
696  }
697  while(true);
698  }
699  catch(std::exception const &e) {
700  //continue
701  }
702 
703  //try to read in the components
704  try {
705  if(components.size() != 0) {
706  std::cerr << "WARNING in ParamComposition::read. your components matrix is not empty. Clearing that array and any other non-empty data members" << std::endl;
707  components.clear();
708  comp.clear();
709  allowed_list.clear();
710  }
711  std::string tcomp = comp_ptree.get<std::string>("components");
712  boost::char_separator< char > sep(" ");
713  boost::tokenizer< boost::char_separator< char > > tokens(tcomp, sep);
714  BOOST_FOREACH(const std::string & t, tokens) {
716  }
717 
718  //resize the other matrices to match this one
719  comp.resize(2);
722  }
723  catch(std::exception const &e) {
724  // continue;
725  }
726 
727  //try to read in the origin
728  try {
729  std::string tcomp = comp_ptree.get<std::string>("origin");
730  if(components.size() == 0) {
731  std::cerr << "ERROR in ParamComposition::read. You are trying to set an origin without specifying the components. This is dangerous, and not allowed. QUITTING." << std::endl;
732  exit(666);
733  }
735  }
736  catch(std::exception const &e) {
737  // continue;
738  }
739 
740  //read in the end members and then set up the transformation matrices
741  try {
742  const ptree &end_members_ptree = comp_ptree.get_child("end_members");
743  std::string comp_axis(1, 'a');
744  do {
745  try {
746  std::string span_string = end_members_ptree.get< std::string > (comp_axis.c_str());
748  }
749  catch(std::exception const &e) {
750  break;
751  }
752  comp_axis[0]++;
753  }
754  while(true);
755  //update the transformation matrices in comp.
757  }
758  catch(std::exception const &e) {
759  // continue;
760  }
761 
762  //reading in the rank_of_space
763  try {
764  std::string trank_str = comp_ptree.get<std::string>("rank_of_space");
765  rank_of_space = atoi(trank_str.c_str());
766  }
767  catch(std::exception const &e) {
768  rank_of_space = -1;
769  //continue
770  }
771 
772  }
773 
774  //*************************************************************
775  //MISCELLANEOUS
776 
777  //*************************************************************
778  /* MAX OUT
779  Given a sublat_comp, say:
780  [1] [2]
781  [Ga] 1 0
782  [As] 1 1
783  [In] 0 1
784  say that we have our priority_index set up to maximize [Ga]
785  we need tochange the 1 in [As] 1st column to 0, since Ga now
786  occupies that sublattice. Max Out does the appropriate subt-
787  ractions and returns the modified matrix
788  */
789  //*************************************************************
790  void ParamComposition::max_out(const int &component_index, Eigen::MatrixXi &sublat_comp) const {
791  for(EigenIndex i = 0; i < sublat_comp.cols(); i++) {
792  if(sublat_comp(component_index, i) > 0) {
793  for(EigenIndex j = 0; j < sublat_comp.rows(); j++) {
794  sublat_comp(j, i) = 0;
795  }
796  }
797  }
798  return;
799  }
800 
802 
803  //printing the data from the 'choice'
804  // std::cout<<"This is the data from choice: "<<std::endl;
805  // allowed_list[choice].print_composition_matrices(std::cout);
806  if(allowed_list.size() < choice + 1) {
807  std::cerr << "ERROR in ParamComposition::select_composition_axes. Your value of choice is outside the range of allowed_list" << std::endl;
808  exit(666);
809  }
810  comp = allowed_list[choice].get_comp();
811  // components = allowed_list[choice].get_components();
812  origin = allowed_list[choice].get_origin();
813  rank_of_space = allowed_list[choice].get_rank_of_space();
814  spanning_end_members = allowed_list[choice].get_spanning_end_members();
815  // print_composition_matrices(std::cout);
816  }
817 
818 
819  //*************************************************************
820  //ACCESSORS
821 
823  std::stringstream ss;
825  return ss.str();
826  }
827 
828 
829 }
830 
Eigen::MatrixXd MatrixXd
ParamComposition calc_composition_object(const Eigen::VectorXd &torigin, const Array< Eigen::VectorXd > tspanning)
Array< ParamComposition > allowed_list
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
Definition: CASM_math.hh:41
void read(const std::string &comp_filename)
bool contains(const T &test_elem) const
Definition: Array.hh:281
Index size() const
Definition: Array.hh:145
Eigen::VectorXd eigen_vector_from_string(const std::string &tstr, const int &size)
Definition: CASM_math.cc:119
void push_back(const T &toPush)
Definition: Array.hh:513
Eigen::MatrixXd prim_end_members
void resize(Index new_N)
Definition: Array.hh:468
std::vector< Molecule > get_struc_molecule() const
Returns an Array of each possible Molecule in this Structure.
Definition: Structure.cc:146
const Structure * prim_struc
bool next_permute()
Definition: Array.hh:956
Main CASM namespace.
Definition: complete.cpp:8
Array< Eigen::VectorXd > spanning_end_members
std::string get_composition_formula() const
void select_composition_axes(const Index &choice)
void print_member_formula(const Eigen::VectorXd &member, std::ostream &stream, const int &stream_width) const
std::vector< std::pair< std::string, Index > > fixed_components()
void clear()
Definition: Array.hh:216
void print_composition_axes(std::ostream &stream) const
Eigen::MatrixXd::Index EigenIndex
For integer indexing:
void print_composition_formula(std::ostream &stream, const int &stream_width) const
Eigen::MatrixXi sublattice_map
Eigen::VectorXd calc_param_composition(const Eigen::VectorXd &num_atoms_per_prim) const
EigenIndex Index
For long integer indexing:
ptree calc_composition_ptree() const
Array< CoordType > basis
Lattice vectors that specifies periodicity of the crystal.
Eigen::VectorXd VectorXd
const Array< Eigen::VectorXd > & get_spanning_end_members() const
Eigen::VectorXd calc(const Eigen::VectorXd &tcomp, const int &MODE)
void generate_composition_space(bool verbose=false)
void print_curr_composition_axes(std::ostream &stream) const
Index find(const T &test_elem) const
Definition: Array.hh:707
Eigen::MatrixXd end_members(const Structure &prim)
Generate a column matrix containing all the possible molecular end members.
void print_origin_formula(std::ostream &stream, const int &stream_width) const
void max_out(const int &component_index, Eigen::MatrixXi &sublat_comp) const
Array< std::string > components
Basic std::vector like container (deprecated)
Eigen::VectorXd calc_num_atoms(const Eigen::VectorXd &param_composition) const
int round(double val)
Definition: CASM_math.cc:6
void remove(Index ind)
Definition: Array.hh:546
Array< Eigen::MatrixXd > comp