CASM  1.1.0
A Clusters Approach to Statistical Mechanics
ChemicalReference.cc
Go to the documentation of this file.
4 #include "casm/clex/ConfigIO.hh"
6 #include "casm/clex/PrimClex.hh"
9 #include "casm/misc/algorithm.hh"
10 
11 namespace CASM {
12 namespace {
13 typedef std::vector<ChemicalReferenceState>::iterator RefStateIterator;
14 }
15 template ChemicalReference::ChemicalReference(const BasicStructure &,
16  RefStateIterator,
17  RefStateIterator, double);
18 template void ChemicalReference::set_config<RefStateIterator>(
19  const std::string &, RefStateIterator, RefStateIterator, double);
20 template void ChemicalReference::set_supercell<RefStateIterator>(
21  const std::string &, RefStateIterator, RefStateIterator, double);
22 template void ChemicalReference::set_global<RefStateIterator>(RefStateIterator,
23  RefStateIterator,
24  double);
25 
31  const Configuration &config,
32  std::function<Eigen::VectorXd(Configuration)> n,
33  std::function<double(Configuration)> e) {
34  auto names = xtal::struc_molecule_name(config.prim());
35  auto vec = n(config);
36 
37  if (vec.size() != names.size()) {
38  std::cerr << "Error constructing ChemicalReferenceState: Number of species "
39  "!= vec.size()\n";
40  std::cerr << " struc_molecule_name: " << names << "\n";
41  std::cerr << " n(config): " << vec << std::endl;
42  throw std::runtime_error(
43  "Error constructing ChemicalReferenceState: Number of species != "
44  "vec.size()");
45  }
46 
47  for (int i = 0; i < names.size(); ++i) {
48  if (!xtal::is_vacancy(names[i])) {
49  species_num[names[i]] = vec(i);
50  }
51  }
53 }
54 
55 // --- ChemicalReference implementations -----------
56 
57 const std::string ChemicalReference::Name = "chem_ref";
58 
59 const std::string ChemicalReference::Desc =
60  "Returns a reference energy as interpolated via a composition-energy "
61  "hyperplane.";
62 
63 namespace {
64 
65 Eigen::MatrixXd _species_frac_matrix(
66  const PrimClex &primclex, const std::vector<std::string> &ref_config) {
68  ref_config.size());
69  for (int i = 0; i < ref_config.size(); ++i) {
70  _N.col(i) = species_frac(*primclex.db<Configuration>().find(ref_config[i]));
71  }
72  return _N;
73 }
74 
75 Eigen::MatrixXd _species_frac_space(const Eigen::MatrixXd &_N) {
76  // The input space
77  Eigen::MatrixXd N(_N.rows(), _N.cols() - 1);
78  for (int i = 0; i < N.cols(); i++) {
79  N.col(i) = _N.col(i + 1) - _N.col(0);
80  }
81  return N;
82 }
83 
84 int _rank(const Eigen::MatrixXd &N, double lin_alg_tol) {
85  auto Qr = N.transpose().fullPivHouseholderQr();
86  Qr.setThreshold(lin_alg_tol);
87  return Qr.rank();
88 }
89 
90 // Eliminate ref config until the rank of the defined species_frac space
91 // is the same as the number of ref config.
92 void _prune_ref_config(const PrimClex &primclex,
93  std::vector<std::string> &ref_config,
94  double lin_alg_tol) {
95  // Each column of _N is the species_frac of the corresponding ref config
96  Eigen::MatrixXd _N = _species_frac_matrix(primclex, ref_config);
97 
98  // Contains vectors spanning the space defined by the ref config
99  // N has _N.cols() - 1 columns, with N.col(i) being _N.col(i) - _N.col(0)
100  Eigen::MatrixXd N = _species_frac_space(_N);
101 
102  while (_rank(N, lin_alg_tol) != N.cols()) {
103  // remove ref_config whose summed distance in species_frac space to all
104  // others is the minimum
105  double min_dist = std::numeric_limits<double>::max();
106  double min_dist_ref = -1;
107  for (int i = 0; i < ref_config.size(); ++i) {
108  double tot_dist = 0.0;
109  for (int j = 0; j < ref_config.size(); ++j) {
110  if (i != j) {
111  tot_dist += (_N.col(i) - _N.col(j)).norm();
112  }
113  }
114  if (tot_dist < min_dist) {
115  min_dist_ref = i;
116  min_dist = tot_dist;
117  }
118  }
119 
120  ref_config.erase(ref_config.begin() + min_dist_ref);
121  _N = _species_frac_matrix(primclex, ref_config);
122  N = _species_frac_space(_N);
123  }
124 }
125 
126 } // namespace
127 
146  const Eigen::VectorXd &_global_ref,
147  SpecializedRef _supercell_ref,
148  SpecializedRef _config_ref)
149  : HyperPlaneReferenceBase(Name, Desc, _global_ref, ConfigIO::SpeciesFrac(),
150  _supercell_ref, _config_ref),
151  m_prim(&prim) {}
152 
154 std::unique_ptr<ChemicalReference> ChemicalReference::clone() const {
155  return notstd::make_unique<ChemicalReference>(*this->_clone());
156 }
157 
159 const BasicStructure &ChemicalReference::prim() const { return *m_prim; }
160 
161 // --- Global reference ---
162 
167 }
168 
173  _global() = ref;
174  m_global_ref_vec.clear();
175 }
176 
183  const {
184  return m_global_ref_vec;
185 }
186 
187 // --- Supercell specialized references ---
188 
192 const std::map<std::string, Eigen::VectorXd> &ChemicalReference::supercell()
193  const {
195 }
196 
201  const Eigen::VectorXd &ref) {
202  _supercell()[scelname] = ref;
204 }
205 
208  const std::string &scelname) {
209  auto result = _supercell().erase(scelname);
211  return result;
212 }
213 
220  const {
221  return m_supercell_ref_map;
222 }
223 
224 // --- Configuration specialized references ---
225 
229 const std::map<std::string, Eigen::VectorXd> &ChemicalReference::config()
230  const {
232 }
233 
238  const Eigen::VectorXd &ref) {
239  _config()[configname] = ref;
241 }
242 
245  const std::string &configname) {
246  auto result = _config().erase(configname);
248  return result;
249 }
250 
257  const {
258  return m_config_ref_map;
259 }
260 
265 }
266 
270 std::map<std::string, Eigen::VectorXd> &ChemicalReference::_supercell() {
272 }
273 
277 std::map<std::string, Eigen::VectorXd> &ChemicalReference::_config() {
279 }
280 
281 // --- For use in hyperplane() ------
282 
285  return new ChemicalReference(*this);
286 }
287 
291  const BasicStructure &prim, const std::vector<std::string> &struc_mol_name,
292  Eigen::MatrixXd _N, Eigen::VectorXd E, double tol) {
293  // --- convert input compositions to atom_frac
294 
295  Index Va_index = find_index_if(struc_mol_name, [=](const std::string &str) {
296  return xtal::is_vacancy(str);
297  });
298  bool has_Va = (Va_index != struc_mol_name.size());
299 
300  if (has_Va) {
301  _N.row(Va_index) = Eigen::VectorXd::Zero(_N.cols());
302  }
303  for (int i = 0; i < _N.cols(); i++) {
304  _N.col(i) /= _N.col(i).sum();
305  }
306 
307  // --- check that the input space is full rank (excluding Va) --------------
308 
309  // The input space
310  Eigen::MatrixXd N = _species_frac_space(_N);
311 
312  int r = _rank(N, tol);
313 
314  if (r != N.cols()) {
315  std::cerr << "Error in ChemicalReference::hyperplane " << std::endl;
316  std::cerr << "Input space (column vectors of atom_frac):\n"
317  << N << std::endl;
318  std::cerr << "Rows correspond to: " << jsonParser(struc_mol_name)
319  << std::endl;
320  std::cerr << "Input space rank: " << r << std::endl;
321  throw std::runtime_error(
322  "Error in ChemicalReference::hyperplane: Too many reference states "
323  "specified");
324  }
325 
326  // --- check that the input space spans the prim space --------------------
327 
328  // get the prim composition space (column vectors are comp_n)
330 
331  Index prim_N_mol = struc_mol_name.size();
332 
333  // ensure that there is a solution X for:
334  // C = N.topRows(prim_N_mol) * X
335  // (prim_space = input_space involving prim species * X)
336  Eigen::MatrixXd X = N.topRows(prim_N_mol).fullPivHouseholderQr().solve(C);
337 
338  double relative_error = (N.topRows(prim_N_mol) * X - C).norm() / C.norm();
339 
340  if (relative_error > tol) {
341  std::cerr << "Error in ChemicalReference::hyperplane " << std::endl;
342  std::cerr << "Input space does not span the composition space of your prim."
343  << std::endl;
344 
345  std::cerr << "Input space (column vectors in atom_frac space):\n"
346  << N.topRows(prim_N_mol) << std::endl;
347  std::cerr << "End members:\n"
348  << end_members(allowed_molecule_names(prim)) << std::endl;
349  std::cerr << "Prim space (column vectors in atom_frac space):\n"
350  << C << std::endl;
351  std::cerr << "Rows correspond to: " << jsonParser(struc_mol_name)
352  << std::endl;
353  std::cerr << "X, prim_space = input_space*X: \n" << X << std::endl;
354  std::cerr << "input_space*X: \n" << N.topRows(prim_N_mol) * X << std::endl;
355  std::cerr << "relative_error: " << relative_error << std::endl;
356  std::cerr << "tol: " << tol << std::endl;
357 
358  throw std::runtime_error(
359  "Error in ChemicalReference::hyperplane: Input space does not span "
360  "prim space");
361  }
362 
363  // --- solve N.transpose() * P = E, for P, the hyperplane reference --------
364 
365  Eigen::VectorXd P = _N.transpose().fullPivHouseholderQr().solve(E);
366 
367  relative_error = (_N.transpose() * P - E).norm() / E.norm();
368 
369  if (relative_error > tol) {
370  std::cerr << "Error in ChemicalReference::hyperplane " << std::endl;
371  std::cerr << "Could not solve for hyperplane reference." << std::endl;
372 
373  std::cerr << "Input space (column vectors in atom_frac space), N:\n"
374  << N << std::endl;
375  std::cerr << "Rows correspond to: " << jsonParser(struc_mol_name)
376  << std::endl;
377  std::cerr << "Solve: _N.transpose()*P = E" << std::endl;
378  std::cerr << "_N.transpose():\n" << _N.transpose() << std::endl;
379  std::cerr << "Reference state energies, E:\n" << E << std::endl;
380  std::cerr << "P:\n" << P.transpose() << std::endl;
381  std::cerr << "relative_err: " << relative_error << std::endl;
382  std::cerr << "tol: " << tol << std::endl;
383 
384  throw std::runtime_error(
385  "Error in ChemicalReference::hyperplane: Could not solve for "
386  "hyperplane reference");
387  }
388 
389  if (has_Va && !almost_zero(P(Va_index))) {
390  std::cerr << "Error in ChemicalReference::hyperplane " << std::endl;
391  std::cerr << "Non-zero pure Va reference: " << P.transpose() << std::endl;
392  std::cerr << "Elements correspond to: " << jsonParser(struc_mol_name)
393  << std::endl;
394 
395  throw std::runtime_error(
396  "Error in ChemicalReference::hyperplane: Input space does not span "
397  "prim space");
398  }
399 
400  return P.head(prim_N_mol);
401 }
402 
406  double lin_alg_tol) {
407  auto closest_calculated_config = [&](const Eigen::VectorXd &target) {
408  // return name of Configuration with param_comp closest to target_param_comp
409  // tie break goes to first Configuration with fewest atoms
410  //
411  // must be Configurations for which the energy has been calculated
412  auto begin = primclex.db<Configuration>().begin();
413  auto end = primclex.db<Configuration>().end();
414  auto res = end;
415 
416  double close_dist = std::numeric_limits<double>::max();
417 
418  for (auto it = begin; it != end; ++it) {
419  if (!it->calc_properties().has_scalar("energy")) {
420  continue;
421  }
422  double curr_dist = (target - comp(*it)).norm();
423  if ((res == end) ||
424  (almost_equal(curr_dist, close_dist, TOL) &&
425  it->size() < res->size()) ||
426  (curr_dist < close_dist)) {
427  res = it;
428  close_dist = curr_dist;
429  }
430  }
431 
432  if (res == end) {
433  std::cerr << "Error in auto_chemical_reference: Could not find any "
434  "configurations\n";
435  throw std::runtime_error(
436  "Error in auto_chemical_reference: Could not find any "
437  "configurations");
438  }
439  return res->name();
440  };
441 
442  // get number of reference states needed minus one... we'll also look for the
443  // 'origin'
445  Eigen::VectorXd target = Eigen::VectorXd::Zero(Naxes);
446 
447  // get 'origin' configuration
448  std::vector<std::string> ref_config;
449  ref_config.push_back(closest_calculated_config(target));
450 
451  for (int i = 0; i < Naxes; i++) {
452  target(i) = 1.0;
453 
454  // get end member configurations
455  std::string configname = closest_calculated_config(target);
456 
457  // ensure no repeats
458  if (std::find(ref_config.begin(), ref_config.end(), configname) !=
459  ref_config.end()) {
460  std::cerr << "Error in auto_chemical_reference: Could not find enough "
461  "calculated configurations\n";
462  throw std::runtime_error(
463  "Error in auto_chemical_reference: Could not find enough calculated "
464  "configurations");
465  }
466 
467  ref_config.push_back(configname);
468 
469  target(i) = 0.0;
470  }
471 
472  // make sure there are the right number of references in species_frac space
473  // (may be 1 extra if pure Va configuration is possible)
474  _prune_ref_config(primclex, ref_config, lin_alg_tol);
475 
476  // construct ChemicalReferenceState
477  std::vector<ChemicalReferenceState> ref_states;
478  for (auto it = ref_config.begin(); it != ref_config.end(); ++it) {
479  ref_states.emplace_back(*primclex.db<Configuration>().find(*it),
482  }
483 
484  return ChemicalReference(primclex.prim(), ref_states.begin(),
485  ref_states.end(), lin_alg_tol);
486 }
487 
488 // --- ChemicalReferencePrinter implementations -----------
489 
491  std::ostream &_stream, const ChemicalReference &_ref, int _indent,
492  int _indent_incr)
493  : stream(_stream),
494  indent(_indent),
495  indent_incr(_indent_incr),
496  ref(_ref),
497  struc_mol_name(xtal::struc_molecule_name(ref.prim())) {}
498 
500 
502 
503 // print regular string
504 void ChemicalReferencePrinter::print(const std::string &str) {
505  stream << std::string(indent, ' ') << str << "\n";
506 }
507 
508 // print plane as '<indent>mol_i(1): energy_per_species\n', for each molecule
510  for (int i = 0; i < plane.size(); ++i) {
511  if (!xtal::is_vacancy(struc_mol_name[i])) {
512  stream << std::string(indent, ' ') << struc_mol_name[i]
513  << "(1): " << plane(i) << "\n";
514  }
515  }
516 }
517 
518 // print plane as:
519 // \code
520 // <indent>mol_i(N_i)mol_j(N_j)...: energy_per_species //for each ref state
521 // ...
522 // \endcode
524  const std::vector<ChemicalReferenceState> &ref_state_vec) {
525  for (auto it = ref_state_vec.begin(); it != ref_state_vec.end(); ++it) {
526  const ChemicalReferenceState &ref_state = *it;
527 
528  stream << std::string(indent, ' ');
529  for (auto it = ref_state.species_num.begin();
530  it != ref_state.species_num.end(); ++it) {
531  double num = it->second;
532  if (almost_zero(num, 1e-14)) {
533  continue;
534  }
535 
536  stream << it->first << "(";
537  // print integer if ~integer
538  if (almost_equal(std::round(num), num, 1e-14)) {
539  stream << std::lround(num);
540  } else {
541  stream << num;
542  }
543  stream << ")";
544  }
545  stream << ": " << ref_state.energy_per_species << "\n";
546  }
547 }
548 
549 // print supercell/config specific plane as:
550 // \code
551 // <indent>name:
552 // <indent> mol_i: energy_per_species // for each molecule
553 // \endcode
555  const std::pair<std::string, Eigen::VectorXd> &_pair) {
556  stream << std::string(indent, ' ') << _pair.first << ":\n";
557  incr();
558  print(_pair.second);
559  decr();
560 }
561 
562 // print supercell/config specific ref states as:
563 // \code
564 // <indent>name:
565 // <indent> mol_i(N_i)mol_j(N_j)...: energy_per_species // for each ref state
566 // \endcode
568  const std::pair<std::string, std::vector<ChemicalReferenceState> > &_pair) {
569  stream << std::string(indent, ' ') << _pair.first << ":\n";
570  incr();
571  print(_pair.second);
572  decr();
573 }
574 
576  print("Global chemical reference:");
577  incr();
578  (ref.global_ref_states().empty()) ? print(ref.global())
580  decr();
581 }
582 
584  if (ref.supercell().size()) {
585  print("Supercell specific chemical references:");
586  for (auto it = ref.supercell().begin(); it != ref.supercell().end(); ++it) {
587  print_supercell(it->first);
588  }
589  }
590 }
591 
593  auto it = ref.supercell().find(name);
594  auto res = ref.supercell_ref_states().find(name);
595  auto ref_state_end = ref.supercell_ref_states().end();
596  (res != ref_state_end) ? print(*res) : print(*it);
597 }
598 
600  if (ref.config().size()) {
601  print("Configuration specific chemical references:");
602  for (auto it = ref.config().begin(); it != ref.config().end(); ++it) {
603  print_config(it->first);
604  }
605  }
606 }
607 
609  auto it = ref.config().find(name);
610  auto res = ref.config_ref_states().find(name);
611  auto ref_state_end = ref.config_ref_states().end();
612  (res != ref_state_end) ? print(*res) : print(*it);
613 }
614 
616  print_global();
617  if (ref.supercell().size()) {
618  print("");
619  print_supercell();
620  }
621  if (ref.config().size()) {
622  print("");
623  print_config();
624  }
625 }
626 } // namespace CASM
const std::map< std::string, Eigen::VectorXd > & supercell() const
const Access a map of scelname to reference for Supercell specialized references
size_type erase_supercell(const std::string &scelname)
Erase hyperplane reference specialized for a Supercell.
std::map< std::string, Eigen::VectorXd > & _supercell()
const Access a map of scelname to reference for Supercell specialized references
const BasicStructure * m_prim
static Eigen::VectorXd _calc_hyperplane(const BasicStructure &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.
std::vector< ChemicalReferenceState > RefStateVec
void set_config(const std::string &configname, const Eigen::VectorXd &ref)
Set hyperplane reference specialized for a Configuration.
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.
const RefStateMap & config_ref_states() const
const Access a map of configname to RefStateVec for Configuration specialized references
static const std::string Desc
const std::map< std::string, Eigen::VectorXd > & config() const
const Access a map of configname to reference for Configuration specialized references
size_type erase_config(const std::string &configname)
Erase hyperplane reference specialized for a Configuration.
void set_supercell(const std::string &scelname, const Eigen::VectorXd &ref)
Set hyperplane reference specialized for a Supercell.
const Eigen::VectorXd & global() const
const Access the global reference
std::map< std::string, Eigen::VectorXd > & _config()
const Access a map of configname to reference for Configuration specialized references
std::unique_ptr< ChemicalReference > clone() const
Clone.
ChemicalReference(const BasicStructure &prim, const Eigen::VectorXd &_global_ref, SpecializedRef _supercell_ref=SpecializedRef(), SpecializedRef _config_ref=SpecializedRef())
Constructor.
const RefStateMap & supercell_ref_states() const
const Access a map of configname to RefStateVec for Supercell specialized references
ChemicalReference * _clone() const
Clone.
const BasicStructure & prim() const
Get primitive BasicStructure.
static const std::string Name
std::map< std::string, RefStateVec > RefStateMap
Eigen::VectorXd & _global()
Access the global reference.
size_type independent_compositions() const
The dimensionality of the composition space.
std::vector< std::string > components() const
The order of components in mol composition vectors.
Returns fraction of all species that are a particular species, excluding vacancies.
Definition: ConfigIO.hh:167
Maps a Configuration to a scalar value via a hyperplane.
Definition: Reference.hh:68
std::map< std::string, Eigen::VectorXd > SpecializedRef
Definition: Reference.hh:70
const std::map< std::string, Eigen::VectorXd > & supercell() const
const Access a map of scelname to reference for Supercell specialized references
Definition: Reference.hh:119
const Eigen::VectorXd & global() const
const Access the global reference
Definition: Reference.hh:114
const std::map< std::string, Eigen::VectorXd > & config() const
const Access a map of configname to reference for Configuration specialized references
Definition: Reference.hh:126
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:55
BasicStructure specifies the lattice and atomic basis of a crystal.
Eigen::VectorXd comp(const Configuration &config)
Returns parametric composition, as calculated using PrimClex::param_comp.
Eigen::VectorXd species_frac(const Configuration &config)
Returns the composition as species fraction, with [Va] = 0.0, in the order of Structure::get_struc_mo...
Eigen::CwiseUnaryOp< decltype(Local::lround_l< typename Derived::Scalar >), const Derived > lround(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd to Eigen::MatrixXl.
Eigen::CwiseUnaryOp< decltype(Local::round_l< typename Derived::Scalar >), const Derived > round(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd.
bool is_vacancy(const std::string &name)
A vacancy is any Specie/Molecule with (name == "VA" || name == "va" || name == "Va")
Definition: Molecule.hh:187
DB::Database< T > & db() const
Definition: PrimClex.cc:302
const CompositionConverter & composition_axes() const
const Access CompositionConverter object
Definition: PrimClex.cc:243
const PrimType & prim() const
const Access to primitive Structure
Definition: PrimClex.cc:262
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.
std::vector< std::string > struc_molecule_name(BasicStructure const &_struc)
Returns an Array of each possible Molecule in this Structure.
std::string scelname(const Structure &prim, const Lattice &superlat)
Make supercell name name [deprecated].
Definition: Supercell.cc:497
T norm(const Tensor< T > &ttens)
Definition: Tensor.hh:932
ConfigIO::GenericConfigFormatter< double > energy_per_species()
Definition: ConfigIO.cc:648
ConfigIO::GenericConfigFormatter< jsonParser > config()
Definition: ConfigIO.cc:777
AtomFrac SpeciesFrac
In the future, AtomFrac will actually be atoms only.
Definition: ConfigIO.hh:191
ConfigIO::GenericConfigFormatter< std::string > configname()
Constructs DataFormmaterDictionary containing all Configuration DatumFormatters.
Definition: ConfigIO.cc:563
Main CASM namespace.
Definition: APICommand.hh:8
bool almost_equal(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Check if ClusterInvariants are equal.
Eigen::MatrixXd MatrixXd
Eigen::MatrixXd composition_space(const ParamComposition::AllowedOccupants &_allowed_occs, double tol=1e-14)
Return the composition space of a ParamComposition::AllowedOccupants.
ChemicalReference auto_chemical_reference(const PrimClex &primclex, double lin_alg_tol)
Automatically set ChemicalReference using calculated Configurations with 'extreme' compositions.
const double TOL
Definition: definitions.hh:30
GenericDatumFormatter< std::string, DataObject > name()
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
Definition: CASM_math.hh:104
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
Iterator find(Iterator begin, Iterator end, const T &value, BinaryCompare q)
Equivalent to std::find(begin, end, value), but with custom comparison.
Definition: algorithm.hh:16
Eigen::MatrixXd end_members(const ParamComposition::AllowedOccupants &_allowed_occs)
Serialize CompositionConverter to JSON.
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
Eigen::VectorXd VectorXd
T max(const T &A, const T &B)
Definition: CASM_math.hh:95
pair_type ref
Definition: settings.cc:144
PrimClex * primclex
Definition: settings.cc:135
std::vector< std::string > struc_mol_name
void print(const std::string &str)
ChemicalReferencePrinter(std::ostream &_stream, const ChemicalReference &_ref, int _indent=0, int _indent_incr=2)
const ChemicalReference & ref
Stores the composition and energy in a single reference state.
std::map< std::string, double > species_num
Map of Molecule name : number of each species in reference state.
double energy_per_species
Energy in this reference state.