CASM  1.1.0
A Clusters Approach to Statistical Mechanics
GrandCanonical.cc
Go to the documentation of this file.
1 
3 
4 #include "casm/basis_set/DoF.hh"
6 #include "casm/clex/Norm.hh"
7 #include "casm/clex/PrimClex.hh"
11 #include "casm/misc/algorithm.hh"
17 
18 namespace CASM {
19 namespace Monte {
20 
21 template MonteCarlo::MonteCarlo(const PrimClex &primclex,
22  const GrandCanonicalSettings &settings,
23  Log &_log);
24 template MonteCarloEnum::MonteCarloEnum(const PrimClex &primclex,
25  const GrandCanonicalSettings &settings,
26  Log &log, GrandCanonical &mc);
27 
30 
31 // note: the construction process needs refactoring
33  GrandCanonicalSettings const &settings) {
34  ClexDescription const &clex_desc = settings.formation_energy(primclex);
35  return Clex{primclex.clexulator(clex_desc.bset), primclex.eci(clex_desc)};
36 }
37 
43  const GrandCanonicalSettings &settings, Log &log)
44  : MonteCarlo(primclex, settings, log),
45  m_site_swaps(supercell()),
46  m_formation_energy_clex(make_clex(primclex, settings)),
47  m_all_correlations(settings.all_correlations()),
48  m_event(primclex.composition_axes().components().size(),
49  _clexulator().corr_size()) {
50  const auto &desc = settings.formation_energy(primclex);
51 
52  // set the SuperNeighborList...
53  set_nlist();
54 
55  // If the simulation is big enough, use delta cluster functions;
56  // else, calculate all cluster functions
58 
59  _log().construct("Grand Canonical Monte Carlo");
60  _log() << "project: " << this->primclex().dir().root_dir() << "\n";
61  _log() << "formation_energy cluster expansion: " << desc.name << "\n";
62  _log() << std::setw(16) << "property: " << desc.property << "\n";
63  _log() << std::setw(16) << "calctype: " << desc.calctype << "\n";
64  _log() << std::setw(16) << "ref: " << desc.ref << "\n";
65  _log() << std::setw(16) << "bset: " << desc.bset << "\n";
66  _log() << std::setw(16) << "eci: " << desc.eci << "\n";
67  _log() << "supercell: \n" << supercell().transf_mat() << "\n";
68  _log() << "use_deltas: " << std::boolalpha << m_use_deltas << "\n";
69  _log() << "\nSampling: \n";
70  _log() << std::setw(24) << "quantity" << std::setw(24)
71  << "requested_precision"
72  << "\n";
73  for (auto it = samplers().begin(); it != samplers().end(); ++it) {
74  _log() << std::setw(24) << it->first;
75  if (it->second->must_converge()) {
76  _log() << std::setw(24) << it->second->requested_precision() << std::endl;
77  } else {
78  _log() << std::setw(24) << "none" << std::endl;
79  }
80  }
81  _log() << "\nautomatic convergence mode?: " << std::boolalpha
82  << must_converge() << std::endl;
83  _log() << std::endl;
84 }
85 
89  return m_site_swaps.variable_sites().size();
90 }
91 
94  return m_condition;
95 }
96 
99  const GrandCanonicalConditions &new_conditions) {
100  _log().set("Conditions");
101  _log() << new_conditions << std::endl << std::endl;
102 
103  m_condition = new_conditions;
104 
105  clear_samples();
107 
108  return;
109 }
110 
113  const std::string &msg) {
114  _log().set("DoF");
115  if (!msg.empty()) {
116  _log() << msg << "\n";
117  }
118  _log() << std::endl;
119 
120  reset(configdof);
122 }
123 
128 std::pair<ConfigDoF, std::string> GrandCanonical::set_state(
129  const GrandCanonicalConditions &new_conditions,
130  const GrandCanonicalSettings &settings) {
131  _log().set("Conditions");
132  _log() << new_conditions << std::endl;
133 
134  m_condition = new_conditions;
135 
137 
138  std::string configname;
139 
142 
143  if (configname == "default") {
144  // configdof = _default_motif();
145  } else if (configname == "auto") {
146  std::tie(configdof, configname) = _auto_motif(new_conditions);
147  } else if (configname == "restricted_auto") {
148  std::tie(configdof, configname) = _restricted_auto_motif(new_conditions);
149  } else {
151  }
152 
153  } else if (settings.is_motif_configdof()) {
154  _log().set("DoF");
155  _log() << "motif configdof: " << settings.motif_configdof_path() << "\n";
156  _log() << "using configdof: " << settings.motif_configdof_path() << "\n"
157  << std::endl;
160  } else {
161  throw std::runtime_error(
162  "Error: Must specify motif \"configname\" or \"configdof\"");
163  }
164 
165  reset(configdof);
167 
168  return std::make_pair(configdof, configname);
169 }
170 
173  const ConfigDoF &configdof,
174  const std::string &msg) {
175  _log().set("Conditions");
176  _log() << new_conditions << std::endl << std::endl;
177 
178  m_condition = new_conditions;
179 
180  _log().set("DoF");
181  if (!msg.empty()) {
182  _log() << msg << "\n";
183  }
184  _log() << std::endl;
185 
186  reset(configdof);
188 
189  return;
190 }
191 
200  // Randomly pick a site that's allowed more than one occupant
201  Index random_variable_site =
202  _mtrand().randInt(m_site_swaps.variable_sites().size() - 1);
203 
204  // Determine what that site's linear index is and what the sublattice index is
205  Index mutating_site = m_site_swaps.variable_sites()[random_variable_site];
206  Index sublat = m_site_swaps.sublattice()[random_variable_site];
207 
208  // Determine the current occupant of the mutating site
209  int current_occupant = configdof().occ(mutating_site);
210 
211  // Randomly pick a new occupant for the mutating site
212  const std::vector<int> &possible_mutation =
213  m_site_swaps.possible_swap()[sublat][current_occupant];
214  int new_occupant =
215  possible_mutation[_mtrand().randInt(possible_mutation.size() - 1)];
216 
217  if (debug()) {
218  const auto &site_occ = primclex().prim().basis()[sublat].occupant_dof();
219  _log().custom("Propose event");
220 
221  _log() << " Mutating site (linear index): " << mutating_site << "\n"
222  << " Mutating site (b, i, j, k): "
223  << supercell().uccoord(mutating_site) << "\n"
224  << " Current occupant: " << current_occupant << " ("
225  << site_occ[current_occupant].name() << ")\n"
226  << " Proposed occupant: " << new_occupant << " ("
227  << site_occ[new_occupant].name() << ")\n\n"
228 
229  << " beta: " << m_condition.beta() << "\n"
230  << " T: " << m_condition.temperature() << std::endl;
231  }
232 
233  // Update delta properties in m_event
234  _update_deltas(m_event, mutating_site, sublat, current_occupant,
235  new_occupant);
236 
237  if (debug()) {
238  auto origin = primclex().composition_axes().origin();
239  auto exchange_chem_pot = m_condition.exchange_chem_pot();
240  auto param_chem_pot = m_condition.param_chem_pot();
241  auto Mpinv = primclex().composition_axes().dparam_dmol();
242  // auto V = supercell().volume();
243  Index curr_species = m_site_swaps.sublat_to_mol()[sublat][current_occupant];
244  Index new_species = m_site_swaps.sublat_to_mol()[sublat][new_occupant];
245 
246  _log() << " components: "
247  << jsonParser(primclex().composition_axes().components()) << "\n"
248  << " d(N): " << m_event.dN().transpose() << "\n"
249  << " dx_dn: \n"
250  << Mpinv << "\n"
251  << " param_chem_pot.transpose() * dx_dn: \n"
252  << param_chem_pot.transpose() * Mpinv << "\n"
253  << " param_chem_pot.transpose() * dx_dn * dN: "
254  << param_chem_pot.transpose() * Mpinv * m_event.dN().cast<double>()
255  << "\n"
256  << " d(Nunit * param_chem_pot * x): "
257  << exchange_chem_pot(new_species, curr_species) << "\n"
258  << " d(Ef): " << m_event.dEf() << "\n"
259  << " d(Epot): "
260  << m_event.dEf() - exchange_chem_pot(new_species, curr_species)
261  << "\n"
262  << std::endl;
263  }
264 
265  return m_event;
266 }
267 
271  if (event.dEpot() < 0.0) {
272  if (debug()) {
273  _log().custom("Check event");
274  _log() << "Probability to accept: 1.0\n" << std::endl;
275  }
276  return true;
277  }
278 
279  double rand = _mtrand().rand53();
280  double prob = exp(-event.dEpot() * m_condition.beta());
281 
282  if (debug()) {
283  _log().custom("Check event");
284  _log() << "Probability to accept: " << prob << "\n"
285  << "Random number: " << rand << "\n"
286  << std::endl;
287  }
288 
289  return rand < prob;
290 }
291 
300 void GrandCanonical::accept(const EventType &event) {
301  if (debug()) {
302  _log().custom("Accept Event");
303  _log() << std::endl;
304  }
305 
306  // First apply changes to configuration (just a single occupant change)
308  event.occupational_change().to_value();
309 
310  // Next update all properties that changed from the event
311  _formation_energy() += event.dEf() / supercell().volume();
312  _potential_energy() += event.dEpot() / supercell().volume();
313  _corr() += event.dCorr() / supercell().volume();
314  _comp_n() += event.dN().cast<double>() / supercell().volume();
315 
316  return;
317 }
318 
320 void GrandCanonical::reject(const EventType &event) {
321  if (debug()) {
322  _log().custom("Reject Event");
323  _log() << std::endl;
324  }
325  return;
326 }
327 
359  const SiteExchanger &site_exch = m_site_swaps;
360  const ConfigDoF &config_dof = configdof();
362 
363  double tol = 1e-12;
364 
365  auto less = [&](const double &A, const double &B) { return A < B - tol; };
366 
367  std::map<double, unsigned long, decltype(less)> hist(less);
368 
369  // no defect case
370  hist[0.0] = 1;
371 
372  // Loop over sites that can change occupants
373  for (Index exch_ind = 0; exch_ind < site_exch.variable_sites().size();
374  exch_ind++) {
375  // Transform exchanger index to ConfigDoF index
376  Index mutating_site = site_exch.variable_sites()[exch_ind];
377  int sublat = site_exch.sublattice()[exch_ind];
378  int current_occupant = config_dof.occ(mutating_site);
379 
380  // Loop over possible occupants for site that can change
381  const auto &possible = site_exch.possible_swap()[sublat][current_occupant];
382  for (auto new_occ_it = possible.begin(); new_occ_it != possible.end();
383  ++new_occ_it) {
384  _update_deltas(event, mutating_site, sublat, current_occupant,
385  *new_occ_it);
386 
387  // save the result
388  double dpot_nrg = event.dEpot();
389  if (dpot_nrg < 0.0) {
391  err_log.error<Log::standard>("Calculating low temperature expansion");
392  err_log << " Defect lowered the potential energy. Your motif "
393  "configuration "
394  << "is not the 0K ground state.\n"
395  << std::endl;
396  throw std::runtime_error(
397  "Error calculating low temperature expansion. Not in the ground "
398  "state.");
399  }
400 
401  auto it = hist.find(dpot_nrg);
402  if (it == hist.end()) {
403  hist[dpot_nrg] = 1;
404  } else {
405  it->second++;
406  }
407  }
408  }
409 
410  _log().results("Ground state and point defect potential energy details");
411  _log() << "T: " << m_condition.temperature() << std::endl;
412  _log() << "kT: " << 1.0 / m_condition.beta() << std::endl;
413  _log() << "Beta: " << m_condition.beta() << std::endl << std::endl;
414 
415  _log() << std::setw(16) << "N/unitcell"
416  << " " << std::setw(16) << "dPE"
417  << " " << std::setw(24) << "N*exp(-dPE/kT)"
418  << " " << std::setw(16) << "dphi"
419  << " " << std::setw(16) << "phi" << std::endl;
420 
421  double tsum = 0.0;
422  double phi = 0.0;
423  double phi_prev;
424  for (auto it = hist.rbegin(); it != hist.rend(); ++it) {
425  phi_prev = phi;
426  tsum += it->second * exp(-(it->first) * m_condition.beta());
427  phi = std::log(tsum) / m_condition.beta() / supercell().volume();
428 
429  if (almost_equal(it->first, 0.0, tol)) {
430  _log() << std::setw(16) << "(gs)"
431  << " ";
432  } else {
433  _log() << std::setw(16) << std::setprecision(8)
434  << (1.0 * it->second) / supercell().volume() << " ";
435  }
436  _log() << std::setw(16) << std::setprecision(8) << it->first << " "
437  << std::setw(24) << std::setprecision(8)
438  << it->second * exp(-it->first * m_condition.beta()) << " "
439  << std::setw(16) << std::setprecision(8) << phi - phi_prev << " "
440  << std::setw(16) << std::setprecision(8) << potential_energy() - phi
441  << std::endl;
442  }
443 
444  _log() << "phi_LTE(1): " << std::setprecision(12) << potential_energy() - phi
445  << std::endl
446  << std::endl;
447 
448  return potential_energy() - phi;
449 }
450 
452 void GrandCanonical::write_results(Index cond_index) const {
454  write_conditions_json(settings(), *this, cond_index, _log());
455  write_observations(settings(), *this, cond_index, _log());
456  write_trajectory(settings(), *this, cond_index, _log());
457  // write_pos_trajectory(settings(), *this, cond_index);
458 }
459 
465  // if(&config == &this->config()) { return potential_energy(); }
466 
467  auto corr = correlations(config, _clexulator());
468  double formation_energy = _eci() * corr.data();
469  auto comp_x =
471  return formation_energy - comp_x.dot(m_condition.param_chem_pot());
472 }
473 
476  int sublat, int current_occupant,
477  int new_occupant, bool use_deltas,
478  bool all_correlations) const {
479  // uses _clexulator(), nlist(), _configdof()
480 
481  if (use_deltas) {
482  // Calculate the change in correlations due to this event
483  if (all_correlations) {
485  _configdof(),
486  nlist().sites(nlist().unitcell_index(mutating_site)).data(),
487  end_ptr(nlist().sites(nlist().unitcell_index(mutating_site))), sublat,
488  current_occupant, new_occupant, event.dCorr().data(),
489  end_ptr(event.dCorr()));
490  } else {
491  auto begin = _eci().index().data();
492  auto end = begin + _eci().index().size();
494  _configdof(),
495  nlist().sites(nlist().unitcell_index(mutating_site)).data(),
496  end_ptr(nlist().sites(nlist().unitcell_index(mutating_site))), sublat,
497  current_occupant, new_occupant, event.dCorr().data(),
498  end_ptr(event.dCorr()), begin, end);
499  }
500  } else {
501  Eigen::VectorXd before{Eigen::VectorXd::Zero(event.dCorr().size())};
502  Eigen::VectorXd after{Eigen::VectorXd::Zero(event.dCorr().size())};
503 
504  // Calculate the change in points correlations due to this event
505  if (all_correlations) {
506  // Calculate before
508  _configdof(),
509  nlist().sites(nlist().unitcell_index(mutating_site)).data(),
510  end_ptr(nlist().sites(nlist().unitcell_index(mutating_site))), sublat,
511  before.data(), end_ptr(before));
512 
513  // Apply change
514  _configdof().occ(mutating_site) = new_occupant;
515 
516  // Calculate after
518  _configdof(),
519  nlist().sites(nlist().unitcell_index(mutating_site)).data(),
520  end_ptr(nlist().sites(nlist().unitcell_index(mutating_site))), sublat,
521  after.data(), end_ptr(after));
522  } else {
523  auto begin = _eci().index().data();
524  auto end = begin + _eci().index().size();
525 
526  // Calculate before
528  _configdof(),
529  nlist().sites(nlist().unitcell_index(mutating_site)).data(),
530  end_ptr(nlist().sites(nlist().unitcell_index(mutating_site))), sublat,
531  before.data(), end_ptr(before), begin, end);
532 
533  // Apply change
534  _configdof().occ(mutating_site) = new_occupant;
535 
536  // Calculate after
538  _configdof(),
539  nlist().sites(nlist().unitcell_index(mutating_site)).data(),
540  end_ptr(nlist().sites(nlist().unitcell_index(mutating_site))), sublat,
541  after.data(), end_ptr(after), begin, end);
542  }
543 
544  // Calculate the change in correlations due to this event
545  event.dCorr() = after - before;
546 
547  // Unapply changes
548  _configdof().occ(mutating_site) = current_occupant;
549  }
550 
551  if (debug()) {
552  _print_correlations(event.dCorr(), "delta correlations", "dCorr",
553  all_correlations);
554  }
555 }
556 
559  std::string title,
560  std::string colheader,
561  bool all_correlations) const {
562  _log().calculate(title);
563  _log() << std::setw(12) << "i" << std::setw(16) << "ECI" << std::setw(16)
564  << colheader << std::endl;
565 
566  for (int i = 0; i < corr.size(); ++i) {
567  double eci = 0.0;
568  bool calculated = true;
569  Index index = find_index(_eci().index(), i);
570  if (index != _eci().index().size()) {
571  eci = _eci().value()[index];
572  }
573  if (!all_correlations && index == _eci().index().size()) {
574  calculated = false;
575  }
576 
577  _log() << std::setw(12) << i << std::setw(16) << std::setprecision(8)
578  << eci;
579  if (calculated) {
580  _log() << std::setw(16) << std::setprecision(8) << corr[i];
581  } else {
582  _log() << std::setw(16) << "unknown";
583  }
584  _log() << std::endl;
585  }
586  _log() << std::endl;
587 }
588 
591  Index mutating_site, int sublat,
592  int current_occupant,
593  int new_occupant) const {
594  // ---- set OccMod --------------
595 
596  event.occupational_change().set(mutating_site, sublat, new_occupant);
597 
598  // ---- set dspecies --------------
599 
600  for (int i = 0; i < event.dN().size(); ++i) {
601  event.set_dN(i, 0);
602  }
603  Index curr_species = m_site_swaps.sublat_to_mol()[sublat][current_occupant];
604  Index new_species = m_site_swaps.sublat_to_mol()[sublat][new_occupant];
605  event.set_dN(curr_species, -1);
606  event.set_dN(new_species, 1);
607 
608  // ---- set dcorr --------------
609 
610  _set_dCorr(event, mutating_site, sublat, current_occupant, new_occupant,
612 
613  // ---- set dformation_energy --------------
614 
615  event.set_dEf(_eci() * event.dCorr().data());
616 
617  // ---- set dpotential_energy --------------
618 
619  event.set_dEpot(event.dEf() -
620  m_condition.exchange_chem_pot(new_species, curr_species));
621 }
622 
625  // initialize properties and store pointers to the data strucures
626  _vector_properties()["corr"] =
628  m_corr = &_vector_property("corr");
629 
631  m_comp_n = &_vector_property("comp_n");
632 
633  _scalar_properties()["formation_energy"] = _eci() * corr().data();
634  m_formation_energy = &_scalar_property("formation_energy");
635 
636  _scalar_properties()["potential_energy"] =
637  formation_energy() -
640  m_potential_energy = &_scalar_property("potential_energy");
641 
642  if (debug()) {
643  _print_correlations(corr(), "correlations", "corr", m_all_correlations);
644 
645  auto origin = primclex().composition_axes().origin();
646  auto exchange_chem_pot = m_condition.exchange_chem_pot();
647  auto param_chem_pot = m_condition.param_chem_pot();
648  auto comp_x = primclex().composition_axes().param_composition(comp_n());
649  auto M = primclex().composition_axes().dmol_dparam();
650 
651  _log().custom("Calculate properties");
652  _log() << "Semi-grand canonical ensemble: \n"
653  << " Thermodynamic potential (per unitcell), phi = -kT*ln(Z)/N \n"
654  << " Partition function, Z = sum_i exp(-N*potential_energy_i/kT) \n"
655  << " composition, comp_n = origin + M * comp_x \n"
656  << " parametric chemical potential, param_chem_pot = M.transpose() "
657  "* chem_pot \n"
658  << " potential_energy (per unitcell) = formation_energy - "
659  "param_chem_pot*comp_x \n\n"
660 
661  << "components: "
662  << jsonParser(primclex().composition_axes().components()) << "\n"
663  << "M:\n"
664  << M << "\n"
665  << "origin: " << origin.transpose() << "\n"
666  << "comp_n: " << comp_n().transpose() << "\n"
667  << "comp_x: " << comp_x.transpose() << "\n"
668  << "param_chem_pot: " << param_chem_pot.transpose() << "\n"
669  << " param_chem_pot*comp_x: " << param_chem_pot.dot(comp_x) << "\n"
670  << "formation_energy: " << formation_energy() << "\n"
671  << " formation_energy - param_chem_pot*comp_x: "
672  << formation_energy() - param_chem_pot.dot(comp_x) << "\n"
673  << "potential_energy: " << potential_energy() << "\n"
674  << std::endl;
675  }
676 }
677 
680  _log().set("DoF");
681  _log() << "motif configname: default\n";
682  _log() << "using configuration with default occupation...\n" << std::endl;
683 
685 }
686 
690 std::pair<ConfigDoF, std::string> GrandCanonical::_auto_motif(
691  const GrandCanonicalConditions &cond) const {
692  _log().set("DoF");
693  _log() << "motif configname: auto\n";
694  _log() << "searching for minimum potential energy motif..." << std::endl;
695 
696  double tol = 1e-6;
697  auto compare = [&](double A, double B) { return A < B - tol; };
698 
699  _log() << "using conditions: \n";
700  _log() << cond << std::endl;
701 
702  std::multimap<double, std::string, decltype(compare)> configmap(compare);
703  const auto &db = primclex().db<Configuration>();
704  for (const auto &tconfig : db) {
705  configmap.insert(
706  std::make_pair(_eci() * correlations(tconfig, _clexulator()) -
707  cond.param_chem_pot().dot(CASM::comp(tconfig)),
708  tconfig.name()));
709  }
710 
711  Configuration min_config = *db.find(configmap.begin()->second);
712  double min_potential_energy = configmap.begin()->first;
713  auto eq_range = configmap.equal_range(min_potential_energy);
714 
715  if (std::distance(eq_range.first, eq_range.second) > 1) {
716  _log() << "Warning: Found degenerate ground states with potential energy: "
717  << std::setprecision(8) << min_potential_energy << std::endl;
718  for (auto it = eq_range.first; it != eq_range.second; ++it) {
719  _log() << " " << db.find(it->second)->name() << std::endl;
720  }
721  _log() << "using: " << min_config.name() << "\n" << std::endl;
722  } else {
723  _log() << "using: " << min_config.name()
724  << " with potential energy: " << std::setprecision(8)
725  << min_potential_energy << "\n"
726  << std::endl;
727  }
728 
729  return std::make_pair(fill_supercell(min_config, _supercell()).configdof(),
730  min_config.name());
731 }
732 
734 std::pair<ConfigDoF, std::string> GrandCanonical::_restricted_auto_motif(
735  const GrandCanonicalConditions &cond) const {
736  _log().set("DoF");
737  _log() << "motif configname: restricted_auto\n";
738  _log() << "searching for minimum potential energy motif..." << std::endl;
739 
740  double tol = 1e-6;
741  auto compare = [&](double A, double B) { return A < B - tol; };
742 
743  _log() << "using conditions: \n";
744  _log() << cond << std::endl;
745 
746  std::multimap<double, std::string, decltype(compare)> configmap(compare);
747  const auto &db = primclex().db<Configuration>();
748  for (const auto &tconfig : db) {
749  configmap.insert(
750  std::make_pair(_eci() * correlations(tconfig, _clexulator()) -
751  cond.param_chem_pot().dot(CASM::comp(tconfig)),
752  tconfig.name()));
753  }
754 
755  // used to check if configurations can fill the monte carlo supercell
756  const Lattice &scel_lat = supercell().lattice();
757  const SymGroup &g = primclex().prim().factor_group();
758  auto begin = g.begin();
759  auto end = g.end();
760 
761  // save iterators pointing to configs that will fill the supercell
762  std::vector<decltype(configmap)::const_iterator> allowed;
763 
764  // iterate through groups of degenerate configs
765  auto next_it = configmap.begin();
766  while (next_it != configmap.end()) {
767  auto eq_range = configmap.equal_range(next_it->first);
768 
769  // save allowed configs
770  for (auto it = eq_range.first; it != eq_range.second; ++it) {
771  const Lattice &motif_lat = db.find(it->second)->supercell().lattice();
772  if (xtal::is_equivalent_superlattice(scel_lat, motif_lat, begin, end, TOL)
773  .first != end) {
774  allowed.push_back(it);
775  }
776  }
777 
778  // if some found, break
779  if (allowed.size()) {
780  break;
781  }
782 
783  // else, continue to next group
784  next_it = eq_range.second;
785  }
786 
787  if (!allowed.size()) {
788  _log()
789  << "Found no enumerated configurations that will fill the supercell\n";
790  _log() << "using configuration with default occupation..." << std::endl;
791  return std::make_pair(Configuration::zeros(_supercell()).configdof(),
792  "default");
793  }
794 
795  if (allowed.size() > 1) {
796  _log() << "Warning: Found degenerate allowed configurations with potential "
797  "energy: "
798  << std::setprecision(8) << allowed[0]->first << std::endl;
799  for (auto it = allowed.begin(); it != allowed.end(); ++it) {
800  _log() << " " << (*it)->second << std::endl;
801  }
802  _log() << "using: " << allowed[0]->second << "\n" << std::endl;
803  } else {
804  _log() << "using: " << allowed[0]->second
805  << " with potential energy: " << std::setprecision(8)
806  << allowed[0]->first << "\n"
807  << std::endl;
808  }
809 
810  Configuration min_config = *db.find(allowed[0]->second);
811  return std::make_pair(fill_supercell(min_config, _supercell()).configdof(),
812  min_config.name());
813 }
814 
817  const std::string &configname) const {
818  _log().set("DoF");
819  _log() << "motif configname: " << configname << "\n";
820  _log() << "using configation: " << configname << "\n" << std::endl;
821 
824 }
825 
826 } // namespace Monte
827 } // namespace CASM
void calc_restricted_point_corr(ConfigDoF const &_input_configdof, long int const *_nlist_begin, long int const *_nlist_end, int neighbor_ind, double *_corr_begin, double *_corr_end, size_type const *_corr_ind_begin, size_type const *_corr_ind_end) const
Calculate select point correlations about basis site 'neighbor_ind'.
Definition: Clexulator.hh:651
void calc_restricted_delta_point_corr(ConfigDoF const &_input_configdof, long int const *_nlist_begin, long int const *_nlist_end, int neighbor_ind, int occ_i, int occ_f, double *_corr_begin, double *_corr_end, size_type const *_corr_ind_begin, size_type const *_corr_ind_end) const
Calculate the change in select point correlations due to changing an occupant.
Definition: Clexulator.hh:716
void calc_point_corr(ConfigDoF const &_input_configdof, long int const *_nlist_begin, long int const *_nlist_end, int neighbor_ind, double *_corr_begin, double *_corr_end) const
Calculate point correlations about basis site 'neighbor_ind'.
Definition: Clexulator.hh:626
void calc_delta_point_corr(ConfigDoF const &_input_configdof, long int const *_nlist_begin, long int const *_nlist_end, int neighbor_ind, int occ_i, int occ_f, double *_corr_begin, double *_corr_end) const
Calculate the change in point correlations due to changing an occupant.
Definition: Clexulator.hh:679
Eigen::VectorXd param_composition(const Eigen::VectorXd &n) const
Convert number of mol per prim, 'n' to parametric composition 'x'.
Eigen::VectorXd origin() const
The mol composition of the parameteric composition axes origin.
Eigen::MatrixXd dparam_dmol() const
Return the matrix Mij = dx_i/dn_j.
Eigen::MatrixXd dmol_dparam() const
Return the matrix Mij = dn_i/dx_j.
int & occ(Index i)
Reference occupation value on site i.
Definition: ConfigDoF.cc:34
const ConfigDoF & configdof() const
const Access the DoF
static Configuration zeros(const std::shared_ptr< Supercell const > &_supercell_ptr)
ConfigInsertResult insert(bool primitive_only=false) const
Insert this configuration (in primitive & canonical form) in the database.
fs::path root_dir() const
Return casm project directory path.
const std::vector< size_type > & index() const
const Access orbit indices of ECI values
Definition: ECIContainer.hh:44
const std::vector< double > & value() const
const Access ECI values
Definition: ECIContainer.hh:41
Definition: Log.hh:48
void custom(const std::string &what)
Definition: Log.hh:139
void results(const std::string &what)
Definition: Log.hh:99
void set(const std::string &what)
Definition: Log.hh:89
void calculate(const std::string &what)
Definition: Log.hh:74
void error(const std::string &what)
Definition: Log.hh:129
void construct(const std::string &what)
Definition: Log.hh:79
static const int standard
Definition: Log.hh:52
Eigen::MatrixXd exchange_chem_pot() const
matrix of exchange chemical potential, M(new, curr) = chem_pot(new)
Eigen::VectorXd param_chem_pot() const
parametric chemical potential: dg/dcomp_x
Data structure for storing information regarding a proposed grand canonical Monte Carlo event.
Eigen::VectorXd & dCorr()
Access the changes in (extensive) correlations associated with this event.
double dEf() const
Return change in (extensive) formation energy associated with this event.
void set_dEpot(double dpot_nrg)
Set change in (extensive) potential energy, dEpot = dEf - sum_i(Nunit * param_chem_pot_i * dcomp_x_i)
void set_dN(size_type species_type_index, long int dn)
Set the change in number of species in supercell. Order as in CompositionConverter::components().
void set_dEf(double dE)
Set the change in (extensive) formation energy associated with this event.
Eigen::VectorXl & dN()
Access change in number of species per supercell. Order as in CompositionConverter::components().
OccMod & occupational_change()
Access the occupational modification for this event.
double dEpot() const
Return change in (extensive) potential energy, dEpot = dEf - sum_i(Nunit * param_chem_pot_i * dcomp_x...
Clexulator const & _clexulator() const
void _update_properties()
Calculate properties given current conditions.
Eigen::VectorXd * m_comp_n
Number of atoms of each type, normalized per primitive cell.
const ECIContainer & _eci() const
const Eigen::VectorXd & corr() const
Correlations, normalized per primitive cell.
void _set_dCorr(GrandCanonicalEvent &event, Index mutating_site, int sublat, int current_occupant, int new_occupant, bool use_deltas, bool all_correlations) const
Calculate delta correlations for an event.
void accept(const EventType &event)
Accept proposed event. Change configuration accordingly and update energies etc.
std::pair< ConfigDoF, std::string > set_state(const GrandCanonicalConditions &new_conditions, const GrandCanonicalSettings &settings)
Set configdof and conditions and clear previously collected data.
const EventType & propose()
Propose a new event, calculate delta properties, and return reference to it.
double * m_potential_energy
Potential energy, normalized per primitive cell.
void reject(const EventType &event)
Nothing needs to be done to reject a GrandCanonicalEvent.
Eigen::VectorXd & _corr()
Correlations, normalized per primitive cell.
void _update_deltas(GrandCanonicalEvent &event, Index mutating_site, int sublat, int current_occupant, int new_occupant) const
Calculate delta properties for an event and update the event with those properties.
double lte_grand_canonical_free_energy() const
Calculate the single spin flip low temperature expansion of the grand canonical potential.
size_type steps_per_pass() const
Return number of steps per pass. Equals number of sites with variable occupation.
void _print_correlations(const Eigen::VectorXd &corr, std::string title, std::string colheader, bool all_correlations) const
Print correlations to _log()
GrandCanonical(const PrimClex &primclex, const SettingsType &settings, Log &_log)
Constructs a GrandCanonical object and prepares it for running based on Settings.
const double & formation_energy() const
Formation energy, normalized per primitive cell.
Eigen::VectorXd * m_corr
Correlations, normalized per primitive cell.
const double & potential_energy() const
Potential energy, normalized per primitive cell.
bool check(const EventType &event)
Based on a random number, decide if the change in energy from the proposed event is low enough to be ...
double & _formation_energy()
Formation energy, normalized per primitive cell.
void write_results(size_type cond_index) const
Write results to files.
ConfigDoF _configname_motif(const std::string &configname) const
Generate supercell filling ConfigDoF from configuration.
const CondType & conditions() const
Return current conditions.
void set_conditions(const CondType &new_conditions)
Set conditions and clear previously collected data.
ConfigDoF _default_motif() const
Generate supercell filling ConfigDoF from default configuration.
Eigen::VectorXd & _comp_n()
Number of atoms of each type, normalized per primitive cell.
std::pair< ConfigDoF, std::string > _auto_motif(const GrandCanonicalConditions &cond) const
Generate minimum potential energy ConfigDoF.
static const ENSEMBLE ensemble
const Eigen::VectorXd & comp_n() const
Number of atoms of each type, normalized per primitive cell.
std::pair< ConfigDoF, std::string > _restricted_auto_motif(const GrandCanonicalConditions &cond) const
Generate minimum potential energy ConfigDoF for this supercell.
double * m_formation_energy
Formation energy, normalized per primitive cell.
double & _potential_energy()
Potential energy, normalized per primitive cell.
GrandCanonicalConditions m_condition
EventType m_event
Event to propose, check, accept/reject:
void set_configdof(const ConfigDoF &configdof, const std::string &msg="")
Set configdof and clear previously collected data.
bool m_use_deltas
If the supercell is large enough, calculate delta correlations directly.
const SiteExchanger m_site_swaps
Keeps track of what sites can change to what.
ClexDescription formation_energy(const PrimClex &primclex) const
Get formation energy cluster expansion.
MonteCarloEnum(const PrimClex &primclex, const MonteTypeSettings &settings, Log &log, MonteCarloType &mc)
Interface base class for all types of Monte Carlo simulations (not meant to be used polymorphically)
Definition: MonteCarlo.hh:44
double & _scalar_property(std::string property_name)
Access a particular scalar property.
Definition: MonteCarlo.hh:197
VectorPropertyMap & _vector_properties()
const Access vector properties map
Definition: MonteCarlo.hh:202
void clear_samples()
Clear all data from all samplers.
Definition: MonteCarlo.cc:50
ConfigDoF & _configdof() const
Access current microstate.
Definition: MonteCarlo.hh:187
const Supercell & _supercell() const
Access the Supercell that *this is based on.
Definition: MonteCarlo.hh:175
void set_nlist()
Set a pointer to the SuperNeighborList once it is ready.
Definition: MonteCarlo.hh:83
const SuperNeighborList & nlist() const
const Access the SuperNeighborList via pointer stored by 'set_nlist'
Definition: MonteCarlo.hh:87
ScalarPropertyMap & _scalar_properties()
Access scalar properties map.
Definition: MonteCarlo.hh:194
const Supercell & supercell() const
const Access the Supercell that *this is based on
Definition: MonteCarlo.hh:80
const MonteSettings & settings() const
const Access settings used for construction
Definition: MonteCarlo.hh:74
void reset(const ConfigDoF &dof)
Set current microstate and clear samplers.
Definition: MonteCarlo.hh:98
const Configuration & config() const
const Access current microstate
Definition: MonteCarlo.hh:90
const PrimClex & primclex() const
const Access the PrimClex that *this is based on
Definition: MonteCarlo.hh:77
Eigen::VectorXd & _vector_property(std::string property_name)
const Access a particular vector property
Definition: MonteCarlo.hh:205
MonteCarlo(const PrimClex &primclex, const MonteTypeSettings &settings, Log &_log)
Construct with a starting ConfigDoF as specified the given MonteSettings and prepare data samplers.
const ConfigDoF & configdof() const
const Access current microstate
Definition: MonteCarlo.hh:93
bool debug() const
return true if running in debug mode
Definition: MonteCarlo.hh:162
const SamplerMap & samplers() const
const Access sampler map
Definition: MonteCarlo.hh:149
bool must_converge() const
Return true if convergence is requested.
Definition: MonteCarlo.hh:135
bool is_motif_configdof() const
Returns true if path to ConfigDoF file to use as starting motif has been specified.
std::string motif_configname() const
Configname of configuration to use as starting motif.
bool is_motif_configname() const
Returns true if configname of configuration to use as starting motif has been specified.
ConfigDoF motif_configdof(Index supercell_volume) const
ConfigDoF to use as starting motif.
fs::path motif_configdof_path() const
Path to ConfigDoF file to use as starting motif.
const std::vector< std::vector< int > > & sublat_to_mol() const
Map the integer values from the possible swaps or variable sites arrays into actual species.
const std::vector< std::vector< std::vector< int > > > & possible_swap() const
For a given sublattice with a particular occupant, show what OTHER occupants it could be.
const std::vector< Index > & variable_sites() const
std::vector of indices into occupation array of ConfigDoF that have more than one allowed occupant
const std::vector< int > & sublattice() const
sublattice()[i] is the sublattice index for site variable_sites()[i]
const T & to_value() const
Returns the value the variable on the site being modified will change to.
Definition: DoFMod.hh:40
size_type site_index() const
Returns the linear index corresponding to site in ConfigDoF.
Definition: DoFMod.hh:33
void set(size_type _site_linear_index, size_type _sublat, const T &_to_value)
Set the values of a SiteMod.
Definition: DoFMod.hh:49
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:55
const std::vector< xtal::Site > & basis() const
Definition: Structure.hh:102
const MasterSymGroup & factor_group() const
Definition: Structure.cc:107
bool overlaps() const
Returns true if periodic images of the neighbor list overlap.
UnitCellCoord uccoord(Index linear_index) const
Return the integral coordinates corresponding to a linear index.
Definition: Supercell.cc:209
const Lattice & lattice() const
The super lattice.
Definition: Supercell.cc:239
Eigen::Matrix3l transf_mat() const
Definition: Supercell.cc:235
Index volume() const
Return number of primitive cells that fit inside of *this.
Definition: Supercell.cc:227
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Definition: SymGroup.hh:42
Eigen::VectorXd correlations(const Configuration &config, Clexulator const &clexulator)
Returns correlations using 'clexulator'.
Eigen::VectorXd comp(const Configuration &config)
Returns parametric composition, as calculated using PrimClex::param_comp.
Eigen::VectorXd comp_n(const Configuration &config)
Returns the composition, as number of each species per unit cell.
DB::Database< T > & db() const
Definition: PrimClex.cc:302
const DirectoryStructure & dir() const
Access DirectoryStructure object. Throw if not set.
Definition: PrimClex.cc:230
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
ConfigIO::GenericConfigFormatter< jsonParser > config()
Definition: ConfigIO.cc:777
ConfigIO::GenericConfigFormatter< std::string > configname()
Constructs DataFormmaterDictionary containing all Configuration DatumFormatters.
Definition: ConfigIO.cc:563
void write_observations(const MonteSettings &settings, const MonteCarlo &mc, size_type cond_index, Log &_log)
Will create (and possibly overwrite) new file with all observations from run with conditions....
Definition: MonteIO.cc:260
void write_trajectory(const MonteSettings &settings, const MonteCarlo &mc, size_type cond_index, Log &_log)
Will create (and possibly overwrite) new file with all observations from run with conditions....
Definition: MonteIO.cc:325
Clex make_clex(PrimClex const &primclex, CanonicalSettings const &settings)
Definition: Canonical.cc:26
void write_results(const MonteSettings &settings, const MonteType &mc, Log &_log)
Will create new file or append to existing file results of the latest run.
void write_conditions_json(const MonteSettings &settings, const MonteType &mc, size_type cond_index, Log &_log)
Write conditions to conditions.cond_index directory.
ENSEMBLE
Monte Carlo ensemble type.
GenericScelFormatter< double > volume()
Definition: SupercellIO.cc:258
bool less(LatticeNode const &A, LatticeNode const &B, double cost_tol)
Compare two LatticeMap objects, based on their mapping cost first, followed by PrimGrid transformatio...
std::pair< OpIterator, Eigen::Matrix3d > is_equivalent_superlattice(const Object &scel, const Object &unit, OpIterator begin, OpIterator end, double tol)
Definition: SymTools.hh:110
Main CASM namespace.
Definition: APICommand.hh:8
bool almost_equal(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Check if ClusterInvariants are equal.
bool compare(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Compare ClusterInvariants.
Configuration fill_supercell(Configuration const &motif, std::shared_ptr< Supercell const > const &shared_supercell)
Log & log()
Definition: Log.hh:424
Index find_index(Iterator begin, Iterator end, const T &value)
Equivalent to std::distance(begin, std::find(begin, end, value))
Definition: algorithm.hh:24
const double TOL
Definition: definitions.hh:30
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
T * end_ptr(std::vector< T > &container)
Return pointer one past end of vector. Equivalent to convainer.data()+container.size()
Definition: algorithm.hh:142
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
Eigen::VectorXd VectorXd
Log & err_log()
Definition: Log.hh:426
pair_type eci
Definition: settings.cc:146
PrimClex * primclex
Definition: settings.cc:135
Log & log
Definition: settings.cc:139
ClexDescription & desc
Definition: settings.cc:138
Specifies a particular cluster expansion.
Pair of Clexulator and ECIContainer.
Definition: Clex.hh:16