CASM  1.1.0
A Clusters Approach to Statistical Mechanics
BasicStructure.cc
Go to the documentation of this file.
2 
3 #include <fstream>
4 #include <stdexcept>
5 
14 #include "casm/misc/algorithm.hh"
15 
16 namespace CASM {
17 namespace xtal {
19  double tol) {
20  BasicStructure poscar_structure;
21  poscar_structure.read(poscar_stream, tol);
22  return poscar_structure;
23 }
24 
25 //***********************************************************
26 
28  : m_lattice(RHS.lattice()),
29  m_title(RHS.title()),
30  m_basis(RHS.basis()),
31  m_global_dof_map(RHS.m_global_dof_map) {
32  for (Index i = 0; i < basis().size(); i++) {
33  m_basis[i].set_lattice(lattice(), CART);
34  }
35 }
36 
37 //***********************************************************
38 
40  m_lattice = RHS.lattice();
41  m_title = RHS.title();
42  set_basis(RHS.basis());
44 
45  for (Index i = 0; i < basis().size(); i++)
47 
48  return *this;
49 }
50 
51 //************************************************************
52 
53 DoFSet const &BasicStructure::global_dof(std::string const &_dof_type) const {
54  auto it = m_global_dof_map.find(_dof_type);
55  if (it != m_global_dof_map.end()) {
56  return (it->second);
57  } else {
58  throw std::runtime_error(
59  std::string("In BasicStructure::dof(), this structure does not contain "
60  "any global DoF's of type " +
61  _dof_type));
62  }
63 }
64 
66  for (Index i = 0; i < basis().size(); i++) {
67  m_basis[i].within();
68  }
69  return;
70 }
71 
72 //***********************************************************
73 
74 void BasicStructure::set_lattice(const Lattice &new_lat, COORD_TYPE mode) {
75  m_lattice = new_lat;
76 
77  for (Index nb = 0; nb < basis().size(); nb++) {
78  m_basis[nb].set_lattice(lattice(), mode);
79  }
80 }
81 
82 //***********************************************************
83 
84 void BasicStructure::set_title(std::string const &_title) { m_title = _title; }
85 
86 //\Liz D 032514
87 //***********************************************************
92 //***********************************************************
93 
94 void BasicStructure::set_basis(std::vector<Site> const &_basis,
95  COORD_TYPE mode) {
96  m_basis.clear();
97  m_basis.reserve(_basis.size());
98  for (Site const &site : _basis) push_back(site, mode);
99 }
100 
101 void BasicStructure::push_back(Site const &_site, COORD_TYPE mode) {
102  m_basis.push_back(_site);
103  m_basis.back().set_lattice(lattice(), mode);
104 }
105 
106 //************************************************************
109  Index result(0);
110  for (Index i = 0; i < basis().size(); i++) {
111  if (m_basis[i].contains("Va")) ++result;
112  }
113  return result;
114 }
115 
116 //************************************************************
117 // read a POSCAR like file and collect all the structure variables
118 // modified to read PRIM file and determine which basis to use
119 // Changed by Ivy to read new VASP POSCAR format
120 
121 void BasicStructure::read(std::istream &stream, double tol) {
122  int i, t_int;
123  char ch;
124  std::vector<double> num_elem;
125  std::vector<std::string> elem_array;
126  bool read_elem = false;
127  std::string tstr;
128  std::stringstream tstrstream;
129 
130  Site tsite(lattice());
131 
132  bool SD_flag = false;
133  getline(stream, m_title);
134  if (title().back() == '\r')
135  throw std::runtime_error(std::string(
136  "Structure file is formatted for DOS. Please convert to Unix format. "
137  "(This can be done with the dos2unix command.)"));
138 
139  m_lattice.read(stream);
140  m_lattice.set_tol(tol);
141 
142  stream.ignore(100, '\n');
143 
144  // Search for Element Names
145  ch = stream.peek();
146  while (ch != '\n' && !stream.eof()) {
147  if (isalpha(ch)) {
148  read_elem = true;
149  stream >> tstr;
150  elem_array.push_back(tstr);
151  ch = stream.peek();
152  } else if (ch == ' ' || ch == '\t') {
153  stream.ignore();
154  ch = stream.peek();
155  } else if (ch >= '0' && ch <= '9') {
156  break;
157  } else {
158  throw std::runtime_error(std::string(
159  "Error attempting to read Structure. Error reading atom names."));
160  }
161  }
162 
163  if (read_elem == true) {
164  stream.ignore(10, '\n');
165  ch = stream.peek();
166  }
167 
168  // Figure out how many species
169  int num_sites = 0;
170  while (ch != '\n' && !stream.eof()) {
171  if (ch >= '0' && ch <= '9') {
172  stream >> t_int;
173  num_elem.push_back(t_int);
174  num_sites += t_int;
175  ch = stream.peek();
176  } else if (ch == ' ' || ch == '\t') {
177  stream.ignore();
178  ch = stream.peek();
179  } else {
180  throw std::runtime_error(std::string(
181  "Error in line 6 of structure input file. Line 6 of structure input "
182  "file should contain the number of sites."));
183  }
184  }
185  stream.get(ch);
186 
187  // fractional coordinates or cartesian
188  COORD_MODE input_mode(FRAC);
189 
190  stream.get(ch);
191  while (ch == ' ' || ch == '\t') {
192  stream.get(ch);
193  }
194 
195  if (ch == 'S' || ch == 's') {
196  SD_flag = true;
197  stream.ignore(1000, '\n');
198  while (ch == ' ' || ch == '\t') {
199  stream.get(ch);
200  }
201  stream.get(ch);
202  }
203 
204  if (ch == 'D' || ch == 'd') {
205  input_mode.set(FRAC);
206  } else if (ch == 'C' || ch == 'c') {
207  input_mode.set(CART);
208  } else if (!SD_flag) {
209  throw std::runtime_error(std::string(
210  "Error in line 7 of structure input file. Line 7 of structure input "
211  "file should specify Direct, Cartesian, or Selective Dynamics."));
212  } else if (SD_flag) {
213  throw std::runtime_error(
214  std::string("Error in line 8 of structure input file. Line 8 of "
215  "structure input file should specify Direct or Cartesian "
216  "when Selective Dynamics is on."));
217  }
218 
219  stream.ignore(1000, '\n');
220  // Clear basis if it is not empty
221  if (basis().size() != 0) {
222  std::cerr << "The structure is going to be overwritten." << std::endl;
223  m_basis.clear();
224  }
225 
226  if (read_elem) {
227  int j = -1;
228  int sum_elem = 0;
229  m_basis.reserve(num_sites);
230  for (i = 0; i < num_sites; i++) {
231  if (i == sum_elem) {
232  j++;
233  sum_elem += num_elem[j];
234  }
235 
236  tsite.read(stream, elem_array[j], SD_flag);
237  push_back(tsite);
238  }
239  } else {
240  // read the site info
241  m_basis.reserve(num_sites);
242  for (i = 0; i < num_sites; i++) {
243  tsite.read(stream, SD_flag);
244  if ((stream.rdstate() & std::ifstream::failbit) != 0) {
245  std::cerr << "Error reading site " << i + 1
246  << " from structure input file." << std::endl;
247  exit(1);
248  }
249  push_back(tsite);
250  }
251  }
252 
253  // Check whether there are additional sites listed in the input file
254  std::string s;
255  getline(stream, s);
256  std::istringstream tmp_stream(s);
257  Eigen::Vector3d coord;
258  tmp_stream >> coord;
259  if (tmp_stream.good()) {
260  throw std::runtime_error(
261  std::string("ERROR: too many sites listed in structure input file."));
262  }
263 
264  return;
265 }
266 
267 //***********************************************************
268 
269 void BasicStructure::print_xyz(std::ostream &stream, bool frac) const {
270  stream << basis().size() << '\n';
271  stream << title() << '\n';
272  stream.precision(7);
273  stream.width(11);
274  stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
275  stream << " a b c" << '\n';
276  stream << lattice().lat_column_mat() << '\n';
277  for (Index i = 0; i < basis().size(); i++) {
278  std::string site_label = basis()[i].allowed_occupants().size() == 1
279  ? basis()[i].allowed_occupants()[0]
280  : "?";
281  stream << std::setw(2) << site_label << " ";
282  if (frac) {
283  stream << std::setw(12) << basis()[i].frac().transpose() << '\n';
284  } else {
285  stream << std::setw(12) << basis()[i].cart() << '\n';
286  }
287  }
288 }
289 
290 //***********************************************************
291 
293  for (Index i = 0; i < basis().size(); i++) {
294  m_basis[i] += shift;
295  }
296 
297  return (*this);
298 }
299 
300 //***********************************************************
301 
303  for (Index i = 0; i < basis().size(); i++) {
304  m_basis[i] -= shift;
305  }
306  // factor_group -= shift;
307  // asym_unit -= shift;
308  return (*this);
309 }
310 
311 //***********************************************************
312 
313 /* BasicStructure operator*(const Lattice &LHS, const BasicStructure &RHS) { */
314 /* BasicStructure tsuper(LHS); */
315 /* tsuper.fill_supercell(RHS); */
316 /* return tsuper; */
317 /* } */
318 
319 //***********************************************************
320 
322 // private for now, expose if necessary
324  for (auto const &dof : m_global_dof_map)
325  if (dof.second.traits().time_reversal_active()) return true;
326  for (Site const &site : basis())
327  if (site.time_reversal_active()) return true;
328  return false;
329 }
330 
331 //***********************************************************
332 
340 std::vector<UnitCellCoord> symop_site_map(SymOp const &_op,
341  BasicStructure const &_struc) {
342  return symop_site_map(_op, _struc, _struc.lattice().tol());
343 }
344 
345 //***********************************************************
346 
353 std::vector<UnitCellCoord> symop_site_map(SymOp const &_op,
354  BasicStructure const &_struc,
355  double _tol) {
356  std::vector<UnitCellCoord> result;
357  // Determine how basis sites transform from the origin unit cell
358  for (int b = 0; b < _struc.basis().size(); b++) {
359  Site transformed_basis_site = _op * _struc.basis()[b];
360  result.emplace_back(
361  UnitCellCoord::from_coordinate(_struc, transformed_basis_site, _tol));
362  }
363  return result;
364 }
365 
366 //************************************************************
367 
369 std::vector<std::string> struc_species(BasicStructure const &_struc) {
370  std::vector<Molecule> tstruc_molecule = struc_molecule(_struc);
371  std::set<std::string> result;
372 
373  Index i, j;
374 
375  // For each molecule type
376  for (i = 0; i < tstruc_molecule.size(); i++) {
377  // For each atomposition in the molecule
378  for (j = 0; j < tstruc_molecule[i].size(); j++)
379  result.insert(tstruc_molecule[i].atom(j).name());
380  }
381 
382  return std::vector<std::string>(result.begin(), result.end());
383 }
384 
385 //************************************************************
386 
388 std::vector<Molecule> struc_molecule(BasicStructure const &_struc) {
389  std::vector<Molecule> tstruc_molecule;
390  Index i, j;
391 
392  // loop over all Sites in basis
393  for (i = 0; i < _struc.basis().size(); i++) {
394  // loop over all Molecules in Site
395  for (j = 0; j < _struc.basis()[i].occupant_dof().size(); j++) {
396  // Collect unique Molecules
397  if (!contains(tstruc_molecule, _struc.basis()[i].occupant_dof()[j])) {
398  tstruc_molecule.push_back(_struc.basis()[i].occupant_dof()[j]);
399  }
400  }
401  } // end loop over all Sites
402 
403  return tstruc_molecule;
404 }
405 
406 //************************************************************
408 std::vector<std::string> struc_molecule_name(BasicStructure const &_struc) {
409  // get Molecule allowed in struc
410  std::vector<Molecule> struc_mol = struc_molecule(_struc);
411 
412  // store Molecule names in vector
413  std::vector<std::string> struc_mol_name;
414  for (int i = 0; i < struc_mol.size(); i++) {
415  struc_mol_name.push_back(struc_mol[i].name());
416  }
417 
418  return struc_mol_name;
419 }
420 
421 //************************************************************
423 std::vector<std::vector<std::string> > allowed_molecule_unique_names(
424  BasicStructure const &_struc) {
425  using IPair = std::pair<Index, Index>;
426  std::map<std::string, std::vector<Molecule> > name_map;
427  std::map<std::string, IPair> imap;
428 
429  std::vector<std::vector<std::string> > result(_struc.basis().size());
430  for (Index b = 0; b < _struc.basis().size(); ++b) {
431  for (Index j = 0; j < _struc.basis()[b].occupant_dof().size(); ++j) {
432  Molecule const &mol(_struc.basis()[b].occupant_dof()[j]);
433  result[b].push_back(mol.name());
434  auto it = name_map.find(mol.name());
435  if (it == name_map.end()) {
436  name_map[mol.name()].push_back(mol);
437  imap[mol.name()] = {b, j};
438  } else {
439  Index i = find_index(it->second, mol);
440  if (i == it->second.size()) {
441  it->second.push_back(mol);
442  if (i == 1) {
443  auto inds = imap[mol.name()];
444  result[inds.first][inds.second] += ".1";
445  }
446  }
447  if (i > 0) result[b][j] += ("." + std::to_string(i + 1));
448  }
449  }
450  }
451  return result;
452 }
453 
454 //************************************************************
456 std::vector<std::vector<std::string> > allowed_molecule_names(
457  BasicStructure const &_struc) {
458  std::vector<std::vector<std::string> > result(_struc.basis().size());
459 
460  for (Index b = 0; b < _struc.basis().size(); ++b)
461  result[b] = _struc.basis()[b].allowed_occupants();
462 
463  return result;
464 }
465 
466 //****************************************************************************************************//
467 
468 std::vector<DoFKey> all_local_dof_types(BasicStructure const &_struc) {
469  std::set<std::string> tresult;
470 
471  for (Site const &site : _struc.basis()) {
472  auto sitetypes = site.dof_types();
473  tresult.insert(sitetypes.begin(), sitetypes.end());
474  if (site.occupant_dof().size() > 1) {
475  tresult.insert("occ"); // TODO: single source for occupation dof name
476  }
477  }
478  return std::vector<std::string>(tresult.begin(), tresult.end());
479 }
480 
481 std::vector<DoFKey> continuous_local_dof_types(BasicStructure const &_struc) {
482  std::set<std::string> tresult;
483 
484  for (Site const &site : _struc.basis()) {
485  auto sitetypes = site.dof_types();
486  tresult.insert(sitetypes.begin(), sitetypes.end());
487  }
488  return std::vector<std::string>(tresult.begin(), tresult.end());
489 }
490 
491 std::vector<DoFKey> global_dof_types(BasicStructure const &_struc) {
492  std::vector<std::string> result;
493  for (auto const &dof : _struc.global_dofs()) result.push_back(dof.first);
494  return result;
495 }
496 
497 std::vector<DoFKey> all_dof_types(BasicStructure const &_struc) {
498  std::vector<std::string> result;
499  for (auto const &global_dof_name : global_dof_types(_struc))
500  result.push_back(global_dof_name);
501  for (auto const &local_dof_name : all_local_dof_types(_struc))
502  result.push_back(local_dof_name);
503  return result;
504 }
505 
506 std::map<DoFKey, Index> local_dof_dims(BasicStructure const &_struc) {
507  std::map<DoFKey, Index> result;
508  for (DoFKey const &type : continuous_local_dof_types(_struc))
509  result[type] = local_dof_dim(type, _struc);
510 
511  return result;
512 }
513 
514 std::map<DoFKey, Index> global_dof_dims(BasicStructure const &_struc) {
515  std::map<DoFKey, Index> result;
516  for (auto const &type : _struc.global_dofs())
517  result[type.first] = type.second.dim();
518  return result;
519 }
520 
521 Index local_dof_dim(DoFKey const &_name, BasicStructure const &_struc) {
522  Index result = 0;
523  for (Site const &site : _struc.basis()) {
524  if (site.has_dof(_name)) result = max(result, site.dof(_name).dim());
525  }
526  return result;
527 }
528 
530  std::vector<DoFKey> global_dof_types = xtal::global_dof_types(structure);
531  Index istrain = find_index_if(global_dof_types, [](DoFKey const &other) {
532  return other.find("strain") != std::string::npos;
533  });
534  return istrain != global_dof_types.size();
535 }
536 
538  std::vector<DoFKey> global_dof_types = xtal::global_dof_types(structure);
539  Index istrain = find_index_if(global_dof_types, [](DoFKey const &other) {
540  return other.find("strain") != std::string::npos;
541  });
542  if (istrain == global_dof_types.size()) {
543  throw std::runtime_error(
544  "Error in get_strain_dof_key: Structure does not have strain DoF.");
545  }
546  return global_dof_types[istrain];
547 }
548 
549 DoFKey get_strain_metric(DoFKey strain_dof_key) {
550  auto pos = strain_dof_key.find("strain");
551  if (pos != std::string::npos) {
552  return strain_dof_key.substr(0, pos);
553  }
554  std::stringstream msg;
555  msg << "Error in get_strain_metric: Failed to get metric name from '"
556  << strain_dof_key << "'.";
557  throw std::runtime_error(msg.str());
558 }
559 
560 } // namespace xtal
561 } // namespace CASM
std::set< std::string > & s
BasicStructure specifies the lattice and atomic basis of a crystal.
void set_lattice(const Lattice &lattice, COORD_TYPE mode)
BasicStructure & operator+=(const Coordinate &shift)
Translates all atoms in cell.
BasicStructure & operator-=(const Coordinate &shift)
Index max_possible_vacancies() const
Counts sites that allow vacancies.
std::map< DoFKey, DoFSet > const & global_dofs() const
static BasicStructure from_poscar_stream(std::istream &poscar_stream, double tol=TOL)
std::vector< Site > & set_basis()
const std::string & title() const
std::string m_title
User-specified name of this Structure.
std::vector< Site > m_basis
Lattice vectors that specifies periodicity of the crystal.
void read(std::istream &stream, double tol=TOL)
void set_title(std::string const &_title)
Set the title of the structure.
void print_xyz(std::ostream &stream, bool frac=false) const
Output other formats.
void within()
Translate all basis sites so that they are inside the unit cell.
const Lattice & lattice() const
void push_back(Site const &_site, COORD_TYPE mode=CART)
Manually set the basis sites.
DoFSet const & global_dof(std::string const &dof_type) const
std::map< DoFKey, DoFSet > m_global_dof_map
continuous global degrees of freedom
bool is_time_reversal_active() const
Returns true if structure has attributes affected by time reversal.
const std::vector< Site > & basis() const
BasicStructure & operator=(const BasicStructure &RHS)
COORD_MODE specifies the current coordinate mode (Fractional or Cartesian)
void set(const COORD_TYPE new_mode)
Represents cartesian and fractional coordinates.
Definition: Coordinate.hh:34
const Eigen::Matrix3d & lat_column_mat() const
3x3 matrix with lattice vectors as its columne
Definition: Lattice.hh:110
void set_tol(double _tol)
Definition: Lattice.hh:197
double tol() const
Definition: Lattice.hh:195
void read(std::istream &stream)
Definition: Lattice.cc:136
Class representing a Molecule.
Definition: Molecule.hh:93
void read(std::istream &stream, bool SD_is_on=false)
Definition: Site.cc:262
static UnitCellCoord from_coordinate(const PrimType &, const Coordinate &coord, double tol)
std::string to_string(ENUM val)
Return string representation of enum class.
Definition: io_traits.hh:172
std::string const & name() const
Designated name of Molecule (may be unrelated to constituent species)
Definition: Molecule.hh:117
std::vector< DoFKey > all_local_dof_types(BasicStructure const &_struc)
std::vector< Molecule > struc_molecule(BasicStructure const &_struc)
Returns an Array of each possible Molecule in this Structure.
std::vector< DoFKey > all_dof_types(BasicStructure const &_struc)
std::vector< std::vector< std::string > > allowed_molecule_names(BasicStructure const &_struc)
Returns a vector with a list of allowed molecule names at each site.
bool has_strain_dof(BasicStructure const &structure)
std::vector< std::string > struc_species(BasicStructure const &_struc)
Returns an Array of each possible AtomSpecie in this Structure.
std::vector< std::vector< std::string > > allowed_molecule_unique_names(BasicStructure const &_struc)
Returns an Array of each possible Molecule in this Structure.
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.
DoFKey get_strain_dof_key(BasicStructure const &structure)
std::vector< std::string > struc_molecule_name(BasicStructure const &_struc)
Returns an Array of each possible Molecule in this Structure.
Index local_dof_dim(DoFKey const &_name, BasicStructure const &_struc)
std::map< DoFKey, Index > local_dof_dims(BasicStructure const &_struc)
std::vector< DoFKey > global_dof_types(BasicStructure const &_struc)
std::map< DoFKey, Index > global_dof_dims(BasicStructure const &_struc)
std::string get_strain_metric(DoFKey strain_dof_key)
ConfigIO::GenericConfigFormatter< jsonParser > structure()
Definition: ConfigIO.cc:766
GenericVectorXdScelFormatter lattice()
Definition: SupercellIO.cc:266
Index find_index(const std::vector< Site > &basis, const Site &test_site, double tol)
Main CASM namespace.
Definition: APICommand.hh:8
COORD_TYPE
Definition: enum.hh:6
const COORD_TYPE FRAC
Definition: enum.hh:8
std::string DoFKey
Definition: DoFDecl.hh:7
GenericDatumFormatter< std::string, DataObject > name()
Index find_index_if(Iterator begin, Iterator end, UnaryPredicate p)
Equivalent to std::distance(begin, std::find_if(begin, end, p))
Definition: algorithm.hh:53
bool contains(const Container &container, const T &value)
Equivalent to container.end() != std::find(container.begin(), container.end(), value)
Definition: algorithm.hh:83
const COORD_TYPE CART
Definition: enum.hh:9
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
T max(const T &A, const T &B)
Definition: CASM_math.hh:95