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