version 1.25 | version 1.26 |
---|
| |
/// -*- c++ -*- | // -*- c++ -*- |
| |
#include <sstream> | #include <sstream> |
#include <string.h> | #include <string.h> |
| |
#include "colvarbias_restraint.h" | #include "colvarbias_restraint.h" |
#include "colvarscript.h" | #include "colvarscript.h" |
| |
| |
colvarmodule::colvarmodule(colvarproxy *proxy_in) | colvarmodule::colvarmodule(colvarproxy *proxy_in) |
{ | { |
// pointer to the proxy object | // pointer to the proxy object |
| |
cvm::log(cvm::line_marker); | cvm::log(cvm::line_marker); |
cvm::log("Initializing the collective variables module, version "+ | cvm::log("Initializing the collective variables module, version "+ |
cvm::to_str(COLVARS_VERSION)+".\n"); | cvm::to_str(COLVARS_VERSION)+".\n"); |
| cvm::log("Please cite Fiorin et al, Mol Phys 2013:\n " |
| "http://dx.doi.org/10.1080/00268976.2013.813594\n" |
| "in any publication based on this calculation.\n"); |
| |
| if (proxy->smp_enabled() == COLVARS_OK) { |
| cvm::log("SMP parallelism is available.\n"); |
| } |
| |
// set initial default values | // set initial default values |
| |
| |
std::string conf = ""; | std::string conf = ""; |
std::string line; | std::string line; |
while (colvarparse::getline_nocomments(config_s, line)) { | while (colvarparse::getline_nocomments(config_s, line)) { |
| // Delete lines that contain only white space after removing comments |
| if (line.find_first_not_of(colvarparse::white_space) != std::string::npos) |
conf.append(line+"\n"); | conf.append(line+"\n"); |
} | } |
config_s.close(); | config_s.close(); |
| |
std::string conf = ""; | std::string conf = ""; |
std::string line; | std::string line; |
while (colvarparse::getline_nocomments(config_s, line)) { | while (colvarparse::getline_nocomments(config_s, line)) { |
| // Delete lines that contain only white space after removing comments |
| if (line.find_first_not_of(colvarparse::white_space) != std::string::npos) |
conf.append(line+"\n"); | conf.append(line+"\n"); |
} | } |
return parse_config(conf); | return parse_config(conf); |
} | } |
| |
| |
int colvarmodule::parse_config(std::string &conf) | int colvarmodule::parse_config(std::string &conf) |
{ | { |
int error_code = 0; | |
| |
// parse global options | // parse global options |
error_code |= parse_global_params(conf); | if (catch_input_errors(parse_global_params(conf))) { |
| return get_error(); |
if (error_code != COLVARS_OK || cvm::get_error()) { | |
set_error_bits(INPUT_ERROR); | |
return COLVARS_ERROR; | |
} | } |
| |
// parse the options for collective variables | // parse the options for collective variables |
error_code |= parse_colvars(conf); | if (catch_input_errors(parse_colvars(conf))) { |
| return get_error(); |
if (error_code != COLVARS_OK || cvm::get_error()) { | |
set_error_bits(INPUT_ERROR); | |
return COLVARS_ERROR; | |
} | } |
| |
// parse the options for biases | // parse the options for biases |
error_code |= parse_biases(conf); | if (catch_input_errors(parse_biases(conf))) { |
| return get_error(); |
if (error_code != COLVARS_OK || cvm::get_error()) { | |
set_error_bits(INPUT_ERROR); | |
return COLVARS_ERROR; | |
} | } |
| |
// done parsing known keywords, check that all keywords found were valid ones | // done parsing known keywords, check that all keywords found were valid ones |
error_code |= parse->check_keywords(conf, "colvarmodule"); | if (catch_input_errors(parse->check_keywords(conf, "colvarmodule"))) { |
| return get_error(); |
if (error_code != COLVARS_OK || cvm::get_error()) { | |
set_error_bits(INPUT_ERROR); | |
return COLVARS_ERROR; | |
} | } |
| |
cvm::log(cvm::line_marker); | cvm::log(cvm::line_marker); |
cvm::log("Collective variables module (re)initialized.\n"); | cvm::log("Collective variables module (re)initialized.\n"); |
cvm::log(cvm::line_marker); | cvm::log(cvm::line_marker); |
| |
| // update any necessary proxy data |
| proxy->setup(); |
| |
if (cv_traj_os.is_open()) { | if (cv_traj_os.is_open()) { |
// configuration might have changed, better redo the labels | // configuration might have changed, better redo the labels |
write_traj_label(cv_traj_os); | write_traj_label(cv_traj_os); |
} | } |
| |
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); | return get_error(); |
} | } |
| |
| |
| |
// we are continuing after a reset(): default to true | // we are continuing after a reset(): default to true |
parse->get_keyval(conf, "colvarsTrajAppend", cv_traj_append, cv_traj_append); | parse->get_keyval(conf, "colvarsTrajAppend", cv_traj_append, cv_traj_append); |
| |
parse->get_keyval(conf, "scriptedColvarForces", use_scripted_forces, false, | parse->get_keyval(conf, "scriptedColvarForces", use_scripted_forces, false); |
colvarparse::parse_silent); | |
| parse->get_keyval(conf, "scriptingAfterBiases", scripting_after_biases, true); |
| |
if (use_scripted_forces && !proxy->force_script_defined) { | if (use_scripted_forces && !proxy->force_script_defined) { |
cvm::fatal_error("User script for scripted colvar forces not found."); | cvm::error("User script for scripted colvar forces not found.", INPUT_ERROR); |
} | } |
| |
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); | return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); |
| |
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); | return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); |
} | } |
| |
| |
bool colvarmodule::check_new_bias(std::string &conf, char const *key) | bool colvarmodule::check_new_bias(std::string &conf, char const *key) |
{ | { |
if (cvm::get_error() || | if (cvm::get_error() || |
| |
if (bias_conf.size()) { | if (bias_conf.size()) { |
cvm::log(cvm::line_marker); | cvm::log(cvm::line_marker); |
cvm::increase_depth(); | cvm::increase_depth(); |
biases.push_back(new bias_type(bias_conf, keyword)); | biases.push_back(new bias_type(keyword)); |
if (cvm::check_new_bias(bias_conf, keyword)) { | biases.back()->init(bias_conf); |
| if (cvm::check_new_bias(bias_conf, keyword) != COLVARS_OK) { |
return COLVARS_ERROR; | return COLVARS_ERROR; |
} | } |
cvm::decrease_depth(); | cvm::decrease_depth(); |
| |
/// initialize histograms | /// initialize histograms |
parse_biases_type<colvarbias_histogram>(conf, "histogram", n_histo_biases); | parse_biases_type<colvarbias_histogram>(conf, "histogram", n_histo_biases); |
| |
| /// initialize histogram restraints |
| parse_biases_type<colvarbias_restraint_histogram>(conf, "histogramRestraint", n_rest_biases); |
| |
/// initialize linear restraints | /// initialize linear restraints |
parse_biases_type<colvarbias_restraint_linear>(conf, "linear", n_rest_biases); | parse_biases_type<colvarbias_restraint_linear>(conf, "linear", n_rest_biases); |
| |
| |
cvm::decrease_depth(); | cvm::decrease_depth(); |
} | } |
| |
| size_t i; |
| |
| for (i = 0; i < biases.size(); i++) { |
| biases[i]->enable(colvardeps::f_cvb_active); |
| if (cvm::debug()) |
| biases[i]->print_state(); |
| } |
| |
| size_t n_hist_dep_biases = 0; |
| std::vector<std::string> hist_dep_biases_names; |
| for (i = 0; i < biases.size(); i++) { |
| if (biases[i]->is_enabled(colvardeps::f_cvb_apply_force) && |
| biases[i]->is_enabled(colvardeps::f_cvb_history_dependent)) { |
| n_hist_dep_biases++; |
| hist_dep_biases_names.push_back(biases[i]->name); |
| } |
| } |
| if (n_hist_dep_biases > 1) { |
| cvm::log("WARNING: there are "+cvm::to_str(n_hist_dep_biases)+ |
| " history-dependent biases with non-zero force parameters:\n"+ |
| cvm::to_str(hist_dep_biases_names)+"\n"+ |
| "Please make sure that their forces do not counteract each other.\n"); |
| } |
| |
if (biases.size() || use_scripted_forces) { | if (biases.size() || use_scripted_forces) { |
cvm::log(cvm::line_marker); | cvm::log(cvm::line_marker); |
cvm::log("Collective variables biases initialized, "+ | cvm::log("Collective variables biases initialized, "+ |
| |
} | } |
| |
| |
| int colvarmodule::catch_input_errors(int result) |
| { |
| if (result != COLVARS_OK || get_error()) { |
| set_error_bits(result); |
| set_error_bits(INPUT_ERROR); |
| parse->init(); |
| return get_error(); |
| } |
| return COLVARS_OK; |
| } |
| |
| |
colvarbias * colvarmodule::bias_by_name(std::string const &name) { | colvarbias * colvarmodule::bias_by_name(std::string const &name) { |
for (std::vector<colvarbias *>::iterator bi = biases.begin(); | for (std::vector<colvarbias *>::iterator bi = biases.begin(); |
bi != biases.end(); | bi != biases.end(); |
| |
} | } |
| |
| |
int colvarmodule::calc() { | int colvarmodule::calc() |
cvm::real total_bias_energy = 0.0; | { |
cvm::real total_colvar_energy = 0.0; | int error_code = COLVARS_OK; |
| |
std::vector<colvar *>::iterator cvi; | |
std::vector<colvarbias *>::iterator bi; | |
| |
if (cvm::debug()) { | if (cvm::debug()) { |
cvm::log(cvm::line_marker); | cvm::log(cvm::line_marker); |
| |
cvm::to_str(cvm::step_absolute())+"\n"); | cvm::to_str(cvm::step_absolute())+"\n"); |
} | } |
| |
// calculate collective variables and their gradients | error_code |= calc_colvars(); |
| // set biasing forces to zero before biases are calculated and summed over |
| for (std::vector<colvar *>::iterator cvi = colvars.begin(); |
| cvi != colvars.end(); cvi++) { |
| (*cvi)->reset_bias_force(); |
| } |
| error_code |= calc_biases(); |
| error_code |= update_colvar_forces(); |
| |
| if (cvm::b_analysis) { |
| error_code |= analyze(); |
| } |
| |
| // write trajectory files, if needed |
| if (cv_traj_freq && cv_traj_name.size()) { |
| error_code |= write_traj_files(); |
| } |
| |
| // write restart files, if needed |
| if (restart_out_freq && restart_out_name.size()) { |
| error_code |= write_restart_files(); |
| } |
| |
| return error_code; |
| } |
| |
| |
| int colvarmodule::calc_colvars() |
| { |
if (cvm::debug()) | if (cvm::debug()) |
cvm::log("Calculating collective variables.\n"); | cvm::log("Calculating collective variables.\n"); |
| // calculate collective variables and their gradients |
| |
| int error_code = COLVARS_OK; |
| std::vector<colvar *>::iterator cvi; |
| |
| // Determine which colvars are active at this time step |
| for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { |
| (*cvi)->feature_states[colvardeps::f_cv_active]->enabled = (step_absolute() % (*cvi)->get_time_step_factor() == 0); |
| } |
| |
| // if SMP support is available, split up the work |
| if (proxy->smp_enabled() == COLVARS_OK) { |
| |
| // first, calculate how much work (currently, how many active CVCs) each colvar has |
| |
| colvars_smp.resize(0); |
| colvars_smp_items.resize(0); |
| |
| colvars_smp.reserve(colvars.size()); |
| colvars_smp_items.reserve(colvars.size()); |
| |
| // set up a vector containing all components |
| size_t num_colvar_items = 0; |
cvm::increase_depth(); | cvm::increase_depth(); |
for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { | for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { |
(*cvi)->calc(); | |
| if (!(*cvi)->is_enabled()) continue; |
| error_code |= (*cvi)->update_cvc_flags(); |
| |
| size_t num_items = (*cvi)->num_active_cvcs(); |
| colvars_smp.reserve(colvars_smp.size() + num_items); |
| colvars_smp_items.reserve(colvars_smp_items.size() + num_items); |
| for (size_t icvc = 0; icvc < num_items; icvc++) { |
| colvars_smp.push_back(*cvi); |
| colvars_smp_items.push_back(icvc); |
| } |
| |
| num_colvar_items += num_items; |
| } |
| cvm::decrease_depth(); |
| |
| // calculate colvar components in parallel |
| error_code |= proxy->smp_colvars_loop(); |
| |
| cvm::increase_depth(); |
| for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { |
| if (!(*cvi)->is_enabled()) continue; |
| error_code |= (*cvi)->collect_cvc_data(); |
| } |
| cvm::decrease_depth(); |
| |
| } else { |
| |
| // calculate colvars one at a time |
| cvm::increase_depth(); |
| for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { |
| if (!(*cvi)->is_enabled()) continue; |
| error_code |= (*cvi)->calc(); |
if (cvm::get_error()) { | if (cvm::get_error()) { |
return COLVARS_ERROR; | return COLVARS_ERROR; |
} | } |
} | } |
cvm::decrease_depth(); | cvm::decrease_depth(); |
| } |
| |
| error_code |= cvm::get_error(); |
| return error_code; |
| } |
| |
| |
| int colvarmodule::calc_biases() |
| { |
// update the biases and communicate their forces to the collective | // update the biases and communicate their forces to the collective |
// variables | // variables |
if (cvm::debug() && biases.size()) | if (cvm::debug() && biases.size()) |
cvm::log("Updating collective variable biases.\n"); | cvm::log("Updating collective variable biases.\n"); |
cvm::increase_depth(); | |
for (bi = biases.begin(); bi != biases.end(); bi++) { | std::vector<colvarbias *>::iterator bi; |
total_bias_energy += (*bi)->update(); | int error_code = COLVARS_OK; |
if (cvm::get_error()) { | |
return COLVARS_ERROR; | // if SMP support is available, split up the work |
| if (proxy->smp_enabled() == COLVARS_OK) { |
| |
| if (use_scripted_forces && !scripting_after_biases) { |
| // calculate biases and scripted forces in parallel |
| error_code |= proxy->smp_biases_script_loop(); |
| } else { |
| // calculate biases in parallel |
| error_code |= proxy->smp_biases_loop(); |
} | } |
| |
| } else { |
| |
| if (use_scripted_forces && !scripting_after_biases) { |
| error_code |= calc_scripted_forces(); |
} | } |
cvm::decrease_depth(); | |
| |
// sum the forces from all biases for each collective variable | |
if (cvm::debug() && biases.size()) | |
cvm::log("Collecting forces from all biases.\n"); | |
cvm::increase_depth(); | cvm::increase_depth(); |
for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { | |
(*cvi)->reset_bias_force(); | |
} | |
for (bi = biases.begin(); bi != biases.end(); bi++) { | for (bi = biases.begin(); bi != biases.end(); bi++) { |
(*bi)->communicate_forces(); | error_code |= (*bi)->update(); |
if (cvm::get_error()) { | if (cvm::get_error()) { |
return COLVARS_ERROR; | return COLVARS_ERROR; |
} | } |
} | } |
| cvm::decrease_depth(); |
// Run user force script, if provided, | |
// potentially adding scripted forces to the colvars | |
if (use_scripted_forces) { | |
int res; | |
res = proxy->run_force_callback(); | |
if (res == COLVARS_NOT_IMPLEMENTED) { | |
cvm::error("Colvar forces scripts are not implemented."); | |
return COLVARS_ERROR; | |
} | } |
if (res != COLVARS_OK) { | |
cvm::error("Error running user colvar forces script"); | cvm::real total_bias_energy = 0.0; |
return COLVARS_ERROR; | for (bi = biases.begin(); bi != biases.end(); bi++) { |
| total_bias_energy += (*bi)->get_energy(); |
} | } |
| |
| proxy->add_energy(total_bias_energy); |
| return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); |
} | } |
| |
cvm::decrease_depth(); | |
| |
if (cvm::b_analysis) { | int colvarmodule::update_colvar_forces() |
// perform runtime analysis of colvars and biases | { |
| int error_code = COLVARS_OK; |
| |
| std::vector<colvar *>::iterator cvi; |
| std::vector<colvarbias *>::iterator bi; |
| |
| // sum the forces from all biases for each collective variable |
if (cvm::debug() && biases.size()) | if (cvm::debug() && biases.size()) |
cvm::log("Perform runtime analyses.\n"); | cvm::log("Collecting forces from all biases.\n"); |
cvm::increase_depth(); | cvm::increase_depth(); |
for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { | |
(*cvi)->analyze(); | |
if (cvm::get_error()) { | |
return COLVARS_ERROR; | |
} | |
} | |
for (bi = biases.begin(); bi != biases.end(); bi++) { | for (bi = biases.begin(); bi != biases.end(); bi++) { |
(*bi)->analyze(); | (*bi)->communicate_forces(); |
if (cvm::get_error()) { | if (cvm::get_error()) { |
return COLVARS_ERROR; | return COLVARS_ERROR; |
} | } |
} | } |
cvm::decrease_depth(); | cvm::decrease_depth(); |
| |
| if (use_scripted_forces && scripting_after_biases) { |
| error_code |= calc_scripted_forces(); |
} | } |
| |
| cvm::real total_colvar_energy = 0.0; |
// sum up the forces for each colvar, including wall forces | // sum up the forces for each colvar, including wall forces |
// and integrate any internal | // and integrate any internal |
// equation of motion (extended system) | // equation of motion (extended system) |
| |
"of colvars (if they have any).\n"); | "of colvars (if they have any).\n"); |
cvm::increase_depth(); | cvm::increase_depth(); |
for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { | for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { |
total_colvar_energy += (*cvi)->update(); | // Here we call even inactive colvars, so they accumulate biasing forces |
| // as well as update their extended-system dynamics |
| total_colvar_energy += (*cvi)->update_forces_energy(); |
if (cvm::get_error()) { | if (cvm::get_error()) { |
return COLVARS_ERROR; | return COLVARS_ERROR; |
} | } |
} | } |
cvm::decrease_depth(); | cvm::decrease_depth(); |
proxy->add_energy(total_bias_energy + total_colvar_energy); | proxy->add_energy(total_colvar_energy); |
| |
// make collective variables communicate their forces to their | // make collective variables communicate their forces to their |
// coupled degrees of freedom (i.e. atoms) | // coupled degrees of freedom (i.e. atoms) |
| |
cvm::log("Communicating forces from the colvars to the atoms.\n"); | cvm::log("Communicating forces from the colvars to the atoms.\n"); |
cvm::increase_depth(); | cvm::increase_depth(); |
for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { | for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { |
if ((*cvi)->tasks[colvar::task_gradients]) { | if ((*cvi)->is_enabled(colvardeps::f_cv_gradient)) { |
| if (!(*cvi)->is_enabled()) continue; |
(*cvi)->communicate_forces(); | (*cvi)->communicate_forces(); |
if (cvm::get_error()) { | if (cvm::get_error()) { |
return COLVARS_ERROR; | return COLVARS_ERROR; |
| |
} | } |
cvm::decrease_depth(); | cvm::decrease_depth(); |
| |
// write restart file, if needed | return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); |
if (restart_out_freq && restart_out_name.size()) { | } |
| |
| |
| int colvarmodule::calc_scripted_forces() |
| { |
| // Run user force script, if provided, |
| // potentially adding scripted forces to the colvars |
| int res; |
| res = proxy->run_force_callback(); |
| if (res == COLVARS_NOT_IMPLEMENTED) { |
| cvm::error("Colvar forces scripts are not implemented."); |
| return COLVARS_NOT_IMPLEMENTED; |
| } |
| if (res != COLVARS_OK) { |
| cvm::error("Error running user colvar forces script"); |
| return COLVARS_ERROR; |
| } |
| return COLVARS_OK; |
| } |
| |
| |
| int colvarmodule::write_restart_files() |
| { |
if ( (cvm::step_relative() > 0) && | if ( (cvm::step_relative() > 0) && |
((cvm::step_absolute() % restart_out_freq) == 0) ) { | ((cvm::step_absolute() % restart_out_freq) == 0) ) { |
cvm::log("Writing the state file \""+ | cvm::log("Writing the state file \""+ |
| |
cvm::error("Error: in writing restart file.\n"); | cvm::error("Error: in writing restart file.\n"); |
restart_out_os.close(); | restart_out_os.close(); |
} | } |
| |
| return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); |
} | } |
| |
// write trajectory file, if needed | |
if (cv_traj_freq && cv_traj_name.size()) { | |
| |
| int colvarmodule::write_traj_files() |
| { |
if (!cv_traj_os.is_open()) { | if (!cv_traj_os.is_open()) { |
open_traj_file(cv_traj_name); | open_traj_file(cv_traj_name); |
} | } |
| |
cv_traj_os.flush(); | cv_traj_os.flush(); |
} | } |
} | } |
} // end if (cv_traj_freq) | |
| |
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); | return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); |
} | } |
| |
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); | return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); |
} | } |
| |
| |
int colvarmodule::setup() | int colvarmodule::setup() |
{ | { |
| if (this->size() == 0) return cvm::get_error(); |
// loop over all components of all colvars to reset masses of all groups | // loop over all components of all colvars to reset masses of all groups |
for (std::vector<colvar *>::iterator cvi = colvars.begin(); | for (std::vector<colvar *>::iterator cvi = colvars.begin(); |
cvi != colvars.end(); cvi++) { | cvi != colvars.end(); cvi++) { |
(*cvi)->setup(); | (*cvi)->setup(); |
} | } |
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); | return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); |
| |
} | } |
| |
| |
colvarmodule::~colvarmodule() | colvarmodule::~colvarmodule() |
{ | { |
| if ((proxy->smp_thread_id() == COLVARS_NOT_IMPLEMENTED) || |
| (proxy->smp_thread_id() == 0)) { |
reset(); | reset(); |
delete parse; | delete parse; |
| parse = NULL; |
proxy = NULL; | proxy = NULL; |
} | } |
| } |
| |
| |
int colvarmodule::reset() | int colvarmodule::reset() |
{ | { |
| parse->init(); |
| |
cvm::log("Resetting the Collective Variables Module.\n"); | cvm::log("Resetting the Collective Variables Module.\n"); |
// Iterate backwards because we are deleting the elements as we go | |
for (std::vector<colvar *>::reverse_iterator cvi = colvars.rbegin(); | |
cvi != colvars.rend(); | |
cvi++) { | |
delete *cvi; // the colvar destructor updates the colvars array | |
} | |
colvars.clear(); | |
| |
// Iterate backwards because we are deleting the elements as we go | // Iterate backwards because we are deleting the elements as we go |
for (std::vector<colvarbias *>::reverse_iterator bi = biases.rbegin(); | for (std::vector<colvarbias *>::reverse_iterator bi = biases.rbegin(); |
| |
} | } |
biases.clear(); | biases.clear(); |
| |
| // Iterate backwards because we are deleting the elements as we go |
| for (std::vector<colvar *>::reverse_iterator cvi = colvars.rbegin(); |
| cvi != colvars.rend(); |
| cvi++) { |
| delete *cvi; // the colvar destructor updates the colvars array |
| } |
| colvars.clear(); |
| |
index_groups.clear(); | index_groups.clear(); |
index_group_names.clear(); | index_group_names.clear(); |
| |
| |
| |
int colvarmodule::setup_input() | int colvarmodule::setup_input() |
{ | { |
// name of input state file | if (this->size() == 0) return cvm::get_error(); |
restart_in_name = proxy->input_prefix().size() ? | |
std::string(proxy->input_prefix()+".colvars.state") : | std::string restart_in_name(""); |
std::string("") ; | |
| |
// read the restart configuration, if available | // read the restart configuration, if available |
if (restart_in_name.size()) { | if (proxy->input_prefix().size()) { |
// read the restart file | // read the restart file |
| restart_in_name = proxy->input_prefix(); |
std::ifstream input_is(restart_in_name.c_str()); | std::ifstream input_is(restart_in_name.c_str()); |
if (!input_is.good()) { | if (!input_is.good()) { |
cvm::error("Error: in opening restart file \""+ | // try by adding the suffix |
| input_is.clear(); |
| restart_in_name = restart_in_name+std::string(".colvars.state"); |
| input_is.open(restart_in_name.c_str()); |
| } |
| |
| if (!input_is.good()) { |
| cvm::error("Error: in opening input file \""+ |
std::string(restart_in_name)+"\".\n", | std::string(restart_in_name)+"\".\n", |
FILE_ERROR); | FILE_ERROR); |
return COLVARS_ERROR; | return COLVARS_ERROR; |
} else { | } else { |
| cvm::log(cvm::line_marker); |
cvm::log("Restarting from file \""+restart_in_name+"\".\n"); | cvm::log("Restarting from file \""+restart_in_name+"\".\n"); |
read_restart(input_is); | read_restart(input_is); |
if (cvm::get_error() != COLVARS_OK) { | if (cvm::get_error() != COLVARS_OK) { |
return COLVARS_ERROR; | return COLVARS_ERROR; |
| } else { |
| proxy->input_prefix().clear(); |
} | } |
cvm::log(cvm::line_marker); | cvm::log(cvm::line_marker); |
} | } |
| |
| |
int colvarmodule::setup_output() | int colvarmodule::setup_output() |
{ | { |
int error_code = 0; | if (this->size() == 0) return cvm::get_error(); |
| |
| int error_code = COLVARS_OK; |
| |
// output state file (restart) | // output state file (restart) |
restart_out_name = proxy->restart_output_prefix().size() ? | restart_out_name = proxy->restart_output_prefix().size() ? |
| |
| |
std::istream & colvarmodule::read_restart(std::istream &is) | std::istream & colvarmodule::read_restart(std::istream &is) |
{ | { |
| bool warn_total_forces = false; |
| |
{ | { |
// read global restart information | // read global restart information |
std::string restart_conf; | std::string restart_conf; |
| |
colvarparse::parse_silent); | colvarparse::parse_silent); |
it = it_restart; | it = it_restart; |
} | } |
| std::string restart_version; |
| parse->get_keyval(restart_conf, "version", |
| restart_version, std::string(""), |
| colvarparse::parse_silent); |
| if (restart_version.size() && (restart_version != std::string(COLVARS_VERSION))) { |
| cvm::log("This state file was generated with version "+restart_version+"\n"); |
| } |
| if ((restart_version.size() == 0) || (restart_version.compare(std::string(COLVARS_VERSION)) < 0)) { |
| // check for total force change |
| if (proxy->total_forces_enabled()) { |
| warn_total_forces = true; |
| } |
| } |
} | } |
is.clear(); | is.clear(); |
parse->clear_keyword_registry(); | parse->clear_keyword_registry(); |
| |
} | } |
cvm::decrease_depth(); | cvm::decrease_depth(); |
| |
| if (warn_total_forces) { |
| cvm::log(cvm::line_marker); |
| cvm::log("WARNING:\n"); |
| std::string const warning("### CHANGES IN THE DEFINITION OF SYSTEM FORCES (NOW TOTAL FORCES)\n\ |
| \n\ |
| Starting from the version 2016-08-10 of the Colvars module, \n\ |
| the role of system forces has been replaced by total forces.\n\ |
| \n\ |
| These include *all* forces acting on a collective variable, whether they\n\ |
| come from the force field potential or from external terms\n\ |
| (e.g. restraints), including forces applied by Colvars itself.\n\ |
| \n\ |
| In NAMD, forces applied by Colvars, IMD, SMD, TMD, symmetry\n\ |
| restraints and tclForces are now all counted in the total force.\n\ |
| \n\ |
| In LAMMPS, forces applied by Colvars itself are now counted in the total\n\ |
| force (all forces from other fixes were being counted already).\n\ |
| \n\ |
| \n\ |
| ### WHEN IS THIS CHANGE RELEVANT\n\ |
| \n\ |
| This change affects results *only* when (1) outputSystemForce is\n\ |
| requested or (2) the ABF bias is used. All other usage cases are\n\ |
| *unaffected* (colvar restraints, metadynamics, etc).\n\ |
| \n\ |
| When system forces are reported (flag: outputSystemForce), their values\n\ |
| in the output may change, but the physical trajectory is never affected.\n\ |
| The physical results of ABF calculations may be affected in some cases.\n\ |
| \n\ |
| \n\ |
| ### CHANGES TO ABF CALCULATIONS\n\ |
| \n\ |
| Compared to previous Colvars versions, the ABF method will now attempt\n\ |
| to cancel external forces (for example, boundary walls) and it may be\n\ |
| not possible to resume through a state file a simulation that was\n\ |
| performed with a previous version.\n\ |
| \n\ |
| There are three possible scenarios:\n\ |
| \n\ |
| 1. No external forces are applied to the atoms used by ABF: results are\n\ |
| unchanged.\n\ |
| \n\ |
| 2. Some of the atoms used by ABF experience external forces, but these\n\ |
| forces are not applied directly to the variables used by ABF\n\ |
| (e.g. another colvar that uses the same atoms, tclForces, etc): in this\n\ |
| case, we recommend beginning a new simulation.\n\ |
| \n\ |
| 3. External forces are applied to one or more of the colvars used by\n\ |
| ABF, but no other forces are applied to their atoms: you may use the\n\ |
| subtractAppliedForce keyword inside the corresponding colvars to\n\ |
| continue the previous simulation.\n\n"); |
| cvm::log(warning); |
| cvm::log(cvm::line_marker); |
| |
| // update this ahead of time in this special case |
| output_prefix = proxy->output_prefix(); |
| cvm::log("All output files will now be saved with the prefix \""+output_prefix+".tmp.*\".\n"); |
| output_prefix = output_prefix+".tmp"; |
| write_output_files(); |
| cvm::log(cvm::line_marker); |
| cvm::log("Please review the important warning above. After that, you may rename:\n\ |
| \""+output_prefix+".tmp.colvars.state\"\n\ |
| to:\n\ |
| \""+output_prefix+".colvars.state\"\n"); |
| cvm::error("Exiting with error until issue is addressed.\n", FATAL_ERROR); |
| } |
| |
return is; | return is; |
} | } |
| |
| |
<< " step " << std::setw(it_width) | << " step " << std::setw(it_width) |
<< it << "\n" | << it << "\n" |
<< " dt " << dt() << "\n" | << " dt " << dt() << "\n" |
| << " version " << std::string(COLVARS_VERSION) << "\n" |
<< "}\n\n"; | << "}\n\n"; |
| |
cvm::increase_depth(); | cvm::increase_depth(); |
| |
| |
int colvarmodule::close_traj_file() | int colvarmodule::close_traj_file() |
{ | { |
if (cv_traj_os.good()) { | if (cv_traj_os.is_open()) { |
cv_traj_os.close(); | cv_traj_os.close(); |
} | } |
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); | return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); |
| |
| |
void cvm::log(std::string const &message) | void cvm::log(std::string const &message) |
{ | { |
if (depth > 0) | size_t const d = depth(); |
proxy->log((std::string(2*depth, ' '))+message); | if (d > 0) |
| proxy->log((std::string(2*d, ' '))+message); |
else | else |
proxy->log(message); | proxy->log(message); |
} | } |
| |
| |
void cvm::increase_depth() | void cvm::increase_depth() |
{ | { |
depth++; | (depth())++; |
} | } |
| |
| |
void cvm::decrease_depth() | void cvm::decrease_depth() |
{ | { |
if (depth) depth--; | if (depth() > 0) { |
| (depth())--; |
| } |
| } |
| |
| |
| size_t & cvm::depth() |
| { |
| // NOTE: do not call log() or error() here, to avoid recursion |
| size_t const nt = proxy->smp_num_threads(); |
| if (proxy->smp_enabled() == COLVARS_OK) { |
| if (depth_v.size() != nt) { |
| // update array of depths |
| proxy->smp_lock(); |
| if (depth_v.size() > 0) { depth_s = depth_v[0]; } |
| depth_v.clear(); |
| depth_v.assign(nt, depth_s); |
| proxy->smp_unlock(); |
| } |
| return depth_v[proxy->smp_thread_id()]; |
| } |
| return depth_s; |
} | } |
| |
| |
| void colvarmodule::set_error_bits(int code) |
| { |
| if (code < 0) { |
| cvm::fatal_error("Error: set_error_bits() received negative error code.\n"); |
| return; |
| } |
| proxy->smp_lock(); |
| errorCode |= code | COLVARS_ERROR; |
| proxy->smp_unlock(); |
| } |
| |
| bool colvarmodule::get_error_bit(int code) |
| { |
| return bool(errorCode & code); |
| } |
| |
| void colvarmodule::clear_error() |
| { |
| proxy->smp_lock(); |
| errorCode = COLVARS_OK; |
| proxy->smp_unlock(); |
| } |
| |
| |
void cvm::error(std::string const &message, int code) | void cvm::error(std::string const &message, int code) |
{ | { |
set_error_bits(code); | set_error_bits(code); |
proxy->error(message); | proxy->error(message); |
} | } |
| |
| |
void cvm::fatal_error(std::string const &message) | void cvm::fatal_error(std::string const &message) |
{ | { |
| // TODO once all non-fatal errors have been set to be handled by error(), |
| // set DELETE_COLVARS here for VMD to handle it |
set_error_bits(FATAL_ERROR); | set_error_bits(FATAL_ERROR); |
proxy->fatal_error(message); | proxy->fatal_error(message); |
} | } |
| |
| |
void cvm::exit(std::string const &message) | void cvm::exit(std::string const &message) |
{ | { |
proxy->exit(message); | proxy->exit(message); |
| |
} | } |
| |
int cvm::load_atoms(char const *file_name, | int cvm::load_atoms(char const *file_name, |
std::vector<cvm::atom> &atoms, | cvm::atom_group &atoms, |
std::string const &pdb_field, | std::string const &pdb_field, |
double const pdb_field_value) | double const pdb_field_value) |
{ | { |
| |
| |
| |
// static runtime data | // static runtime data |
cvm::real colvarmodule::debug_gradients_step_size = 1.0e-03; | cvm::real colvarmodule::debug_gradients_step_size = 1.0e-07; |
int colvarmodule::errorCode = 0; | int colvarmodule::errorCode = 0; |
long colvarmodule::it = 0; | long colvarmodule::it = 0; |
long colvarmodule::it_restart = 0; | long colvarmodule::it_restart = 0; |
size_t colvarmodule::restart_out_freq = 0; | size_t colvarmodule::restart_out_freq = 0; |
size_t colvarmodule::cv_traj_freq = 0; | size_t colvarmodule::cv_traj_freq = 0; |
size_t colvarmodule::depth = 0; | size_t colvarmodule::depth_s = 0; |
| std::vector<size_t> colvarmodule::depth_v(0); |
bool colvarmodule::b_analysis = false; | bool colvarmodule::b_analysis = false; |
std::list<std::string> colvarmodule::index_group_names; | std::list<std::string> colvarmodule::index_group_names; |
std::list<std::vector<int> > colvarmodule::index_groups; | std::list<std::vector<int> > colvarmodule::index_groups; |
bool colvarmodule::use_scripted_forces = false; | bool colvarmodule::use_scripted_forces = false; |
| bool colvarmodule::scripting_after_biases = true; |
// file name prefixes | |
std::string colvarmodule::output_prefix = ""; | std::string colvarmodule::output_prefix = ""; |
std::string colvarmodule::restart_in_name = ""; | |
| |
| |
// i/o constants | // i/o constants |
size_t const colvarmodule::it_width = 12; | size_t const colvarmodule::it_width = 12; |