CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
ChemicalReference.hh
Go to the documentation of this file.
1 #ifndef CASM_ChemicalReference
2 #define CASM_ChemicalReference
3 
4 #include "casm/clex/Reference.hh"
5 #include "casm/misc/algorithm.hh"
6 #include "casm/clex/ConfigIO.hh"
7 
8 namespace CASM {
9 
10  class PrimClex;
11  class Structure;
12 
18  struct ChemicalReferenceState {
22 
24 
27  std::function<Eigen::VectorXd(Configuration)> n,
28  std::function<double(Configuration)> e);
29 
31  std::map<std::string, double> species_num;
32 
35  };
36 
37 
39 
40  public:
41 
42  typedef std::vector<ChemicalReferenceState> RefStateVec;
43  typedef std::map<std::string, RefStateVec> RefStateMap;
44  typedef Index size_type;
45 
46  static const std::string Name;
47  static const std::string Desc;
48 
49 
67  explicit ChemicalReference(const Structure &prim,
68  const Eigen::VectorXd &_global_ref,
69  SpecializedRef _supercell_ref = SpecializedRef(),
70  SpecializedRef _config_ref = SpecializedRef()) :
71  HyperPlaneReferenceBase(Name, Desc, _global_ref, ConfigIO::SpeciesFrac(), _supercell_ref, _config_ref),
72  m_prim(&prim) {}
73 
76  template<typename RefStateIterator>
77  explicit ChemicalReference(const Structure &prim,
78  RefStateIterator begin,
79  RefStateIterator end,
80  double tol) :
81  HyperPlaneReferenceBase(Name, Desc, Eigen::VectorXd::Zero(0), ConfigIO::AtomFrac()),
82  m_prim(&prim) {
83  set_global(begin, end, tol);
84  }
85 
86 
88  std::unique_ptr<ChemicalReference> clone() const {
89  return notstd::make_unique<ChemicalReference>(*this->_clone());
90  }
91 
93  const Structure &prim() const {
94  return *m_prim;
95  }
96 
97  // --- Global reference ---
98 
101  const Eigen::VectorXd &global() const {
103  }
104 
109  _global() = ref;
110  m_global_ref_vec.clear();
111  }
112 
125  template<typename RefStateIterator>
126  void set_global(RefStateIterator begin,
127  RefStateIterator end,
128  double tol) {
129  Eigen::VectorXd ref = hyperplane(*m_prim, begin, end, tol);
130  m_global_ref_vec = RefStateVec(begin, end);
131  _global() = ref;
132  }
133 
139  const RefStateVec &global_ref_states() const {
140  return m_global_ref_vec;
141  }
142 
143 
144  // --- Supercell specialized references ---
145 
149  const std::map<std::string, Eigen::VectorXd> &supercell() const {
151  }
152 
156  void set_supercell(const std::string &scelname, const Eigen::VectorXd &ref) {
157  _supercell()[scelname] = ref;
158  m_supercell_ref_map.erase(scelname);
159  }
160 
164  template<typename RefStateIterator>
165  void set_supercell(const std::string &scelname,
166  RefStateIterator begin,
167  RefStateIterator end,
168  double tol) {
169  Eigen::VectorXd ref = hyperplane(*m_prim, begin, end, tol);
171  _supercell()[scelname] = ref;
172  }
173 
175  size_type erase_supercell(const std::string &scelname) {
176  auto result = _supercell().erase(scelname);
177  m_supercell_ref_map.erase(scelname);
178  return result;
179  }
180 
186  const RefStateMap &supercell_ref_states() const {
187  return m_supercell_ref_map;
188  }
189 
190 
191  // --- Configuration specialized references ---
192 
193 
197  const std::map<std::string, Eigen::VectorXd> &config() const {
199  }
200 
204  void set_config(const std::string &configname, const Eigen::VectorXd &ref) {
205  _config()[configname] = ref;
206  m_config_ref_map.erase(configname);
207  }
208 
212  template<typename RefStateIterator>
213  void set_config(const std::string &configname,
214  RefStateIterator begin,
215  RefStateIterator end,
216  double tol) {
217  Eigen::VectorXd ref = hyperplane(*m_prim, begin, end, tol);
218  m_config_ref_map[configname] = RefStateVec(begin, end);
219  _config()[configname] = ref;
220  }
221 
223  size_type erase_config(const std::string &configname) {
224  auto result = _config().erase(configname);
225  m_config_ref_map.erase(configname);
226  return result;
227  }
228 
234  const RefStateMap &config_ref_states() const {
235  return m_config_ref_map;
236  }
237 
238 
249  template<typename RefStateIterator>
250  static Eigen::VectorXd hyperplane(const Structure &prim,
251  RefStateIterator begin,
252  RefStateIterator end,
253  double tol);
254 
255  private:
256 
261  }
262 
266  std::map<std::string, Eigen::VectorXd> &_supercell() {
268  }
269 
273  std::map<std::string, Eigen::VectorXd> &_config() {
275  }
276 
277 
278  // --- For use in hyperplane() ------
279 
282  const Structure &prim,
283  const std::vector<std::string> &struc_mol_name,
284  Eigen::MatrixXd N,
285  Eigen::VectorXd E,
286  double tol);
287 
290  return new ChemicalReference(*this);
291  }
292 
293  // \brief non-owning pointer to const primitive Structure
295 
296 
297  // --- Store ChemicalReferenceState if known ----
298 
299  RefStateVec m_global_ref_vec;
300  RefStateMap m_supercell_ref_map;
301  RefStateMap m_config_ref_map;
302  };
303 
306  ChemicalReference auto_chemical_reference(const PrimClex &primclex, double lin_alg_tol);
307 
310 
311  // -- constructor --
312  ChemicalReferencePrinter(std::ostream &_stream,
313  const ChemicalReference &_ref,
314  int _indent = 0,
315  int _indent_incr = 2) :
316  stream(_stream),
317  indent(_indent),
318  indent_incr(_indent_incr),
319  ref(_ref),
320  struc_mol_name(ref.prim().get_struc_molecule_name()) {}
321 
322  // -- data --
323  std::ostream &stream;
324  int indent;
327  std::vector<std::string> struc_mol_name;
328 
329 
330  void incr() {
331  indent += indent_incr;
332  }
333 
334  void decr() {
335  indent -= indent_incr;
336  }
337 
338  // print regular string
339  void print(const std::string &str) {
340  stream << std::string(indent, ' ') << str << "\n";
341  }
342 
343  // print plane as '<indent>mol_i(1): energy_per_species\n', for each molecule
344  void print(const Eigen::VectorXd &plane) {
345  for(int i = 0; i < plane.size(); ++i) {
346  if(!is_vacancy(struc_mol_name[i])) {
347  stream << std::string(indent, ' ') << struc_mol_name[i] << "(1): " << plane(i) << "\n";
348  }
349  }
350  }
351 
352  // print plane as:
353  // \code
354  // <indent>mol_i(N_i)mol_j(N_j)...: energy_per_species //for each ref state
355  // ...
356  // \endcode
357  void print(const std::vector<ChemicalReferenceState> &ref_state_vec) {
358  for(auto it = ref_state_vec.begin(); it != ref_state_vec.end(); ++it) {
359 
360  const ChemicalReferenceState &ref_state = *it;
361 
362  stream << std::string(indent, ' ');
363  for(auto it = ref_state.species_num.begin(); it != ref_state.species_num.end(); ++it) {
364  double num = it->second;
365  if(almost_zero(num, 1e-14)) {
366  continue;
367  }
368 
369  stream << it->first << "(";
370  // print integer if ~integer
371  if(almost_equal(std::round(num), num, 1e-14)) {
372  stream << std::lround(num);
373  }
374  else {
375  stream << num;
376  }
377  stream << ")";
378 
379  }
380  stream << ": " << ref_state.energy_per_species << "\n";
381  }
382  }
383 
384  // print supercell/config specific plane as:
385  // \code
386  // <indent>name:
387  // <indent> mol_i: energy_per_species // for each molecule
388  // \endcode
389  void print(const std::pair<std::string, Eigen::VectorXd> &_pair) {
390  stream << std::string(indent, ' ') << _pair.first << ":\n";
391  incr();
392  print(_pair.second);
393  decr();
394  }
395 
396  // print supercell/config specific ref states as:
397  // \code
398  // <indent>name:
399  // <indent> mol_i(N_i)mol_j(N_j)...: energy_per_species // for each ref state
400  // \endcode
401  void print(const std::pair<std::string, std::vector<ChemicalReferenceState> > &_pair) {
402  stream << std::string(indent, ' ') << _pair.first << ":\n";
403  incr();
404  print(_pair.second);
405  decr();
406  }
407 
408  void print_global() {
409  print("Global chemical reference:");
410  incr();
411  (ref.global_ref_states().empty()) ? print(ref.global()) : print(ref.global_ref_states());
412  decr();
413  }
414 
416  if(ref.supercell().size()) {
417  print("Supercell specific chemical references:");
418  for(auto it = ref.supercell().begin(); it != ref.supercell().end(); ++it) {
419  print_supercell(it->first);
420  }
421  }
422  }
423 
424  void print_supercell(const std::string &name) {
425  auto it = ref.supercell().find(name);
426  auto res = ref.supercell_ref_states().find(name);
427  auto ref_state_end = ref.supercell_ref_states().end();
428  (res != ref_state_end) ? print(*res) : print(*it);
429  }
430 
431  void print_config() {
432  if(ref.config().size()) {
433  print("Configuration specific chemical references:");
434  for(auto it = ref.config().begin(); it != ref.config().end(); ++it) {
435  print_config(it->first);
436  }
437  }
438  }
439 
440  void print_config(const std::string &name) {
441  auto it = ref.config().find(name);
442  auto res = ref.config_ref_states().find(name);
443  auto ref_state_end = ref.config_ref_states().end();
444  (res != ref_state_end) ? print(*res) : print(*it);
445  }
446 
447  void print_all() {
448  print_global();
449  if(ref.supercell().size()) {
450  print("");
451  print_supercell();
452  }
453  if(ref.config().size()) {
454  print("");
455  print_config();
456  }
457  }
458  };
459 
460 
471  template<typename RefStateIterator>
473  RefStateIterator begin,
474  RefStateIterator end,
475  double tol) {
476 
477  // store Molecule names in vector
478  std::vector<std::string> struc_mol_name = prim.get_struc_molecule_name();
479 
480  // --- find any Molecule not in the prim, add to end of vector -------------
481 
482  // increase struc_mol_name to include all Molecule names in input
483  // ensure no vacancies included
484  for(auto it = begin; it != end; ++it) {
485  for(auto mol_it = it->species_num.begin(); mol_it != it->species_num.end(); ++mol_it) {
486  if(is_vacancy(mol_it->first)) {
487  throw std::runtime_error("Error in ChemicalReference::hyperplane: Input should not include vacancies");
488  }
489  if(!contains(struc_mol_name, mol_it->first)) {
490  struc_mol_name.push_back(mol_it->first);
491  }
492  }
493  }
494 
495  // --- initialize vectors, matrices ----------------------------------------
496 
497  // reference 'relaxed_energy_per_species'
498  Eigen::VectorXd E = Eigen::VectorXd::Zero(std::distance(begin, end));
499 
500  // column vector matrix of number of each Molecule in each reference state
501  Eigen::MatrixXd N = Eigen::MatrixXd::Zero(struc_mol_name.size(), std::distance(begin, end));
502 
503 
504  // --- get input values ---------------------------------------------------
505 
506  // populate E, N
507  Index index = 0;
508  for(auto it = begin; it != end; ++it, ++index) {
509  E(index) = it->energy_per_species;
510  for(auto mol_it = it->species_num.begin(); mol_it != it->species_num.end(); ++mol_it) {
511  N(find_index(struc_mol_name, mol_it->first), index) = mol_it->second;
512  }
513  }
514 
515  // use E, N to calculate hyperplane
516  return _calc_hyperplane(prim, struc_mol_name, N, E, tol);
517  }
518 
520 }
521 
522 #endif
Eigen::MatrixXd MatrixXd
AtomFrac SpeciesFrac
In the future, AtomFrac will actually be atoms only.
Definition: ConfigIO.hh:233
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 set_supercell(const std::string &scelname, RefStateIterator begin, RefStateIterator end, double tol)
Set hyperplane reference specialized for a Supercell.
double energy_per_species
Energy in this reference state.
ChemicalReference auto_chemical_reference(const PrimClex &primclex, double lin_alg_tol)
Automatically set ChemicalReference using calculated Configurations with 'extreme' compositions...
std::unique_ptr< ChemicalReference > clone() const
Clone.
const std::map< std::string, Eigen::VectorXd > & supercell() const
const Access a map of scelname to reference for Supercell specialized references
bool is_vacancy(const std::string &name)
A vacancy is any Specie/Molecule with (name == "VA" || name == "va" || name == "Va") ...
Definition: Molecule.hh:27
Structure specifies the lattice and atomic basis of a crystal.
Definition: Structure.hh:29
ChemicalReferencePrinter(std::ostream &_stream, const ChemicalReference &_ref, int _indent=0, int _indent_incr=2)
PrimClex * primclex
Definition: settings.cc:101
std::vector< ChemicalReferenceState > RefStateVec
void print(const std::pair< std::string, Eigen::VectorXd > &_pair)
const RefStateMap & config_ref_states() const
const Access a map of configname to RefStateVec for Configuration specialized references ...
void print(const std::pair< std::string, std::vector< ChemicalReferenceState > > &_pair)
Index find_index(Iterator begin, Iterator end, const T &value)
Equivalent to std::distance(begin, std::find(begin, end, value))
Definition: algorithm.hh:16
void print(const std::vector< ChemicalReferenceState > &ref_state_vec)
static const std::string Name
Main CASM namespace.
Definition: complete.cpp:8
std::map< std::string, double > species_num
Map of Molecule name : number of each species in reference state.
static const std::string Desc
void print_supercell(const std::string &name)
ChemicalReference(const Structure &prim, RefStateIterator begin, RefStateIterator end, double tol)
Construct global reference via range ChemicalReferenceState.
std::map< std::string, Eigen::VectorXd > SpecializedRef
Definition: Reference.hh:78
std::vector< std::string > get_struc_molecule_name() const
Returns an Array of each possible Molecule in this Structure.
Definition: Structure.cc:166
pair_type ref
Definition: settings.cc:110
const std::map< std::string, Eigen::VectorXd > & config() const
const Access a map of configname to reference for Configuration specialized references ...
void print_config(const std::string &name)
double tol
void set_supercell(const std::string &scelname, const Eigen::VectorXd &ref)
Set hyperplane reference specialized for a Supercell.
size_type erase_config(const std::string &configname)
Erase hyperplane reference specialized for a Configuration.
const std::map< std::string, Eigen::VectorXd > & supercell() const
const Access a map of scelname to reference for Supercell specialized references
Definition: Reference.hh:128
void set_config(const std::string &configname, const Eigen::VectorXd &ref)
Set hyperplane reference specialized for a Configuration.
static Eigen::VectorXd _calc_hyperplane(const Structure &prim, const std::vector< std::string > &struc_mol_name, Eigen::MatrixXd N, Eigen::VectorXd E, double tol)
Convert a set of ChemicalReferenceState to a hyperplane, including checks.
EigenIndex Index
For long integer indexing:
Eigen::VectorXd & _global()
Access the global reference.
std::vector< std::string > struc_mol_name
Eigen::CwiseUnaryOp< decltype(std::ptr_fun(boost::math::lround< typename Derived::Scalar >)), const Derived > lround(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd to Eigen::MatrixXl.
std::map< std::string, Eigen::VectorXd > & _supercell()
const Access a map of scelname to reference for Supercell specialized references
Eigen::VectorXd VectorXd
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:52
void set_global(RefStateIterator begin, RefStateIterator end, double tol)
Set global hyperplane reference.
static Eigen::VectorXd hyperplane(const Structure &prim, RefStateIterator begin, RefStateIterator end, double tol)
Convert a set of ChemicalReferenceState to a hyperplane, including checks.
void print(const Eigen::VectorXd &plane)
size_type erase_supercell(const std::string &scelname)
Erase hyperplane reference specialized for a Supercell.
Structure to help print ChemicalReference.
const Eigen::VectorXd & global() const
const Access the global reference
ConfigIO::GenericConfigFormatter< std::string > configname()
Constructs DataFormmaterDictionary containing all Configuration DatumFormatters.
Definition: ConfigIO.cc:340
const RefStateVec & global_ref_states() const
const Access a map of configname to RefStateVec for Supercell specialized references ...
void set_global(const Eigen::VectorXd &ref)
Set global hyperplane reference.
Stores the composition and energy in a single reference state.
std::map< std::string, RefStateVec > RefStateMap
const Eigen::VectorXd & global() const
const Access the global reference
Definition: Reference.hh:120
const RefStateMap & supercell_ref_states() const
const Access a map of configname to RefStateVec for Supercell specialized references ...
Maps a Configuration to a scalar value via a hyperplane.
Definition: Reference.hh:74
std::map< std::string, Eigen::VectorXd > & _config()
const Access a map of configname to reference for Configuration specialized references ...
void print(const std::string &str)
ChemicalReference(const Structure &prim, const Eigen::VectorXd &_global_ref, SpecializedRef _supercell_ref=SpecializedRef(), SpecializedRef _config_ref=SpecializedRef())
Constructor.
const Structure & prim() const
Get primitive Structure.
ConfigIO::GenericConfigFormatter< std::string > scelname()
Definition: ConfigIO.cc:348
bool contains(const Container &container, const T &value)
Equivalent to container.end() != std::find(container.begin(), container.end(), value) ...
Definition: algorithm.hh:66
ChemicalReference * _clone() const
Clone.
const std::map< std::string, Eigen::VectorXd > & config() const
const Access a map of configname to reference for Configuration specialized references ...
Definition: Reference.hh:135
void set_config(const std::string &configname, RefStateIterator begin, RefStateIterator end, double tol)
Set hyperplane reference specialized for a Configuration.
bool almost_equal(const GenericCluster< CoordType > &LHS, const GenericCluster< CoordType > &RHS, double tol)
A Configuration represents the values of all degrees of freedom in a Supercell.
int round(double val)
Definition: CASM_math.cc:6
const ChemicalReference & ref