CASM  1.1.0
A Clusters Approach to Statistical Mechanics
GrandCanonicalSettings_impl.hh
Go to the documentation of this file.
1 #ifndef CASM_GrandCanonicalSettings_impl
2 #define CASM_GrandCanonicalSettings_impl
3 
4 #include <boost/algorithm/string/trim.hpp>
5 
9 #include "casm/clex/Supercell.hh"
12 
13 namespace CASM {
14 namespace Monte {
15 
21 template <typename SamplerInsertIterator>
22 SamplerInsertIterator GrandCanonicalSettings::samplers(
23  const PrimClex &primclex, SamplerInsertIterator result) const {
24  if (method() == Monte::METHOD::LTE1) { // hack
25  return result;
26  }
27 
28  size_type data_maxlength = max_data_length();
29  std::string prop_name;
30  std::string print_name;
31  bool must_converge;
32  double prec;
33  MonteSampler *ptr;
34 
35  // copy so we can add required measurements
36  std::string level1 = "data";
37  std::string level2 = "measurements";
38  jsonParser t_measurements = (*this)[level1][level2];
39 
40  // find existing measurements
41  std::set<std::string> input_measurements;
42  for (auto it = t_measurements.cbegin(); it != t_measurements.cend(); it++) {
43  input_measurements.insert((*it)["quantity"].get<std::string>());
44  }
45 
46  std::vector<std::string> required = {"potential_energy", "formation_energy",
47  "comp", "comp_n"};
48 
49  // add required if not already requested
50  for (auto it = required.begin(); it != required.end(); ++it) {
51  if (std::find(input_measurements.begin(), input_measurements.end(), *it) ==
52  input_measurements.end()) {
53  jsonParser json;
54  json["quantity"] = *it;
55  t_measurements.push_back(json);
56  }
57  }
58 
59  try {
60  for (auto it = t_measurements.cbegin(); it != t_measurements.cend(); it++) {
61  prop_name = (*it)["quantity"].get<std::string>();
62 
63  // scalar quantities that we incrementally update
64  std::vector<std::string> scalar_possible = {"formation_energy",
65  "potential_energy"};
66 
67  // check if property found is in list of possible scalar properties
68  if (std::find(scalar_possible.cbegin(), scalar_possible.cend(),
69  prop_name) != scalar_possible.cend()) {
70  std::tie(must_converge, prec) = _get_precision(it);
71 
72  // if 'must converge'
73  if (must_converge) {
74  ptr = new ScalarMonteSampler(prop_name, prop_name, prec, confidence(),
75  data_maxlength);
76  } else {
77  ptr = new ScalarMonteSampler(prop_name, prop_name, confidence(),
78  data_maxlength);
79  }
80 
81  *result++ =
82  std::make_pair(prop_name, notstd::cloneable_ptr<MonteSampler>(ptr));
83  continue;
84  }
85 
86  // scalar quantities that we incrementally update
87  std::vector<std::string> vector_possible = {
88  "comp", "comp_n", "site_frac",
89  "atom_frac", "all_correlations", "non_zero_eci_correlations"};
90 
91  // check if property found is in list of possible vector properties
92  if (std::find(vector_possible.cbegin(), vector_possible.cend(),
93  prop_name) != vector_possible.cend()) {
94  // construct MonteSamplers for 'comp'
95  if (prop_name == "comp") {
96  result = _make_comp_samplers(primclex, it, result);
97 
98  }
99 
100  // construct MonteSamplers for 'comp_n'
101  else if (prop_name == "comp_n") {
102  result = _make_comp_n_samplers(primclex, it, result);
103 
104  }
105 
106  // construct MonteSamplers for 'site_frac'
107  else if (prop_name == "site_frac") {
108  result = _make_site_frac_samplers(primclex, it, result);
109 
110  }
111 
112  // construct MonteSamplers for 'atom_frac'
113  else if (prop_name == "atom_frac") {
114  result = _make_atom_frac_samplers(primclex, it, result);
115 
116  }
117 
118  // construct MonteSamplers for 'all_correlations'
119  else if (prop_name == "all_correlations") {
120  result = _make_all_correlations_samplers(primclex, it, result);
121 
122  }
123 
124  // construct MonteSamplers for 'non_zero_eci_correlations'
125  else if (prop_name == "non_zero_eci_correlations") {
126  result =
128  }
129  continue;
130  }
131 
132  // custom query
133  _make_query_samplers(primclex, it, result);
134  }
135 
136  } catch (std::runtime_error &e) {
139  "'MonteSettings::samplers(const PrimClex &primclex, "
140  "SamplerInsertIterator result)'");
141  err_log << "Error reading [\"" << level1 << "\"][\"" << level2 << "\"]\n"
142  << std::endl;
143  throw;
144  }
145 
146  return result;
147 }
148 
149 template <typename jsonParserIteratorType>
150 std::tuple<bool, double> GrandCanonicalSettings::_get_precision(
151  jsonParserIteratorType it) const {
152  if (it->contains("precision")) {
153  return std::make_tuple(true, (*it)["precision"].template get<double>());
154  } else {
155  return std::make_tuple(false, 0.0);
156  }
157 }
158 
159 template <typename jsonParserIteratorType, typename SamplerInsertIterator>
161  const PrimClex &primclex, jsonParserIteratorType it,
162  SamplerInsertIterator result) const {
163  size_type data_maxlength = max_data_length();
164  std::string print_name;
165  bool must_converge;
166  double prec;
167  MonteSampler *ptr;
168 
169  for (size_type i = 0;
170  i < primclex.composition_axes().independent_compositions(); i++) {
171  print_name =
172  std::string("comp(") + std::string(1, (char)(i + ((int)'a'))) + ")";
173 
174  std::tie(must_converge, prec) = _get_precision(it);
175 
176  // if 'must converge'
177  if (must_converge) {
178  ptr = new CompMonteSampler(i, primclex.composition_axes(), print_name,
179  prec, confidence(), data_maxlength);
180  } else {
181  ptr = new CompMonteSampler(i, primclex.composition_axes(), print_name,
182  confidence(), data_maxlength);
183  }
184 
185  *result++ =
186  std::make_pair(print_name, notstd::cloneable_ptr<MonteSampler>(ptr));
187  }
188 
189  return result;
190 }
191 
192 template <typename jsonParserIteratorType, typename SamplerInsertIterator>
194  const PrimClex &primclex, jsonParserIteratorType it,
195  SamplerInsertIterator result) const {
196  size_type data_maxlength = max_data_length();
197  std::string prop_name;
198  std::string print_name;
199  bool must_converge;
200  double prec;
201  MonteSampler *ptr;
202 
203  for (size_type i = 0; i < primclex.composition_axes().components().size();
204  i++) {
205  prop_name = "comp_n";
206 
207  print_name = std::string("comp_n(") +
208  primclex.composition_axes().components()[i] + ")";
209 
210  std::tie(must_converge, prec) = _get_precision(it);
211 
212  // if 'must converge'
213  if (must_converge) {
214  ptr = new VectorMonteSampler(prop_name, i, print_name, prec, confidence(),
215  data_maxlength);
216  } else {
217  ptr = new VectorMonteSampler(prop_name, i, print_name, confidence(),
218  data_maxlength);
219  }
220 
221  *result++ =
222  std::make_pair(print_name, notstd::cloneable_ptr<MonteSampler>(ptr));
223  }
224 
225  return result;
226 }
227 
228 template <typename jsonParserIteratorType, typename SamplerInsertIterator>
230  const PrimClex &primclex, jsonParserIteratorType it,
231  SamplerInsertIterator result) const {
232  size_type data_maxlength = max_data_length();
233  std::string print_name;
234  bool must_converge;
235  double prec;
236  MonteSampler *ptr;
237 
238  for (size_type i = 0; i < primclex.composition_axes().components().size();
239  i++) {
240  // SiteFracMonteSampler uses 'comp_n' to calculate 'site_frac'
241  print_name = std::string("site_frac(") +
242  primclex.composition_axes().components()[i] + ")";
243 
244  std::tie(must_converge, prec) = _get_precision(it);
245 
246  // if 'must converge'
247  if (must_converge) {
248  ptr = new SiteFracMonteSampler(i, primclex.prim().basis().size(),
249  print_name, prec, confidence(),
250  data_maxlength);
251  } else {
252  ptr = new SiteFracMonteSampler(i, primclex.prim().basis().size(),
253  print_name, confidence(), data_maxlength);
254  }
255 
256  *result++ =
257  std::make_pair(print_name, notstd::cloneable_ptr<MonteSampler>(ptr));
258  }
259 
260  return result;
261 }
262 
263 template <typename jsonParserIteratorType, typename SamplerInsertIterator>
265  const PrimClex &primclex, jsonParserIteratorType it,
266  SamplerInsertIterator result) const {
267  size_type data_maxlength = max_data_length();
268  std::string print_name;
269  bool must_converge;
270  double prec;
271  MonteSampler *ptr;
272 
273  // find the index for vacancies, if they are allowed,
274  // if not set to primclex.composition_axes().components().size()
275 
276  size_type vacancy_index = primclex.composition_axes().components().size();
277  for (size_type i = 0; i < primclex.composition_axes().components().size();
278  i++) {
279  // sample for non-vacancy components
281  vacancy_index = i;
282  break;
283  }
284  }
285 
286  for (size_type i = 0; i < primclex.composition_axes().components().size();
287  i++) {
288  // sample for non-vacancy components
290  print_name = std::string("atom_frac(") +
291  primclex.composition_axes().components()[i] + ")";
292 
293  std::tie(must_converge, prec) = _get_precision(it);
294 
295  // if 'must converge'
296  if (must_converge) {
297  ptr = new AtomFracMonteSampler(i, vacancy_index, print_name, prec,
298  confidence(), data_maxlength);
299  } else {
300  ptr = new AtomFracMonteSampler(i, vacancy_index, print_name,
301  confidence(), data_maxlength);
302  }
303 
304  *result++ =
305  std::make_pair(print_name, notstd::cloneable_ptr<MonteSampler>(ptr));
306  }
307  }
308 
309  return result;
310 }
311 
312 template <typename jsonParserIteratorType, typename SamplerInsertIterator>
314  const PrimClex &primclex, jsonParserIteratorType it,
315  SamplerInsertIterator result) const {
316  size_type data_maxlength = max_data_length();
317  std::string prop_name;
318  std::string print_name;
319  bool must_converge;
320  double prec;
321  MonteSampler *ptr;
322 
323  for (size_type i = 0;
325  i++) {
326  prop_name = "corr";
327  print_name = std::string("corr(") + std::to_string(i) + ")";
328 
329  std::tie(must_converge, prec) = _get_precision(it);
330 
331  // if 'must converge'
332  if (must_converge) {
333  ptr = new VectorMonteSampler(prop_name, i, print_name, prec, confidence(),
334  data_maxlength);
335  } else {
336  ptr = new VectorMonteSampler(prop_name, i, print_name, confidence(),
337  data_maxlength);
338  }
339 
340  *result++ =
341  std::make_pair(print_name, notstd::cloneable_ptr<MonteSampler>(ptr));
342  }
343 
344  return result;
345 }
346 
347 template <typename jsonParserIteratorType, typename SamplerInsertIterator>
348 SamplerInsertIterator
350  const PrimClex &primclex, jsonParserIteratorType it,
351  SamplerInsertIterator result) const {
352  size_type data_maxlength = max_data_length();
353  std::string prop_name;
354  std::string print_name;
355  bool must_converge;
356  double prec;
357 
358  MonteSampler *ptr;
359 
361 
362  for (size_type ii = 0; ii < _eci.index().size(); ii++) {
363  prop_name = "corr";
364 
365  // store non-zero eci index in i
366  size_type i = _eci.index()[ii];
367 
368  print_name = std::string("corr(") + std::to_string(i) + ")";
369 
370  std::tie(must_converge, prec) = _get_precision(it);
371 
372  // if 'must converge'
373  if (must_converge) {
374  ptr = new VectorMonteSampler(prop_name, i, print_name, prec, confidence(),
375  data_maxlength);
376  } else {
377  ptr = new VectorMonteSampler(prop_name, i, print_name, confidence(),
378  data_maxlength);
379  }
380 
381  *result++ =
382  std::make_pair(print_name, notstd::cloneable_ptr<MonteSampler>(ptr));
383  }
384 
385  return result;
386 }
387 
388 template <typename jsonParserIteratorType, typename SamplerInsertIterator>
390  const PrimClex &primclex, jsonParserIteratorType it,
391  SamplerInsertIterator result) const {
392  size_type data_maxlength = max_data_length();
393  double must_converge;
394  double prec;
395  std::string prop_name = (*it)["quantity"].template get<std::string>();
396  MonteSampler *ptr;
397 
398  const auto &dict = primclex.settings().query_handler<Configuration>().dict();
399 
400  typedef QueryMonteSampler::Formatter FormatterType;
401  std::shared_ptr<FormatterType> formatter =
402  std::make_shared<FormatterType>(dict.parse(prop_name));
403 
404  // make example config to test:
405  Supercell tscel(const_cast<PrimClex *>(&primclex), simulation_cell_matrix());
406  Configuration config(tscel);
407  config.init_occupation();
408  Eigen::VectorXd test = formatter->get().evaluate_as_matrix(config).row(0);
409  auto col = formatter->get().col_header(config);
410 
411  if (test.size() != col.size()) {
412  std::stringstream ss;
413  ss << "Error constructing Monte Carlo samplers from query: '" << prop_name
414  << "'";
416  err_log << ss.str();
417  err_log << "headers: " << col << std::endl;
418  err_log << " Some queries may not be available for sampling at this time."
419  << std::endl;
420  throw std::runtime_error(ss.str());
421  }
422 
423  for (int i = 0; i < col.size(); ++i) {
424  std::string print_name = col[i];
425  boost::algorithm::trim(print_name);
426 
427  std::tie(must_converge, prec) = _get_precision(it);
428 
429  // if 'must converge'
430  if (must_converge) {
431  ptr = new QueryMonteSampler(formatter, i, print_name, prec, confidence(),
432  data_maxlength);
433  } else {
434  ptr = new QueryMonteSampler(formatter, i, print_name, confidence(),
435  data_maxlength);
436  }
437 
438  *result++ =
439  std::make_pair(print_name, notstd::cloneable_ptr<MonteSampler>(ptr));
440  }
441 
442  return result;
443 }
444 } // namespace Monte
445 } // namespace CASM
446 
447 #endif
std::vector< std::string > components() const
The order of components in mol composition vectors.
A sparse container of ECI values and their corresponding orbit indices.
Definition: ECIContainer.hh:12
const std::vector< size_type > & index() const
const Access orbit indices of ECI values
Definition: ECIContainer.hh:44
Definition: Log.hh:48
void error(const std::string &what)
Definition: Log.hh:129
static const int standard
Definition: Log.hh:52
Sampler for atom fraction.
Sampler for parametric composition.
size_type max_data_length() const
Figure out how large data containers should be.
SamplerInsertIterator _make_atom_frac_samplers(const PrimClex &primclex, jsonParserIteratorType it, SamplerInsertIterator result) const
SamplerInsertIterator _make_query_samplers(const PrimClex &primclex, jsonParserIteratorType it, SamplerInsertIterator result) const
SamplerInsertIterator _make_all_correlations_samplers(const PrimClex &primclex, jsonParserIteratorType it, SamplerInsertIterator result) const
SamplerInsertIterator _make_site_frac_samplers(const PrimClex &primclex, jsonParserIteratorType it, SamplerInsertIterator result) const
SamplerInsertIterator _make_comp_samplers(const PrimClex &primclex, jsonParserIteratorType it, SamplerInsertIterator result) const
SamplerInsertIterator samplers(const PrimClex &primclex, SamplerInsertIterator result) const
Construct Samplers as specified in the Settings.
std::tuple< bool, double > _get_precision(jsonParserIteratorType it) const
SamplerInsertIterator _make_comp_n_samplers(const PrimClex &primclex, jsonParserIteratorType it, SamplerInsertIterator result) const
SamplerInsertIterator _make_non_zero_eci_correlations_samplers(const PrimClex &primclex, jsonParserIteratorType it, SamplerInsertIterator result) const
ClexDescription formation_energy(const PrimClex &primclex) const
Get formation energy cluster expansion.
An abstract base class for sampling and storing data observations.
Definition: MonteSampler.hh:26
const PrimClex & primclex() const
Monte::METHOD method() const
Return type of Monte Carlo method.
double confidence() const
Given a settings jsonParser figure out the global tolerance (probably for == operator)....
Eigen::Matrix3l simulation_cell_matrix() const
Supercell matrix defining the simulation cell.
Data structure to make queries occur once each sample time.
Sampler for individual elements of a vector property.
Sampler for a scalar property.
Sampler for site fraction.
Sampler for individual elements of a vector property.
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:55
QueryHandler< DataObject > & query_handler()
const std::vector< xtal::Site > & basis() const
Definition: Structure.hh:102
Represents a supercell of the primitive parent crystal structure.
Definition: Supercell.hh:51
size_type size() const
Definition: jsonParser.cc:487
json_spirit::mObject::size_type size_type
Definition: jsonParser.hh:87
const_iterator cend() const
Returns const_iterator to end of JSON object or JSON array.
Definition: jsonParser.cc:533
const_iterator cbegin() const
Returns const_iterator to beginning of JSON object or JSON array.
Definition: jsonParser.cc:510
A 'cloneable_ptr' can be used in place of 'unique_ptr'.
std::string to_string(ENUM val)
Return string representation of enum class.
Definition: io_traits.hh:172
bool is_vacancy(const std::string &name)
A vacancy is any Specie/Molecule with (name == "VA" || name == "va" || name == "Va")
Definition: Molecule.hh:187
ProjectSettings & settings()
Definition: PrimClex.cc:224
ECIContainer const & eci(const ClexDescription &key) const
Definition: PrimClex.cc:406
Clexulator clexulator(std::string const &basis_set_name) const
Definition: PrimClex.cc:366
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
jsonParser & push_back(const T &value, Args &&... args)
Definition: jsonParser.hh:684
T get(Args &&... args) const
Get data from json, using one of several alternatives.
Definition: jsonParser.hh:716
ConfigIO::GenericConfigFormatter< jsonParser > config()
Definition: ConfigIO.cc:777
Main CASM namespace.
Definition: APICommand.hh:8
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::VectorXd VectorXd
Log & err_log()
Definition: Log.hh:426
PrimClex * primclex
Definition: settings.cc:135
pair_type bset
Definition: settings.cc:145