/// -*- c++ -*- #include #include "colvarmodule.h" #include "colvarparse.h" #include "colvarproxy.h" #include "colvar.h" #include "colvarbias.h" #include "colvarbias_alb.h" #include "colvarbias_meta.h" #include "colvarbias_abf.h" #include "colvarbias_restraint.h" #include "colvarscript.h" colvarmodule::colvarmodule (colvarproxy *proxy_in) { // pointer to the proxy object if (proxy == NULL) { proxy = proxy_in; parse = new colvarparse(); } else { // TODO relax this error to handle multiple molecules in VMD // once the module is not static anymore cvm::error ("Error: trying to allocate the collective " "variable module twice.\n"); return; } cvm::log (cvm::line_marker); cvm::log ("Initializing the collective variables module, version "+ cvm::to_str (COLVARS_VERSION)+".\n"); // set initial default values // "it_restart" will be set by the input state file, if any; // "it" should be updated by the proxy colvarmodule::it = colvarmodule::it_restart = 0; colvarmodule::it_restart_from_state_file = true; colvarmodule::use_scripted_forces = false; colvarmodule::b_analysis = false; colvarmodule::debug_gradients_step_size = 1.0e-07; colvarmodule::rotation::crossing_threshold = 1.0e-02; colvarmodule::cv_traj_freq = 100; colvarmodule::restart_out_freq = proxy->restart_frequency(); // by default overwrite the existing trajectory file colvarmodule::cv_traj_append = false; } int colvarmodule::config_file (char const *config_filename) { cvm::log (cvm::line_marker); cvm::log ("Reading new configuration from file \""+ std::string (config_filename)+"\":\n"); // open the configfile config_s.open (config_filename); if (!config_s) { cvm::error ("Error: in opening configuration file \""+ std::string (config_filename)+"\".\n", FILE_ERROR); return COLVARS_ERROR; } // read the config file into a string std::string conf = ""; std::string line; while (colvarparse::getline_nocomments (config_s, line)) { conf.append (line+"\n"); } config_s.close(); return config (conf); } int colvarmodule::config_string (std::string const &config_str) { cvm::log (cvm::line_marker); cvm::log ("Reading new configuration:\n"); std::istringstream config_s (config_str); // strip the comments away std::string conf = ""; std::string line; while (colvarparse::getline_nocomments (config_s, line)) { conf.append (line+"\n"); } return config (conf); } int colvarmodule::config (std::string &conf) { int error_code = 0; // parse global options error_code |= parse_global_params (conf); if (error_code != COLVARS_OK) { set_error_bits(INPUT_ERROR); return COLVARS_ERROR; } // parse the options for collective variables error_code |= parse_colvars (conf); // parse the options for biases error_code |= parse_biases (conf); // done parsing known keywords, check that all keywords found were valid ones error_code |= parse->check_keywords (conf, "colvarmodule"); if (error_code != COLVARS_OK) { set_error_bits(INPUT_ERROR); return COLVARS_ERROR; } cvm::log (cvm::line_marker); cvm::log ("Collective variables module (re)initialized.\n"); cvm::log (cvm::line_marker); // configuration might have changed, better redo the labels write_traj_label(cv_traj_os); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } int colvarmodule::parse_global_params (std::string const &conf) { std::string index_file_name; if (parse->get_keyval (conf, "indexFile", index_file_name)) { read_index_file (index_file_name.c_str()); } parse->get_keyval (conf, "analysis", b_analysis, b_analysis); parse->get_keyval (conf, "debugGradientsStepSize", debug_gradients_step_size, debug_gradients_step_size, colvarparse::parse_silent); parse->get_keyval (conf, "eigenvalueCrossingThreshold", colvarmodule::rotation::crossing_threshold, colvarmodule::rotation::crossing_threshold, colvarparse::parse_silent); parse->get_keyval (conf, "colvarsTrajFrequency", cv_traj_freq, cv_traj_freq); parse->get_keyval (conf, "colvarsRestartFrequency", restart_out_freq, restart_out_freq); // if this is true when initializing, it means // we are continuing after a reset(): default to true parse->get_keyval (conf, "colvarsTrajAppend", cv_traj_append, cv_traj_append); parse->get_keyval (conf, "scriptedColvarForces", use_scripted_forces, false, colvarparse::parse_silent); if (use_scripted_forces && !proxy->force_script_defined) { cvm::fatal_error("User script for scripted colvars forces not found."); } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } int colvarmodule::parse_colvars (std::string const &conf) { if (cvm::debug()) cvm::log ("Initializing the collective variables.\n"); std::string colvar_conf = ""; size_t pos = 0; while (parse->key_lookup (conf, "colvar", colvar_conf, pos)) { if (colvar_conf.size()) { cvm::log (cvm::line_marker); cvm::increase_depth(); colvars.push_back (new colvar (colvar_conf)); if (cvm::get_error()) { delete colvars.back(); colvars.pop_back(); return COLVARS_ERROR; } if ((colvars.back())->check_keywords (colvar_conf, "colvar") != COLVARS_OK) { return COLVARS_ERROR; } cvm::decrease_depth(); } else { cvm::error("Error: \"colvar\" keyword found without any configuration.\n", INPUT_ERROR); return COLVARS_ERROR; } colvar_conf = ""; } if (!colvars.size()) { cvm::log ("Warning: no collective variables defined.\n"); } if (colvars.size()) cvm::log (cvm::line_marker); cvm::log ("Collective variables initialized, "+ cvm::to_str (colvars.size())+ " in total.\n"); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } int colvarmodule::parse_biases (std::string const &conf) { if (cvm::debug()) cvm::log ("Initializing the collective variables biases.\n"); { /// initialize ABF instances std::string abf_conf = ""; size_t abf_pos = 0; while (parse->key_lookup (conf, "abf", abf_conf, abf_pos)) { if (abf_conf.size()) { cvm::log (cvm::line_marker); cvm::increase_depth(); biases.push_back (new colvarbias_abf (abf_conf, "abf")); if (cvm::get_error()) { delete biases.back(); biases.pop_back(); return COLVARS_ERROR; } if ((biases.back())->check_keywords (abf_conf, "abf") != COLVARS_OK) { return COLVARS_ERROR; } cvm::decrease_depth(); n_abf_biases++; } else { cvm::error("Error: \"abf\" keyword found without configuration.\n", INPUT_ERROR); return COLVARS_ERROR; } abf_conf = ""; } } { /// initialize harmonic restraints std::string harm_conf = ""; size_t harm_pos = 0; while (parse->key_lookup (conf, "harmonic", harm_conf, harm_pos)) { if (harm_conf.size()) { cvm::log (cvm::line_marker); cvm::increase_depth(); biases.push_back (new colvarbias_restraint_harmonic (harm_conf, "harmonic")); if (cvm::get_error()) { delete biases.back(); biases.pop_back(); return COLVARS_ERROR; } if ((biases.back())->check_keywords (harm_conf, "harmonic") != COLVARS_OK) { return COLVARS_ERROR; } cvm::decrease_depth(); n_rest_biases++; } else { cvm::error("Error: \"harmonic\" keyword found without configuration.\n", INPUT_ERROR); return COLVARS_ERROR; } harm_conf = ""; } } { /// initialize linear restraints std::string lin_conf = ""; size_t lin_pos = 0; while (parse->key_lookup (conf, "linear", lin_conf, lin_pos)) { if (lin_conf.size()) { cvm::log (cvm::line_marker); cvm::increase_depth(); biases.push_back (new colvarbias_restraint_linear (lin_conf, "linear")); if (cvm::get_error()) { delete biases.back(); biases.pop_back(); return COLVARS_ERROR; } if ((biases.back())->check_keywords (lin_conf, "linear") != COLVARS_OK) { return COLVARS_ERROR; } cvm::decrease_depth(); n_rest_biases++; } else { cvm::error("Error: \"linear\" keyword found without configuration.\n", INPUT_ERROR); return COLVARS_ERROR; } lin_conf = ""; } } { /// initialize adaptive linear biases std::string alb_conf = ""; size_t alb_pos = 0; while (parse->key_lookup (conf, "ALB", alb_conf, alb_pos)) { if (alb_conf.size()) { cvm::log (cvm::line_marker); cvm::increase_depth(); biases.push_back (new colvarbias_alb (alb_conf, "ALB")); if (cvm::get_error()) { delete biases.back(); biases.pop_back(); return COLVARS_ERROR; } if ((biases.back())->check_keywords (alb_conf, "ALB") != COLVARS_OK) { return COLVARS_ERROR; } cvm::decrease_depth(); n_rest_biases++; } else { cvm::error("Error: \"ALB\" keyword found without configuration.\n", INPUT_ERROR); return COLVARS_ERROR; } alb_conf = ""; } } { /// initialize histograms std::string histo_conf = ""; size_t histo_pos = 0; while (parse->key_lookup (conf, "histogram", histo_conf, histo_pos)) { if (histo_conf.size()) { cvm::log (cvm::line_marker); cvm::increase_depth(); biases.push_back (new colvarbias_histogram (histo_conf, "histogram")); if (cvm::get_error()) { delete biases.back(); biases.pop_back(); return COLVARS_ERROR; } if ((biases.back())->check_keywords (histo_conf, "histogram") != COLVARS_OK) { return COLVARS_ERROR; } cvm::decrease_depth(); n_histo_biases++; } else { cvm::error("Error: \"histogram\" keyword found without configuration.\n", INPUT_ERROR); return COLVARS_ERROR; } histo_conf = ""; } } { /// initialize metadynamics instances std::string meta_conf = ""; size_t meta_pos = 0; while (parse->key_lookup (conf, "metadynamics", meta_conf, meta_pos)) { if (meta_conf.size()) { cvm::log (cvm::line_marker); cvm::increase_depth(); biases.push_back (new colvarbias_meta (meta_conf, "metadynamics")); if (cvm::get_error()) { delete biases.back(); biases.pop_back(); return COLVARS_ERROR; } if ((biases.back())->check_keywords (meta_conf, "metadynamics") != COLVARS_OK) { return COLVARS_ERROR; } cvm::decrease_depth(); n_meta_biases++; } else { cvm::error("Error: \"metadynamics\" keyword found without configuration.\n", INPUT_ERROR); return COLVARS_ERROR; } meta_conf = ""; } } if (use_scripted_forces) { cvm::log (cvm::line_marker); cvm::increase_depth(); cvm::log("User forces script will be run at each bias update."); cvm::decrease_depth(); } if (biases.size() || use_scripted_forces) cvm::log (cvm::line_marker); cvm::log ("Collective variables biases initialized, "+ cvm::to_str (biases.size())+" in total.\n"); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } colvarbias * colvarmodule::bias_by_name(std::string const &name) { for (std::vector::iterator bi = biases.begin(); bi != biases.end(); bi++) { if ((*bi)->name == name) { return (*bi); } } return NULL; } colvar *colvarmodule::colvar_by_name(std::string const &name) { for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { if ((*cvi)->name == name) { return (*cvi); } } return NULL; } int colvarmodule::change_configuration (std::string const &bias_name, std::string const &conf) { // This is deprecated; supported strategy is to delete the bias // and parse the new config cvm::increase_depth(); colvarbias *b; b = bias_by_name (bias_name); if (b == NULL) { cvm::error ("Error: bias not found: " + bias_name); } b->change_configuration (conf); cvm::decrease_depth(); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } std::string colvarmodule::read_colvar(std::string const &name) { cvm::increase_depth(); colvar *c; std::stringstream ss; c = colvar_by_name (name); if (c == NULL) { cvm::fatal_error ("Error: colvar not found: " + name); } ss << c->value(); cvm::decrease_depth(); return ss.str(); } cvm::real colvarmodule::energy_difference (std::string const &bias_name, std::string const &conf) { cvm::increase_depth(); colvarbias *b; cvm::real energy_diff = 0.; b = bias_by_name (bias_name); if (b == NULL) { cvm::fatal_error ("Error: bias not found: " + bias_name); } energy_diff = b->energy_difference (conf); cvm::decrease_depth(); return energy_diff; } int colvarmodule::calc() { cvm::real total_bias_energy = 0.0; cvm::real total_colvar_energy = 0.0; std::vector::iterator cvi; std::vector::iterator bi; if (cvm::debug()) { cvm::log (cvm::line_marker); cvm::log ("Collective variables module, step no. "+ cvm::to_str (cvm::step_absolute())+"\n"); } // calculate collective variables and their gradients if (cvm::debug()) cvm::log ("Calculating collective variables.\n"); cvm::increase_depth(); for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { (*cvi)->calc(); if (cvm::get_error()) { return COLVARS_ERROR; } } cvm::decrease_depth(); // update the biases and communicate their forces to the collective // variables if (cvm::debug() && biases.size()) cvm::log ("Updating collective variable biases.\n"); cvm::increase_depth(); for (bi = biases.begin(); bi != biases.end(); bi++) { total_bias_energy += (*bi)->update(); if (cvm::get_error()) { return COLVARS_ERROR; } } 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(); for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { (*cvi)->reset_bias_force(); } for (bi = biases.begin(); bi != biases.end(); bi++) { (*bi)->communicate_forces(); if (cvm::get_error()) { return COLVARS_ERROR; } } // 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"); return COLVARS_ERROR; } } cvm::decrease_depth(); if (cvm::b_analysis) { // perform runtime analysis of colvars and biases if (cvm::debug() && biases.size()) cvm::log ("Perform runtime analyses.\n"); cvm::increase_depth(); for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { (*cvi)->analyse(); if (cvm::get_error()) { return COLVARS_ERROR; } } for (bi = biases.begin(); bi != biases.end(); bi++) { (*bi)->analyse(); if (cvm::get_error()) { return COLVARS_ERROR; } } cvm::decrease_depth(); } // sum up the forces for each colvar, including wall forces // and integrate any internal // equation of motion (extended system) if (cvm::debug()) cvm::log ("Updating the internal degrees of freedom " "of colvars (if they have any).\n"); cvm::increase_depth(); for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { total_colvar_energy += (*cvi)->update(); if (cvm::get_error()) { return COLVARS_ERROR; } } cvm::decrease_depth(); proxy->add_energy (total_bias_energy + total_colvar_energy); // make collective variables communicate their forces to their // coupled degrees of freedom (i.e. atoms) if (cvm::debug()) cvm::log ("Communicating forces from the colvars to the atoms.\n"); cvm::increase_depth(); for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { if ((*cvi)->tasks[colvar::task_gradients]) { (*cvi)->communicate_forces(); if (cvm::get_error()) { return COLVARS_ERROR; } } } cvm::decrease_depth(); // write restart file, if needed if (restart_out_freq && restart_out_name.size()) { if ( (cvm::step_relative() > 0) && ((cvm::step_absolute() % restart_out_freq) == 0) ) { cvm::log ("Writing the state file \""+ restart_out_name+"\".\n"); proxy->backup_file (restart_out_name.c_str()); restart_out_os.open (restart_out_name.c_str()); if (!write_restart (restart_out_os)) cvm::error ("Error: in writing restart file.\n"); restart_out_os.close(); } } // write trajectory file, if needed if (cv_traj_freq && cv_traj_name.size()) { if (!cv_traj_os.good()) { open_traj_file (cv_traj_name); } // write labels in the traj file every 1000 lines and at first timestep if ((cvm::step_absolute() % (cv_traj_freq * 1000)) == 0 || cvm::step_relative() == 0) { write_traj_label (cv_traj_os); } if ((cvm::step_absolute() % cv_traj_freq) == 0) { write_traj (cv_traj_os); } if (restart_out_freq) { // flush the trajectory file if we are at the restart frequency if ( (cvm::step_relative() > 0) && ((cvm::step_absolute() % restart_out_freq) == 0) ) { cvm::log ("Synchronizing (emptying the buffer of) trajectory file \""+ cv_traj_name+"\".\n"); cv_traj_os.flush(); } } } // end if (cv_traj_freq) return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } int colvarmodule::analyze() { if (cvm::debug()) { cvm::log ("colvarmodule::analyze(), step = "+cvm::to_str (it)+".\n"); } if (cvm::step_relative() == 0) cvm::log ("Performing analysis.\n"); // perform colvar-specific analysis for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { cvm::increase_depth(); (*cvi)->analyse(); cvm::decrease_depth(); } // perform bias-specific analysis for (std::vector::iterator bi = biases.begin(); bi != biases.end(); bi++) { cvm::increase_depth(); (*bi)->analyse(); cvm::decrease_depth(); } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } int colvarmodule::setup() { // loop over all components of all colvars to reset masses of all groups for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { (*cvi)->setup(); } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } colvarmodule::~colvarmodule() { reset(); delete parse; proxy = NULL; } int colvarmodule::reset() { if (cvm::debug()) cvm::log ("colvars::reset() called.\n"); for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { delete *cvi; cvi--; } colvars.clear(); for (std::vector::iterator bi = biases.begin(); bi != biases.end(); bi++) { delete *bi; bi--; } biases.clear(); index_groups.clear(); index_group_names.clear(); // Do not close file here, as we might not be done with it yet. cv_traj_os.flush(); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } int colvarmodule::setup_input() { // name of input state file restart_in_name = proxy->input_prefix().size() ? std::string (proxy->input_prefix()+".colvars.state") : std::string ("") ; // read the restart configuration, if available if (restart_in_name.size()) { // read the restart file std::ifstream input_is (restart_in_name.c_str()); if (!input_is.good()) { cvm::error ("Error: in opening restart file \""+ std::string (restart_in_name)+"\".\n", FILE_ERROR); return COLVARS_ERROR; } else { cvm::log ("Restarting from file \""+restart_in_name+"\".\n"); read_restart (input_is); if (cvm::get_error() != COLVARS_OK) { return COLVARS_ERROR; } cvm::log (cvm::line_marker); } } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } int colvarmodule::setup_output() { // output state file (restart) restart_out_name = proxy->restart_output_prefix().size() ? std::string (proxy->restart_output_prefix()+".colvars.state") : std::string (""); if (restart_out_name.size()) { cvm::log ("The restart output state file will be \""+restart_out_name+"\".\n"); } output_prefix = proxy->output_prefix(); if (output_prefix.size()) { cvm::log ("The final output state file will be \""+ (output_prefix.size() ? std::string (output_prefix+".colvars.state") : std::string ("colvars.state"))+"\".\n"); // cvm::log (cvm::line_marker); } cv_traj_name = (output_prefix.size() ? std::string (output_prefix+".colvars.traj") : std::string ("")); if (cv_traj_freq && cv_traj_name.size()) { // open trajectory file if (cv_traj_append) { cvm::log ("Appending to colvar trajectory file \""+cv_traj_name+ "\".\n"); cv_traj_os.open (cv_traj_name.c_str(), std::ios::app); } else { cvm::log ("Writing to colvar trajectory file \""+cv_traj_name+ "\".\n"); proxy->backup_file (cv_traj_name.c_str()); cv_traj_os.open (cv_traj_name.c_str(), std::ios::out); } cv_traj_os.setf (std::ios::scientific, std::ios::floatfield); } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } std::istream & colvarmodule::read_restart (std::istream &is) { { // read global restart information std::string restart_conf; if (is >> colvarparse::read_block ("configuration", restart_conf)) { if (it_restart_from_state_file) { parse->get_keyval (restart_conf, "step", it_restart, (size_t) 0, colvarparse::parse_silent); it = it_restart; } } is.clear(); } // colvars restart cvm::increase_depth(); for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { if ( !((*cvi)->read_restart (is)) ) { cvm::error ("Error: in reading restart configuration for collective variable \""+ (*cvi)->name+"\".\n", INPUT_ERROR); } } // biases restart for (std::vector::iterator bi = biases.begin(); bi != biases.end(); bi++) { if (!((*bi)->read_restart (is))) cvm::error ("Error: in reading restart configuration for bias \""+ (*bi)->name+"\".\n", INPUT_ERROR); } cvm::decrease_depth(); return is; } int colvarmodule::backup_file (char const *filename) { return proxy->backup_file (filename); } int colvarmodule::write_output_files() { // if this is a simulation run (i.e. not a postprocessing), output data // must be written to be able to restart the simulation std::string const out_name = (output_prefix.size() ? std::string (output_prefix+".colvars.state") : std::string ("colvars.state")); cvm::log ("Saving collective variables state to \""+out_name+"\".\n"); proxy->backup_file (out_name.c_str()); std::ofstream out (out_name.c_str()); out.setf (std::ios::scientific, std::ios::floatfield); this->write_restart (out); out.close(); cvm::increase_depth(); for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { (*cvi)->write_output_files(); } cvm::decrease_depth(); // do not close to avoid problems with multiple NAMD runs cv_traj_os.flush(); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } int colvarmodule::read_traj (char const *traj_filename, size_t traj_read_begin, size_t traj_read_end) { cvm::log ("Opening trajectory file \""+ std::string (traj_filename)+"\".\n"); std::ifstream traj_is (traj_filename); while (true) { while (true) { std::string line (""); do { if (!colvarparse::getline_nocomments (traj_is, line)) { cvm::log ("End of file \""+std::string (traj_filename)+ "\" reached, or corrupted file.\n"); traj_is.close(); return false; } } while (line.find_first_not_of (colvarparse::white_space) == std::string::npos); std::istringstream is (line); if (!(is >> it)) return false; if ( (it < traj_read_begin) ) { if ((it % 1000) == 0) std::cerr << "Skipping trajectory step " << it << " \r"; continue; } else { if ((it % 1000) == 0) std::cerr << "Reading from trajectory, step = " << it << " \r"; if ( (traj_read_end > traj_read_begin) && (it > traj_read_end) ) { std::cerr << "\n"; cvm::error ("Reached the end of the trajectory, " "read_end = "+cvm::to_str (traj_read_end)+"\n", FILE_ERROR); return COLVARS_ERROR; } for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { if (!(*cvi)->read_traj (is)) { cvm::error ("Error: in reading colvar \""+(*cvi)->name+ "\" from trajectory file \""+ std::string (traj_filename)+"\".\n", FILE_ERROR); return COLVARS_ERROR; } } break; } } } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } std::ostream & colvarmodule::write_restart (std::ostream &os) { os.setf (std::ios::scientific, std::ios::floatfield); os << "configuration {\n" << " step " << std::setw (it_width) << it << "\n" << " dt " << dt() << "\n" << "}\n\n"; cvm::increase_depth(); for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { (*cvi)->write_restart (os); } for (std::vector::iterator bi = biases.begin(); bi != biases.end(); bi++) { (*bi)->write_restart (os); } cvm::decrease_depth(); return os; } int colvarmodule::open_traj_file (std::string const &file_name) { // (re)open trajectory file if (cv_traj_append) { cvm::log ("Appending to colvar trajectory file \""+file_name+ "\".\n"); cv_traj_os.open (file_name.c_str(), std::ios::app); } else { cvm::log ("Overwriting colvar trajectory file \""+file_name+ "\".\n"); proxy->backup_file (file_name.c_str()); cv_traj_os.open (file_name.c_str(), std::ios::out); } if (!cv_traj_os.good()) { cvm::error ("Error: cannot write to file \""+file_name+"\".\n", FILE_ERROR); } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } int colvarmodule::close_traj_file() { if (cv_traj_os.good()) { cv_traj_os.close(); } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } std::ostream & colvarmodule::write_traj_label (std::ostream &os) { if (!os.good()) { cvm::error("Cannot write to trajectory file."); return os; } os.setf (std::ios::scientific, std::ios::floatfield); os << "# " << cvm::wrap_string ("step", cvm::it_width-2) << " "; cvm::increase_depth(); for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { (*cvi)->write_traj_label (os); } for (std::vector::iterator bi = biases.begin(); bi != biases.end(); bi++) { (*bi)->write_traj_label (os); } os << "\n"; if (cvm::debug()) os.flush(); cvm::decrease_depth(); return os; } std::ostream & colvarmodule::write_traj (std::ostream &os) { os.setf (std::ios::scientific, std::ios::floatfield); os << std::setw (cvm::it_width) << it << " "; cvm::increase_depth(); for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { (*cvi)->write_traj (os); } for (std::vector::iterator bi = biases.begin(); bi != biases.end(); bi++) { (*bi)->write_traj (os); } os << "\n"; if (cvm::debug()) os.flush(); cvm::decrease_depth(); return os; } void cvm::log (std::string const &message) { if (depth > 0) proxy->log ((std::string (2*depth, ' '))+message); else proxy->log (message); } void cvm::increase_depth() { depth++; } void cvm::decrease_depth() { if (depth) depth--; } void cvm::error (std::string const &message, int code) { set_error_bits(code); proxy->error (message); } void cvm::fatal_error (std::string const &message) { set_error_bits(FATAL_ERROR); proxy->fatal_error (message); } void cvm::exit (std::string const &message) { proxy->exit (message); } int cvm::read_index_file (char const *filename) { std::ifstream is (filename, std::ios::binary); if (!is.good()) cvm::error ("Error: in opening index file \""+ std::string (filename)+"\".\n", FILE_ERROR); while (is.good()) { char open, close; std::string group_name; if ( (is >> open) && (open == '[') && (is >> group_name) && (is >> close) && (close == ']') ) { for (std::list::iterator names_i = index_group_names.begin(); names_i != index_group_names.end(); names_i++) { if (*names_i == group_name) { cvm::error ("Error: the group name \""+group_name+ "\" appears in multiple index files.\n", FILE_ERROR); } } cvm::index_group_names.push_back (group_name); cvm::index_groups.push_back (std::vector ()); } else { cvm::error ("Error: in parsing index file \""+ std::string (filename)+"\".\n", INPUT_ERROR); } int atom_number = 1; size_t pos = is.tellg(); while ( (is >> atom_number) && (atom_number > 0) ) { (cvm::index_groups.back()).push_back (atom_number); pos = is.tellg(); } is.clear(); is.seekg (pos, std::ios::beg); std::string delim; if ( (is >> delim) && (delim == "[") ) { // new group is.clear(); is.seekg (pos, std::ios::beg); } else { break; } } cvm::log ("The following index groups were read from the index file \""+ std::string (filename)+"\":\n"); std::list::iterator names_i = index_group_names.begin(); std::list >::iterator lists_i = index_groups.begin(); for ( ; names_i != index_group_names.end() ; names_i++, lists_i++) { cvm::log (" "+(*names_i)+" ("+cvm::to_str (lists_i->size())+" atoms).\n"); } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } int cvm::load_atoms (char const *file_name, std::vector &atoms, std::string const &pdb_field, double const pdb_field_value) { return proxy->load_atoms (file_name, atoms, pdb_field, pdb_field_value); } int cvm::load_coords (char const *file_name, std::vector &pos, const std::vector &indices, std::string const &pdb_field, double const pdb_field_value) { // Differentiate between PDB and XYZ files // for XYZ files, use CVM internal parser // otherwise call proxy function for PDB std::string const ext (strlen(file_name) > 4 ? (file_name + (strlen(file_name) - 4)) : file_name); if (colvarparse::to_lower_cppstr (ext) == std::string (".xyz")) { if ( pdb_field.size() > 0 ) { cvm::error("Error: PDB column may not be specified for XYZ coordinate file.\n", INPUT_ERROR); return COLVARS_ERROR; } return cvm::load_coords_xyz (file_name, pos, indices); } else { return proxy->load_coords (file_name, pos, indices, pdb_field, pdb_field_value); } } int cvm::load_coords_xyz (char const *filename, std::vector &pos, const std::vector &indices) { std::ifstream xyz_is (filename); unsigned int natoms; char symbol[256]; std::string line; if ( ! (xyz_is >> natoms) ) { cvm::error ("Error: cannot parse XYZ file " + std::string (filename) + ".\n", INPUT_ERROR); } // skip comment line std::getline (xyz_is, line); std::getline (xyz_is, line); xyz_is.width (255); std::vector::iterator pos_i = pos.begin(); if (pos.size() != natoms) { // Use specified indices int next = 0; // indices are zero-based std::vector::const_iterator index = indices.begin(); for ( ; pos_i != pos.end() ; pos_i++, index++) { while ( next < *index ) { std::getline (xyz_is, line); next++; } xyz_is >> symbol; xyz_is >> (*pos_i)[0] >> (*pos_i)[1] >> (*pos_i)[2]; } } else { // Use all positions for ( ; pos_i != pos.end() ; pos_i++) { xyz_is >> symbol; xyz_is >> (*pos_i)[0] >> (*pos_i)[1] >> (*pos_i)[2]; } } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } // static pointers std::vector colvarmodule::colvars; std::vector colvarmodule::biases; size_t colvarmodule::n_abf_biases = 0; size_t colvarmodule::n_rest_biases = 0; size_t colvarmodule::n_histo_biases = 0; size_t colvarmodule::n_meta_biases = 0; colvarproxy *colvarmodule::proxy = NULL; // static runtime data cvm::real colvarmodule::debug_gradients_step_size = 1.0e-03; int colvarmodule::errorCode = 0; size_t colvarmodule::it = 0; size_t colvarmodule::it_restart = 0; size_t colvarmodule::restart_out_freq = 0; size_t colvarmodule::cv_traj_freq = 0; size_t colvarmodule::depth = 0; bool colvarmodule::b_analysis = false; cvm::real colvarmodule::rotation::crossing_threshold = 1.0E-04; std::list colvarmodule::index_group_names; std::list > colvarmodule::index_groups; // file name prefixes std::string colvarmodule::output_prefix = ""; std::string colvarmodule::restart_in_name = ""; // i/o constants size_t const colvarmodule::it_width = 12; size_t const colvarmodule::cv_prec = 14; size_t const colvarmodule::cv_width = 21; size_t const colvarmodule::en_prec = 14; size_t const colvarmodule::en_width = 21; std::string const colvarmodule::line_marker = "----------------------------------------------------------------------\n";