1 #ifndef CASM_MonteDriver_HH
2 #define CASM_MonteDriver_HH
25 template<
typename RunType>
85 template<
typename RunType>
89 template<
typename RunType>
94 m_dir(m_settings.output_directory()),
95 m_drive_mode(m_settings.drive_mode()),
96 m_mc(primclex, m_settings, _log),
97 m_conditions_list(make_conditions_list(primclex, m_settings)),
98 m_debug(m_settings.debug()),
99 m_enum(m_settings.is_enumeration() ? new
MonteCarloEnum(primclex, settings, _log, m_mc) : nullptr) {
109 template<
typename RunType>
112 m_log.check(
"For existing calculations");
114 if(!m_settings.write_json() && !m_settings.write_csv()) {
115 throw std::runtime_error(
116 std::string(
"No valid monte carlo output format.\n") +
117 " Expected [\"data\"][\"storage\"][\"output_format\"] to contain a string or array of strings.\n" +
118 " Valid options are 'csv' or 'json'.");
122 Index start_i = _find_starting_conditions();
125 std::vector<Index> repeats;
126 for(
Index i = start_i; i < m_conditions_list.size(); ++i) {
127 if(fs::exists(m_dir.conditions_dir(i))) {
128 repeats.push_back(i);
132 if(start_i == m_conditions_list.size()) {
133 m_log <<
"calculations already complete." << std::endl;
138 if(start_i > 0 || repeats.size() > 0) {
140 m_log <<
"found existing calculations\n";
141 m_log <<
"will begin with condition " << start_i <<
"\n";
146 m_log <<
"will overwrite existing results for condition(s): " << json <<
"\n";
150 m_log <<
"did not find existing calculations\n";
154 if(m_settings.dependent_runs()) {
160 m_mc.set_state(m_conditions_list[0], m_settings);
163 if(m_settings.dependent_runs() && m_settings.is_equilibration_passes_first_run()) {
165 auto equil_passes = m_settings.equilibration_passes_first_run();
168 m_log <<
"write: " << m_dir.initial_state_firstruneq_json(0) <<
"\n" << std::endl;
171 fs::create_directories(m_dir.conditions_dir(0));
172 to_json(m_mc.configdof(), json).write(m_dir.initial_state_firstruneq_json(0));
174 m_log.
begin(
"Equilibration passes");
175 m_log << equil_passes <<
" equilibration passes\n" << std::endl;
177 MonteCounter equil_counter(m_settings, m_mc.steps_per_pass());
178 while(equil_counter.pass() != equil_passes) {
191 m_conditions_list[start_i],
193 std::string(
"Using: ") + m_dir.final_state_json(start_i - 1).string());
198 for(
Index i = start_i; i < m_conditions_list.size(); i++) {
199 if(!m_settings.dependent_runs()) {
200 m_mc.set_state(m_conditions_list[i], m_settings);
202 else if(i != start_i) {
204 m_mc.set_conditions(m_conditions_list[i]);
206 m_log.custom(
"Continue with existing DoF");
223 template<
typename RunType>
227 Index start_max = m_conditions_list.size();
228 Index start_json = m_settings.write_json() ? 0 : start_max;
229 Index start_csv = m_settings.write_csv() ? 0 : start_max;
231 fs::ifstream csv_results;
233 std::stringstream ss;
238 if(m_settings.write_json() && fs::exists(m_dir.results_json())) {
240 json_results.
read(m_dir.results_json());
243 while(json_results.
begin()->size() > start_json && fs::exists(m_dir.final_state_json(start_i)) && start_i < start_max) {
247 start_max = start_json;
251 if(m_settings.write_csv() && fs::exists(m_dir.results_csv())) {
253 csv_results.open(m_dir.results_csv());
256 std::getline(csv_results, str);
260 while(!csv_results.eof() && fs::exists(m_dir.final_state_json(start_csv)) && start_i < start_max) {
262 std::getline(csv_results, str);
266 start_max = start_csv;
271 start_i =
std::min(start_json, start_csv);
277 if(m_settings.write_json() && fs::exists(m_dir.results_json())) {
281 for(
auto it = json_results.
begin(); it != json_results.
end(); ++it) {
283 for(
Index i = 0; i < start_i; ++i) {
287 m_log <<
"update: " << m_dir.results_json() <<
"\n";
288 finished_results.
write(m_dir.results_json());
292 if(m_settings.write_csv() && fs::exists(m_dir.results_csv())) {
293 m_log <<
"update: " << m_dir.results_csv() <<
"\n";
294 fs::ofstream out(m_dir.results_csv());
302 template<
typename RunType>
305 fs::create_directories(m_dir.conditions_dir(cond_index));
308 if(m_settings.is_equilibration_passes_each_run()) {
311 m_log <<
"write: " << m_dir.initial_state_runeq_json(cond_index) <<
"\n" << std::endl;
314 to_json(m_mc.configdof(), json).write(m_dir.initial_state_runeq_json(cond_index));
315 auto equil_passes = m_settings.equilibration_passes_each_run();
317 m_log.
begin(
"Equilibration passes");
318 m_log << equil_passes <<
" equilibration passes\n" << std::endl;
320 MonteCounter equil_counter(m_settings, m_mc.steps_per_pass());
321 while(equil_counter.pass() != equil_passes) {
329 m_log <<
"write: " << m_dir.initial_state_json(cond_index) <<
"\n" << std::endl;
331 to_json(m_mc.configdof(), json).write(m_dir.initial_state_json(cond_index));
333 std::stringstream ss;
334 ss <<
"Conditions " << cond_index;
335 m_log.
begin(ss.str());
339 MonteCounter run_counter(m_settings, m_mc.steps_per_pass());
348 m_log <<
"pass: " << run_counter.pass() <<
" "
349 <<
"step: " << run_counter.step() <<
" "
350 <<
"samples: " << run_counter.samples() <<
"\n" << std::endl;
353 if(m_mc.must_converge()) {
355 if(!run_counter.minimums_met()) {
358 if(run_counter.maximums_met()) {
359 throw std::runtime_error(
360 std::string(
"Error in 'MonteDriver<RunType>::single_run()'\n") +
361 " Conflicting input: Minimum number of passes, steps, or samples not met,\n" +
362 " but maximum number of passes, steps, or samples are met.");
367 if(m_mc.check_convergence_time()) {
371 m_log <<
"samples: " << m_mc.sample_times().size() << std::endl;
374 if(m_mc.is_converged()) {
379 if(run_counter.maximums_met()) {
384 else if(run_counter.is_complete()) {
391 if(res && m_enum && m_enum->on_accept()) {
392 m_enum->insert(m_mc.config());
397 if(run_counter.sample_time()) {
400 m_log <<
"pass: " << run_counter.pass() <<
" "
401 <<
"step: " << run_counter.step() <<
" "
402 <<
"take sample " << m_mc.sample_times().size() <<
"\n" << std::endl;
405 m_mc.sample_data(run_counter);
406 run_counter.increment_samples();
407 if(m_enum && m_enum->on_sample()) {
408 m_enum->insert(m_mc.config());
416 double s = m_log.lap_time();
418 m_log <<
"run time: " << s <<
" (s), " << s / run_counter.pass() <<
" (s/pass), " << s / (run_counter.pass()*run_counter.steps_per_pass() + run_counter.step()) <<
"(s/step)\n" << std::endl;
421 m_log <<
"write: " << m_dir.final_state_json(cond_index) <<
"\n" << std::endl;
422 to_json(m_mc.configdof(), json).write(m_dir.final_state_json(cond_index));
424 m_log.
write(
"Output files");
425 m_mc.write_results(cond_index);
429 m_enum->save_configs();
446 template<
typename RunType>
447 std::vector<typename MonteDriver<RunType>::CondType>
450 std::vector<CondType> conditions_list;
452 switch(m_drive_mode) {
457 std::vector<CondType> custom_cond(settings.custom_conditions());
459 while(fs::exists(m_dir.conditions_json(i))) {
464 if(existing != custom_cond[i]) {
465 m_err_log.error(
"Conditions mismatch");
466 m_err_log <<
"existing conditions: " << m_dir.conditions_json(i) <<
"\n";
467 m_err_log << existing <<
"\n\n";
468 m_err_log <<
"specified custom conditions " << i <<
":\n";
469 m_err_log << custom_cond[i] <<
"\n" << std::endl;
470 throw std::runtime_error(
"ERROR: custom_conditions list has changed.");
480 CondType init_cond(settings.initial_conditions());
481 CondType final_cond(settings.final_conditions());
482 CondType cond_increment(settings.incremental_conditions());
484 CondType incrementing_cond = init_cond;
486 int num_increments = 1 + (final_cond - init_cond) / cond_increment;
488 for(
int i = 0; i < num_increments; i++) {
489 conditions_list.push_back(incrementing_cond);
490 incrementing_cond += cond_increment;
494 while(fs::exists(m_dir.conditions_json(i)) && i < conditions_list.size()) {
499 if(existing != conditions_list[i]) {
500 m_err_log.error(
"Conditions mismatch");
501 m_err_log <<
"existing conditions: " << m_dir.conditions_json(i) <<
"\n";
502 m_err_log << existing <<
"\n";
503 m_err_log <<
"incremental conditions " << i <<
":\n";
504 m_err_log << conditions_list[i] <<
"\n" << std::endl;
505 throw std::runtime_error(
"ERROR: initial_conditions or incremental_conditions has changed.");
511 return conditions_list;
515 throw std::runtime_error(
"ERROR: An invalid drive mode was given.");
520 template<
typename RunType>
523 typedef typename RunType::EventType EventType;
525 const EventType &
event = monte_run.propose();
527 if(monte_run.check(event)) {
528 monte_run.accept(event);
533 monte_run.reject(event);
void run()
Run everything requested by the MonteSettings.
bool m_debug
run in debug mode?
void single_run(Index cond_index)
Converge the MonteCarlo for conditions 'cond_index'.
void from_json(ClexDescription &desc, const jsonParser &json)
iterator end()
Returns iterator to end of JSON object or JSON array.
MonteCarloDirectoryStructure m_dir
describes where to write output
SettingsType m_settings
Copy of initial settings given at construction. Will expand to have MonteCarlo states dumped into it...
void write(const std::string &file_name, unsigned int indent=2, unsigned int prec=12) const
Write json to file.
jsonParser & to_json(const ClexDescription &desc, jsonParser &json)
std::vector< CondType > make_conditions_list(const PrimClex &primclex, const SettingsType &settings)
Return the appropriate std::vector of conditions to visit based from settings. Use for construction...
bool read(std::istream &stream)
Reads json from the stream.
MonteDriver(PrimClex &primclex, const SettingsType &settings, Log &_log, Log &_err_log)
Constructor via MonteSettings.
RunType::CondType CondType
iterator begin()
Returns const_iterator to beginning of JSON object or JSON array.
Track the number of passes, steps and samples taken in a Monte Carlo calculation. ...
DRIVE_MODE
How to change conditions.
void reset()
Set all counter variables back to 0.
const std::vector< CondType > m_conditions_list
List of specialized conditions to visit in sequential order. Does not include initial conditions...
EigenIndex Index
For long integer indexing:
A container class for the different degrees of freedom a Configuration might have.
RunType m_mc
Specialized Monte Carlo object to use throughout.
PrimClex is the top-level data structure for a CASM project.
T min(const T &A, const T &B)
bool debug() const
run in debug mode?
bool monte_carlo_step(RunType &monte_run)
Perform a single monte carlo step, return true if accepted.
const Monte::DRIVE_MODE m_drive_mode
Specifies how to build the conditions list from the settings.
notstd::cloneable_ptr< MonteCarloEnum > m_enum
Enumerated configurations encountered during Monte Carlo calculations.
Index _find_starting_conditions() const
Check for existing calculations to find starting conditions.
jsonParser & push_back(const T &value)
Puts new valued element at end of array of any type T for which 'jsonParser& to_json( const T &value...
Log & m_err_log
target for error messages
A 'cloneable_ptr' can be used in place of 'unique_ptr'.
RunType::SettingsType SettingsType
jsonParser & put_array()
Puts new empty JSON array.
Log & m_log
target for log messages