diff --git a/lib/colvars/colvaratoms.cpp b/lib/colvars/colvaratoms.cpp index 0d0a339a69..e8046a97d5 100644 --- a/lib/colvars/colvaratoms.cpp +++ b/lib/colvars/colvaratoms.cpp @@ -367,6 +367,7 @@ int cvm::atom_group::parse(std::string const &conf) cvm::error("Error: atomsColValue, if provided, must be non-zero.\n", INPUT_ERROR); } + // NOTE: calls to add_atom() and/or add_atom_id() are in the proxy-implemented function cvm::load_atoms(atoms_file_name.c_str(), *this, atoms_col, atoms_col_value); } } @@ -403,11 +404,21 @@ int cvm::atom_group::parse(std::string const &conf) } } + // We need to know the fitting options to decide whether the group is scalable + parse_error |= parse_fitting_options(group_conf); + + if (is_available(f_ag_scalable_com) && !b_rotate) { + enable(f_ag_scalable_com); + enable(f_ag_scalable); + } + if (is_enabled(f_ag_scalable) && !b_dummy) { + cvm::log("Enabling scalable calculation for group \""+this->key+"\".\n"); index = (cvm::proxy)->init_atom_group(atoms_ids); } - parse_error |= parse_fitting_options(group_conf); + bool b_print_atom_ids = false; + get_keyval(group_conf, "printAtomIDs", b_print_atom_ids, false, colvarparse::parse_silent); // TODO move this to colvarparse object check_keywords(group_conf, key.c_str()); @@ -427,6 +438,10 @@ int cvm::atom_group::parse(std::string const &conf) cvm::to_str(total_mass)+", total charge = "+ cvm::to_str(total_charge)+".\n"); + if (b_print_atom_ids) { + cvm::log("Internal definition of the atom group:\n"); + } + cvm::decrease_depth(); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); @@ -583,6 +598,21 @@ int cvm::atom_group::add_atom_name_residue_range(std::string const &psf_segid, } +std::string const cvm::atom_group::print_atom_ids() const +{ + size_t line_count = 0; + std::ostringstream os(""); + for (size_t i = 0; i < atoms_ids.size(); i++) { + os << " " << std::setw(9) << atoms_ids[i]; + if (++line_count == 7) { + os << "\n"; + line_count = 0; + } + } + return os.str(); +} + + int cvm::atom_group::parse_fitting_options(std::string const &group_conf) { bool b_defined_center = get_keyval(group_conf, "centerReference", b_center, false); @@ -1118,8 +1148,7 @@ void cvm::atom_group::apply_colvar_force(cvm::real const &force) log("Communicating a colvar force from atom group to the MD engine.\n"); } - if (b_dummy) - return; + if (b_dummy) return; if (noforce) { cvm::error("Error: sending a force to a group that has " @@ -1161,17 +1190,21 @@ void cvm::atom_group::apply_colvar_force(cvm::real const &force) void cvm::atom_group::apply_force(cvm::rvector const &force) { - if (b_dummy) - return; + if (cvm::debug()) { + log("Communicating a colvar force from atom group to the MD engine.\n"); + } + + if (b_dummy) return; if (noforce) { cvm::error("Error: sending a force to a group that has " - "\"disableForces\" defined.\n"); + "\"enableForces\" set to off.\n"); return; } if (is_enabled(f_ag_scalable)) { (cvm::proxy)->apply_atom_group_force(index, force); + return; } if (b_rotate) { diff --git a/lib/colvars/colvaratoms.h b/lib/colvars/colvaratoms.h index 7a4d031daa..a2a771a8a3 100644 --- a/lib/colvars/colvaratoms.h +++ b/lib/colvars/colvaratoms.h @@ -253,6 +253,8 @@ public: return atoms.size(); } + std::string const print_atom_ids() const; + /// \brief If this option is on, this group merely acts as a wrapper /// for a fixed position; any calls to atoms within or to /// functions that return disaggregated data will fail diff --git a/lib/colvars/colvarcomp.cpp b/lib/colvars/colvarcomp.cpp index 73b1dbd81c..050e03f78e 100644 --- a/lib/colvars/colvarcomp.cpp +++ b/lib/colvars/colvarcomp.cpp @@ -84,15 +84,12 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf, if (is_available(f_cvc_scalable_com) && is_available(f_cvc_com_based)) { enable(f_cvc_scalable_com); enable(f_cvc_scalable); - group->enable(f_ag_scalable_com); - group->enable(f_ag_scalable); + // The CVC makes the feature available; + // the atom group will enable it unless it needs to compute a rotational fit + group->provide(f_ag_scalable_com); } // TODO check for other types of parallelism here - - if (is_enabled(f_cvc_scalable)) { - cvm::log("Will enable scalable calculation for group \""+group->key+"\".\n"); - } } if (group->parse(conf) == COLVARS_OK) { diff --git a/lib/colvars/colvardeps.cpp b/lib/colvars/colvardeps.cpp index 7736ea14bd..a44f86c292 100644 --- a/lib/colvars/colvardeps.cpp +++ b/lib/colvars/colvardeps.cpp @@ -449,8 +449,10 @@ void colvardeps::init_ag_requires() { // Features that are implemented (or not) by all atom groups feature_states[f_ag_active]->available = true; - feature_states[f_ag_scalable_com]->available = (cvm::proxy->scalable_group_coms() == COLVARS_OK); - feature_states[f_ag_scalable]->available = feature_states[f_ag_scalable_com]->available; + // f_ag_scalable_com is provided by the CVC iff it is COM-based + feature_states[f_ag_scalable_com]->available = false; + // TODO make f_ag_scalable depend on f_ag_scalable_com (or something else) + feature_states[f_ag_scalable]->available = true; } diff --git a/lib/colvars/colvarmodule.cpp b/lib/colvars/colvarmodule.cpp index ee5db06e30..bd9548a748 100644 --- a/lib/colvars/colvarmodule.cpp +++ b/lib/colvars/colvarmodule.cpp @@ -810,6 +810,7 @@ int colvarmodule::analyze() int colvarmodule::setup() { + if (this->size() == 0) return cvm::get_error(); // loop over all components of all colvars to reset masses of all groups for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { @@ -867,25 +868,35 @@ int colvarmodule::reset() 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("") ; + if (this->size() == 0) return cvm::get_error(); + + std::string restart_in_name(""); // read the restart configuration, if available - if (restart_in_name.size()) { + if (proxy->input_prefix().size()) { // read the restart file + restart_in_name = proxy->input_prefix(); std::ifstream input_is(restart_in_name.c_str()); 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", FILE_ERROR); return COLVARS_ERROR; } else { + cvm::log(cvm::line_marker); cvm::log("Restarting from file \""+restart_in_name+"\".\n"); read_restart(input_is); if (cvm::get_error() != COLVARS_OK) { return COLVARS_ERROR; + } else { + proxy->input_prefix().clear(); } cvm::log(cvm::line_marker); } @@ -897,7 +908,9 @@ int colvarmodule::setup_input() 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) restart_out_name = proxy->restart_output_prefix().size() ? @@ -1545,11 +1558,7 @@ std::list colvarmodule::index_group_names; std::list > colvarmodule::index_groups; bool colvarmodule::use_scripted_forces = false; bool colvarmodule::scripting_after_biases = true; - -// file name prefixes std::string colvarmodule::output_prefix = ""; -std::string colvarmodule::restart_in_name = ""; - // i/o constants size_t const colvarmodule::it_width = 12; diff --git a/lib/colvars/colvarmodule.h b/lib/colvars/colvarmodule.h index 0b19d1f779..c8df6c7b5e 100644 --- a/lib/colvars/colvarmodule.h +++ b/lib/colvars/colvarmodule.h @@ -4,7 +4,7 @@ #define COLVARMODULE_H #ifndef COLVARS_VERSION -#define COLVARS_VERSION "2016-10-05" +#define COLVARS_VERSION "2016-10-21" #endif #ifndef COLVARS_DEBUG @@ -12,6 +12,9 @@ #endif /*! \mainpage Main page +This is the Developer's documentation for the Collective Variables Module. + +You can browse the class hierarchy or the list of source files. */ /// \file colvarmodule.h @@ -154,9 +157,6 @@ public: /// Prefix for all output files for this run static std::string output_prefix; - /// input restart file name (determined from input_prefix) - static std::string restart_in_name; - /// Array of collective variables static std::vector colvars; @@ -197,6 +197,11 @@ public: return COLVARS_DEBUG; } + /// \brief How many objects are configured yet? + inline size_t const size() const + { + return colvars.size() + biases.size(); + } /// \brief Constructor \param config_name Configuration file name /// \param restart_name (optional) Restart file name diff --git a/lib/colvars/colvarparse.cpp b/lib/colvars/colvarparse.cpp index e222fa9ecf..86cd00ad29 100644 --- a/lib/colvars/colvarparse.cpp +++ b/lib/colvars/colvarparse.cpp @@ -644,9 +644,9 @@ bool colvarparse::key_lookup(std::string const &conf, // find the matching closing brace - if (cvm::debug()) { - cvm::log("Multi-line value, config is now \""+line+"\".\n"); - } +// if (cvm::debug()) { +// cvm::log("Multi-line value, config is now \""+line+"\".\n"); +// } int brace_count = 1; @@ -689,9 +689,9 @@ bool colvarparse::key_lookup(std::string const &conf, line_end = nl; line.append(conf, line_begin, (line_end-line_begin)); - if (cvm::debug()) { - cvm::log("Added a new line, config is now \""+line+"\".\n"); - } +// if (cvm::debug()) { +// cvm::log("Added a new line, config is now \""+line+"\".\n"); +// } } if (brace_count < 0) { diff --git a/lib/colvars/colvarproxy.h b/lib/colvars/colvarproxy.h index 3d41cb58a7..0a0f550767 100644 --- a/lib/colvars/colvarproxy.h +++ b/lib/colvars/colvarproxy.h @@ -80,7 +80,7 @@ public: /// configuration) std::string input_prefix_str, output_prefix_str, restart_output_prefix_str; - inline std::string input_prefix() + inline std::string & input_prefix() { return input_prefix_str; } diff --git a/lib/colvars/colvarscript.cpp b/lib/colvars/colvarscript.cpp index a43907b07d..a0269aa7a9 100644 --- a/lib/colvars/colvarscript.cpp +++ b/lib/colvars/colvarscript.cpp @@ -155,7 +155,7 @@ int colvarscript::run(int argc, char const *argv[]) { result = "Missing arguments\n" + help_string(); return COLVARSCRIPT_ERROR; } - proxy->input_prefix_str = argv[2]; + proxy->input_prefix() = argv[2]; if (colvars->setup_input() == COLVARS_OK) { return COLVARS_OK; } else {