diff --git a/lib/colvars/Makefile.fermi b/lib/colvars/Makefile.fermi index 2923b564e1..ba00a2e6d8 100644 --- a/lib/colvars/Makefile.fermi +++ b/lib/colvars/Makefile.fermi @@ -7,8 +7,8 @@ EXTRAMAKE = Makefile.lammps.empty # ------ SETTINGS ------ CXX = g++ -CXXFLAGS = -O2 -mpc64 -march=native -funroll-loops -g \ - -fno-rtti -fno-exceptions -Wall -Wno-sign-compare # -DCOLVARS_DEBUG +CXXFLAGS = -O2 -mpc64 -g -fPIC \ + -Wall -Wno-sign-compare # -DCOLVARS_DEBUG ARCHIVE = ar ARCHFLAG = -rscv SHELL = /bin/sh diff --git a/lib/colvars/colvar.cpp b/lib/colvars/colvar.cpp index 5e90636e1d..1a42f85eea 100644 --- a/lib/colvars/colvar.cpp +++ b/lib/colvars/colvar.cpp @@ -9,11 +9,17 @@ #include +/// Compare two cvcs using their names +/// Used to sort CVC array in scripted coordinates +bool compare(colvar::cvc *i, colvar::cvc *j) { + return i->name < j->name; +} + colvar::colvar(std::string const &conf) : colvarparse(conf) { - size_t i, j; + size_t i; cvm::log("Initializing a new collective variable.\n"); get_keyval(conf, "name", this->name, @@ -81,9 +87,12 @@ colvar::colvar(std::string const &conf) return; \ } \ } \ - if ( ! cvcs.back()->name.size()) \ - cvcs.back()->name = std::string(def_config_key)+ \ - (cvm::to_str(++def_count)); \ + if ( ! cvcs.back()->name.size()){ \ + std::ostringstream s; \ + s << def_config_key << std::setfill('0') << std::setw(4) << ++def_count;\ + cvcs.back()->name = s.str(); \ + /* pad cvc number for correct ordering when sorting by name */\ + } \ if (cvm::debug()) \ cvm::log("Done initializing a \""+ \ std::string(def_config_key)+ \ @@ -193,27 +202,21 @@ colvar::colvar(std::string const &conf) x.vector1d_value.resize(size); } - // Sort array of cvcs based on values of componentExp - std::vector temp_vec; - for (i = 1; i <= cvcs.size(); i++) { - for (j = 0; j < cvcs.size(); j++) { - if (cvcs[j]->sup_np == int(i)) { - temp_vec.push_back(cvcs[j]); - break; - } + // Sort array of cvcs based on their names + // Note: default CVC names are in input order for same type of CVC + std::sort(cvcs.begin(), cvcs.end(), compare); + + if(cvcs.size() > 1) { + cvm::log("Sorted list of components for this scripted colvar:"); + for (i = 0; i < cvcs.size(); i++) { + cvm::log(cvm::to_str(i+1) + " " + cvcs[i]->name); } } - if (temp_vec.size() != cvcs.size()) { - cvm::error("Could not find order numbers for all components " - "in componentExp values."); - return; - } - cvcs = temp_vec; // Build ordered list of component values that will be // passed to the script - for (j = 0; j < cvcs.size(); j++) { - sorted_cvc_values.push_back(&(cvcs[j]->value())); + for (i = 0; i < cvcs.size(); i++) { + sorted_cvc_values.push_back(&(cvcs[i]->value())); } b_homogeneous = false; @@ -846,7 +849,22 @@ void colvar::calc() if (cvm::debug()) cvm::log("Collecting data from atom groups.\n"); + // Update the enabled/disabled status of cvcs if necessary + if (cvc_flags.size()) { + bool any = false; + for (i = 0; i < cvcs.size(); i++) { + cvcs[i]->b_enabled = cvc_flags[i]; + any = any || cvc_flags[i]; + } + if (!any) { + cvm::error("ERROR: All CVCs are disabled for colvar " + this->name +"\n"); + return; + } + cvc_flags.resize(0); + } + for (i = 0; i < cvcs.size(); i++) { + if (!cvcs[i]->b_enabled) continue; for (ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) { cvm::atom_group &atoms = *(cvcs[i]->atom_groups[ig]); atoms.reset_atoms_data(); @@ -1101,9 +1119,9 @@ cvm::real colvar::update() // closer one (on a periodic colvar, both walls may be applicable // at the same time) if ( (!tasks[task_upper_wall]) || - (this->dist2(x, lower_wall) < this->dist2(x, upper_wall)) ) { + (this->dist2(x_reported, lower_wall) < this->dist2(x_reported, upper_wall)) ) { - cvm::real const grad = this->dist2_lgrad(x, lower_wall); + cvm::real const grad = this->dist2_lgrad(x_reported, lower_wall); if (grad < 0.0) { fw = -0.5 * lower_wall_k * grad; if (cvm::debug()) @@ -1115,7 +1133,7 @@ cvm::real colvar::update() } else { - cvm::real const grad = this->dist2_lgrad(x, upper_wall); + cvm::real const grad = this->dist2_lgrad(x_reported, upper_wall); if (grad > 0.0) { fw = -0.5 * upper_wall_k * grad; if (cvm::debug()) @@ -1220,12 +1238,13 @@ void colvar::communicate_forces() return; } + int grad_index = 0; // index in the scripted gradients, to account for some components being disabled for (i = 0; i < cvcs.size(); i++) { if (!cvcs[i]->b_enabled) continue; cvm::increase_depth(); // cvc force is colvar force times colvar/cvc Jacobian // (vector-matrix product) - (cvcs[i])->apply_force(colvarvalue(f.as_vector() * func_grads[i], + (cvcs[i])->apply_force(colvarvalue(f.as_vector() * func_grads[grad_index++], cvcs[i]->value().type())); cvm::decrease_depth(); } @@ -1258,20 +1277,13 @@ void colvar::communicate_forces() int colvar::set_cvc_flags(std::vector const &flags) { - size_t i; if (flags.size() != cvcs.size()) { cvm::error("ERROR: Wrong number of CVC flags provided."); return COLVARS_ERROR; } - bool e = false; - for (i = 0; i < cvcs.size(); i++) { - cvcs[i]->b_enabled = flags[i]; - e = e || flags[i]; - } - if (!e) { - cvm::error("ERROR: All CVCs are disabled for this colvar."); - return COLVARS_ERROR; - } + // We cannot enable or disable cvcs in the middle of a timestep or colvar evaluation sequence + // so we store the flags that will be enforced at the next call to calc() + cvc_flags = flags; return COLVARS_OK; } diff --git a/lib/colvars/colvar.h b/lib/colvars/colvar.h index 79b00c026b..8a3e40518a 100644 --- a/lib/colvars/colvar.h +++ b/lib/colvars/colvar.h @@ -514,6 +514,9 @@ protected: /// \brief Array of \link cvc \endlink objects std::vector cvcs; + /// \brief Flags to enable or disable cvcs at next colvar evaluation + std::vector cvc_flags; + /// \brief Initialize the sorted list of atom IDs for atoms involved /// in all cvcs (called when enabling task_collect_gradients) void build_atom_list(void); diff --git a/lib/colvars/colvarbias_histogram.cpp b/lib/colvars/colvarbias_histogram.cpp index a131456663..21d68eeee4 100644 --- a/lib/colvars/colvarbias_histogram.cpp +++ b/lib/colvars/colvarbias_histogram.cpp @@ -155,6 +155,7 @@ int colvarbias_histogram::write_output_files() if (out_name.size()) { cvm::log("Writing the histogram file \""+out_name+"\".\n"); + cvm::backup_file(out_name.c_str()); cvm::ofstream grid_os(out_name.c_str()); if (!grid_os.is_open()) { cvm::error("Error opening histogram file " + out_name + " for writing.\n", FILE_ERROR); @@ -166,6 +167,7 @@ int colvarbias_histogram::write_output_files() if (out_name_dx.size()) { cvm::log("Writing the histogram file \""+out_name_dx+"\".\n"); + cvm::backup_file(out_name_dx.c_str()); cvm::ofstream grid_os(out_name_dx.c_str()); if (!grid_os.is_open()) { cvm::error("Error opening histogram file " + out_name_dx + " for writing.\n", FILE_ERROR); diff --git a/lib/colvars/colvargrid.cpp b/lib/colvars/colvargrid.cpp index 6cc667b51c..e2e660b984 100644 --- a/lib/colvars/colvargrid.cpp +++ b/lib/colvars/colvargrid.cpp @@ -24,31 +24,6 @@ colvar_grid_count::colvar_grid_count(std::vector &colvars, : colvar_grid(colvars, def_count, 1) {} -std::istream & colvar_grid_count::read_restart(std::istream &is) -{ - size_t const start_pos = is.tellg(); - std::string key, conf; - if ((is >> key) && (key == std::string("grid_parameters"))) { - is.seekg(start_pos, std::ios::beg); - is >> colvarparse::read_block("grid_parameters", conf); - parse_params(conf); - } else { - cvm::log("Grid parameters are missing in the restart file, using those from the configuration.\n"); - is.seekg(start_pos, std::ios::beg); - } - read_raw(is); - return is; -} - -std::ostream & colvar_grid_count::write_restart(std::ostream &os) -{ - write_params(os); - write_raw(os); - return os; -} - - - colvar_grid_scalar::colvar_grid_scalar() : colvar_grid(), samples(NULL), grad(NULL) {} @@ -79,30 +54,6 @@ colvar_grid_scalar::~colvar_grid_scalar() } } -std::istream & colvar_grid_scalar::read_restart(std::istream &is) -{ - size_t const start_pos = is.tellg(); - std::string key, conf; - if ((is >> key) && (key == std::string("grid_parameters"))) { - is.seekg(start_pos, std::ios::beg); - is >> colvarparse::read_block("grid_parameters", conf); - parse_params(conf); - } else { - cvm::log("Grid parameters are missing in the restart file, using those from the configuration.\n"); - is.seekg(start_pos, std::ios::beg); - } - read_raw(is); - return is; -} - -std::ostream & colvar_grid_scalar::write_restart(std::ostream &os) -{ - write_params(os); - write_raw(os); - return os; -} - - cvm::real colvar_grid_scalar::maximum_value() const { cvm::real max = data[0]; @@ -163,29 +114,6 @@ colvar_grid_gradient::colvar_grid_gradient(std::vector &colvars) : colvar_grid(colvars, 0.0, colvars.size()), samples(NULL) {} -std::istream & colvar_grid_gradient::read_restart(std::istream &is) -{ - size_t const start_pos = is.tellg(); - std::string key, conf; - if ((is >> key) && (key == std::string("grid_parameters"))) { - is.seekg(start_pos, std::ios::beg); - is >> colvarparse::read_block("grid_parameters", conf); - parse_params(conf); - } else { - cvm::log("Grid parameters are missing in the restart file, using those from the configuration.\n"); - is.seekg(start_pos, std::ios::beg); - } - read_raw(is); - return is; -} - -std::ostream & colvar_grid_gradient::write_restart(std::ostream &os) -{ - write_params(os); - write_raw(os); - return os; -} - void colvar_grid_gradient::write_1D_integral(std::ostream &os) { cvm::real bin, min, integral; diff --git a/lib/colvars/colvargrid.h b/lib/colvars/colvargrid.h index 29d21feb35..ac192ed0ee 100644 --- a/lib/colvars/colvargrid.h +++ b/lib/colvars/colvargrid.h @@ -836,6 +836,32 @@ public: } + /// \brief Read grid entry in restart file + std::istream & read_restart(std::istream &is) + { + size_t const start_pos = is.tellg(); + std::string key, conf; + if ((is >> key) && (key == std::string("grid_parameters"))) { + is.seekg(start_pos, std::ios::beg); + is >> colvarparse::read_block("grid_parameters", conf); + parse_params(conf); + } else { + cvm::log("Grid parameters are missing in the restart file, using those from the configuration.\n"); + is.seekg(start_pos, std::ios::beg); + } + read_raw(is); + return is; + } + + /// \brief Write grid entry in restart file + std::ostream & write_restart(std::ostream &os) + { + write_params(os); + write_raw(os); + return os; + } + + /// \brief Write the grid data without labels, as they are /// represented in memory /// \param buf_size Number of values per line @@ -1106,12 +1132,6 @@ public: return new_data[address(ix) + imult]; } - /// \brief Read the grid from a restart - std::istream & read_restart(std::istream &is); - - /// \brief Write the grid to a restart - std::ostream & write_restart(std::ostream &os); - /// \brief Get the value from a formatted output and transform it /// into the internal representation (it may have been rescaled or /// manipulated) @@ -1240,12 +1260,6 @@ public: has_data = true; } - /// \brief Read the grid from a restart - std::istream & read_restart(std::istream &is); - - /// \brief Write the grid to a restart - std::ostream & write_restart(std::ostream &os); - /// \brief Return the highest value cvm::real maximum_value() const; @@ -1343,12 +1357,6 @@ public: } - /// \brief Read the grid from a restart - std::istream & read_restart(std::istream &is); - - /// \brief Write the grid to a restart - std::ostream & write_restart(std::ostream &os); - /// Compute and return average value for a 1D gradient grid inline cvm::real average() { diff --git a/lib/colvars/colvarmodule.h b/lib/colvars/colvarmodule.h index e1d25b1d97..d9f6a03d7c 100644 --- a/lib/colvars/colvarmodule.h +++ b/lib/colvars/colvarmodule.h @@ -4,7 +4,7 @@ #define COLVARMODULE_H #ifndef COLVARS_VERSION -#define COLVARS_VERSION "2015-07-21" +#define COLVARS_VERSION "2015-09-03" #endif #ifndef COLVARS_DEBUG