CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
monte.cc
Go to the documentation of this file.
1 #include <string>
2 #include <iostream>
3 
4 #include "casm/clex/PrimClex.hh"
13 
14 namespace CASM {
15 
16  void print_monte_help(std::ostream &sout, const po::options_description &desc) {
17  sout << "\n";
18  sout << desc << std::endl;
19  }
20 
21  void print_monte_desc(std::ostream &sout, const po::options_description &desc) {
22  sout << "\n";
23  sout << desc << std::endl;
24 
25  sout << "DESCRIPTION\n" <<
26  " Perform Monte Carlo calculations. \n\n" <<
27 
28  " casm monte --settings input_file.json \n" <<
29  " - Run Monte Carlo calculations given the input file \n" <<
30  " settings. \n" <<
31  " - See 'casm format --monte' for a description of the \n" <<
32  " Monte Carlo input file. \n\n" <<
33 
34  " casm monte --settings input_file.json --initial-POSCAR 3 \n" <<
35  " - Write a POSCAR.initial file containing the initial state of\n" <<
36  " the Monte Carlo calculation. The argument is a condition\n" <<
37  " index specifying which run is being requested.\n" <<
38  " - Written at: output_directory/conditions.3/trajectory/POSCAR.initial\n\n" <<
39 
40  " casm monte --settings input_file.json --final-POSCAR 3 \n" <<
41  " - Write a POSCAR.final file containing the final state of\n" <<
42  " the Monte Carlo calculation. The argument is a condition\n" <<
43  " index specifying which run is being requested.\n" <<
44  " - Written at: output_directory/conditions.3/trajectory/POSCAR.final\n\n" <<
45 
46  " casm monte --settings input_file.json --traj-POSCAR 5 \n" <<
47  " - Write the Monte Carlo calculation trajectory as a \n" <<
48  " series of POSCAR files containing the state of the \n" <<
49  " Monte Carlo calculation every time a sample was taken.\n" <<
50  " The argument is a condition index specifying which run\n" <<
51  " is being requested. \n" <<
52  " - The trajectory file must exist. This is generated when\n" <<
53  " using input option \"data\"/\"storage\"/\"write_trajectory\" = true \n" <<
54  " - Written at: output_directory/conditions.5/trajectory/POSCAR.i,\n" <<
55  " where i is the sample index. \n\n";
56 
57  }
58 
59  namespace Completer {
60 
62 
67 
68  m_desc.add_options()
69  ("initial-POSCAR", po::value<Index>(&m_condition_index), "Given the condition index, print a POSCAR for the initial state of a monte carlo run.")
70  ("final-POSCAR", po::value<Index>(&m_condition_index), "Given the condition index, print a POSCAR for the final state of a monte carlo run.")
71  ("traj-POSCAR", po::value<Index>(&m_condition_index), "Given the condition index, print POSCARs for the state at every sample of monte carlo run. Requires an existing trajectory file.");
72  return;
73  }
74 
76  return m_condition_index;
77  };
78 
79  }
80 
81  template<typename MCType>
82  int _initial_POSCAR(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt);
83 
84  template<typename MCType>
85  int _final_POSCAR(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt);
86 
87  template<typename MCType>
88  int _traj_POSCAR(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt);
89 
90  template<typename MCType>
91  int _driver(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt);
92 
95  const MonteSettings &monte_settings,
96  const CommandArgs &args,
97  const Completer::MonteOption &monte_opt);
98 
99  int _run_Canonical(
101  const MonteSettings &monte_settings,
102  const CommandArgs &args,
103  const Completer::MonteOption &monte_opt);
104 
105 
106  int monte_command(const CommandArgs &args) {
107 
108  fs::path settings_path;
109  std::string verbosity_str;
110 
111  // Set command line options using boost program_options
112  Completer::MonteOption monte_opt;
113  po::variables_map &vm = monte_opt.vm();
114 
115  try {
116  po::store(po::parse_command_line(args.argc, args.argv, monte_opt.desc()), vm); // can throw
117 
120  if(vm.count("help")) {
121  print_monte_help(args.log, monte_opt.desc());
122  return 0;
123  }
124 
125  if(vm.count("desc")) {
126  print_monte_desc(args.log, monte_opt.desc());
127  return 0;
128  }
129 
130  po::notify(vm); // throws on error, so do after help in case
131  // there are any problems
132 
133  settings_path = monte_opt.settings_path();
134  verbosity_str = monte_opt.verbosity_str();
135 
136  if(vm.count("verbosity")) {
137  auto res = Log::verbosity_level(verbosity_str);
138  if(!res.first) {
139  args.err_log.error("--verbosity");
140  args.err_log << "Expected: 'none', 'quiet', 'standard', 'verbose', "
141  "'debug', or an integer 0-100 (0: none, 100: all)" << "\n" << std::endl;
142  return ERR_INVALID_ARG;
143  }
144  args.log.set_verbosity(res.second);
145  }
146 
147  }
148  catch(po::error &e) {
149  args.err_log << "ERROR: " << e.what() << std::endl << std::endl;
150  args.err_log << monte_opt.desc() << std::endl;
151  return 1;
152  }
153  catch(std::exception &e) {
154  args.err_log << "Unhandled Exception reached the top of main: "
155  << e.what() << ", application will now exit" << std::endl;
156  return 1;
157 
158  }
159 
160  const fs::path &root = args.root;
161  if(root.empty()) {
162  args.err_log.error("No casm project found");
163  args.err_log << std::endl;
164  return ERR_NO_PROJ;
165  }
166 
167  // If 'args.primclex', use that, else construct PrimClex in 'uniq_primclex'
168  // Then whichever exists, store reference in 'primclex'
169  std::unique_ptr<PrimClex> uniq_primclex;
170  PrimClex &primclex = make_primclex_if_not(args, uniq_primclex);
171  Log &log = args.log;
172 
173 
174  //Get path to settings json file
175  settings_path = fs::absolute(settings_path);
176 
177  //args.log << "Example settings so far..." << std::endl;
178  //jsonParser example_settings = Monte::example_testing_json_settings(primclex);
179  //std::ofstream outsettings("monte_settings.json");
180  //example_settings.print(outsettings);
181 
182  MonteSettings monte_settings;
183 
184  try {
185  log.read("Monte Carlo settings");
186  log << "from: " << settings_path << "\n";
187  monte_settings = MonteSettings(primclex, settings_path);
188  log << "ensemble: " << monte_settings.ensemble() << "\n";
189  log << "method: " << monte_settings.method() << "\n";
190  if(args.log.verbosity() == 100) {
191  monte_settings.set_debug(true);
192  }
193  if(monte_settings.debug()) {
194  log << "debug: " << monte_settings.debug() << "\n";
195  }
196  log << std::endl;
197 
198  }
199  catch(std::exception &e) {
200  args.err_log << "ERROR reading Monte Carlo settings.\n\n";
201  args.err_log << e.what() << std::endl;
202  return 1;
203  }
204 
205  if(monte_settings.ensemble() == Monte::ENSEMBLE::GrandCanonical) {
206  return _run_GrandCanonical(primclex, monte_settings, args, monte_opt);
207  }
208  else if(monte_settings.ensemble() == Monte::ENSEMBLE::Canonical) {
209  return _run_Canonical(primclex, monte_settings, args, monte_opt);
210  }
211 
212  return ERR_INVALID_ARG;
213  }
214 
215 
216  template<typename MCType>
217  int _initial_POSCAR(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt) {
218  try {
219  typename MCType::SettingsType mc_settings(primclex, monte_opt.settings_path());
220  const MCType mc(primclex, mc_settings, args.log);
221 
222  args.log.write("Initial POSCAR");
223  write_POSCAR_initial(mc, monte_opt.condition_index(), args.log);
224  args.log << std::endl;
225  return 0;
226  }
227  catch(std::exception &e) {
228  args.err_log << "ERROR printing " << to_string(MCType::ensemble) <<
229  " Monte Carlo initial snapshot for condition: " << monte_opt.condition_index() << "\n\n";
230  args.err_log << e.what() << std::endl;
231  return 1;
232  }
233  }
234 
235  template<typename MCType>
236  int _final_POSCAR(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt) {
237  try {
238  typename MCType::SettingsType mc_settings(primclex, monte_opt.settings_path());
239  const MCType mc(primclex, mc_settings, args.log);
240 
241  args.log.write("Final POSCAR");
242  write_POSCAR_final(mc, monte_opt.condition_index(), args.log);
243  args.log << std::endl;
244  return 0;
245  }
246  catch(std::exception &e) {
247  args.err_log << "ERROR printing " << to_string(MCType::ensemble) <<
248  " Monte Carlo initial snapshot for condition: " << monte_opt.condition_index() << "\n\n";
249  args.err_log << e.what() << std::endl;
250  return 1;
251  }
252  }
253 
254  template<typename MCType>
255  int _traj_POSCAR(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt) {
256  try {
257  typename MCType::SettingsType mc_settings(primclex, monte_opt.settings_path());
258  const MCType mc(primclex, mc_settings, args.log);
259 
260  args.log.write("Trajectory POSCAR");
261  write_POSCAR_trajectory(mc, monte_opt.condition_index(), args.log);
262  args.log << std::endl;
263  return 0;
264  }
265  catch(std::exception &e) {
266  args.err_log << "ERROR printing " << to_string(MCType::ensemble) <<
267  " Monte Carlo path snapshots for condition: " << monte_opt.condition_index() << "\n\n";
268  args.err_log << e.what() << std::endl;
269  return 1;
270  }
271  }
272 
273  template<typename MCType>
274  int _driver(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt) {
275  try {
276  typename MCType::SettingsType mc_settings(primclex, monte_opt.settings_path());
277  MonteDriver<MCType> driver(primclex, mc_settings, args.log, args.err_log);
278  driver.run();
279  return 0;
280  }
281  catch(std::exception &e) {
282  args.err_log << "ERROR running " << to_string(MCType::ensemble) << " Monte Carlo.\n\n";
283  args.err_log << e.what() << std::endl;
284  return 1;
285  }
286  }
287 
290  const MonteSettings &monte_settings,
291  const CommandArgs &args,
292  const Completer::MonteOption &monte_opt) {
293 
294  typedef GrandCanonical MCType;
295  const po::variables_map &vm = monte_opt.vm();
296 
297  if(vm.count("initial-POSCAR")) {
298  return _initial_POSCAR<MCType>(primclex, args, monte_opt);
299  }
300  else if(vm.count("final-POSCAR")) {
301  return _final_POSCAR<MCType>(primclex, args, monte_opt);
302  }
303  else if(vm.count("traj-POSCAR")) {
304  return _traj_POSCAR<MCType>(primclex, args, monte_opt);
305  }
306  else if(monte_settings.method() == Monte::METHOD::LTE1) {
307 
308  try {
309 
310  GrandCanonicalSettings gc_settings(primclex, monte_opt.settings_path());
311 
312  if(gc_settings.dependent_runs()) {
313  throw std::invalid_argument("ERROR in LTE1 calculation: dependents_runs must be false");
314  }
315 
316  bool ok = false;
317  if(gc_settings.is_motif_configname() &&
318  (gc_settings.motif_configname() == "auto" ||
319  gc_settings.motif_configname() == "restricted_auto")) {
320  ok = true;
321  }
322 
323  if(!ok) {
324  throw std::invalid_argument("ERROR in LTE1 calculation: must use one of\n"
325  " \"driver\"/\"motif\"/\"configname\": \"auto\"\n"
326  " \"driver\"/\"motif\"/\"configname\": \"restricted_auto\"");
327  }
328 
329  MonteCarloDirectoryStructure dir(gc_settings.output_directory());
330  if(gc_settings.write_csv()) {
331  if(fs::exists(dir.results_csv())) {
332  args.err_log << "Existing file at: " << dir.results_csv() << std::endl;
333  args.err_log << " Exiting..." << std::endl;
334  return ERR_EXISTING_FILE;
335  }
336  }
337  if(gc_settings.write_json()) {
338  if(fs::exists(dir.results_json())) {
339  args.err_log << "Existing file at: " << dir.results_json() << std::endl;
340  args.err_log << " Exiting..." << std::endl;
341  return ERR_EXISTING_FILE;
342  }
343  }
344 
345  GrandCanonical gc(primclex, gc_settings, args.log);
346 
347  // config, param_potential, T,
348  args.log.custom("LTE Calculation");
349  args.log << "Phi_LTE(1) = potential_energy_gs - kT*ln(Z'(1))/N" << std::endl;
350  args.log << "Z'(1) = sum_i(exp(-dPE_i/kT), summing over ground state and single spin flips" << std::endl;
351  args.log << "dPE_i: (potential_energy_i - potential_energy_gs)*N" << "\n\n" << std::endl;
352 
353  auto init = gc_settings.initial_conditions();
354  auto incr = init;
355  int num_conditions = 1;
356 
357  if(monte_settings.drive_mode() == Monte::DRIVE_MODE::INCREMENTAL) {
358 
359  incr = gc_settings.incremental_conditions();
360  auto final = gc_settings.final_conditions();
361  num_conditions = (final - init) / incr + 1;
362  }
363 
364  std::string configname;
365 
366  auto cond = init;
367  for(int index = 0; index < num_conditions; ++index) {
368 
369  configname = gc.set_state(cond, gc_settings).second;
370 
371  if(gc.debug()) {
372  const auto &comp_converter = gc.primclex().composition_axes();
373  args.log << "formation_energy: " << std::setprecision(12) << gc.formation_energy() << std::endl;
374  args.log << " components: " << jsonParser(gc.primclex().composition_axes().components()) << std::endl;
375  args.log << " comp_n: " << gc.comp_n().transpose() << std::endl;
376  args.log << " param_chem_pot: " << gc.conditions().param_chem_pot().transpose() << std::endl;
377  args.log << " comp_x: " << comp_converter.param_composition(gc.comp_n()).transpose() << std::endl;
378  args.log << "potential energy: " << std::setprecision(12) << gc.potential_energy() << std::endl << std::endl;
379  }
380 
381  double phi_LTE1 = gc.lte_grand_canonical_free_energy();
382 
383  args.log.write("Output files");
384  write_lte_results(gc_settings, gc, phi_LTE1, configname, args.log);
385  args.log << std::endl;
386  cond += incr;
387 
388  args.log << std::endl;
389  }
390 
391  return 0;
392 
393  }
394  catch(std::exception &e) {
395  args.err_log << "ERROR calculating single spin flip LTE grand canonical potential.\n\n";
396  args.err_log << e.what() << std::endl;
397  return 1;
398  }
399  }
400  else if(monte_settings.method() == Monte::METHOD::Metropolis) {
401  return _driver<GrandCanonical>(primclex, args, monte_opt);
402  }
403  else {
404  args.err_log << "ERROR running " << to_string(GrandCanonical::ensemble) << " Monte Carlo. No valid option given.\n\n";
405  return ERR_INVALID_INPUT_FILE;
406  }
407  }
408 
411  const MonteSettings &monte_settings,
412  const CommandArgs &args,
413  const Completer::MonteOption &monte_opt) {
414 
415  typedef Monte::Canonical MCType;
416  const po::variables_map &vm = monte_opt.vm();
417 
418  if(vm.count("initial-POSCAR")) {
419  return _initial_POSCAR<MCType>(primclex, args, monte_opt);
420  }
421  else if(vm.count("final-POSCAR")) {
422  return _final_POSCAR<MCType>(primclex, args, monte_opt);
423  }
424  else if(vm.count("traj-POSCAR")) {
425  return _traj_POSCAR<MCType>(primclex, args, monte_opt);
426  }
427  else if(monte_settings.method() == Monte::METHOD::Metropolis) {
428  return _driver<MCType>(primclex, args, monte_opt);
429  }
430  else {
431  args.err_log << "ERROR running " << to_string(Monte::Canonical::ensemble) << " Monte Carlo. No valid option given.\n\n";
432  return ERR_INVALID_INPUT_FILE;
433  }
434  }
435 }
Data structure holding basic CASM command info.
ClexDescription & desc
Definition: settings.cc:104
void add_verbosity_suboption()
Add a –verbosity suboption. Default "standard" of "none", "quiet", "standard", "verbose", "debug" or an int 0-100.
Definition: Handlers.cc:289
Eigen::VectorXd param_chem_pot() const
parametric chemical potential: dg/dcomp_x
void write_POSCAR_trajectory(const MonteCarlo &mc, Index cond_index, Log &_log)
For every snapshot taken, write a POSCAR file.
Definition: MonteIO.cc:427
int _run_GrandCanonical(PrimClex &primclex, const MonteSettings &monte_settings, const CommandArgs &args, const Completer::MonteOption &monte_opt)
Definition: monte.cc:288
#define ERR_INVALID_ARG
void write_lte_results(const MonteSettings &settings, const GrandCanonical &mc, const double &phi_LTE1, const std::string &configname, Log &_log)
Will create new file or append to existing results file the results of the latest run...
void write(const std::string &what)
Definition: Log.hh:66
PrimClex * primclex
Definition: settings.cc:101
const fs::path settings_path() const
Returns the path corresponding to add_settings_suboption.
Definition: Handlers.cc:180
void add_help_suboption()
Add a plain –help suboption.
Definition: Handlers.cc:276
void add_settings_suboption(bool required=true)
Add a –settings suboption. Expects a corresponding casm format to go with it.
Definition: Handlers.cc:296
const Eigen::VectorXd & comp_n() const
Number of atoms of each type, normalized per primitive cell.
Main CASM namespace.
Definition: complete.cpp:8
std::string to_string(ENUM val)
Return string representation of enum class.
Definition: EnumIO.hh:83
Log & log
Definition: settings.cc:105
const std::string & verbosity_str() const
Returns the string corresponding to add_verbosity_suboption()
Definition: Handlers.cc:176
void read(const std::string &what)
Definition: Log.hh:61
bool debug() const
return true if running in debug mode
Definition: MonteCarlo.hh:171
static std::pair< bool, int > verbosity_level(std::string s)
Read verbosity level from a string.
Definition: Log.cc:66
void print_monte_help(std::ostream &sout, const po::options_description &desc)
Definition: monte.cc:16
std::vector< std::string > components() const
The order of components in mol composition vectors.
void custom(const std::string &what)
Definition: Log.hh:96
int _traj_POSCAR(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt)
Definition: monte.cc:255
int verbosity() const
Definition: Log.cc:38
double lte_grand_canonical_free_energy() const
Calculate the single spin flip low temperature expansion of the grand canonical potential.
const po::options_description & desc()
Get the program options, filled with the initialized values.
Definition: Handlers.cc:160
const double & potential_energy() const
Potential energy, normalized per primitive cell.
void write_POSCAR_initial(const MonteCarlo &mc, Index cond_index, Log &_log)
For the initial state, write a POSCAR file.
Definition: MonteIO.cc:372
EigenIndex Index
For long integer indexing:
Index condition_index() const
Definition: monte.cc:75
int _initial_POSCAR(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt)
Definition: monte.cc:217
const PrimClex & primclex() const
const Access the PrimClex that *this is based on
Definition: MonteCarlo.hh:68
po::options_description m_desc
Boost program options. All the derived classes have them, but will fill them up themselves.
Definition: Handlers.hh:126
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:52
int monte_command(const CommandArgs &args)
Definition: monte.cc:106
void set_debug(bool _debug)
Set debug mode.
const CompositionConverter & composition_axes() const
const Access CompositionConverter object
Definition: PrimClex.cc:237
ConfigIO::GenericConfigFormatter< std::string > configname()
Constructs DataFormmaterDictionary containing all Configuration DatumFormatters.
Definition: ConfigIO.cc:340
po::variables_map & vm()
Get the variables map.
Definition: Handlers.cc:145
std::pair< ConfigDoF, std::string > set_state(const GrandCanonicalConditions &new_conditions, const GrandCanonicalSettings &settings)
Set configdof and conditions and clear previously collected data.
DirectoryStructure & dir
Definition: settings.cc:102
PrimClex & make_primclex_if_not(const CommandArgs &args, std::unique_ptr< PrimClex > &uniq_primclex)
If !_primclex, construct new PrimClex stored in uniq_primclex, then return reference to existing or c...
virtual const Monte::DRIVE_MODE drive_mode() const
Given a settings jsonParser figure out the drive mode. Expects drive_mode/incremental,custom.
bool debug() const
Run in debug mode?
const double & formation_energy() const
Formation energy, normalized per primitive cell.
void write_POSCAR_final(const MonteCarlo &mc, Index cond_index, Log &_log)
For the final state, write a POSCAR file.
Definition: MonteIO.cc:399
void set_verbosity(int _verbosity)
Definition: Log.cc:42
Monte::ENSEMBLE ensemble() const
Return type of Monte Carlo ensemble.
const CondType & conditions() const
Return current conditions.
static const Monte::ENSEMBLE ensemble
void print_monte_desc(std::ostream &sout, const po::options_description &desc)
Definition: monte.cc:21
Monte::METHOD method() const
Return type of Monte Carlo method.
void initialize() override
Fill in the options descriptions accordingly.
Definition: monte.cc:63
void error(const std::string &what)
Definition: Log.hh:86
int _run_Canonical(PrimClex &primclex, const MonteSettings &monte_settings, const CommandArgs &args, const Completer::MonteOption &monte_opt)
Definition: monte.cc:409
Settings for Monte Carlo calculations.
Definition: Log.hh:9
int _final_POSCAR(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt)
Definition: monte.cc:236
#define ERR_EXISTING_FILE
int _driver(PrimClex &primclex, const CommandArgs &args, const Completer::MonteOption &monte_opt)
Definition: monte.cc:274
static const Monte::ENSEMBLE ensemble
Definition: Canonical.hh:38
#define ERR_NO_PROJ
#define ERR_INVALID_INPUT_FILE