From 5fe62066381334174990afce7c173d8c559d3059 Mon Sep 17 00:00:00 2001 From: Giacomo Fiorin Date: Fri, 10 Mar 2017 09:16:58 -0500 Subject: [PATCH] Update Colvars module to version 2017-03-10 --- doc/src/PDF/colvars-refman-lammps.pdf | Bin 566080 -> 566757 bytes doc/src/fix_colvars.txt | 4 +- lib/colvars/colvar.cpp | 362 +++++++++--------- lib/colvars/colvar.h | 14 +- lib/colvars/colvaratoms.cpp | 14 +- lib/colvars/colvarbias.cpp | 51 +-- lib/colvars/colvarbias.h | 39 +- lib/colvars/colvarbias_abf.cpp | 14 +- lib/colvars/colvarbias_alb.cpp | 5 - lib/colvars/colvarbias_histogram.cpp | 10 +- lib/colvars/colvarbias_meta.cpp | 473 +++++++++++++----------- lib/colvars/colvarbias_meta.h | 26 +- lib/colvars/colvarbias_restraint.cpp | 214 ++++++----- lib/colvars/colvarbias_restraint.h | 6 + lib/colvars/colvarcomp.cpp | 20 +- lib/colvars/colvarcomp.h | 9 + lib/colvars/colvarcomp_angles.cpp | 8 +- lib/colvars/colvarcomp_distances.cpp | 41 +- lib/colvars/colvardeps.cpp | 272 +++++++------- lib/colvars/colvardeps.h | 86 +++-- lib/colvars/colvarmodule.cpp | 302 ++++++++++----- lib/colvars/colvarmodule.h | 115 ++++-- lib/colvars/colvarparse.cpp | 7 +- lib/colvars/colvarparse.h | 3 +- lib/colvars/colvarproxy.h | 2 - lib/colvars/colvarscript.cpp | 117 +++++- lib/colvars/colvarscript.h | 4 + src/USER-COLVARS/colvarproxy_lammps.cpp | 19 +- src/USER-COLVARS/colvarproxy_lammps.h | 2 +- 29 files changed, 1371 insertions(+), 868 deletions(-) diff --git a/doc/src/PDF/colvars-refman-lammps.pdf b/doc/src/PDF/colvars-refman-lammps.pdf index 5b776defca36759dadaaabebcc6df409000d52cd..468f6feb76076d8f6bc198da91f67bd99c0d6091 100644 GIT binary patch delta 49029 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 delta 48345 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 f&QQ8Pz{OfNpFv&4aKs4gTzp*cR8*2mQtname, - (std::string("colvar")+cvm::to_str(cvm::colvars.size()+1))); + colvarmodule *cv = cvm::main(); - if (cvm::colvar_by_name(this->name) != NULL) { + get_keyval(conf, "name", this->name, + (std::string("colvar")+cvm::to_str(cv->variables()->size()+1))); + + if ((cvm::colvar_by_name(this->name) != NULL) && + (cvm::colvar_by_name(this->name) != this)) { cvm::error("Error: this colvar cannot have the same name, \""+this->name+ "\", as another colvar.\n", INPUT_ERROR); - return; + return INPUT_ERROR; } // Initialize dependency members @@ -44,14 +56,13 @@ colvar::colvar(std::string const &conf) this->description = "colvar " + this->name; - // Initialize static array once and for all - init_cv_requires(); - kinetic_energy = 0.0; potential_energy = 0.0; error_code |= init_components(conf); - if (error_code != COLVARS_OK) return; + if (error_code != COLVARS_OK) { + return cvm::get_error(); + } size_t i; @@ -59,8 +70,6 @@ colvar::colvar(std::string const &conf) if (get_keyval(conf, "scriptedFunction", scripted_function, "", colvarparse::parse_silent)) { - // Make feature available only on user request - provide(f_cv_scripted); enable(f_cv_scripted); cvm::log("This colvar uses scripted function \"" + scripted_function + "\"."); @@ -76,8 +85,8 @@ colvar::colvar(std::string const &conf) } } if (x.type() == colvarvalue::type_notset) { - cvm::error("Could not parse scripted colvar type."); - return; + cvm::error("Could not parse scripted colvar type.", INPUT_ERROR); + return INPUT_ERROR; } cvm::log(std::string("Expecting colvar value of type ") @@ -86,8 +95,9 @@ colvar::colvar(std::string const &conf) if (x.type() == colvarvalue::type_vector) { int size; if (!get_keyval(conf, "scriptedFunctionVectorSize", size)) { - cvm::error("Error: no size specified for vector scripted function."); - return; + cvm::error("Error: no size specified for vector scripted function.", + INPUT_ERROR); + return INPUT_ERROR; } x.vector1d_value.resize(size); } @@ -154,7 +164,7 @@ colvar::colvar(std::string const &conf) } } } - feature_states[f_cv_linear]->enabled = lin; + set_enabled(f_cv_linear, lin); } // Colvar is homogeneous if: @@ -168,7 +178,7 @@ colvar::colvar(std::string const &conf) homogeneous = false; } } - feature_states[f_cv_homogeneous]->enabled = homogeneous; + set_enabled(f_cv_homogeneous, homogeneous); } // Colvar is deemed periodic if: @@ -188,7 +198,7 @@ colvar::colvar(std::string const &conf) "Make sure that you know what you are doing!"); } } - feature_states[f_cv_periodic]->enabled = b_periodic; + set_enabled(f_cv_periodic, b_periodic); } // check that cvcs are compatible @@ -202,7 +212,7 @@ colvar::colvar(std::string const &conf) "by using components of different types. " "You must use the same type in order to " "sum them together.\n", INPUT_ERROR); - return; + return INPUT_ERROR; } } @@ -215,44 +225,110 @@ colvar::colvar(std::string const &conf) f.type(value()); f_accumulated.type(value()); + x_old.type(value()); + v_fdiff.type(value()); + v_reported.type(value()); + fj.type(value()); + ft.type(value()); + ft_reported.type(value()); + f_old.type(value()); + f_old.reset(); + + x_restart.type(value()); + after_restart = false; + reset_bias_force(); + // TODO use here information from the CVCs' own natural boundaries + error_code |= init_grid_parameters(conf); + + get_keyval(conf, "timeStepFactor", time_step_factor, 1); + + error_code |= init_extended_Lagrangian(conf); + error_code |= init_output_flags(conf); + + // Start in active state by default + enable(f_cv_active); + // Make sure dependency side-effects are correct + refresh_deps(); + + if (cvm::b_analysis) + parse_analysis(conf); + + if (cvm::debug()) + cvm::log("Done initializing collective variable \""+this->name+"\".\n"); + + return error_code; +} + + +int colvar::init_grid_parameters(std::string const &conf) +{ + colvarmodule *cv = cvm::main(); + get_keyval(conf, "width", width, 1.0); if (width <= 0.0) { cvm::error("Error: \"width\" must be positive.\n", INPUT_ERROR); - return; + return INPUT_ERROR; } lower_boundary.type(value()); - lower_wall.type(value()); upper_boundary.type(value()); upper_wall.type(value()); - feature_states[f_cv_scalar]->enabled = (value().type() == colvarvalue::type_scalar); + set_enabled(f_cv_scalar, (value().type() == colvarvalue::type_scalar)); if (is_enabled(f_cv_scalar)) { if (get_keyval(conf, "lowerBoundary", lower_boundary, lower_boundary)) { - provide(f_cv_lower_boundary); enable(f_cv_lower_boundary); } + std::string lw_conf, uw_conf; - get_keyval(conf, "lowerWallConstant", lower_wall_k, 0.0); - if (lower_wall_k > 0.0) { + if (get_keyval(conf, "lowerWallConstant", lower_wall_k, 0.0, parse_silent)) { + cvm::log("Warning: lowerWallConstant and lowerWall are deprecated, " + "please define a harmonicWalls bias instead.\n"); + lower_wall.type(value()); get_keyval(conf, "lowerWall", lower_wall, lower_boundary); - enable(f_cv_lower_wall); + lw_conf = std::string("\n\ + lowerWallConstant "+cvm::to_str(lower_wall_k*width*width)+"\n\ + lowerWalls "+cvm::to_str(lower_wall)+"\n"); } if (get_keyval(conf, "upperBoundary", upper_boundary, upper_boundary)) { - provide(f_cv_upper_boundary); enable(f_cv_upper_boundary); } - get_keyval(conf, "upperWallConstant", upper_wall_k, 0.0); - if (upper_wall_k > 0.0) { + if (get_keyval(conf, "upperWallConstant", upper_wall_k, 0.0, parse_silent)) { + cvm::log("Warning: upperWallConstant and upperWall are deprecated, " + "please define a harmonicWalls bias instead.\n"); + upper_wall.type(value()); get_keyval(conf, "upperWall", upper_wall, upper_boundary); - enable(f_cv_upper_wall); + uw_conf = std::string("\n\ + upperWallConstant "+cvm::to_str(upper_wall_k*width*width)+"\n\ + upperWalls "+cvm::to_str(upper_wall)+"\n"); + } + + if (lw_conf.size() && uw_conf.size()) { + if (lower_wall >= upper_wall) { + cvm::error("Error: the upper wall, "+ + cvm::to_str(upper_wall)+ + ", is not higher than the lower wall, "+ + cvm::to_str(lower_wall)+".\n", + INPUT_ERROR); + return INPUT_ERROR; + } + } + + if (lw_conf.size() || uw_conf.size()) { + cvm::log("Generating a new harmonicWalls bias for compatibility purposes.\n"); + std::string const walls_conf("\n\ +harmonicWalls {\n\ + name "+this->name+"w\n\ + colvars "+this->name+"\n"+lw_conf+uw_conf+ + "}\n"); + cv->append_new_config(walls_conf); } } @@ -271,16 +347,7 @@ colvar::colvar(std::string const &conf) ", is not higher than the lower boundary, "+ cvm::to_str(lower_boundary)+".\n", INPUT_ERROR); - } - } - - if (is_enabled(f_cv_lower_wall) && is_enabled(f_cv_upper_wall)) { - if (lower_wall >= upper_wall) { - cvm::error("Error: the upper wall, "+ - cvm::to_str(upper_wall)+ - ", is not higher than the lower wall, "+ - cvm::to_str(lower_wall)+".\n", - INPUT_ERROR); + return INPUT_ERROR; } } @@ -289,83 +356,90 @@ colvar::colvar(std::string const &conf) cvm::error("Error: trying to expand boundaries that already " "cover a whole period of a periodic colvar.\n", INPUT_ERROR); + return INPUT_ERROR; } if (expand_boundaries && hard_lower_boundary && hard_upper_boundary) { cvm::error("Error: inconsistent configuration " "(trying to expand boundaries with both " "hardLowerBoundary and hardUpperBoundary enabled).\n", INPUT_ERROR); + return INPUT_ERROR; } - get_keyval(conf, "timeStepFactor", time_step_factor, 1); + return COLVARS_OK; +} - { - bool b_extended_Lagrangian; - get_keyval(conf, "extendedLagrangian", b_extended_Lagrangian, false); - if (b_extended_Lagrangian) { - cvm::real temp, tolerance, period; +int colvar::init_extended_Lagrangian(std::string const &conf) +{ + bool b_extended_Lagrangian; + get_keyval(conf, "extendedLagrangian", b_extended_Lagrangian, false); - cvm::log("Enabling the extended Lagrangian term for colvar \""+ - this->name+"\".\n"); + if (b_extended_Lagrangian) { + cvm::real temp, tolerance, period; - // Make feature available only on user request - provide(f_cv_extended_Lagrangian); - enable(f_cv_extended_Lagrangian); - provide(f_cv_Langevin); + cvm::log("Enabling the extended Lagrangian term for colvar \""+ + this->name+"\".\n"); - // The extended mass will apply forces - enable(f_cv_gradient); + enable(f_cv_extended_Lagrangian); - xr.type(value()); - vr.type(value()); - fr.type(value()); + xr.type(value()); + vr.type(value()); + fr.type(value()); - const bool found = get_keyval(conf, "extendedTemp", temp, cvm::temperature()); - if (temp <= 0.0) { - if (found) - cvm::error("Error: \"extendedTemp\" must be positive.\n", INPUT_ERROR); - else - cvm::error("Error: a positive temperature must be provided, either " - "by enabling a thermostat, or through \"extendedTemp\".\n", - INPUT_ERROR); + const bool found = get_keyval(conf, "extendedTemp", temp, cvm::temperature()); + if (temp <= 0.0) { + if (found) + cvm::error("Error: \"extendedTemp\" must be positive.\n", INPUT_ERROR); + else + cvm::error("Error: a positive temperature must be provided, either " + "by enabling a thermostat, or through \"extendedTemp\".\n", + INPUT_ERROR); + return INPUT_ERROR; + } + + get_keyval(conf, "extendedFluctuation", tolerance); + if (tolerance <= 0.0) { + cvm::error("Error: \"extendedFluctuation\" must be positive.\n", INPUT_ERROR); + return INPUT_ERROR; + } + ext_force_k = cvm::boltzmann() * temp / (tolerance * tolerance); + cvm::log("Computed extended system force constant: " + cvm::to_str(ext_force_k) + " kcal/mol/U^2"); + + get_keyval(conf, "extendedTimeConstant", period, 200.0); + if (period <= 0.0) { + cvm::error("Error: \"extendedTimeConstant\" must be positive.\n", INPUT_ERROR); + } + ext_mass = (cvm::boltzmann() * temp * period * period) + / (4.0 * PI * PI * tolerance * tolerance); + cvm::log("Computed fictitious mass: " + cvm::to_str(ext_mass) + " kcal/mol/(U/fs)^2 (U: colvar unit)"); + + { + bool b_output_energy; + get_keyval(conf, "outputEnergy", b_output_energy, false); + if (b_output_energy) { + enable(f_cv_output_energy); } + } - get_keyval(conf, "extendedFluctuation", tolerance); - if (tolerance <= 0.0) { - cvm::error("Error: \"extendedFluctuation\" must be positive.\n", INPUT_ERROR); - } - ext_force_k = cvm::boltzmann() * temp / (tolerance * tolerance); - cvm::log("Computed extended system force constant: " + cvm::to_str(ext_force_k) + " kcal/mol/U^2"); - - get_keyval(conf, "extendedTimeConstant", period, 200.0); - if (period <= 0.0) { - cvm::error("Error: \"extendedTimeConstant\" must be positive.\n", INPUT_ERROR); - } - ext_mass = (cvm::boltzmann() * temp * period * period) - / (4.0 * PI * PI * tolerance * tolerance); - cvm::log("Computed fictitious mass: " + cvm::to_str(ext_mass) + " kcal/mol/(U/fs)^2 (U: colvar unit)"); - - { - bool b_output_energy; - get_keyval(conf, "outputEnergy", b_output_energy, false); - if (b_output_energy) { - enable(f_cv_output_energy); - } - } - - get_keyval(conf, "extendedLangevinDamping", ext_gamma, 1.0); - if (ext_gamma < 0.0) { - cvm::error("Error: \"extendedLangevinDamping\" may not be negative.\n", INPUT_ERROR); - } - if (ext_gamma != 0.0) { - enable(f_cv_Langevin); - ext_gamma *= 1.0e-3; // convert from ps-1 to fs-1 - ext_sigma = std::sqrt(2.0 * cvm::boltzmann() * temp * ext_gamma * ext_mass / cvm::dt()); - } + get_keyval(conf, "extendedLangevinDamping", ext_gamma, 1.0); + if (ext_gamma < 0.0) { + cvm::error("Error: \"extendedLangevinDamping\" may not be negative.\n", INPUT_ERROR); + return INPUT_ERROR; + } + if (ext_gamma != 0.0) { + enable(f_cv_Langevin); + ext_gamma *= 1.0e-3; // convert from ps-1 to fs-1 + ext_sigma = std::sqrt(2.0 * cvm::boltzmann() * temp * ext_gamma * ext_mass / cvm::dt()); } } + return COLVARS_OK; +} + + +int colvar::init_output_flags(std::string const &conf) +{ { bool b_output_value; get_keyval(conf, "outputValue", b_output_value, true); @@ -387,7 +461,7 @@ colvar::colvar(std::string const &conf) if (get_keyval(conf, "outputSystemForce", temp, false, colvarparse::parse_silent)) { cvm::error("Option outputSystemForce is deprecated: only outputTotalForce is supported instead.\n" "The two are NOT identical: see http://colvars.github.io/totalforce.html.\n", INPUT_ERROR); - return; + return INPUT_ERROR; } } @@ -395,28 +469,7 @@ colvar::colvar(std::string const &conf) get_keyval_feature(this, conf, "outputAppliedForce", f_cv_output_applied_force, false); get_keyval_feature(this, conf, "subtractAppliedForce", f_cv_subtract_applied_force, false); - // Start in active state by default - enable(f_cv_active); - // Make sure dependency side-effects are correct - refresh_deps(); - - x_old.type(value()); - v_fdiff.type(value()); - v_reported.type(value()); - fj.type(value()); - ft.type(value()); - ft_reported.type(value()); - f_old.type(value()); - f_old.reset(); - - x_restart.type(value()); - after_restart = false; - - if (cvm::b_analysis) - parse_analysis(conf); - - if (cvm::debug()) - cvm::log("Done initializing collective variable \""+this->name+"\".\n"); + return COLVARS_OK; } @@ -637,7 +690,7 @@ int colvar::parse_analysis(std::string const &conf) std::string runave_outfile; get_keyval(conf, "runAveOutputFile", runave_outfile, - std::string(cvm::output_prefix+"."+ + std::string(cvm::output_prefix()+"."+ this->name+".runave.traj")); size_t const this_cv_width = x.output_width(cvm::cv_width); @@ -693,7 +746,7 @@ int colvar::parse_analysis(std::string const &conf) get_keyval(conf, "corrFuncNormalize", acf_normalize, true); get_keyval(conf, "corrFuncOutputFile", acf_outfile, - std::string(cvm::output_prefix+"."+this->name+ + std::string(cvm::output_prefix()+"."+this->name+ ".corrfunc.dat")); } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); @@ -730,11 +783,12 @@ colvar::~colvar() } // remove reference to this colvar from the CVM - for (std::vector::iterator cvi = cvm::colvars.begin(); - cvi != cvm::colvars.end(); + colvarmodule *cv = cvm::main(); + for (std::vector::iterator cvi = cv->variables()->begin(); + cvi != cv->variables()->end(); ++cvi) { if ( *cvi == this) { - cvm::colvars.erase(cvi); + cv->variables()->erase(cvi); break; } } @@ -892,7 +946,6 @@ int colvar::collect_cvc_values() cvm::to_str(x, cvm::cv_width, cvm::cv_prec)+".\n"); if (after_restart) { - after_restart = false; if (cvm::proxy->simulation_running()) { cvm::real const jump2 = dist2(x, x_restart) / (width*width); if (jump2 > 0.25) { @@ -1122,8 +1175,7 @@ int colvar::calc_colvar_properties() // initialize the restraint center in the first step to the value // just calculated from the cvcs - // TODO: put it in the restart information - if (cvm::step_relative() == 0) { + if (cvm::step_relative() == 0 && !after_restart) { xr = x; vr.reset(); // (already 0; added for clarity) } @@ -1148,6 +1200,8 @@ int colvar::calc_colvar_properties() ft_reported = ft; } + // At the end of the first update after a restart, we can reset the flag + after_restart = false; return COLVARS_OK; } @@ -1173,51 +1227,17 @@ cvm::real colvar::update_forces_energy() f -= fj; } - // Wall force - colvarvalue fw(x); - fw.reset(); - - if (is_enabled(f_cv_lower_wall) || is_enabled(f_cv_upper_wall)) { - - if (cvm::debug()) - cvm::log("Calculating wall forces for colvar \""+this->name+"\".\n"); - - // For a periodic colvar, both walls may be applicable at the same time - // in which case we pick the closer one - if ( (!is_enabled(f_cv_upper_wall)) || - (this->dist2(x, lower_wall) < this->dist2(x, upper_wall)) ) { - - cvm::real const grad = this->dist2_lgrad(x, lower_wall); - if (grad < 0.0) { - fw = -0.5 * lower_wall_k * grad; - if (cvm::debug()) - cvm::log("Applying a lower wall force("+ - cvm::to_str(fw)+") to \""+this->name+"\".\n"); - } - - } else { - - cvm::real const grad = this->dist2_lgrad(x, upper_wall); - if (grad > 0.0) { - fw = -0.5 * upper_wall_k * grad; - if (cvm::debug()) - cvm::log("Applying an upper wall force("+ - cvm::to_str(fw)+") to \""+this->name+"\".\n"); - } - } - } - // At this point f is the force f from external biases that will be applied to the // extended variable if there is one if (is_enabled(f_cv_extended_Lagrangian)) { if (cvm::debug()) { - cvm::log("Updating extended-Lagrangian degrees of freedom.\n"); + cvm::log("Updating extended-Lagrangian degree of freedom.\n"); } cvm::real dt = cvm::dt(); - colvarvalue f_ext(fr.type()); + colvarvalue f_ext(fr.type()); // force acting on the extended variable f_ext.reset(); // the total force is applied to the fictitious mass, while the @@ -1226,7 +1246,7 @@ cvm::real colvar::update_forces_energy() // f_ext: total force on extended variable (including harmonic spring) // f: - initially, external biasing force // - after this code block, colvar force to be applied to atomic coordinates - // ie. spring force + wall force + // ie. spring force (fb_actual will be added just below) fr = f; f_ext = f + (-0.5 * ext_force_k) * this->dist2_lgrad(xr, x); f = (-0.5 * ext_force_k) * this->dist2_rgrad(xr, x); @@ -1259,8 +1279,6 @@ cvm::real colvar::update_forces_energy() if (this->is_enabled(f_cv_periodic)) this->wrap(xr); } - // TODO remove the wall force - f += fw; // Now adding the force on the actual colvar (for those biases who // bypass the extended Lagrangian mass) f += fb_actual; @@ -1286,8 +1304,10 @@ cvm::real colvar::update_forces_energy() void colvar::communicate_forces() { size_t i; - if (cvm::debug()) + if (cvm::debug()) { cvm::log("Communicating forces from colvar \""+this->name+"\".\n"); + cvm::log("Force to be applied: " + cvm::to_str(f_accumulated) + "\n"); + } if (is_enabled(f_cv_scripted)) { std::vector > func_grads; @@ -1364,7 +1384,7 @@ int colvar::update_cvc_flags() active_cvc_square_norm = 0.; for (size_t i = 0; i < cvcs.size(); i++) { - cvcs[i]->feature_states[f_cvc_active]->enabled = cvc_flags[i]; + cvcs[i]->set_enabled(f_cvc_active, cvc_flags[i]); if (cvcs[i]->is_enabled()) { n_active_cvcs++; active_cvc_square_norm += cvcs[i]->sup_coeff * cvcs[i]->sup_coeff; diff --git a/lib/colvars/colvar.h b/lib/colvars/colvar.h index 2cf3d2dac5..0cbda450b8 100644 --- a/lib/colvars/colvar.h +++ b/lib/colvars/colvar.h @@ -227,11 +227,23 @@ public: /// Constructor - colvar(std::string const &conf); + colvar(); + + /// Main init function + int init(std::string const &conf); /// Parse the CVC configuration and allocate their data int init_components(std::string const &conf); + /// Init defaults for grid options + int init_grid_parameters(std::string const &conf); + + /// Init extended Lagrangian parameters + int init_extended_Lagrangian(std::string const &conf); + + /// Init output flags + int init_output_flags(std::string const &conf); + private: /// Parse the CVC configuration for all components of a certain type template int init_components_type(std::string const &conf, diff --git a/lib/colvars/colvaratoms.cpp b/lib/colvars/colvaratoms.cpp index 48c16e887a..32cfadf3b6 100644 --- a/lib/colvars/colvaratoms.cpp +++ b/lib/colvars/colvaratoms.cpp @@ -98,7 +98,7 @@ cvm::atom_group::atom_group() cvm::atom_group::~atom_group() { - if (is_enabled(f_ag_scalable)) { + if (is_enabled(f_ag_scalable) && !b_dummy) { (cvm::proxy)->clear_atom_group(index); index = -1; } @@ -418,7 +418,7 @@ 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) { + if (is_available(f_ag_scalable_com) && !b_rotate && !b_center) { enable(f_ag_scalable_com); enable(f_ag_scalable); } @@ -500,14 +500,16 @@ int cvm::atom_group::add_atom_numbers(std::string const &numbers_conf) int cvm::atom_group::add_index_group(std::string const &index_group_name) { - std::list::iterator names_i = cvm::index_group_names.begin(); - std::list >::iterator index_groups_i = cvm::index_groups.begin(); - for ( ; names_i != cvm::index_group_names.end() ; ++names_i, ++index_groups_i) { + colvarmodule *cv = cvm::main(); + + std::list::iterator names_i = cv->index_group_names.begin(); + std::list >::iterator index_groups_i = cv->index_groups.begin(); + for ( ; names_i != cv->index_group_names.end() ; ++names_i, ++index_groups_i) { if (*names_i == index_group_name) break; } - if (names_i == cvm::index_group_names.end()) { + if (names_i == cv->index_group_names.end()) { cvm::error("Error: could not find index group "+ index_group_name+" among those provided by the index file.\n", INPUT_ERROR); diff --git a/lib/colvars/colvarbias.cpp b/lib/colvars/colvarbias.cpp index fdd2b6254c..3779c82aa3 100644 --- a/lib/colvars/colvarbias.cpp +++ b/lib/colvars/colvarbias.cpp @@ -19,20 +19,6 @@ colvarbias::colvarbias(char const *key) rank = 1; - if (bias_type == std::string("abf")) { - rank = cvm::n_abf_biases+1; - } - if (bias_type == std::string("harmonic") || - bias_type == std::string("linear")) { - rank = cvm::n_rest_biases+1; - } - if (bias_type == std::string("histogram")) { - rank = cvm::n_histo_biases+1; - } - if (bias_type == std::string("metadynamics")) { - rank = cvm::n_meta_biases+1; - } - has_data = false; b_output_energy = false; reset(); @@ -48,7 +34,11 @@ int colvarbias::init(std::string const &conf) colvarparse::init(conf); if (name.size() == 0) { + + // first initialization + cvm::log("Initializing a new \""+bias_type+"\" instance.\n"); + rank = cvm::num_biases_type(bias_type); get_keyval(conf, "name", name, bias_type+cvm::to_str(rank)); { @@ -69,7 +59,7 @@ int colvarbias::init(std::string const &conf) // lookup the associated colvars std::vector colvar_names; if (get_keyval(conf, "colvars", colvar_names)) { - if (colvars.size()) { + if (num_variables()) { cvm::error("Error: cannot redefine the colvars that a bias was already defined on.\n", INPUT_ERROR); return INPUT_ERROR; @@ -80,7 +70,7 @@ int colvarbias::init(std::string const &conf) } } - if (!colvars.size()) { + if (!num_variables()) { cvm::error("Error: no collective variables specified.\n", INPUT_ERROR); return INPUT_ERROR; } @@ -89,6 +79,8 @@ int colvarbias::init(std::string const &conf) cvm::log("Reinitializing bias \""+name+"\".\n"); } + output_prefix = cvm::output_prefix(); + get_keyval(conf, "outputEnergy", b_output_energy, b_output_energy); return COLVARS_OK; @@ -98,7 +90,7 @@ int colvarbias::init(std::string const &conf) int colvarbias::reset() { bias_energy = 0.0; - for (size_t i = 0; i < colvars.size(); i++) { + for (size_t i = 0; i < num_variables(); i++) { colvar_forces[i].reset(); } return COLVARS_OK; @@ -132,12 +124,13 @@ int colvarbias::clear() } } + colvarmodule *cv = cvm::main(); // ...and from the colvars module - for (std::vector::iterator bi = cvm::biases.begin(); - bi != cvm::biases.end(); + for (std::vector::iterator bi = cv->biases.begin(); + bi != cv->biases.end(); ++bi) { if ( *bi == this) { - cvm::biases.erase(bi); + cv->biases.erase(bi); break; } } @@ -185,21 +178,29 @@ int colvarbias::add_colvar(std::string const &cv_name) int colvarbias::update() { - // Note: if anything is added here, it should be added also in the SMP block of calc_biases() - // TODO move here debug msg of bias update + if (cvm::debug()) { + cvm::log("Updating the "+bias_type+" bias \""+this->name+"\".\n"); + } + has_data = true; + + bias_energy = 0.0; + for (size_t ir = 0; ir < num_variables(); ir++) { + colvar_forces[ir].reset(); + } + return COLVARS_OK; } void colvarbias::communicate_forces() { - for (size_t i = 0; i < colvars.size(); i++) { + for (size_t i = 0; i < num_variables(); i++) { if (cvm::debug()) { cvm::log("Communicating a force to colvar \""+ - colvars[i]->name+"\".\n"); + variables(i)->name+"\".\n"); } - colvars[i]->add_bias_force(colvar_forces[i]); + variables(i)->add_bias_force(colvar_forces[i]); } } diff --git a/lib/colvars/colvarbias.h b/lib/colvars/colvarbias.h index 12397dcb8f..6d5776d3db 100644 --- a/lib/colvars/colvarbias.h +++ b/lib/colvars/colvarbias.h @@ -32,17 +32,39 @@ public: /// Add a new collective variable to this bias int add_colvar(std::string const &cv_name); - /// Add a new collective variable to this bias - size_t number_of_colvars() const + /// How many variables are defined for this bias + inline size_t num_variables() const { return colvars.size(); } + /// Access the variables vector + inline std::vector *variables() + { + return &colvars; + } + + /// Access the i-th variable + inline colvar * variables(int i) const + { + return colvars[i]; + } + /// Retrieve colvar values and calculate their biasing forces /// Return bias energy virtual int update(); - // TODO: move update_bias here (share with metadynamics) + /// \brief Compute the energy of the bias with alternative values of the + /// collective variables (suitable for bias exchange) + virtual int calc_energy(std::vector const &values = + std::vector(0)) + { + cvm::error("Error: calc_energy() not implemented.\n", COLVARS_NOT_IMPLEMENTED); + return COLVARS_NOT_IMPLEMENTED; + } + + /// Send forces to the collective variables + virtual void communicate_forces(); /// Load new configuration - force constant and/or centers only virtual int change_configuration(std::string const &conf); @@ -51,10 +73,13 @@ public: virtual cvm::real energy_difference(std::string const &conf); /// Give the total number of bins for a given bias. + // FIXME this is currently 1D only virtual int bin_num(); /// Calculate the bin index for a given bias. + // FIXME this is currently 1D only virtual int current_bin(); //// Give the count at a given bin index. + // FIXME this is currently 1D only virtual int bin_count(int bin_index); //// Share information between replicas, whatever it may be. virtual int replica_share(); @@ -62,9 +87,6 @@ public: /// Perform analysis tasks virtual void analyze() {} - /// Send forces to the collective variables - virtual void communicate_forces(); - /// \brief Constructor colvarbias(char const *key); @@ -135,6 +157,9 @@ public: return COLVARS_OK; } + /// Use this prefix for all output files + std::string output_prefix; + /// If this bias is communicating with other replicas through files, send it to them virtual int write_state_to_replicas() { @@ -162,7 +187,7 @@ protected: /// through each colvar object std::vector colvars; - /// \brief Current forces from this bias to the colvars + /// \brief Current forces from this bias to the variables std::vector colvar_forces; /// \brief Current energy of this bias (colvar_forces should be obtained by deriving this) diff --git a/lib/colvars/colvarbias_abf.cpp b/lib/colvars/colvarbias_abf.cpp index ccfa401697..d039004f09 100644 --- a/lib/colvars/colvarbias_abf.cpp +++ b/lib/colvars/colvarbias_abf.cpp @@ -30,9 +30,8 @@ int colvarbias_abf::init(std::string const &conf) { colvarbias::init(conf); - provide(f_cvb_scalar_variables); enable(f_cvb_scalar_variables); - provide(f_cvb_history_dependent); + enable(f_cvb_calc_pmf); // TODO relax this in case of VMD plugin if (cvm::temperature() == 0.0) @@ -221,9 +220,6 @@ colvarbias_abf::~colvarbias_abf() delete [] system_force; system_force = NULL; } - - if (cvm::n_abf_biases > 0) - cvm::n_abf_biases -= 1; } @@ -319,11 +315,11 @@ int colvarbias_abf::update() } // update the output prefix; TODO: move later to setup_output() function - if ( cvm::n_abf_biases == 1 && cvm::n_meta_biases == 0 ) { - // This is the only ABF bias - output_prefix = cvm::output_prefix; + if (cvm::num_biases_feature(colvardeps::f_cvb_calc_pmf) == 1) { + // This is the only bias computing PMFs + output_prefix = cvm::output_prefix(); } else { - output_prefix = cvm::output_prefix + "." + this->name; + output_prefix = cvm::output_prefix() + "." + this->name; } if (output_freq && (cvm::step_absolute() % output_freq) == 0) { diff --git a/lib/colvars/colvarbias_alb.cpp b/lib/colvars/colvarbias_alb.cpp index 9e414d4db4..d096ac3daf 100644 --- a/lib/colvars/colvarbias_alb.cpp +++ b/lib/colvars/colvarbias_alb.cpp @@ -40,11 +40,8 @@ int colvarbias_alb::init(std::string const &conf) { colvarbias::init(conf); - provide(f_cvb_scalar_variables); enable(f_cvb_scalar_variables); - provide(f_cvb_history_dependent); - size_t i; // get the initial restraint centers @@ -138,8 +135,6 @@ int colvarbias_alb::init(std::string const &conf) colvarbias_alb::~colvarbias_alb() { - if (cvm::n_rest_biases > 0) - cvm::n_rest_biases -= 1; } diff --git a/lib/colvars/colvarbias_histogram.cpp b/lib/colvars/colvarbias_histogram.cpp index 900ad213d5..502a7455b1 100644 --- a/lib/colvars/colvarbias_histogram.cpp +++ b/lib/colvars/colvarbias_histogram.cpp @@ -24,10 +24,7 @@ int colvarbias_histogram::init(std::string const &conf) { colvarbias::init(conf); - provide(f_cvb_scalar_variables); enable(f_cvb_scalar_variables); - - provide(f_cvb_history_dependent); enable(f_cvb_history_dependent); size_t i; @@ -104,9 +101,6 @@ colvarbias_histogram::~colvarbias_histogram() delete grid; grid = NULL; } - - if (cvm::n_histo_biases > 0) - cvm::n_histo_biases -= 1; } @@ -127,14 +121,14 @@ int colvarbias_histogram::update() // At the first timestep, we need to assign out_name since // output_prefix is unset during the constructor if (cvm::step_relative() == 0) { - out_name = cvm::output_prefix + "." + this->name + ".dat"; + out_name = cvm::output_prefix() + "." + this->name + ".dat"; cvm::log("Histogram " + this->name + " will be written to file \"" + out_name + "\""); } } if (out_name_dx.size() == 0) { if (cvm::step_relative() == 0) { - out_name_dx = cvm::output_prefix + "." + this->name + ".dx"; + out_name_dx = cvm::output_prefix() + "." + this->name + ".dx"; cvm::log("Histogram " + this->name + " will be written to file \"" + out_name_dx + "\""); } } diff --git a/lib/colvars/colvarbias_meta.cpp b/lib/colvars/colvarbias_meta.cpp index 01a04d1a01..b0acfe974a 100644 --- a/lib/colvars/colvarbias_meta.cpp +++ b/lib/colvars/colvarbias_meta.cpp @@ -43,7 +43,7 @@ int colvarbias_meta::init(std::string const &conf) { colvarbias::init(conf); - provide(f_cvb_history_dependent); + enable(f_cvb_calc_pmf); get_keyval(conf, "hillWeight", hill_weight, 0.0); if (hill_weight > 0.0) { @@ -59,9 +59,9 @@ int colvarbias_meta::init(std::string const &conf) get_keyval(conf, "hillWidth", hill_width, std::sqrt(2.0 * PI) / 2.0); cvm::log("Half-widths of the Gaussian hills (sigma's):\n"); - for (size_t i = 0; i < colvars.size(); i++) { - cvm::log(colvars[i]->name+std::string(": ")+ - cvm::to_str(0.5 * colvars[i]->width * hill_width)); + for (size_t i = 0; i < num_variables(); i++) { + cvm::log(variables(i)->name+std::string(": ")+ + cvm::to_str(0.5 * variables(i)->width * hill_width)); } { @@ -73,8 +73,10 @@ int colvarbias_meta::init(std::string const &conf) comm = single_replica; } - // This implies gradients for all colvars - enable(f_cvb_apply_force); + // in all cases, the first replica is this bias itself + if (replicas.size() == 0) { + replicas.push_back(this); + } get_keyval(conf, "useGrids", use_grids, true); @@ -84,14 +86,14 @@ int colvarbias_meta::init(std::string const &conf) expand_grids = false; size_t i; - for (i = 0; i < colvars.size(); i++) { - colvars[i]->enable(f_cv_grid); - if (colvars[i]->expand_boundaries) { + for (i = 0; i < num_variables(); i++) { + variables(i)->enable(f_cv_grid); + if (variables(i)->expand_boundaries) { expand_grids = true; cvm::log("Metadynamics bias \""+this->name+"\""+ ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ ": Will expand grids when the colvar \""+ - colvars[i]->name+"\" approaches its boundaries.\n"); + variables(i)->name+"\" approaches its boundaries.\n"); } } @@ -100,7 +102,7 @@ int colvarbias_meta::init(std::string const &conf) get_keyval(conf, "dumpFreeEnergyFile", dump_fes, true, colvarparse::parse_silent); if (get_keyval(conf, "saveFreeEnergyFile", dump_fes_save, false, colvarparse::parse_silent)) { cvm::log("Option \"saveFreeEnergyFile\" is deprecated, " - "please use \"keepFreeEnergyFiles\" instead."); + "please use \"keepFreeEnergyFile\" instead."); } get_keyval(conf, "keepFreeEnergyFiles", dump_fes_save, dump_fes_save); @@ -154,6 +156,20 @@ int colvarbias_meta::init(std::string const &conf) get_keyval(conf, "writeHillsTrajectory", b_hills_traj, false); + init_well_tempered_params(conf); + init_ebmeta_params(conf); + + if (cvm::debug()) + cvm::log("Done initializing the metadynamics bias \""+this->name+"\""+ + ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+".\n"); + + save_delimiters = false; + return COLVARS_OK; +} + + +int colvarbias_meta::init_well_tempered_params(std::string const &conf) +{ // for well-tempered metadynamics get_keyval(conf, "wellTempered", well_tempered, false); get_keyval(conf, "biasTemperature", bias_temperature, -1.0); @@ -164,8 +180,12 @@ int colvarbias_meta::init(std::string const &conf) cvm::log("Well-tempered metadynamics is used.\n"); cvm::log("The bias temperature is "+cvm::to_str(bias_temperature)+".\n"); } + return COLVARS_OK; +} +int colvarbias_meta::init_ebmeta_params(std::string const &conf) +{ // for ebmeta target_dist = NULL; get_keyval(conf, "ebMeta", ebmeta, false); @@ -203,11 +223,6 @@ int colvarbias_meta::init(std::string const &conf) get_keyval(conf, "ebMetaEquilSteps", ebmeta_equil_steps, 0); } - if (cvm::debug()) - cvm::log("Done initializing the metadynamics bias \""+this->name+"\""+ - ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+".\n"); - - save_delimiters = false; return COLVARS_OK; } @@ -234,9 +249,6 @@ colvarbias_meta::~colvarbias_meta() delete target_dist; target_dist = NULL; } - - if (cvm::n_meta_biases > 0) - cvm::n_meta_biases -= 1; } @@ -314,23 +326,45 @@ colvarbias_meta::delete_hill(hill_iter &h) int colvarbias_meta::update() { - if (cvm::debug()) - cvm::log("Updating the metadynamics bias \""+this->name+"\""+ - ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+".\n"); + int error_code = COLVARS_OK; + // update base class + error_code |= colvarbias::update(); + + // update grid definition, if needed + error_code |= update_grid_params(); + // add new biasing energy/forces + error_code |= update_bias(); + // update grid content to reflect new bias + error_code |= update_grid_data(); + + if (comm != single_replica && + (cvm::step_absolute() % replica_update_freq) == 0) { + // sync with the other replicas (if needed) + error_code |= replica_share(); + } + + error_code |= calc_energy(); + error_code |= calc_forces(); + + return error_code; +} + + +int colvarbias_meta::update_grid_params() +{ if (use_grids) { std::vector curr_bin = hills_energy->get_colvars_index(); + if (cvm::debug()) { + cvm::log("Metadynamics bias \""+this->name+"\""+ + ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ + ": current coordinates on the grid: "+ + cvm::to_str(curr_bin)+".\n"); + } if (expand_grids) { - // first of all, expand the grids, if specified - if (cvm::debug()) - cvm::log("Metadynamics bias \""+this->name+"\""+ - ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ - ": current coordinates on the grid: "+ - cvm::to_str(curr_bin)+".\n"); - bool changed_grids = false; int const min_buffer = (3 * (size_t) std::floor(hill_width)) + 1; @@ -339,9 +373,9 @@ int colvarbias_meta::update() std::vector new_lower_boundaries(hills_energy->lower_boundaries); std::vector new_upper_boundaries(hills_energy->upper_boundaries); - for (size_t i = 0; i < colvars.size(); i++) { + for (size_t i = 0; i < num_variables(); i++) { - if (! colvars[i]->expand_boundaries) + if (! variables(i)->expand_boundaries) continue; cvm::real &new_lb = new_lower_boundaries[i].real_value; @@ -349,10 +383,10 @@ int colvarbias_meta::update() int &new_size = new_sizes[i]; bool changed_lb = false, changed_ub = false; - if (!colvars[i]->hard_lower_boundary) + if (!variables(i)->hard_lower_boundary) if (curr_bin[i] < min_buffer) { int const extra_points = (min_buffer - curr_bin[i]); - new_lb -= extra_points * colvars[i]->width; + new_lb -= extra_points * variables(i)->width; new_size += extra_points; // changed offset in this direction => the pointer needs to // be changed, too @@ -362,21 +396,21 @@ int colvarbias_meta::update() cvm::log("Metadynamics bias \""+this->name+"\""+ ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ ": new lower boundary for colvar \""+ - colvars[i]->name+"\", at "+ + variables(i)->name+"\", at "+ cvm::to_str(new_lower_boundaries[i])+".\n"); } - if (!colvars[i]->hard_upper_boundary) + if (!variables(i)->hard_upper_boundary) if (curr_bin[i] > new_size - min_buffer - 1) { int const extra_points = (curr_bin[i] - (new_size - 1) + min_buffer); - new_ub += extra_points * colvars[i]->width; + new_ub += extra_points * variables(i)->width; new_size += extra_points; changed_ub = true; cvm::log("Metadynamics bias \""+this->name+"\""+ ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ ": new upper boundary for colvar \""+ - colvars[i]->name+"\", at "+ + variables(i)->name+"\", at "+ cvm::to_str(new_upper_boundaries[i])+".\n"); } @@ -401,7 +435,7 @@ int colvarbias_meta::update() new_hills_energy_gradients->lower_boundaries = new_lower_boundaries; new_hills_energy_gradients->upper_boundaries = new_upper_boundaries; - new_hills_energy_gradients->setup(new_sizes, 0.0, colvars.size()); + new_hills_energy_gradients->setup(new_sizes, 0.0, num_variables()); new_hills_energy->map_grid(*hills_energy); new_hills_energy_gradients->map_grid(*hills_energy_gradients); @@ -418,25 +452,32 @@ int colvarbias_meta::update() } } } + return COLVARS_OK; +} + +int colvarbias_meta::update_bias() +{ // add a new hill if the required time interval has passed - if ((cvm::step_absolute() % new_hill_freq) == 0) { + if ((cvm::step_absolute() % new_hill_freq) == 0 && + is_enabled(f_cvb_history_dependent)) { - if (cvm::debug()) + if (cvm::debug()) { cvm::log("Metadynamics bias \""+this->name+"\""+ ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ ": adding a new hill at step "+cvm::to_str(cvm::step_absolute())+".\n"); + } cvm::real hills_scale=1.0; if (ebmeta) { - hills_scale *= 1.0/target_dist->value(target_dist->get_colvars_index()); - if(cvm::step_absolute() <= long(ebmeta_equil_steps)) { - cvm::real const hills_lambda = - (cvm::real(long(ebmeta_equil_steps) - cvm::step_absolute())) / - (cvm::real(ebmeta_equil_steps)); - hills_scale = hills_lambda + (1-hills_lambda)*hills_scale; - } + hills_scale *= 1.0/target_dist->value(target_dist->get_colvars_index()); + if(cvm::step_absolute() <= long(ebmeta_equil_steps)) { + cvm::real const hills_lambda = + (cvm::real(long(ebmeta_equil_steps) - cvm::step_absolute())) / + (cvm::real(ebmeta_equil_steps)); + hills_scale = hills_lambda + (1-hills_lambda)*hills_scale; + } } if (well_tempered) { @@ -471,160 +512,165 @@ int colvarbias_meta::update() } } - // sync with the other replicas (if needed) - if (comm != single_replica) { + return COLVARS_OK; +} - // reread the replicas registry - if ((cvm::step_absolute() % replica_update_freq) == 0) { - update_replicas_registry(); - // empty the output buffer - if (replica_hills_os.is_open()) - replica_hills_os.flush(); - read_replica_files(); +int colvarbias_meta::update_grid_data() +{ + if ((cvm::step_absolute() % grids_freq) == 0) { + // map the most recent gaussians to the grids + project_hills(new_hills_begin, hills.end(), + hills_energy, hills_energy_gradients); + new_hills_begin = hills.end(); + + // TODO: we may want to condense all into one replicas array, + // including "this" as the first element + if (comm == multiple_replicas) { + for (size_t ir = 0; ir < replicas.size(); ir++) { + replicas[ir]->project_hills(replicas[ir]->new_hills_begin, + replicas[ir]->hills.end(), + replicas[ir]->hills_energy, + replicas[ir]->hills_energy_gradients); + replicas[ir]->new_hills_begin = replicas[ir]->hills.end(); + } } } - // calculate the biasing energy and forces - bias_energy = 0.0; - for (size_t ir = 0; ir < colvars.size(); ir++) { - colvar_forces[ir].reset(); + return COLVARS_OK; +} + + +int colvarbias_meta::calc_energy(std::vector const &values) +{ + size_t ir = 0; + + for (ir = 0; ir < replicas.size(); ir++) { + replicas[ir]->bias_energy = 0.0; } - if (comm == multiple_replicas) - for (size_t ir = 0; ir < replicas.size(); ir++) { - replicas[ir]->bias_energy = 0.0; - for (size_t ic = 0; ic < colvars.size(); ic++) { - replicas[ir]->colvar_forces[ic].reset(); + + std::vector const curr_bin = values.size() ? + hills_energy->get_colvars_index(values) : + hills_energy->get_colvars_index(); + + if (hills_energy->index_ok(curr_bin)) { + // index is within the grid: get the energy from there + for (ir = 0; ir < replicas.size(); ir++) { + + bias_energy += replicas[ir]->hills_energy->value(curr_bin); + if (cvm::debug()) { + cvm::log("Metadynamics bias \""+this->name+"\""+ + ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ + ": current coordinates on the grid: "+ + cvm::to_str(curr_bin)+".\n"); + cvm::log("Grid energy = "+cvm::to_str(bias_energy)+".\n"); } } - - if (use_grids) { - - // get the forces from the grid - - if ((cvm::step_absolute() % grids_freq) == 0) { - // map the most recent gaussians to the grids - project_hills(new_hills_begin, hills.end(), - hills_energy, hills_energy_gradients); - new_hills_begin = hills.end(); - - // TODO: we may want to condense all into one replicas array, - // including "this" as the first element - if (comm == multiple_replicas) { - for (size_t ir = 0; ir < replicas.size(); ir++) { - replicas[ir]->project_hills(replicas[ir]->new_hills_begin, - replicas[ir]->hills.end(), - replicas[ir]->hills_energy, - replicas[ir]->hills_energy_gradients); - replicas[ir]->new_hills_begin = replicas[ir]->hills.end(); - } - } - } - - std::vector curr_bin = hills_energy->get_colvars_index(); - if (cvm::debug()) - cvm::log("Metadynamics bias \""+this->name+"\""+ - ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ - ": current coordinates on the grid: "+ - cvm::to_str(curr_bin)+".\n"); - - if (hills_energy->index_ok(curr_bin)) { - - // within the grid: add the energy and the forces from there - - bias_energy += hills_energy->value(curr_bin); - for (size_t ic = 0; ic < colvars.size(); ic++) { - cvm::real const *f = &(hills_energy_gradients->value(curr_bin)); - colvar_forces[ic].real_value += -1.0 * f[ic]; - // the gradients are stored, not the forces - } - if (comm == multiple_replicas) - for (size_t ir = 0; ir < replicas.size(); ir++) { - bias_energy += replicas[ir]->hills_energy->value(curr_bin); - cvm::real const *f = &(replicas[ir]->hills_energy_gradients->value(curr_bin)); - for (size_t ic = 0; ic < colvars.size(); ic++) { - colvar_forces[ic].real_value += -1.0 * f[ic]; - } - } - - } else { - - // off the grid: compute analytically only the hills at the grid's edges - - calc_hills(hills_off_grid.begin(), hills_off_grid.end(), bias_energy); - for (size_t ic = 0; ic < colvars.size(); ic++) { - calc_hills_force(ic, hills_off_grid.begin(), hills_off_grid.end(), colvar_forces); - } - - if (comm == multiple_replicas) - for (size_t ir = 0; ir < replicas.size(); ir++) { - calc_hills(replicas[ir]->hills_off_grid.begin(), - replicas[ir]->hills_off_grid.end(), - bias_energy); - for (size_t ic = 0; ic < colvars.size(); ic++) { - calc_hills_force(ic, - replicas[ir]->hills_off_grid.begin(), - replicas[ir]->hills_off_grid.end(), - colvar_forces); - } - } + } else { + // off the grid: compute analytically only the hills at the grid's edges + for (ir = 0; ir < replicas.size(); ir++) { + calc_hills(replicas[ir]->hills_off_grid.begin(), + replicas[ir]->hills_off_grid.end(), + bias_energy, + values); } } // now include the hills that have not been binned yet (starting // from new_hills_begin) - calc_hills(new_hills_begin, hills.end(), bias_energy); - for (size_t ic = 0; ic < colvars.size(); ic++) { - calc_hills_force(ic, new_hills_begin, hills.end(), colvar_forces); - } - - if (cvm::debug()) - cvm::log("Hills energy = "+cvm::to_str(bias_energy)+ - ", hills forces = "+cvm::to_str(colvar_forces)+".\n"); - - if (cvm::debug()) - cvm::log("Metadynamics bias \""+this->name+"\""+ - ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ - ": adding the forces from the other replicas.\n"); - - if (comm == multiple_replicas) - for (size_t ir = 0; ir < replicas.size(); ir++) { - calc_hills(replicas[ir]->new_hills_begin, - replicas[ir]->hills.end(), - bias_energy); - for (size_t ic = 0; ic < colvars.size(); ic++) { - calc_hills_force(ic, - replicas[ir]->new_hills_begin, - replicas[ir]->hills.end(), - colvar_forces); - } - if (cvm::debug()) - cvm::log("Hills energy = "+cvm::to_str(bias_energy)+ - ", hills forces = "+cvm::to_str(colvar_forces)+".\n"); + for (ir = 0; ir < replicas.size(); ir++) { + calc_hills(replicas[ir]->new_hills_begin, + replicas[ir]->hills.end(), + bias_energy); + if (cvm::debug()) { + cvm::log("Hills energy = "+cvm::to_str(bias_energy)+".\n"); } + } return COLVARS_OK; } +int colvarbias_meta::calc_forces(std::vector const &values) +{ + size_t ir = 0, ic = 0; + for (ir = 0; ir < replicas.size(); ir++) { + for (ic = 0; ic < num_variables(); ic++) { + replicas[ir]->colvar_forces[ic].reset(); + } + } + + std::vector const curr_bin = values.size() ? + hills_energy->get_colvars_index(values) : + hills_energy->get_colvars_index(); + + if (hills_energy->index_ok(curr_bin)) { + for (ir = 0; ir < replicas.size(); ir++) { + cvm::real const *f = &(replicas[ir]->hills_energy_gradients->value(curr_bin)); + for (ic = 0; ic < num_variables(); ic++) { + // the gradients are stored, not the forces + colvar_forces[ic].real_value += -1.0 * f[ic]; + } + } + } else { + // off the grid: compute analytically only the hills at the grid's edges + for (ir = 0; ir < replicas.size(); ir++) { + for (ic = 0; ic < num_variables(); ic++) { + calc_hills_force(ic, + replicas[ir]->hills_off_grid.begin(), + replicas[ir]->hills_off_grid.end(), + colvar_forces, + values); + } + } + } + + // now include the hills that have not been binned yet (starting + // from new_hills_begin) + + if (cvm::debug()) { + cvm::log("Metadynamics bias \""+this->name+"\""+ + ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ + ": adding the forces from the other replicas.\n"); + } + + for (ir = 0; ir < replicas.size(); ir++) { + for (ic = 0; ic < num_variables(); ic++) { + calc_hills_force(ic, + replicas[ir]->new_hills_begin, + replicas[ir]->hills.end(), + colvar_forces, + values); + if (cvm::debug()) { + cvm::log("Hills forces = "+cvm::to_str(colvar_forces)+".\n"); + } + } + } + + return COLVARS_OK; +} + + + void colvarbias_meta::calc_hills(colvarbias_meta::hill_iter h_first, colvarbias_meta::hill_iter h_last, cvm::real &energy, std::vector const &colvar_values) { - std::vector curr_values(colvars.size()); - for (size_t i = 0; i < colvars.size(); i++) { - curr_values[i].type(colvars[i]->value()); + size_t i = 0; + std::vector curr_values(num_variables()); + for (i = 0; i < num_variables(); i++) { + curr_values[i].type(variables(i)->value()); } if (colvar_values.size()) { - for (size_t i = 0; i < colvars.size(); i++) { + for (i = 0; i < num_variables(); i++) { curr_values[i] = colvar_values[i]; } } else { - for (size_t i = 0; i < colvars.size(); i++) { - curr_values[i] = colvars[i]->value(); + for (i = 0; i < num_variables(); i++) { + curr_values[i] = variables(i)->value(); } } @@ -632,11 +678,11 @@ void colvarbias_meta::calc_hills(colvarbias_meta::hill_iter h_first, // compute the gaussian exponent cvm::real cv_sqdev = 0.0; - for (size_t i = 0; i < colvars.size(); i++) { + for (i = 0; i < num_variables(); i++) { colvarvalue const &x = curr_values[i]; colvarvalue const ¢er = h->centers[i]; cvm::real const half_width = 0.5 * h->widths[i]; - cv_sqdev += (colvars[i]->dist2(x, center)) / (half_width*half_width); + cv_sqdev += (variables(i)->dist2(x, center)) / (half_width*half_width); } // compute the gaussian @@ -658,14 +704,14 @@ void colvarbias_meta::calc_hills_force(size_t const &i, std::vector const &values) { // Retrieve the value of the colvar - colvarvalue const x(values.size() ? values[i] : colvars[i]->value()); + colvarvalue const x(values.size() ? values[i] : variables(i)->value()); // do the type check only once (all colvarvalues in the hills series // were already saved with their types matching those in the // colvars) hill_iter h; - switch (colvars[i]->value().type()) { + switch (variables(i)->value().type()) { case colvarvalue::type_scalar: for (h = h_first; h != h_last; h++) { @@ -674,7 +720,7 @@ void colvarbias_meta::calc_hills_force(size_t const &i, cvm::real const half_width = 0.5 * h->widths[i]; forces[i].real_value += ( h->weight() * h->value() * (0.5 / (half_width*half_width)) * - (colvars[i]->dist2_lgrad(x, center)).real_value ); + (variables(i)->dist2_lgrad(x, center)).real_value ); } break; @@ -687,7 +733,7 @@ void colvarbias_meta::calc_hills_force(size_t const &i, cvm::real const half_width = 0.5 * h->widths[i]; forces[i].rvector_value += ( h->weight() * h->value() * (0.5 / (half_width*half_width)) * - (colvars[i]->dist2_lgrad(x, center)).rvector_value ); + (variables(i)->dist2_lgrad(x, center)).rvector_value ); } break; @@ -699,7 +745,7 @@ void colvarbias_meta::calc_hills_force(size_t const &i, cvm::real const half_width = 0.5 * h->widths[i]; forces[i].quaternion_value += ( h->weight() * h->value() * (0.5 / (half_width*half_width)) * - (colvars[i]->dist2_lgrad(x, center)).quaternion_value ); + (variables(i)->dist2_lgrad(x, center)).quaternion_value ); } break; @@ -710,7 +756,7 @@ void colvarbias_meta::calc_hills_force(size_t const &i, cvm::real const half_width = 0.5 * h->widths[i]; forces[i].vector1d_value += ( h->weight() * h->value() * (0.5 / (half_width*half_width)) * - (colvars[i]->dist2_lgrad(x, center)).vector1d_value ); + (variables(i)->dist2_lgrad(x, center)).vector1d_value ); } break; @@ -739,13 +785,13 @@ void colvarbias_meta::project_hills(colvarbias_meta::hill_iter h_first, // TODO: improve it by looping over a small subgrid instead of the whole grid - std::vector colvar_values(colvars.size()); - std::vector colvar_forces_scalar(colvars.size()); + std::vector colvar_values(num_variables()); + std::vector colvar_forces_scalar(num_variables()); std::vector he_ix = he->new_index(); std::vector hg_ix = (hg != NULL) ? hg->new_index() : std::vector (0); cvm::real hills_energy_here = 0.0; - std::vector hills_forces_here(colvars.size(), 0.0); + std::vector hills_forces_here(num_variables(), 0.0); size_t count = 0; size_t const print_frequency = ((hills.size() >= 1000000) ? 1 : (1000000/(hills.size()+1))); @@ -757,7 +803,7 @@ void colvarbias_meta::project_hills(colvarbias_meta::hill_iter h_first, (he->index_ok(he_ix)) && (hg->index_ok(hg_ix)); count++) { size_t i; - for (i = 0; i < colvars.size(); i++) { + for (i = 0; i < num_variables(); i++) { colvar_values[i] = hills_energy->bin_to_value_scalar(he_ix[i], i); } @@ -766,7 +812,7 @@ void colvarbias_meta::project_hills(colvarbias_meta::hill_iter h_first, calc_hills(h_first, h_last, hills_energy_here, colvar_values); he->acc_value(he_ix, hills_energy_here); - for (i = 0; i < colvars.size(); i++) { + for (i = 0; i < num_variables(); i++) { hills_forces_here[i].reset(); calc_hills_force(i, h_first, h_last, hills_forces_here, colvar_values); colvar_forces_scalar[i] = hills_forces_here[i].real_value; @@ -795,7 +841,7 @@ void colvarbias_meta::project_hills(colvarbias_meta::hill_iter h_first, for ( ; (he->index_ok(he_ix)); ) { - for (size_t i = 0; i < colvars.size(); i++) { + for (size_t i = 0; i < num_variables(); i++) { colvar_values[i] = hills_energy->bin_to_value_scalar(he_ix[i], i); } @@ -851,6 +897,21 @@ void colvarbias_meta::recount_hills_off_grid(colvarbias_meta::hill_iter h_first // ********************************************************************** +int colvarbias_meta::replica_share() +{ + // sync with the other replicas (if needed) + if (comm == multiple_replicas) { + // reread the replicas registry + update_replicas_registry(); + // empty the output buffer + if (replica_hills_os.is_open()) + replica_hills_os.flush(); + read_replica_files(); + } + return COLVARS_OK; +} + + void colvarbias_meta::update_replicas_registry() { if (cvm::debug()) @@ -975,7 +1036,6 @@ void colvarbias_meta::update_replicas_registry() } } - if (cvm::debug()) cvm::log("Metadynamics bias \""+this->name+"\": the list of replicas contains "+ cvm::to_str(replicas.size())+" elements.\n"); @@ -984,7 +1044,8 @@ void colvarbias_meta::update_replicas_registry() void colvarbias_meta::read_replica_files() { - for (size_t ir = 0; ir < replicas.size(); ir++) { + // Note: we start from the 2nd replica. + for (size_t ir = 1; ir < replicas.size(); ir++) { if (! (replicas[ir])->replica_state_file_in_sync) { // if a new state file is being read, the hills file is also new @@ -1352,9 +1413,9 @@ std::istream & colvarbias_meta::read_hill(std::istream &is) cvm::real h_weight; get_keyval(data, "weight", h_weight, hill_weight, parse_silent); - std::vector h_centers(colvars.size()); - for (size_t i = 0; i < colvars.size(); i++) { - h_centers[i].type(colvars[i]->value()); + std::vector h_centers(num_variables()); + for (size_t i = 0; i < num_variables(); i++) { + h_centers[i].type(variables(i)->value()); } { // it is safer to read colvarvalue objects one at a time; @@ -1362,14 +1423,14 @@ std::istream & colvarbias_meta::read_hill(std::istream &is) std::string centers_input; key_lookup(data, "centers", centers_input); std::istringstream centers_is(centers_input); - for (size_t i = 0; i < colvars.size(); i++) { + for (size_t i = 0; i < num_variables(); i++) { centers_is >> h_centers[i]; } } - std::vector h_widths(colvars.size()); + std::vector h_widths(num_variables()); get_keyval(data, "widths", h_widths, - std::vector (colvars.size(), (std::sqrt(2.0 * PI) / 2.0)), + std::vector(num_variables(), (std::sqrt(2.0 * PI) / 2.0)), parse_silent); std::string h_replica = ""; @@ -1406,6 +1467,13 @@ std::istream & colvarbias_meta::read_hill(std::istream &is) int colvarbias_meta::setup_output() { + output_prefix = cvm::output_prefix(); + if (cvm::num_biases_feature(colvardeps::f_cvb_calc_pmf) > 1) { + // if this is not the only free energy integrator, append + // this bias's name, to distinguish it from the output of the other + // biases producing a .pmf file + output_prefix += ("."+this->name); + } if (comm == multiple_replicas) { @@ -1421,10 +1489,10 @@ int colvarbias_meta::setup_output() // those by another replica replica_hills_file = (std::string(pwd)+std::string(PATHSEP)+ - cvm::output_prefix+".colvars."+this->name+"."+replica_id+".hills"); + cvm::output_prefix()+".colvars."+this->name+"."+replica_id+".hills"); replica_state_file = (std::string(pwd)+std::string(PATHSEP)+ - cvm::output_prefix+".colvars."+this->name+"."+replica_id+".state"); + cvm::output_prefix()+".colvars."+this->name+"."+replica_id+".state"); delete[] pwd; // now register this replica @@ -1492,13 +1560,14 @@ int colvarbias_meta::setup_output() } if (b_hills_traj) { - std::string const traj_file_name(cvm::output_prefix+ + std::string const traj_file_name(cvm::output_prefix()+ ".colvars."+this->name+ ( (comm != single_replica) ? ("."+replica_id) : ("") )+ ".hills.traj"); if (!hills_traj_os.is_open()) { + cvm::backup_file(traj_file_name.c_str()); hills_traj_os.open(traj_file_name.c_str()); } if (!hills_traj_os.is_open()) @@ -1585,16 +1654,6 @@ void colvarbias_meta::write_pmf() colvar_grid_scalar *pmf = new colvar_grid_scalar(*hills_energy); pmf->setup(); - std::string fes_file_name_prefix(cvm::output_prefix); - - if ((cvm::n_meta_biases > 1) || (cvm::n_abf_biases > 0)) { - // if this is not the only free energy integrator, append - // this bias's name, to distinguish it from the output of the other - // biases producing a .pmf file - // TODO: fix for ABF with updateBias == no - fes_file_name_prefix += ("."+this->name); - } - if ((comm == single_replica) || (dump_replica_fes)) { // output the PMF from this instance or replica pmf->reset(); @@ -1607,7 +1666,7 @@ void colvarbias_meta::write_pmf() pmf->multiply_constant(well_temper_scale); } { - std::string const fes_file_name(fes_file_name_prefix + + std::string const fes_file_name(this->output_prefix + ((comm != single_replica) ? ".partial" : "") + (dump_fes_save ? "."+cvm::to_str(cvm::step_absolute()) : "") + @@ -1632,7 +1691,7 @@ void colvarbias_meta::write_pmf() cvm::real const well_temper_scale = (bias_temperature + cvm::temperature()) / bias_temperature; pmf->multiply_constant(well_temper_scale); } - std::string const fes_file_name(fes_file_name_prefix + + std::string const fes_file_name(this->output_prefix + (dump_fes_save ? "."+cvm::to_str(cvm::step_absolute()) : "") + ".pmf"); diff --git a/lib/colvars/colvarbias_meta.h b/lib/colvars/colvarbias_meta.h index a88a34ba00..01921eaf64 100644 --- a/lib/colvars/colvarbias_meta.h +++ b/lib/colvars/colvarbias_meta.h @@ -36,8 +36,20 @@ public: colvarbias_meta(char const *key); virtual int init(std::string const &conf); + virtual int init_well_tempered_params(std::string const &conf); + virtual int init_ebmeta_params(std::string const &conf); virtual ~colvarbias_meta(); + virtual int update(); + virtual int update_grid_params(); + virtual int update_bias(); + virtual int update_grid_data(); + virtual int replica_share(); + + virtual int calc_energy(std::vector const &values = + std::vector(0)); + virtual int calc_forces(std::vector const &values = + std::vector(0)); virtual std::string const get_state_params() const; virtual int set_state_params(std::string const &state_conf); @@ -102,18 +114,18 @@ protected: /// \brief Calculate the values of the hills, incrementing /// bias_energy virtual void calc_hills(hill_iter h_first, - hill_iter h_last, - cvm::real &energy, - std::vector const &values = std::vector (0)); + hill_iter h_last, + cvm::real &energy, + std::vector const &values = std::vector(0)); /// \brief Calculate the forces acting on the i-th colvar, /// incrementing colvar_forces[i]; must be called after calc_hills /// each time the values of the colvars are changed virtual void calc_hills_force(size_t const &i, - hill_iter h_first, - hill_iter h_last, - std::vector &forces, - std::vector const &values = std::vector (0)); + hill_iter h_first, + hill_iter h_last, + std::vector &forces, + std::vector const &values = std::vector(0)); /// Height of new hills diff --git a/lib/colvars/colvarbias_restraint.cpp b/lib/colvars/colvarbias_restraint.cpp index 84630984e5..159d9eae64 100644 --- a/lib/colvars/colvarbias_restraint.cpp +++ b/lib/colvars/colvarbias_restraint.cpp @@ -33,17 +33,15 @@ int colvarbias_restraint::init(std::string const &conf) int colvarbias_restraint::update() { - bias_energy = 0.0; - - if (cvm::debug()) - cvm::log("Updating the restraint bias \""+this->name+"\".\n"); + // Update base class (bias_energy and colvar_forces are zeroed there) + colvarbias::update(); // Force and energy calculation - for (size_t i = 0; i < colvars.size(); i++) { - colvar_forces[i].type(colvars[i]->value()); + for (size_t i = 0; i < num_variables(); i++) { + bias_energy += restraint_potential(i); + colvar_forces[i].type(variables(i)->value()); colvar_forces[i].is_derivative(); colvar_forces[i] = restraint_force(i); - bias_energy += restraint_potential(i); } if (cvm::debug()) @@ -59,8 +57,6 @@ int colvarbias_restraint::update() colvarbias_restraint::~colvarbias_restraint() { - if (cvm::n_rest_biases > 0) - cvm::n_rest_biases -= 1; } @@ -102,18 +98,18 @@ int colvarbias_restraint_centers::init(std::string const &conf) bool null_centers = (colvar_centers.size() == 0); if (null_centers) { // try to initialize the restraint centers for the first time - colvar_centers.resize(colvars.size()); - colvar_centers_raw.resize(colvars.size()); - for (i = 0; i < colvars.size(); i++) { - colvar_centers[i].type(colvars[i]->value()); + colvar_centers.resize(num_variables()); + colvar_centers_raw.resize(num_variables()); + for (i = 0; i < num_variables(); i++) { + colvar_centers[i].type(variables(i)->value()); colvar_centers[i].reset(); - colvar_centers_raw[i].type(colvars[i]->value()); + colvar_centers_raw[i].type(variables(i)->value()); colvar_centers_raw[i].reset(); } } if (get_keyval(conf, "centers", colvar_centers, colvar_centers)) { - for (i = 0; i < colvars.size(); i++) { + for (i = 0; i < num_variables(); i++) { if (cvm::debug()) { cvm::log("colvarbias_restraint: parsing initial centers, i = "+cvm::to_str(i)+".\n"); } @@ -129,7 +125,7 @@ int colvarbias_restraint_centers::init(std::string const &conf) return INPUT_ERROR; } - if (colvar_centers.size() != colvars.size()) { + if (colvar_centers.size() != num_variables()) { cvm::error("Error: number of centers does not match " "that of collective variables.\n", INPUT_ERROR); return INPUT_ERROR; @@ -142,10 +138,10 @@ int colvarbias_restraint_centers::init(std::string const &conf) int colvarbias_restraint_centers::change_configuration(std::string const &conf) { if (get_keyval(conf, "centers", colvar_centers, colvar_centers)) { - for (size_t i = 0; i < colvars.size(); i++) { - colvar_centers[i].type(colvars[i]->value()); + for (size_t i = 0; i < num_variables(); i++) { + colvar_centers[i].type(variables(i)->value()); colvar_centers[i].apply_constraints(); - colvar_centers_raw[i].type(colvars[i]->value()); + colvar_centers_raw[i].type(variables(i)->value()); colvar_centers_raw[i] = colvar_centers[i]; } } @@ -269,7 +265,7 @@ int colvarbias_restraint_centers_moving::init(std::string const &conf) size_t i; if (get_keyval(conf, "targetCenters", target_centers, colvar_centers)) { - if (colvar_centers.size() != colvars.size()) { + if (colvar_centers.size() != num_variables()) { cvm::error("Error: number of target centers does not match " "that of collective variables.\n"); } @@ -308,9 +304,9 @@ int colvarbias_restraint_centers_moving::update() // at each simulation step (or stage, if applicable) // (take current stage into account: it can be non-zero // if we are restarting a staged calculation) - centers_incr.resize(colvars.size()); - for (size_t i = 0; i < colvars.size(); i++) { - centers_incr[i].type(colvars[i]->value()); + centers_incr.resize(num_variables()); + for (size_t i = 0; i < num_variables(); i++) { + centers_incr[i].type(variables(i)->value()); centers_incr[i] = (target_centers[i] - colvar_centers_raw[i]) / cvm::real( target_nstages ? (target_nstages - stage) : (target_nsteps - cvm::step_absolute())); @@ -326,10 +322,10 @@ int colvarbias_restraint_centers_moving::update() && (cvm::step_absolute() % target_nsteps) == 0 && stage < target_nstages) { - for (size_t i = 0; i < colvars.size(); i++) { + for (size_t i = 0; i < num_variables(); i++) { colvar_centers_raw[i] += centers_incr[i]; colvar_centers[i] = colvar_centers_raw[i]; - colvars[i]->wrap(colvar_centers[i]); + variables(i)->wrap(colvar_centers[i]); colvar_centers[i].apply_constraints(); } stage++; @@ -341,10 +337,10 @@ int colvarbias_restraint_centers_moving::update() } else if ((cvm::step_relative() > 0) && (cvm::step_absolute() <= target_nsteps)) { // move the restraint centers in the direction of the targets // (slow growth) - for (size_t i = 0; i < colvars.size(); i++) { + for (size_t i = 0; i < num_variables(); i++) { colvar_centers_raw[i] += centers_incr[i]; colvar_centers[i] = colvar_centers_raw[i]; - colvars[i]->wrap(colvar_centers[i]); + variables(i)->wrap(colvar_centers[i]); colvar_centers[i].apply_constraints(); } } @@ -363,7 +359,7 @@ int colvarbias_restraint_centers_moving::update_acc_work() { if (b_output_acc_work) { if ((cvm::step_relative() > 0) || (cvm::step_absolute() == 0)) { - for (size_t i = 0; i < colvars.size(); i++) { + for (size_t i = 0; i < num_variables(); i++) { // project forces on the calculated increments at this step acc_work += colvar_forces[i] * centers_incr[i]; } @@ -381,14 +377,14 @@ std::string const colvarbias_restraint_centers_moving::get_state_params() const if (b_chg_centers) { size_t i; os << "centers "; - for (i = 0; i < colvars.size(); i++) { + for (i = 0; i < num_variables(); i++) { os << " " << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width) << colvar_centers[i]; } os << "\n"; os << "centers_raw "; - for (i = 0; i < colvars.size(); i++) { + for (i = 0; i < num_variables(); i++) { os << " " << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width) << colvar_centers_raw[i]; @@ -429,10 +425,10 @@ int colvarbias_restraint_centers_moving::set_state_params(std::string const &con std::ostream & colvarbias_restraint_centers_moving::write_traj_label(std::ostream &os) { if (b_output_centers) { - for (size_t i = 0; i < colvars.size(); i++) { - size_t const this_cv_width = (colvars[i]->value()).output_width(cvm::cv_width); + for (size_t i = 0; i < num_variables(); i++) { + size_t const this_cv_width = (variables(i)->value()).output_width(cvm::cv_width); os << " x0_" - << cvm::wrap_string(colvars[i]->name, this_cv_width-3); + << cvm::wrap_string(variables(i)->name, this_cv_width-3); } } @@ -448,7 +444,7 @@ std::ostream & colvarbias_restraint_centers_moving::write_traj_label(std::ostrea std::ostream & colvarbias_restraint_centers_moving::write_traj(std::ostream &os) { if (b_output_centers) { - for (size_t i = 0; i < colvars.size(); i++) { + for (size_t i = 0; i < num_variables(); i++) { os << " " << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width) << colvar_centers[i]; @@ -539,9 +535,9 @@ int colvarbias_restraint_k_moving::update() } force_k = starting_force_k + (target_force_k - starting_force_k) * std::pow(lambda, force_k_exp); - cvm::log("Restraint " + this->name + ", stage " + - cvm::to_str(stage) + " : lambda = " + cvm::to_str(lambda)); - cvm::log("Setting force constant to " + cvm::to_str(force_k)); + cvm::log("Restraint " + this->name + ", stage " + cvm::to_str(stage) + + " : lambda = " + cvm::to_str(lambda) + + ", k = " + cvm::to_str(force_k)); } // TI calculation: estimate free energy derivative @@ -557,7 +553,7 @@ int colvarbias_restraint_k_moving::update() // Square distance normalized by square colvar width cvm::real dist_sq = 0.0; - for (size_t i = 0; i < colvars.size(); i++) { + for (size_t i = 0; i < num_variables(); i++) { dist_sq += d_restraint_potential_dk(i); } @@ -569,7 +565,8 @@ int colvarbias_restraint_k_moving::update() if (cvm::step_absolute() % target_nsteps == 0 && cvm::step_absolute() > 0) { - cvm::log("Lambda= " + cvm::to_str(lambda) + " dA/dLambda= " + cvm::log("Restraint " + this->name + " Lambda= " + + cvm::to_str(lambda) + " dA/dLambda= " + cvm::to_str(restraint_FE / cvm::real(target_nsteps - target_equil_steps))); // ...and move on to the next one @@ -584,9 +581,9 @@ int colvarbias_restraint_k_moving::update() } force_k = starting_force_k + (target_force_k - starting_force_k) * std::pow(lambda, force_k_exp); - cvm::log("Restraint " + this->name + ", stage " + - cvm::to_str(stage) + " : lambda = " + cvm::to_str(lambda)); - cvm::log("Setting force constant to " + cvm::to_str(force_k)); + cvm::log("Restraint " + this->name + ", stage " + cvm::to_str(stage) + + " : lambda = " + cvm::to_str(lambda) + + ", k = " + cvm::to_str(force_k)); } } @@ -721,11 +718,11 @@ int colvarbias_restraint_harmonic::init(std::string const &conf) colvarbias_restraint_centers_moving::init(conf); colvarbias_restraint_k_moving::init(conf); - for (size_t i = 0; i < colvars.size(); i++) { - if (colvars[i]->width != 1.0) - cvm::log("The force constant for colvar \""+colvars[i]->name+ + for (size_t i = 0; i < num_variables(); i++) { + if (variables(i)->width != 1.0) + cvm::log("The force constant for colvar \""+variables(i)->name+ "\" will be rescaled to "+ - cvm::to_str(force_k / (colvars[i]->width * colvars[i]->width))+ + cvm::to_str(force_k / (variables(i)->width * variables(i)->width))+ " according to the specified width.\n"); } @@ -751,22 +748,22 @@ int colvarbias_restraint_harmonic::update() cvm::real colvarbias_restraint_harmonic::restraint_potential(size_t i) const { - return 0.5 * force_k / (colvars[i]->width * colvars[i]->width) * - colvars[i]->dist2(colvars[i]->value(), colvar_centers[i]); + return 0.5 * force_k / (variables(i)->width * variables(i)->width) * + variables(i)->dist2(variables(i)->value(), colvar_centers[i]); } colvarvalue const colvarbias_restraint_harmonic::restraint_force(size_t i) const { - return -0.5 * force_k / (colvars[i]->width * colvars[i]->width) * - colvars[i]->dist2_lgrad(colvars[i]->value(), colvar_centers[i]); + return -0.5 * force_k / (variables(i)->width * variables(i)->width) * + variables(i)->dist2_lgrad(variables(i)->value(), colvar_centers[i]); } cvm::real colvarbias_restraint_harmonic::d_restraint_potential_dk(size_t i) const { - return 0.5 / (colvars[i]->width * colvars[i]->width) * - colvars[i]->dist2(colvars[i]->value(), colvar_centers[i]); + return 0.5 / (variables(i)->width * variables(i)->width) * + variables(i)->dist2(variables(i)->value(), colvar_centers[i]); } @@ -840,6 +837,8 @@ colvarbias_restraint_harmonic_walls::colvarbias_restraint_harmonic_walls(char co colvarbias_restraint_moving(key), colvarbias_restraint_k_moving(key) { + lower_wall_k = 0.0; + upper_wall_k = 0.0; } @@ -849,7 +848,11 @@ int colvarbias_restraint_harmonic_walls::init(std::string const &conf) colvarbias_restraint_moving::init(conf); colvarbias_restraint_k_moving::init(conf); - provide(f_cvb_scalar_variables); + get_keyval(conf, "lowerWallConstant", lower_wall_k, + (lower_wall_k > 0.0) ? lower_wall_k : force_k); + get_keyval(conf, "upperWallConstant", upper_wall_k, + (upper_wall_k > 0.0) ? upper_wall_k : force_k); + enable(f_cvb_scalar_variables); size_t i; @@ -857,9 +860,9 @@ int colvarbias_restraint_harmonic_walls::init(std::string const &conf) bool b_null_lower_walls = false; if (lower_walls.size() == 0) { b_null_lower_walls = true; - lower_walls.resize(number_of_colvars()); - for (i = 0; i < colvars.size(); i++) { - lower_walls[i].type(colvars[i]->value()); + lower_walls.resize(num_variables()); + for (i = 0; i < num_variables(); i++) { + lower_walls[i].type(variables(i)->value()); lower_walls[i].reset(); } } @@ -872,9 +875,9 @@ int colvarbias_restraint_harmonic_walls::init(std::string const &conf) bool b_null_upper_walls = false; if (upper_walls.size() == 0) { b_null_upper_walls = true; - upper_walls.resize(number_of_colvars()); - for (i = 0; i < colvars.size(); i++) { - upper_walls[i].type(colvars[i]->value()); + upper_walls.resize(num_variables()); + for (i = 0; i < num_variables(); i++) { + upper_walls[i].type(variables(i)->value()); upper_walls[i].reset(); } } @@ -890,17 +893,17 @@ int colvarbias_restraint_harmonic_walls::init(std::string const &conf) } if ((lower_walls.size() == 0) || (upper_walls.size() == 0)) { - for (i = 0; i < colvars.size(); i++) { - if (colvars[i]->is_enabled(f_cv_periodic)) { + for (i = 0; i < num_variables(); i++) { + if (variables(i)->is_enabled(f_cv_periodic)) { cvm::error("Error: at least one variable is periodic, " - "both walls must be provided .\n", INPUT_ERROR); + "both walls must be provided.\n", INPUT_ERROR); return INPUT_ERROR; } } } if ((lower_walls.size() > 0) && (upper_walls.size() > 0)) { - for (i = 0; i < colvars.size(); i++) { + for (i = 0; i < num_variables(); i++) { if (lower_walls[i] >= upper_walls[i]) { cvm::error("Error: one upper wall, "+ cvm::to_str(upper_walls[i])+ @@ -909,13 +912,24 @@ int colvarbias_restraint_harmonic_walls::init(std::string const &conf) INPUT_ERROR); } } + if (lower_wall_k * upper_wall_k == 0.0) { + cvm::error("Error: lowerWallConstant and upperWallConstant, " + "when defined, must both be positive.\n", + INPUT_ERROR); + return INPUT_ERROR; + } + force_k = lower_wall_k * upper_wall_k; + // transform the two constants to relative values + // (allow changing both via force_k) + lower_wall_k /= force_k; + upper_wall_k /= force_k; } - for (i = 0; i < colvars.size(); i++) { - if (colvars[i]->width != 1.0) - cvm::log("The force constant for colvar \""+colvars[i]->name+ + for (i = 0; i < num_variables(); i++) { + if (variables(i)->width != 1.0) + cvm::log("The force constant for colvar \""+variables(i)->name+ "\" will be rescaled to "+ - cvm::to_str(force_k / (colvars[i]->width * colvars[i]->width))+ + cvm::to_str(force_k / (variables(i)->width * variables(i)->width))+ " according to the specified width.\n"); } @@ -935,20 +949,20 @@ int colvarbias_restraint_harmonic_walls::update() void colvarbias_restraint_harmonic_walls::communicate_forces() { - for (size_t i = 0; i < colvars.size(); i++) { + for (size_t i = 0; i < num_variables(); i++) { if (cvm::debug()) { cvm::log("Communicating a force to colvar \""+ - colvars[i]->name+"\".\n"); + variables(i)->name+"\".\n"); } - colvars[i]->add_bias_force_actual_value(colvar_forces[i]); + variables(i)->add_bias_force_actual_value(colvar_forces[i]); } } cvm::real colvarbias_restraint_harmonic_walls::colvar_distance(size_t i) const { - colvar *cv = colvars[i]; - colvarvalue const &cvv = colvars[i]->actual_value(); + colvar *cv = variables(i); + colvarvalue const &cvv = variables(i)->actual_value(); // For a periodic colvar, both walls may be applicable at the same time // in which case we pick the closer one @@ -958,21 +972,21 @@ cvm::real colvarbias_restraint_harmonic_walls::colvar_distance(size_t i) const cvm::real const upper_wall_dist2 = cv->dist2(cvv, upper_walls[i]); if (lower_wall_dist2 < upper_wall_dist2) { cvm::real const grad = cv->dist2_lgrad(cvv, lower_walls[i]); - if (grad < 0.0) { return grad; } + if (grad < 0.0) { return 0.5 * grad; } } else { cvm::real const grad = cv->dist2_lgrad(cvv, upper_walls[i]); - if (grad > 0.0) { return grad; } + if (grad > 0.0) { return 0.5 * grad; } } return 0.0; } if (lower_walls.size() > 0) { cvm::real const grad = cv->dist2_lgrad(cvv, lower_walls[i]); - if (grad < 0.0) { return grad; } + if (grad < 0.0) { return 0.5 * grad; } } if (upper_walls.size() > 0) { cvm::real const grad = cv->dist2_lgrad(cvv, upper_walls[i]); - if (grad > 0.0) { return grad; } + if (grad > 0.0) { return 0.5 * grad; } } return 0.0; } @@ -981,7 +995,8 @@ cvm::real colvarbias_restraint_harmonic_walls::colvar_distance(size_t i) const cvm::real colvarbias_restraint_harmonic_walls::restraint_potential(size_t i) const { cvm::real const dist = colvar_distance(i); - return 0.5 * force_k / (colvars[i]->width * colvars[i]->width) * + cvm::real const scale = dist > 0.0 ? upper_wall_k : lower_wall_k; + return 0.5 * force_k * scale / (variables(i)->width * variables(i)->width) * dist * dist; } @@ -989,15 +1004,16 @@ cvm::real colvarbias_restraint_harmonic_walls::restraint_potential(size_t i) con colvarvalue const colvarbias_restraint_harmonic_walls::restraint_force(size_t i) const { cvm::real const dist = colvar_distance(i); - return -0.5 * force_k / (colvars[i]->width * colvars[i]->width) * - dist; + cvm::real const scale = dist > 0.0 ? upper_wall_k : lower_wall_k; + return - force_k * scale / (variables(i)->width * variables(i)->width) * dist; } cvm::real colvarbias_restraint_harmonic_walls::d_restraint_potential_dk(size_t i) const { cvm::real const dist = colvar_distance(i); - return 0.5 / (colvars[i]->width * colvars[i]->width) * + cvm::real const scale = dist > 0.0 ? upper_wall_k : lower_wall_k; + return 0.5 * scale / (variables(i)->width * variables(i)->width) * dist * dist; } @@ -1054,16 +1070,16 @@ int colvarbias_restraint_linear::init(std::string const &conf) colvarbias_restraint_centers_moving::init(conf); colvarbias_restraint_k_moving::init(conf); - for (size_t i = 0; i < colvars.size(); i++) { - if (colvars[i]->is_enabled(f_cv_periodic)) { + for (size_t i = 0; i < num_variables(); i++) { + if (variables(i)->is_enabled(f_cv_periodic)) { cvm::error("Error: linear biases cannot be applied to periodic variables.\n", INPUT_ERROR); return INPUT_ERROR; } - if (colvars[i]->width != 1.0) - cvm::log("The force constant for colvar \""+colvars[i]->name+ + if (variables(i)->width != 1.0) + cvm::log("The force constant for colvar \""+variables(i)->name+ "\" will be rescaled to "+ - cvm::to_str(force_k / colvars[i]->width)+ + cvm::to_str(force_k / variables(i)->width)+ " according to the specified width.\n"); } @@ -1113,19 +1129,19 @@ cvm::real colvarbias_restraint_linear::energy_difference(std::string const &conf cvm::real colvarbias_restraint_linear::restraint_potential(size_t i) const { - return force_k / colvars[i]->width * (colvars[i]->value() - colvar_centers[i]); + return force_k / variables(i)->width * (variables(i)->value() - colvar_centers[i]); } colvarvalue const colvarbias_restraint_linear::restraint_force(size_t i) const { - return -1.0 * force_k / colvars[i]->width; + return -1.0 * force_k / variables(i)->width; } cvm::real colvarbias_restraint_linear::d_restraint_potential_dk(size_t i) const { - return 1.0 / colvars[i]->width * (colvars[i]->value() - colvar_centers[i]); + return 1.0 / variables(i)->width * (variables(i)->value() - colvar_centers[i]); } @@ -1279,16 +1295,16 @@ int colvarbias_restraint_histogram::update() size_t vector_size = 0; size_t icv; - for (icv = 0; icv < colvars.size(); icv++) { - vector_size += colvars[icv]->value().size(); + for (icv = 0; icv < num_variables(); icv++) { + vector_size += variables(icv)->value().size(); } cvm::real const norm = 1.0/(std::sqrt(2.0*PI)*gaussian_width*vector_size); // calculate the histogram p.reset(); - for (icv = 0; icv < colvars.size(); icv++) { - colvarvalue const &cv = colvars[icv]->value(); + for (icv = 0; icv < num_variables(); icv++) { + colvarvalue const &cv = variables(icv)->value(); if (cv.type() == colvarvalue::type_scalar) { cvm::real const cv_value = cv.real_value; size_t igrid; @@ -1309,7 +1325,9 @@ int colvarbias_restraint_histogram::update() } } } else { - // TODO + cvm::error("Error: unsupported type for variable "+variables(icv)->name+".\n", + COLVARS_NOT_IMPLEMENTED); + return COLVARS_NOT_IMPLEMENTED; } } @@ -1320,8 +1338,8 @@ int colvarbias_restraint_histogram::update() bias_energy = 0.5 * force_k_cv * p_diff * p_diff; // calculate the forces - for (icv = 0; icv < colvars.size(); icv++) { - colvarvalue const &cv = colvars[icv]->value(); + for (icv = 0; icv < num_variables(); icv++) { + colvarvalue const &cv = variables(icv)->value(); colvarvalue &cv_force = colvar_forces[icv]; cv_force.type(cv); cv_force.reset(); @@ -1363,10 +1381,10 @@ int colvarbias_restraint_histogram::update() std::ostream & colvarbias_restraint_histogram::write_restart(std::ostream &os) { if (b_write_histogram) { - std::string file_name(cvm::output_prefix+"."+this->name+".hist.dat"); + std::string file_name(cvm::output_prefix()+"."+this->name+".hist.dat"); std::ofstream os(file_name.c_str()); - os << "# " << cvm::wrap_string(colvars[0]->name, cvm::cv_width) - << " " << "p(" << cvm::wrap_string(colvars[0]->name, cvm::cv_width-3) + os << "# " << cvm::wrap_string(variables(0)->name, cvm::cv_width) + << " " << "p(" << cvm::wrap_string(variables(0)->name, cvm::cv_width-3) << ")\n"; size_t igrid; for (igrid = 0; igrid < p.size(); igrid++) { diff --git a/lib/colvars/colvarbias_restraint.h b/lib/colvars/colvarbias_restraint.h index cbdd9c44d1..98b967abdb 100644 --- a/lib/colvars/colvarbias_restraint.h +++ b/lib/colvars/colvarbias_restraint.h @@ -260,6 +260,12 @@ protected: /// \brief Location of the upper walls std::vector upper_walls; + /// \brief If both walls are defined, use this k for the lower + cvm::real lower_wall_k; + + /// \brief If both walls are defined, use this k for the upper + cvm::real upper_wall_k; + virtual cvm::real colvar_distance(size_t i) const; virtual cvm::real restraint_potential(size_t i) const; virtual colvarvalue const restraint_force(size_t i) const; diff --git a/lib/colvars/colvarcomp.cpp b/lib/colvars/colvarcomp.cpp index d99da56386..786bc032d2 100644 --- a/lib/colvars/colvarcomp.cpp +++ b/lib/colvars/colvarcomp.cpp @@ -48,8 +48,6 @@ colvar::cvc::cvc(std::string const &conf) get_keyval(conf, "period", period, 0.0); get_keyval(conf, "wrapAround", wrap_center, 0.0); - // All cvcs implement this - provide(f_cvc_debug_gradient); get_keyval_feature((colvarparse *)this, conf, "debugGradients", f_cvc_debug_gradient, false, parse_silent); @@ -63,6 +61,8 @@ colvar::cvc::cvc(std::string const &conf) int colvar::cvc::init_total_force_params(std::string const &conf) { + if (cvm::get_error()) return COLVARS_ERROR; + if (get_keyval_feature(this, conf, "oneSiteSystemForce", f_cvc_one_site_total_force, is_enabled(f_cvc_one_site_total_force))) { cvm::log("Warning: keyword \"oneSiteSystemForce\" is deprecated: " @@ -72,6 +72,19 @@ int colvar::cvc::init_total_force_params(std::string const &conf) f_cvc_one_site_total_force, is_enabled(f_cvc_one_site_total_force))) { cvm::log("Computing total force on group 1 only"); } + + if (! is_enabled(f_cvc_one_site_total_force)) { + // check whether any of the other atom groups is dummy + std::vector::iterator agi = atom_groups.begin(); + agi++; + for ( ; agi != atom_groups.end(); agi++) { + if ((*agi)->b_dummy) { + provide(f_cvc_inv_gradient, false); + provide(f_cvc_Jacobian, false); + } + } + } + return COLVARS_OK; } @@ -87,8 +100,7 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf, group->key = group_key; if (b_try_scalable) { - // TODO rewrite this logic in terms of dependencies - if (is_available(f_cvc_scalable_com) && is_available(f_cvc_com_based)) { + if (is_available(f_cvc_scalable_com) && is_enabled(f_cvc_com_based)) { enable(f_cvc_scalable_com); enable(f_cvc_scalable); // The CVC makes the feature available; diff --git a/lib/colvars/colvarcomp.h b/lib/colvars/colvarcomp.h index a230cae8a9..ec215cbad1 100644 --- a/lib/colvars/colvarcomp.h +++ b/lib/colvars/colvarcomp.h @@ -343,6 +343,15 @@ public: virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); + /// Redefined to override the distance ones + virtual cvm::real dist2(colvarvalue const &x1, + colvarvalue const &x2) const; + /// Redefined to override the distance ones + virtual colvarvalue dist2_lgrad(colvarvalue const &x1, + colvarvalue const &x2) const; + /// Redefined to override the distance ones + virtual colvarvalue dist2_rgrad(colvarvalue const &x1, + colvarvalue const &x2) const; }; diff --git a/lib/colvars/colvarcomp_angles.cpp b/lib/colvars/colvarcomp_angles.cpp index 4c3390a8bd..0204f3b4b1 100644 --- a/lib/colvars/colvarcomp_angles.cpp +++ b/lib/colvars/colvarcomp_angles.cpp @@ -21,7 +21,7 @@ colvar::angle::angle(std::string const &conf) function_type = "angle"; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); - provide(f_cvc_com_based); + enable(f_cvc_com_based); group1 = parse_group(conf, "group1"); group2 = parse_group(conf, "group2"); @@ -40,7 +40,7 @@ colvar::angle::angle(cvm::atom const &a1, function_type = "angle"; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); - provide(f_cvc_com_based); + enable(f_cvc_com_based); group1 = new cvm::atom_group(std::vector(1, a1)); group2 = new cvm::atom_group(std::vector(1, a2)); @@ -259,7 +259,7 @@ colvar::dihedral::dihedral(std::string const &conf) b_periodic = true; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); - provide(f_cvc_com_based); + enable(f_cvc_com_based); group1 = parse_group(conf, "group1"); group2 = parse_group(conf, "group2"); @@ -285,7 +285,7 @@ colvar::dihedral::dihedral(cvm::atom const &a1, b_periodic = true; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); - provide(f_cvc_com_based); + enable(f_cvc_com_based); b_1site_force = false; diff --git a/lib/colvars/colvarcomp_distances.cpp b/lib/colvars/colvarcomp_distances.cpp index 7481dd360b..f46270246f 100644 --- a/lib/colvars/colvarcomp_distances.cpp +++ b/lib/colvars/colvarcomp_distances.cpp @@ -23,7 +23,7 @@ colvar::distance::distance(std::string const &conf) function_type = "distance"; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); - provide(f_cvc_com_based); + enable(f_cvc_com_based); group1 = parse_group(conf, "group1"); group2 = parse_group(conf, "group2"); @@ -44,7 +44,7 @@ colvar::distance::distance() function_type = "distance"; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); - provide(f_cvc_com_based); + enable(f_cvc_com_based); b_no_PBC = false; x.type(colvarvalue::type_scalar); } @@ -106,7 +106,7 @@ colvar::distance_vec::distance_vec(std::string const &conf) : distance(conf) { function_type = "distance_vec"; - provide(f_cvc_com_based); + enable(f_cvc_com_based); x.type(colvarvalue::type_3vector); } @@ -115,7 +115,7 @@ colvar::distance_vec::distance_vec() : distance() { function_type = "distance_vec"; - provide(f_cvc_com_based); + enable(f_cvc_com_based); x.type(colvarvalue::type_3vector); } @@ -176,7 +176,7 @@ colvar::distance_z::distance_z(std::string const &conf) function_type = "distance_z"; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); - provide(f_cvc_com_based); + enable(f_cvc_com_based); x.type(colvarvalue::type_scalar); // TODO detect PBC from MD engine (in simple cases) @@ -228,7 +228,7 @@ colvar::distance_z::distance_z() function_type = "distance_z"; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); - provide(f_cvc_com_based); + enable(f_cvc_com_based); x.type(colvarvalue::type_scalar); } @@ -372,7 +372,7 @@ colvar::distance_xy::distance_xy(std::string const &conf) function_type = "distance_xy"; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); - provide(f_cvc_com_based); + enable(f_cvc_com_based); x.type(colvarvalue::type_scalar); } @@ -383,7 +383,7 @@ colvar::distance_xy::distance_xy() function_type = "distance_xy"; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); - provide(f_cvc_com_based); + enable(f_cvc_com_based); x.type(colvarvalue::type_scalar); } @@ -479,7 +479,7 @@ colvar::distance_dir::distance_dir(std::string const &conf) : distance(conf) { function_type = "distance_dir"; - provide(f_cvc_com_based); + enable(f_cvc_com_based); x.type(colvarvalue::type_unit3vector); } @@ -488,7 +488,7 @@ colvar::distance_dir::distance_dir() : distance() { function_type = "distance_dir"; - provide(f_cvc_com_based); + enable(f_cvc_com_based); x.type(colvarvalue::type_unit3vector); } @@ -529,6 +529,27 @@ void colvar::distance_dir::apply_force(colvarvalue const &force) } +cvm::real colvar::distance_dir::dist2(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return (x1.rvector_value - x2.rvector_value).norm2(); +} + + +colvarvalue colvar::distance_dir::dist2_lgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return colvarvalue((x1.rvector_value - x2.rvector_value), colvarvalue::type_unit3vector); +} + + +colvarvalue colvar::distance_dir::dist2_rgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return colvarvalue((x2.rvector_value - x1.rvector_value), colvarvalue::type_unit3vector); +} + + colvar::distance_inv::distance_inv(std::string const &conf) : distance(conf) diff --git a/lib/colvars/colvardeps.cpp b/lib/colvars/colvardeps.cpp index e3ccd4ecf5..8252f77e62 100644 --- a/lib/colvars/colvardeps.cpp +++ b/lib/colvars/colvardeps.cpp @@ -14,9 +14,6 @@ colvardeps::~colvardeps() { size_t i; - for (i=0; iavailable = true; +void colvardeps::provide(int feature_id, bool truefalse) { + feature_states[feature_id].available = truefalse; +} + + +void colvardeps::set_enabled(int feature_id, bool truefalse) { +// if (!is_static(feature_id)) { +// cvm::error("Cannot set feature " + features()[feature_id]->description + " statically in " + description + ".\n"); +// return; +// } + if (truefalse) { + // Resolve dependencies too + enable(feature_id); + } else { + feature_states[feature_id].enabled = false; + } } bool colvardeps::get_keyval_feature(colvarparse *cvp, - std::string const &conf, char const *key, - int feature_id, bool const &def_value, - colvarparse::Parse_Mode const parse_mode) + std::string const &conf, char const *key, + int feature_id, bool const &def_value, + colvarparse::Parse_Mode const parse_mode) { + if (!is_user(feature_id)) { + cvm::error("Cannot set feature " + features()[feature_id]->description + " from user input in " + description + ".\n"); + return false; + } bool value; bool const found = cvp->get_keyval(conf, key, value, def_value, parse_mode); if (value) enable(feature_id); @@ -52,19 +67,19 @@ bool colvardeps::get_keyval_feature(colvarparse *cvp, int colvardeps::enable(int feature_id, - bool dry_run /* default: false */, - // dry_run: fail silently, do not enable if available - // flag is passed recursively to deps of this feature - bool toplevel /* default: true */) - // toplevel: false if this is called as part of a chain of dependency resolution - // this is used to diagnose failed dependencies by displaying the full stack - // only the toplevel dependency will throw a fatal error + bool dry_run /* default: false */, + // dry_run: fail silently, do not enable if available + // flag is passed recursively to deps of this feature + bool toplevel /* default: true */) +// toplevel: false if this is called as part of a chain of dependency resolution +// this is used to diagnose failed dependencies by displaying the full stack +// only the toplevel dependency will throw a fatal error { int res; size_t i, j; bool ok; feature *f = features()[feature_id]; - feature_state *fs = feature_states[feature_id]; + feature_state *fs = &feature_states[feature_id]; if (cvm::debug()) { cvm::log("DEPS: " + description + @@ -88,6 +103,14 @@ int colvardeps::enable(int feature_id, return COLVARS_ERROR; } + if (!toplevel && !is_dynamic(feature_id)) { + if (!dry_run) { + cvm::log("Non-dynamic feature : \"" + f->description + + "\" in " + description + " may not be enabled as a dependency.\n"); + } + return COLVARS_ERROR; + } + // 1) enforce exclusions for (i=0; irequires_exclude.size(); i++) { feature *g = features()[f->requires_exclude[i]]; @@ -168,9 +191,9 @@ int colvardeps::enable(int feature_id, if (res != COLVARS_OK) { if (!dry_run) { cvm::log("...required by \"" + f->description + "\" in " + description); - } - if (toplevel) { - cvm::error("Error: Failed dependency in " + description + "."); + if (toplevel) { + cvm::error("Error: Failed dependency in " + description + "."); + } } return res; } @@ -194,9 +217,12 @@ int colvardeps::enable(int feature_id, // // we need refs to parents to walk up the deps tree! // // or refresh // } +void colvardeps::init_feature(int feature_id, const char *description, feature_type type) { + features()[feature_id]->description = description; + features()[feature_id]->type = type; +} - // Shorthand macros for describing dependencies -#define f_description(f, d) features()[f]->description = d +// Shorthand macros for describing dependencies #define f_req_self(f, g) features()[f]->requires_self.push_back(g) // This macro ensures that exclusions are symmetric #define f_req_exclude(f, g) features()[f]->requires_exclude.push_back(g); \ @@ -216,35 +242,31 @@ void colvardeps::init_cvb_requires() { for (i = 0; i < f_cvb_ntot; i++) { features().push_back(new feature); } + + init_feature(f_cvb_active, "active", f_type_dynamic); + f_req_children(f_cvb_active, f_cv_active); + + init_feature(f_cvb_apply_force, "apply force", f_type_user); + f_req_children(f_cvb_apply_force, f_cv_gradient); + + init_feature(f_cvb_get_total_force, "obtain total force"); + f_req_children(f_cvb_get_total_force, f_cv_total_force); + + init_feature(f_cvb_history_dependent, "history-dependent", f_type_static); + + init_feature(f_cvb_scalar_variables, "require scalar variables", f_type_static); + f_req_children(f_cvb_scalar_variables, f_cv_scalar); + + init_feature(f_cvb_calc_pmf, "calculate a PMF", f_type_static); } - f_description(f_cvb_active, "active"); - f_req_children(f_cvb_active, f_cv_active); - - f_description(f_cvb_apply_force, "apply force"); - f_req_children(f_cvb_apply_force, f_cv_gradient); - - f_description(f_cvb_get_total_force, "obtain total force"); - f_req_children(f_cvb_get_total_force, f_cv_total_force); - - f_description(f_cvb_history_dependent, "history-dependent"); - - f_description(f_cvb_scalar_variables, "require scalar variables"); - f_req_children(f_cvb_scalar_variables, f_cv_scalar); - // Initialize feature_states for each instance feature_states.reserve(f_cvb_ntot); for (i = 0; i < f_cvb_ntot; i++) { - feature_states.push_back(new feature_state(true, false)); + feature_states.push_back(feature_state(true, false)); // Most features are available, so we set them so // and list exceptions below } - - // some biases are not history-dependent - feature_states[f_cvb_history_dependent]->available = false; - - // by default, biases should work with vector variables, too - feature_states[f_cvb_scalar_variables]->available = false; } @@ -255,117 +277,111 @@ void colvardeps::init_cv_requires() { features().push_back(new feature); } - f_description(f_cv_active, "active"); + init_feature(f_cv_active, "active", f_type_dynamic); f_req_children(f_cv_active, f_cvc_active); // Colvars must be either a linear combination, or scalar (and polynomial) or scripted f_req_alt3(f_cv_active, f_cv_scalar, f_cv_linear, f_cv_scripted); - f_description(f_cv_gradient, "gradient"); + init_feature(f_cv_gradient, "gradient", f_type_dynamic); f_req_children(f_cv_gradient, f_cvc_gradient); - f_description(f_cv_collect_gradient, "collect gradient"); + init_feature(f_cv_collect_gradient, "collect gradient", f_type_dynamic); f_req_self(f_cv_collect_gradient, f_cv_gradient); f_req_self(f_cv_collect_gradient, f_cv_scalar); - f_description(f_cv_fdiff_velocity, "fdiff_velocity"); + init_feature(f_cv_fdiff_velocity, "fdiff_velocity", f_type_dynamic); // System force: either trivial (spring force); through extended Lagrangian, or calculated explicitly - f_description(f_cv_total_force, "total force"); + init_feature(f_cv_total_force, "total force", f_type_dynamic); f_req_alt2(f_cv_total_force, f_cv_extended_Lagrangian, f_cv_total_force_calc); // Deps for explicit total force calculation - f_description(f_cv_total_force_calc, "total force calculation"); + init_feature(f_cv_total_force_calc, "total force calculation", f_type_dynamic); f_req_self(f_cv_total_force_calc, f_cv_scalar); f_req_self(f_cv_total_force_calc, f_cv_linear); f_req_children(f_cv_total_force_calc, f_cvc_inv_gradient); f_req_self(f_cv_total_force_calc, f_cv_Jacobian); - f_description(f_cv_Jacobian, "Jacobian derivative"); + init_feature(f_cv_Jacobian, "Jacobian derivative", f_type_dynamic); f_req_self(f_cv_Jacobian, f_cv_scalar); f_req_self(f_cv_Jacobian, f_cv_linear); f_req_children(f_cv_Jacobian, f_cvc_Jacobian); - f_description(f_cv_hide_Jacobian, "hide Jacobian force"); + init_feature(f_cv_hide_Jacobian, "hide Jacobian force", f_type_user); f_req_self(f_cv_hide_Jacobian, f_cv_Jacobian); // can only hide if calculated - f_description(f_cv_extended_Lagrangian, "extended Lagrangian"); + init_feature(f_cv_extended_Lagrangian, "extended Lagrangian", f_type_user); + f_req_self(f_cv_extended_Lagrangian, f_cv_scalar); + f_req_self(f_cv_extended_Lagrangian, f_cv_gradient); - f_description(f_cv_Langevin, "Langevin dynamics"); + init_feature(f_cv_Langevin, "Langevin dynamics", f_type_user); f_req_self(f_cv_Langevin, f_cv_extended_Lagrangian); - f_description(f_cv_linear, "linear"); + init_feature(f_cv_linear, "linear", f_type_static); - f_description(f_cv_scalar, "scalar"); + init_feature(f_cv_scalar, "scalar", f_type_static); - f_description(f_cv_output_energy, "output energy"); + init_feature(f_cv_output_energy, "output energy", f_type_user); - f_description(f_cv_output_value, "output value"); + init_feature(f_cv_output_value, "output value", f_type_user); - f_description(f_cv_output_velocity, "output velocity"); + init_feature(f_cv_output_velocity, "output velocity", f_type_user); f_req_self(f_cv_output_velocity, f_cv_fdiff_velocity); - f_description(f_cv_output_applied_force, "output applied force"); + init_feature(f_cv_output_applied_force, "output applied force", f_type_user); - f_description(f_cv_output_total_force, "output total force"); + init_feature(f_cv_output_total_force, "output total force", f_type_user); f_req_self(f_cv_output_total_force, f_cv_total_force); - f_description(f_cv_subtract_applied_force, "subtract applied force from total force"); + init_feature(f_cv_subtract_applied_force, "subtract applied force from total force", f_type_user); f_req_self(f_cv_subtract_applied_force, f_cv_total_force); - f_description(f_cv_lower_boundary, "lower boundary"); + init_feature(f_cv_lower_boundary, "lower boundary", f_type_user); f_req_self(f_cv_lower_boundary, f_cv_scalar); - f_description(f_cv_upper_boundary, "upper boundary"); + init_feature(f_cv_upper_boundary, "upper boundary", f_type_user); f_req_self(f_cv_upper_boundary, f_cv_scalar); - f_description(f_cv_grid, "grid"); + init_feature(f_cv_grid, "grid", f_type_user); f_req_self(f_cv_grid, f_cv_lower_boundary); f_req_self(f_cv_grid, f_cv_upper_boundary); - f_description(f_cv_lower_wall, "lower wall"); - f_req_self(f_cv_lower_wall, f_cv_lower_boundary); - f_req_self(f_cv_lower_wall, f_cv_gradient); + init_feature(f_cv_runave, "running average", f_type_user); - f_description(f_cv_upper_wall, "upper wall"); - f_req_self(f_cv_upper_wall, f_cv_upper_boundary); - f_req_self(f_cv_upper_wall, f_cv_gradient); + init_feature(f_cv_corrfunc, "correlation function", f_type_user); - f_description(f_cv_runave, "running average"); - - f_description(f_cv_corrfunc, "correlation function"); - - // The features below are set programmatically - f_description(f_cv_scripted, "scripted"); - f_description(f_cv_periodic, "periodic"); + init_feature(f_cv_scripted, "scripted", f_type_static); + init_feature(f_cv_periodic, "periodic", f_type_static); f_req_self(f_cv_periodic, f_cv_homogeneous); - f_description(f_cv_scalar, "scalar"); - f_description(f_cv_linear, "linear"); - f_description(f_cv_homogeneous, "homogeneous"); + init_feature(f_cv_scalar, "scalar", f_type_static); + init_feature(f_cv_linear, "linear", f_type_static); + init_feature(f_cv_homogeneous, "homogeneous", f_type_static); } // Initialize feature_states for each instance feature_states.reserve(f_cv_ntot); for (i = 0; i < f_cv_ntot; i++) { - feature_states.push_back(new feature_state(true, false)); + feature_states.push_back(feature_state(true, false)); // Most features are available, so we set them so // and list exceptions below } - // properties that may NOT be enabled as a dependency - int unavailable_deps[] = { - f_cv_lower_boundary, - f_cv_upper_boundary, - f_cv_extended_Lagrangian, - f_cv_Langevin, - f_cv_scripted, - f_cv_periodic, - f_cv_scalar, - f_cv_linear, - f_cv_homogeneous - }; - for (i = 0; i < sizeof(unavailable_deps) / sizeof(unavailable_deps[0]); i++) { - feature_states[unavailable_deps[i]]->available = false; - } +// // properties that may NOT be enabled as a dependency +// // This will be deprecated by feature types +// int unavailable_deps[] = { +// f_cv_lower_boundary, +// f_cv_upper_boundary, +// f_cv_extended_Lagrangian, +// f_cv_Langevin, +// f_cv_scripted, +// f_cv_periodic, +// f_cv_scalar, +// f_cv_linear, +// f_cv_homogeneous +// }; +// for (i = 0; i < sizeof(unavailable_deps) / sizeof(unavailable_deps[0]); i++) { +// feature_states[unavailable_deps[i]].available = false; +// } } @@ -377,34 +393,34 @@ void colvardeps::init_cvc_requires() { features().push_back(new feature); } - f_description(f_cvc_active, "active"); + init_feature(f_cvc_active, "active", f_type_dynamic); // The dependency below may become useful if we use dynamic atom groups // f_req_children(f_cvc_active, f_ag_active); - f_description(f_cvc_scalar, "scalar"); + init_feature(f_cvc_scalar, "scalar", f_type_static); - f_description(f_cvc_gradient, "gradient"); + init_feature(f_cvc_gradient, "gradient", f_type_dynamic); - f_description(f_cvc_inv_gradient, "inverse gradient"); + init_feature(f_cvc_inv_gradient, "inverse gradient", f_type_dynamic); f_req_self(f_cvc_inv_gradient, f_cvc_gradient); - f_description(f_cvc_debug_gradient, "debug gradient"); + init_feature(f_cvc_debug_gradient, "debug gradient", f_type_user); f_req_self(f_cvc_debug_gradient, f_cvc_gradient); - f_description(f_cvc_Jacobian, "Jacobian derivative"); + init_feature(f_cvc_Jacobian, "Jacobian derivative", f_type_dynamic); f_req_self(f_cvc_Jacobian, f_cvc_inv_gradient); - f_description(f_cvc_com_based, "depends on group centers of mass"); + init_feature(f_cvc_com_based, "depends on group centers of mass", f_type_static); // Compute total force on first site only to avoid unwanted // coupling to other colvars (see e.g. Ciccotti et al., 2005) - f_description(f_cvc_one_site_total_force, "compute total collective force only from one group center"); + init_feature(f_cvc_one_site_total_force, "compute total collective force only from one group center", f_type_user); f_req_self(f_cvc_one_site_total_force, f_cvc_com_based); - f_description(f_cvc_scalable, "scalable calculation"); + init_feature(f_cvc_scalable, "scalable calculation", f_type_static); f_req_self(f_cvc_scalable, f_cvc_scalable_com); - f_description(f_cvc_scalable_com, "scalable calculation of centers of mass"); + init_feature(f_cvc_scalable_com, "scalable calculation of centers of mass", f_type_static); f_req_self(f_cvc_scalable_com, f_cvc_com_based); @@ -414,23 +430,25 @@ void colvardeps::init_cvc_requires() { } // Initialize feature_states for each instance - // default as unavailable, not enabled + // default as available, not enabled + // except dynamic features which default as unavailable feature_states.reserve(f_cvc_ntot); for (i = 0; i < colvardeps::f_cvc_ntot; i++) { - feature_states.push_back(new feature_state(false, false)); + bool avail = is_dynamic(i) ? false : true; + feature_states.push_back(feature_state(avail, false)); } // Features that are implemented by all cvcs by default // Each cvc specifies what other features are available - feature_states[f_cvc_active]->available = true; - feature_states[f_cvc_gradient]->available = true; + feature_states[f_cvc_active].available = true; + feature_states[f_cvc_gradient].available = true; // Features that are implemented by default if their requirements are - feature_states[f_cvc_one_site_total_force]->available = true; + feature_states[f_cvc_one_site_total_force].available = true; // Features That are implemented only for certain simulation engine configurations - feature_states[f_cvc_scalable_com]->available = (cvm::proxy->scalable_group_coms() == COLVARS_OK); - feature_states[f_cvc_scalable]->available = feature_states[f_cvc_scalable_com]->available; + feature_states[f_cvc_scalable_com].available = (cvm::proxy->scalable_group_coms() == COLVARS_OK); + feature_states[f_cvc_scalable].available = feature_states[f_cvc_scalable_com].available; } @@ -442,21 +460,21 @@ void colvardeps::init_ag_requires() { features().push_back(new feature); } - f_description(f_ag_active, "active"); - f_description(f_ag_center, "translational fit"); - f_description(f_ag_rotate, "rotational fit"); - f_description(f_ag_fitting_group, "reference positions group"); - f_description(f_ag_fit_gradient_group, "fit gradient for main group"); - f_description(f_ag_fit_gradient_ref, "fit gradient for reference group"); - f_description(f_ag_atom_forces, "atomic forces"); + init_feature(f_ag_active, "active", f_type_dynamic); + init_feature(f_ag_center, "translational fit", f_type_static); + init_feature(f_ag_rotate, "rotational fit", f_type_static); + init_feature(f_ag_fitting_group, "reference positions group", f_type_static); + init_feature(f_ag_fit_gradient_group, "fit gradient for main group", f_type_static); + init_feature(f_ag_fit_gradient_ref, "fit gradient for reference group", f_type_static); + init_feature(f_ag_atom_forces, "atomic forces", f_type_dynamic); // parallel calculation implies that we have at least a scalable center of mass, // but f_ag_scalable is kept as a separate feature to deal with future dependencies - f_description(f_ag_scalable, "scalable group calculation"); - f_description(f_ag_scalable_com, "scalable group center of mass calculation"); + init_feature(f_ag_scalable, "scalable group calculation", f_type_static); + init_feature(f_ag_scalable_com, "scalable group center of mass calculation", f_type_static); f_req_self(f_ag_scalable, f_ag_scalable_com); -// f_description(f_ag_min_msd_fit, "minimum MSD fit") +// init_feature(f_ag_min_msd_fit, "minimum MSD fit") // f_req_self(f_ag_min_msd_fit, f_ag_center) // f_req_self(f_ag_min_msd_fit, f_ag_rotate) // f_req_exclude(f_ag_min_msd_fit, f_ag_fitting_group) @@ -466,15 +484,15 @@ void colvardeps::init_ag_requires() { // default as unavailable, not enabled feature_states.reserve(f_ag_ntot); for (i = 0; i < colvardeps::f_ag_ntot; i++) { - feature_states.push_back(new feature_state(false, false)); + feature_states.push_back(feature_state(false, false)); } // Features that are implemented (or not) by all atom groups - feature_states[f_ag_active]->available = true; + feature_states[f_ag_active].available = true; // f_ag_scalable_com is provided by the CVC iff it is COM-based - feature_states[f_ag_scalable_com]->available = false; + 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; + feature_states[f_ag_scalable].available = true; } @@ -482,7 +500,7 @@ void colvardeps::print_state() { size_t i; cvm::log("Enabled features of " + description); for (i = 0; i < feature_states.size(); i++) { - if (feature_states[i]->enabled) + if (feature_states[i].enabled) cvm::log("- " + features()[i]->description); } for (i=0; i feature_states; + +private: + /// List of the states of all features + std::vector feature_states; + + /// Enum of possible feature types + enum feature_type { + f_type_not_set, + f_type_dynamic, + f_type_user, + f_type_static + }; + +public: + /// Pair a numerical feature ID with a description and type + void init_feature(int feature_id, const char *description, feature_type type = f_type_not_set); /// Describes a feature and its dependecies /// used in a static array within each subclass @@ -83,8 +91,18 @@ public: // features that this feature requires in children std::vector requires_children; + + inline bool is_dynamic() { return type == f_type_dynamic; } + inline bool is_static() { return type == f_type_static; } + inline bool is_user() { return type == f_type_user; } + /// Type of this feature, from the enum feature_type + feature_type type; }; + inline bool is_dynamic(int id) { return features()[id]->type == f_type_dynamic; } + inline bool is_static(int id) { return features()[id]->type == f_type_static; } + inline bool is_user(int id) { return features()[id]->type == f_type_user; } + // Accessor to array of all features with deps, static in most derived classes // Subclasses with dynamic dependency trees may override this // with a non-static array @@ -100,9 +118,8 @@ public: /// (useful for cvcs because their children are member objects) void remove_all_children(); - - private: + // pointers to objects this object depends on // list should be maintained by any code that modifies the object // this could be secured by making lists of colvars / cvcs / atom groups private and modified through accessor functions @@ -130,16 +147,28 @@ public: // Checks whether given feature is enabled // Defaults to querying f_*_active inline bool is_enabled(int f = f_cv_active) const { - return feature_states[f]->enabled; + return feature_states[f].enabled; } // Checks whether given feature is available // Defaults to querying f_*_active inline bool is_available(int f = f_cv_active) const { - return feature_states[f]->available; + return feature_states[f].available; } - void provide(int feature_id); // set the feature's flag to available in local object + /// Set the feature's available flag, without checking + /// To be used for dynamic properties + /// dependencies will be checked by enable() + void provide(int feature_id, bool truefalse = true); + + /// Set the feature's enabled flag, without dependency check or resolution + /// To be used for static properties only + /// Checking for availability is up to the caller + void set_enabled(int feature_id, bool truefalse = true); + +protected: + + /// Parse a keyword and enable a feature accordingly bool get_keyval_feature(colvarparse *cvp, @@ -147,6 +176,8 @@ public: int feature_id, bool const &def_value, colvarparse::Parse_Mode const parse_mode = colvarparse::parse_normal); +public: + int enable(int f, bool dry_run = false, bool toplevel = true); // enable a feature and recursively solve its dependencies // dry_run is set to true to recursively test if a feature is available, without enabling it // int disable(int f); @@ -165,6 +196,7 @@ public: f_cvb_get_total_force, // requires total forces f_cvb_history_dependent, // depends on simulation history f_cvb_scalar_variables, // requires scalar colvars + f_cvb_calc_pmf, // whether this bias will compute a PMF f_cvb_ntot }; @@ -216,12 +248,6 @@ public: /// be used by the biases or in analysis (needs lower and upper /// boundary) f_cv_grid, - /// \brief Apply a restraining potential (|x-xb|^2) to the colvar - /// when it goes below the lower wall - f_cv_lower_wall, - /// \brief Apply a restraining potential (|x-xb|^2) to the colvar - /// when it goes above the upper wall - f_cv_upper_wall, /// \brief Compute running average f_cv_runave, /// \brief Compute time correlation function diff --git a/lib/colvars/colvarmodule.cpp b/lib/colvars/colvarmodule.cpp index b9a435152b..10cd3c0e47 100644 --- a/lib/colvars/colvarmodule.cpp +++ b/lib/colvars/colvarmodule.cpp @@ -36,6 +36,9 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in) "variable module twice.\n"); return; } + + depth_s = 0; + cvm::log(cvm::line_marker); cvm::log("Initializing the collective variables module, version "+ cvm::to_str(COLVARS_VERSION)+".\n"); @@ -71,6 +74,48 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in) } +colvarmodule * colvarmodule::main() +{ + return proxy->colvars; +} + + +std::vector *colvarmodule::variables() +{ + return &colvars; +} + + +std::vector *colvarmodule::variables_active() +{ + return &colvars_active; +} + + +std::vector *colvarmodule::variables_active_smp() +{ + return &colvars_smp; +} + + +std::vector *colvarmodule::variables_active_smp_items() +{ + return &colvars_smp_items; +} + + +std::vector *colvarmodule::biases_active() +{ + return &(biases_active_); +} + + +size_t colvarmodule::size() const +{ + return colvars.size() + biases.size(); +} + + int colvarmodule::read_config_file(char const *config_filename) { cvm::log(cvm::line_marker); @@ -118,8 +163,29 @@ int colvarmodule::read_config_string(std::string const &config_str) } +std::istream & colvarmodule::getline(std::istream &is, std::string &line) +{ + std::string l; + if (std::getline(is, l)) { + size_t const sz = l.size(); + if (sz > 0) { + if (l[sz-1] == '\r' ) { + line = l.substr(0, sz-1); + } else { + line = l; + } + } else { + line.clear(); + } + } + return is; +} + + int colvarmodule::parse_config(std::string &conf) { + extra_conf.clear(); + // parse global options if (catch_input_errors(parse_global_params(conf))) { return get_error(); @@ -140,6 +206,15 @@ int colvarmodule::parse_config(std::string &conf) return get_error(); } + if (extra_conf.size()) { + catch_input_errors(parse_global_params(extra_conf)); + catch_input_errors(parse_colvars(extra_conf)); + catch_input_errors(parse_biases(extra_conf)); + parse->check_keywords(extra_conf, "colvarmodule"); + extra_conf.clear(); + if (get_error() != COLVARS_OK) return get_error(); + } + cvm::log(cvm::line_marker); cvm::log("Collective variables module (re)initialized.\n"); cvm::log(cvm::line_marker); @@ -156,11 +231,20 @@ int colvarmodule::parse_config(std::string &conf) } +int colvarmodule::append_new_config(std::string const &new_conf) +{ + extra_conf += new_conf; + return COLVARS_OK; +} + + int colvarmodule::parse_global_params(std::string const &conf) { + colvarmodule *cvm = cvm::main(); + std::string index_file_name; if (parse->get_keyval(conf, "indexFile", index_file_name)) { - read_index_file(index_file_name.c_str()); + cvm->read_index_file(index_file_name.c_str()); } if (parse->get_keyval(conf, "smp", proxy->b_smp_active, proxy->b_smp_active)) { @@ -216,8 +300,8 @@ int colvarmodule::parse_colvars(std::string const &conf) if (colvar_conf.size()) { cvm::log(cvm::line_marker); cvm::increase_depth(); - colvars.push_back(new colvar(colvar_conf)); - if (cvm::get_error() || + colvars.push_back(new colvar()); + if (((colvars.back())->init(colvar_conf) != COLVARS_OK) || ((colvars.back())->check_keywords(colvar_conf, "colvar") != COLVARS_OK)) { cvm::log("Error while constructing colvar number " + cvm::to_str(colvars.size()) + " : deleting."); @@ -262,8 +346,7 @@ bool colvarmodule::check_new_bias(std::string &conf, char const *key) template int colvarmodule::parse_biases_type(std::string const &conf, - char const *keyword, - size_t &bias_count) + char const *keyword) { std::string bias_conf = ""; size_t conf_saved_pos = 0; @@ -277,7 +360,6 @@ int colvarmodule::parse_biases_type(std::string const &conf, return COLVARS_ERROR; } cvm::decrease_depth(); - bias_count++; } else { cvm::error("Error: keyword \""+std::string(keyword)+"\" found without configuration.\n", INPUT_ERROR); @@ -295,28 +377,28 @@ int colvarmodule::parse_biases(std::string const &conf) cvm::log("Initializing the collective variables biases.\n"); /// initialize ABF instances - parse_biases_type(conf, "abf", n_abf_biases); + parse_biases_type(conf, "abf"); /// initialize adaptive linear biases - parse_biases_type(conf, "ALB", n_rest_biases); + parse_biases_type(conf, "ALB"); /// initialize harmonic restraints - parse_biases_type(conf, "harmonic", n_rest_biases); + parse_biases_type(conf, "harmonic"); /// initialize harmonic walls restraints - parse_biases_type(conf, "harmonicWalls", n_rest_biases); + parse_biases_type(conf, "harmonicWalls"); /// initialize histograms - parse_biases_type(conf, "histogram", n_histo_biases); + parse_biases_type(conf, "histogram"); /// initialize histogram restraints - parse_biases_type(conf, "histogramRestraint", n_rest_biases); + parse_biases_type(conf, "histogramRestraint"); /// initialize linear restraints - parse_biases_type(conf, "linear", n_rest_biases); + parse_biases_type(conf, "linear"); /// initialize metadynamics instances - parse_biases_type(conf, "metadynamics", n_meta_biases); + parse_biases_type(conf, "metadynamics"); if (use_scripted_forces) { cvm::log(cvm::line_marker); @@ -363,6 +445,36 @@ int colvarmodule::parse_biases(std::string const &conf) } +int colvarmodule::num_biases_feature(int feature_id) +{ + colvarmodule *cv = cvm::main(); + size_t n = 0; + for (std::vector::iterator bi = cv->biases.begin(); + bi != cv->biases.end(); + bi++) { + if ((*bi)->is_enabled(feature_id)) { + n++; + } + } + return n; +} + + +int colvarmodule::num_biases_type(std::string const &type) +{ + colvarmodule *cv = cvm::main(); + size_t n = 0; + for (std::vector::iterator bi = cv->biases.begin(); + bi != cv->biases.end(); + bi++) { + if ((*bi)->bias_type == type) { + n++; + } + } + return n; +} + + int colvarmodule::catch_input_errors(int result) { if (result != COLVARS_OK || get_error()) { @@ -376,8 +488,9 @@ int colvarmodule::catch_input_errors(int result) colvarbias * colvarmodule::bias_by_name(std::string const &name) { - for (std::vector::iterator bi = biases.begin(); - bi != biases.end(); + colvarmodule *cv = cvm::main(); + for (std::vector::iterator bi = cv->biases.begin(); + bi != cv->biases.end(); bi++) { if ((*bi)->name == name) { return (*bi); @@ -388,8 +501,9 @@ colvarbias * colvarmodule::bias_by_name(std::string const &name) { colvar *colvarmodule::colvar_by_name(std::string const &name) { - for (std::vector::iterator cvi = colvars.begin(); - cvi != colvars.end(); + colvarmodule *cv = cvm::main(); + for (std::vector::iterator cvi = cv->colvars.begin(); + cvi != cv->colvars.end(); cvi++) { if ((*cvi)->name == name) { return (*cvi); @@ -555,9 +669,15 @@ int colvarmodule::calc_colvars() int error_code = COLVARS_OK; std::vector::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); + // Determine which colvars are active at this iteration + variables_active()->resize(0); + variables_active()->reserve(variables()->size()); + for (cvi = variables()->begin(); cvi != variables()->end(); cvi++) { + // This is a dynamic feature - the next call should be to enable() + // or disable() when dynamic dependency resolution is fully implemented + (*cvi)->set_enabled(colvardeps::f_cv_active, + step_absolute() % (*cvi)->get_time_step_factor() == 0); + variables_active()->push_back(*cvi); } // if SMP support is available, split up the work @@ -565,25 +685,24 @@ int colvarmodule::calc_colvars() // first, calculate how much work (currently, how many active CVCs) each colvar has - colvars_smp.resize(0); - colvars_smp_items.resize(0); + variables_active_smp()->resize(0); + variables_active_smp_items()->resize(0); - colvars_smp.reserve(colvars.size()); - colvars_smp_items.reserve(colvars.size()); + variables_active_smp()->reserve(variables_active()->size()); + variables_active_smp_items()->reserve(variables_active()->size()); // set up a vector containing all components cvm::increase_depth(); - for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { + for (cvi = variables_active()->begin(); cvi != variables_active()->end(); cvi++) { - 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); + variables_active_smp()->reserve(variables_active_smp()->size() + num_items); + variables_active_smp_items()->reserve(variables_active_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); + variables_active_smp()->push_back(*cvi); + variables_active_smp_items()->push_back(icvc); } } cvm::decrease_depth(); @@ -592,8 +711,7 @@ int colvarmodule::calc_colvars() error_code |= proxy->smp_colvars_loop(); cvm::increase_depth(); - for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { - if (!(*cvi)->is_enabled()) continue; + for (cvi = variables_active()->begin(); cvi != variables_active()->end(); cvi++) { error_code |= (*cvi)->collect_cvc_data(); } cvm::decrease_depth(); @@ -602,8 +720,7 @@ int colvarmodule::calc_colvars() // calculate colvars one at a time cvm::increase_depth(); - for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { - if (!(*cvi)->is_enabled()) continue; + for (cvi = variables_active()->begin(); cvi != variables_active()->end(); cvi++) { error_code |= (*cvi)->calc(); if (cvm::get_error()) { return COLVARS_ERROR; @@ -627,6 +744,18 @@ int colvarmodule::calc_biases() std::vector::iterator bi; int error_code = COLVARS_OK; + // Total bias energy is reset before calling scripted biases + total_bias_energy = 0.0; + + // update the list of active biases + biases_active()->resize(0); + biases_active()->reserve(biases.size()); + for (bi = biases.begin(); bi != biases.end(); bi++) { + if ((*bi)->is_enabled()) { + biases_active()->push_back(*bi); + } + } + // if SMP support is available, split up the work if (proxy->smp_enabled() == COLVARS_OK) { @@ -645,7 +774,7 @@ int colvarmodule::calc_biases() } cvm::increase_depth(); - for (bi = biases.begin(); bi != biases.end(); bi++) { + for (bi = biases_active()->begin(); bi != biases_active()->end(); bi++) { error_code |= (*bi)->update(); if (cvm::get_error()) { return error_code; @@ -654,12 +783,10 @@ int colvarmodule::calc_biases() cvm::decrease_depth(); } - cvm::real total_bias_energy = 0.0; - for (bi = biases.begin(); bi != biases.end(); bi++) { + for (bi = biases_active()->begin(); bi != biases_active()->end(); bi++) { total_bias_energy += (*bi)->get_energy(); } - proxy->add_energy(total_bias_energy); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); } @@ -675,7 +802,7 @@ int colvarmodule::update_colvar_forces() if (cvm::debug() && biases.size()) cvm::log("Collecting forces from all biases.\n"); cvm::increase_depth(); - for (bi = biases.begin(); bi != biases.end(); bi++) { + for (bi = biases_active()->begin(); bi != biases_active()->end(); bi++) { (*bi)->communicate_forces(); if (cvm::get_error()) { return COLVARS_ERROR; @@ -687,6 +814,11 @@ int colvarmodule::update_colvar_forces() error_code |= calc_scripted_forces(); } + // Now we have collected energies from both built-in and scripted biases + if (cvm::debug()) + cvm::log("Adding total bias energy: " + cvm::to_str(total_bias_energy) + "\n"); + proxy->add_energy(total_bias_energy); + cvm::real total_colvar_energy = 0.0; // sum up the forces for each colvar, including wall forces // and integrate any internal @@ -695,7 +827,7 @@ int colvarmodule::update_colvar_forces() 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++) { + for (cvi = variables()->begin(); cvi != variables()->end(); cvi++) { // 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(); @@ -704,6 +836,8 @@ int colvarmodule::update_colvar_forces() } } cvm::decrease_depth(); + if (cvm::debug()) + cvm::log("Adding total colvar energy: " + cvm::to_str(total_colvar_energy) + "\n"); proxy->add_energy(total_colvar_energy); // make collective variables communicate their forces to their @@ -711,9 +845,8 @@ int colvarmodule::update_colvar_forces() 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++) { + for (cvi = variables_active()->begin(); cvi != variables_active()->end(); cvi++) { if ((*cvi)->is_enabled(colvardeps::f_cv_gradient)) { - if (!(*cvi)->is_enabled()) continue; (*cvi)->communicate_forces(); if (cvm::get_error()) { return COLVARS_ERROR; @@ -800,8 +933,8 @@ int colvarmodule::analyze() cvm::log("Performing analysis.\n"); // perform colvar-specific analysis - for (std::vector::iterator cvi = colvars.begin(); - cvi != colvars.end(); + for (std::vector::iterator cvi = variables_active()->begin(); + cvi != variables_active()->end(); cvi++) { cvm::increase_depth(); (*cvi)->analyze(); @@ -825,8 +958,8 @@ 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++) { + for (std::vector::iterator cvi = variables()->begin(); + cvi != variables()->end(); cvi++) { (*cvi)->setup(); } return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); @@ -934,18 +1067,18 @@ int colvarmodule::setup_output() cvm::log("The restart output state file will be \""+restart_out_name+"\".\n"); } - output_prefix = proxy->output_prefix(); - if (output_prefix.size()) { + 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") : + (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") : + (output_prefix().size() ? + std::string(output_prefix()+".colvars.traj") : std::string("")); if (cv_traj_freq && cv_traj_name.size()) { @@ -1077,14 +1210,14 @@ continue the previous simulation.\n\n"); cvm::log(cvm::line_marker); // update this ahead of time in this special case - output_prefix = proxy->input_prefix(); - cvm::log("All output files will now be saved with the prefix \""+output_prefix+".tmp.*\".\n"); + output_prefix() = proxy->input_prefix(); + cvm::log("All output files will now be saved with the prefix \""+output_prefix()+".tmp.*\".\n"); 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\ +\""+output_prefix()+".tmp.colvars.state\"\n\ to:\n\ \""+ proxy->input_prefix()+".colvars.state\"\n"); - output_prefix = output_prefix+".tmp"; + output_prefix() = output_prefix()+".tmp"; write_output_files(); cvm::error("Exiting with error until issue is addressed.\n", FATAL_ERROR); } @@ -1104,8 +1237,8 @@ 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") : + (output_prefix().size() ? + std::string(output_prefix()+".colvars.state") : std::string("colvars.state")); cvm::log("Saving collective variables state to \""+out_name+"\".\n"); @@ -1340,7 +1473,8 @@ std::ostream & colvarmodule::write_traj(std::ostream &os) void cvm::log(std::string const &message) { - size_t const d = depth(); + // allow logging when the module is not fully initialized + size_t const d = (cvm::main() != NULL) ? depth() : 0; if (d > 0) proxy->log((std::string(2*d, ' '))+message); else @@ -1365,19 +1499,20 @@ void cvm::decrease_depth() size_t & cvm::depth() { // NOTE: do not call log() or error() here, to avoid recursion - size_t const nt = proxy->smp_num_threads(); + colvarmodule *cv = cvm::main(); if (proxy->smp_enabled() == COLVARS_OK) { - if (depth_v.size() != nt) { - // update array of depths + int const nt = proxy->smp_num_threads(); + if (int(cv->depth_v.size()) != nt) { proxy->smp_lock(); - if (depth_v.size() > 0) { depth_s = depth_v[0]; } - depth_v.clear(); - depth_v.assign(nt, depth_s); + // update array of depths + if (cv->depth_v.size() > 0) { cv->depth_s = cv->depth_v[0]; } + cv->depth_v.clear(); + cv->depth_v.assign(nt, cv->depth_s); proxy->smp_unlock(); } - return depth_v[proxy->smp_thread_id()]; + return cv->depth_v[proxy->smp_thread_id()]; } - return depth_s; + return cv->depth_s; } @@ -1451,8 +1586,8 @@ int cvm::read_index_file(char const *filename) FILE_ERROR); } } - cvm::index_group_names.push_back(group_name); - cvm::index_groups.push_back(std::vector ()); + index_group_names.push_back(group_name); + index_groups.push_back(std::vector()); } else { cvm::error("Error: in parsing index file \""+ std::string(filename)+"\".\n", @@ -1462,7 +1597,7 @@ int cvm::read_index_file(char const *filename) int atom_number = 1; size_t pos = is.tellg(); while ( (is >> atom_number) && (atom_number > 0) ) { - (cvm::index_groups.back()).push_back(atom_number); + (index_groups.back()).push_back(atom_number); pos = is.tellg(); } is.clear(); @@ -1532,8 +1667,8 @@ int cvm::load_coords_xyz(char const *filename, + std::string(filename) + ".\n", INPUT_ERROR); } // skip comment line - std::getline(xyz_is, line); - std::getline(xyz_is, line); + cvm::getline(xyz_is, line); + cvm::getline(xyz_is, line); xyz_is.width(255); std::vector::iterator pos_i = pos.begin(); @@ -1543,7 +1678,7 @@ int cvm::load_coords_xyz(char const *filename, for ( ; pos_i != pos.end() ; pos_i++, index++) { while ( next < *index ) { - std::getline(xyz_is, line); + cvm::getline(xyz_is, line); next++; } xyz_is >> symbol; @@ -1558,15 +1693,9 @@ int cvm::load_coords_xyz(char const *filename, 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; +// shared pointer to the proxy object +colvarproxy *colvarmodule::proxy = NULL; // static runtime data cvm::real colvarmodule::debug_gradients_step_size = 1.0e-07; @@ -1575,14 +1704,9 @@ long colvarmodule::it = 0; long colvarmodule::it_restart = 0; size_t colvarmodule::restart_out_freq = 0; size_t colvarmodule::cv_traj_freq = 0; -size_t colvarmodule::depth_s = 0; -std::vector colvarmodule::depth_v(0); bool colvarmodule::b_analysis = false; -std::list colvarmodule::index_group_names; -std::list > colvarmodule::index_groups; -bool colvarmodule::use_scripted_forces = false; -bool colvarmodule::scripting_after_biases = true; -std::string colvarmodule::output_prefix = ""; +bool colvarmodule::use_scripted_forces = false; +bool colvarmodule::scripting_after_biases = true; // i/o constants size_t const colvarmodule::it_width = 12; diff --git a/lib/colvars/colvarmodule.h b/lib/colvars/colvarmodule.h index 0e98709adb..b4f80e0b5e 100644 --- a/lib/colvars/colvarmodule.h +++ b/lib/colvars/colvarmodule.h @@ -11,7 +11,7 @@ #define COLVARMODULE_H #ifndef COLVARS_VERSION -#define COLVARS_VERSION "2016-12-27" +#define COLVARS_VERSION "2017-03-09" #endif #ifndef COLVARS_DEBUG @@ -161,12 +161,37 @@ public: /// dt) static real debug_gradients_step_size; - /// Prefix for all output files for this run - static std::string output_prefix; +private: + /// Prefix for all output files for this run + std::string cvm_output_prefix; + +public: + /// Accessor for the above + static inline std::string &output_prefix() + { + colvarmodule *cv = colvarmodule::main(); + return cv->cvm_output_prefix; + } + +private: /// Array of collective variables - static std::vector colvars; + std::vector colvars; + + /// Array of collective variables + std::vector colvars_active; + + /// Collective variables to be calculated on different threads; + /// colvars with multple items (e.g. multiple active CVCs) are duplicated + std::vector colvars_smp; + /// Indexes of the items to calculate for each colvar + std::vector colvars_smp_items; + +public: + + /// Array of collective variables + std::vector *variables(); /* TODO: implement named CVCs /// Array of named (reusable) collective variable components @@ -177,26 +202,31 @@ public: } */ + /// Collective variables with the active flag on + std::vector *variables_active(); + /// Collective variables to be calculated on different threads; /// colvars with multple items (e.g. multiple active CVCs) are duplicated - std::vector colvars_smp; + std::vector *variables_active_smp(); + /// Indexes of the items to calculate for each colvar - std::vector colvars_smp_items; + std::vector *variables_active_smp_items(); /// Array of collective variable biases - static std::vector biases; - /// \brief Number of ABF biases initialized (in normal conditions - /// should be 1) - static size_t n_abf_biases; - /// \brief Number of metadynamics biases initialized (in normal - /// conditions should be 1) - static size_t n_meta_biases; - /// \brief Number of restraint biases initialized (no limit on the - /// number) - static size_t n_rest_biases; - /// \brief Number of histograms initialized (no limit on the - /// number) - static size_t n_histo_biases; + std::vector biases; + + /// Energy of built-in and scripted biases, summed per time-step + real total_bias_energy; + +private: + + /// Array of active collective variable biases + std::vector biases_active_; + +public: + + /// Array of active collective variable biases + std::vector *biases_active(); /// \brief Whether debug output should be enabled (compile-time option) static inline bool debug() @@ -205,10 +235,7 @@ public: } /// \brief How many objects are configured yet? - inline size_t size() const - { - return colvars.size() + biases.size(); - } + size_t size() const; /// \brief Constructor \param config_name Configuration file name /// \param restart_name (optional) Restart file name @@ -230,9 +257,12 @@ public: /// \brief Parse a "clean" config string (no comments) int parse_config(std::string &conf); - // Parse functions (setup internal data based on a string) + /// Allow reading from Windows text files using using std::getline + /// (which can still be used when the text is produced by Colvars itself) + static std::istream & getline(std::istream &is, std::string &line); + /// Parse the few module's global parameters int parse_global_params(std::string const &conf); @@ -242,14 +272,33 @@ public: /// Parse and initialize collective variable biases int parse_biases(std::string const &conf); + /// \brief Add new configuration during parsing (e.g. to implement + /// back-compatibility); cannot be nested, i.e. conf should not contain + /// anything that triggers another call + int append_new_config(std::string const &conf); + +private: + + /// Auto-generated configuration during parsing (e.g. to implement + /// back-compatibility) + std::string extra_conf; + /// Parse and initialize collective variable biases of a specific type template - int parse_biases_type(std::string const &conf, char const *keyword, size_t &bias_count); + int parse_biases_type(std::string const &conf, char const *keyword); /// Test error condition and keyword parsing /// on error, delete new bias bool check_new_bias(std::string &conf, char const *key); +public: + + /// Return how many biases have this feature enabled + static int num_biases_feature(int feature_id); + + /// Return how many biases are defined with this type + static int num_biases_type(std::string const &type); + private: /// Useful wrapper to interrupt parsing if any error occurs int catch_input_errors(int result); @@ -449,13 +498,13 @@ public: /// \brief Names of groups from a Gromacs .ndx file to be read at startup - static std::list index_group_names; + std::list index_group_names; /// \brief Groups from a Gromacs .ndx file read at startup - static std::list > index_groups; + std::list > index_groups; /// \brief Read a Gromacs .ndx file - static int read_index_file(char const *filename); + int read_index_file(char const *filename); /// \brief Create atoms from a file \param filename name of the file @@ -515,13 +564,13 @@ protected: /// Output restart file colvarmodule::ofstream restart_out_os; -protected: +private: /// Counter for the current depth in the object hierarchy (useg e.g. in output) - static size_t depth_s; + size_t depth_s; /// Thread-specific depth - static std::vector depth_v; + std::vector depth_v; public: @@ -552,6 +601,10 @@ public: /// from the hosting program; it is static in order to be accessible /// from static functions in the colvarmodule class static colvarproxy *proxy; + + /// \brief Accessor for the above + static colvarmodule *main(); + }; diff --git a/lib/colvars/colvarparse.cpp b/lib/colvars/colvarparse.cpp index 4d2e17f098..8055d925db 100644 --- a/lib/colvars/colvarparse.cpp +++ b/lib/colvars/colvarparse.cpp @@ -503,7 +503,7 @@ int colvarparse::check_keywords(std::string &conf, char const *key) std::string line; std::istringstream is(conf); - while (std::getline(is, line)) { + while (cvm::getline(is, line)) { if (line.size() == 0) continue; if (line.find_first_not_of(white_space) == @@ -539,10 +539,9 @@ int colvarparse::check_keywords(std::string &conf, char const *key) std::istream & colvarparse::getline_nocomments(std::istream &is, - std::string &line, - char const delim) + std::string &line) { - std::getline(is, line, delim); + cvm::getline(is, line); size_t const comment = line.find('#'); if (comment != std::string::npos) { line.erase(comment); diff --git a/lib/colvars/colvarparse.h b/lib/colvars/colvarparse.h index acdc46ddc9..9f116caafd 100644 --- a/lib/colvars/colvarparse.h +++ b/lib/colvars/colvarparse.h @@ -304,8 +304,7 @@ public: /// \brief Works as std::getline() but also removes everything /// between a comment character and the following newline static std::istream & getline_nocomments(std::istream &is, - std::string &s, - char const delim = '\n'); + std::string &s); /// Check if the content of the file has matching braces bool brace_check(std::string const &conf, diff --git a/lib/colvars/colvarproxy.h b/lib/colvars/colvarproxy.h index bdf65c0b1f..5b216c9d41 100644 --- a/lib/colvars/colvarproxy.h +++ b/lib/colvars/colvarproxy.h @@ -336,8 +336,6 @@ public: /// Are total forces being used? virtual bool total_forces_enabled() const { - cvm::error("Error: total forces are currently not implemented.\n", - COLVARS_NOT_IMPLEMENTED); return false; } diff --git a/lib/colvars/colvarscript.cpp b/lib/colvars/colvarscript.cpp index ffb83e9780..f192dcb7c0 100644 --- a/lib/colvars/colvarscript.cpp +++ b/lib/colvars/colvarscript.cpp @@ -12,6 +12,7 @@ #include #include "colvarscript.h" +#include "colvardeps.h" colvarscript::colvarscript(colvarproxy *p) @@ -221,6 +222,16 @@ int colvarscript::run(int argc, char const *argv[]) { } } + if (cmd == "addenergy") { + if (argc == 3) { + colvars->total_bias_energy += strtod(argv[2], NULL); + return COLVARS_OK; + } else { + result = "Wrong arguments to command \"addenergy\"\n" + help_string(); + return COLVARSCRIPT_ERROR; + } + } + result = "Syntax error\n" + help_string(); return COLVARSCRIPT_ERROR; } @@ -263,10 +274,11 @@ int colvarscript::proc_colvar(int argc, char const *argv[]) { } if (subcmd == "delete") { - if (cv->biases.size() > 0) { - result = "Cannot delete a colvar currently used by biases, delete those biases first"; - return COLVARSCRIPT_ERROR; + size_t i; + for (i = 0; i < cv->biases.size(); i++) { + delete cv->biases[i]; } + cv->biases.resize(0); // colvar destructor is tasked with the cleanup delete cv; // TODO this could be done by the destructors @@ -338,9 +350,8 @@ int colvarscript::proc_colvar(int argc, char const *argv[]) { return COLVARS_OK; } - if (subcmd == "state") { - cv->print_state(); - return COLVARS_OK; + if ((subcmd == "get") || (subcmd == "set") || (subcmd == "state")) { + return proc_features(cv, argc, argv); } result = "Syntax error\n" + help_string(); @@ -379,11 +390,6 @@ int colvarscript::proc_bias(int argc, char const *argv[]) { return COLVARS_OK; } - if (subcmd == "state") { - b->print_state(); - return COLVARS_OK; - } - // Subcommands for MW ABF if (subcmd == "bin") { int r = b->current_bin(); @@ -420,6 +426,10 @@ int colvarscript::proc_bias(int argc, char const *argv[]) { return COLVARS_OK; } + if ((subcmd == "get") || (subcmd == "set") || (subcmd == "state")) { + return proc_features(b, argc, argv); + } + if (argc >= 4) { std::string param = argv[3]; if (subcmd == "count") { @@ -441,6 +451,83 @@ int colvarscript::proc_bias(int argc, char const *argv[]) { } +int colvarscript::proc_features(colvardeps *obj, + int argc, char const *argv[]) { + // size was already checked before calling + std::string subcmd = argv[2]; + + if (argc == 3) { + if (subcmd == "state") { + // TODO make this returned as result? + obj->print_state(); + return COLVARS_OK; + } + + // get and set commands require more arguments + result = "Syntax error\n" + help_string(); + return COLVARSCRIPT_ERROR; + } + + if ((subcmd == "get") || (subcmd == "set")) { + std::vector &features = obj->features(); + std::string const req_feature(argv[3]); + colvardeps::feature *f = NULL; + int fid = 0; + for (fid = 0; fid < int(features.size()); fid++) { + if (features[fid]->description == + colvarparse::to_lower_cppstr(req_feature)) { + f = features[fid]; + break; + } + } + + if (f == NULL) { + + result = "Error: feature \""+req_feature+"\" does not exist.\n"; + return COLVARSCRIPT_ERROR; + + } else { + + if (! obj->is_available(fid)) { + result = "Error: feature \""+req_feature+"\" is unavailable.\n"; + return COLVARSCRIPT_ERROR; + } + + if (subcmd == "get") { + result = cvm::to_str(obj->is_enabled(fid) ? 1 : 0); + return COLVARS_OK; + } + + if (subcmd == "set") { + if (argc == 5) { + std::string const yesno = + colvarparse::to_lower_cppstr(std::string(argv[4])); + if ((yesno == std::string("yes")) || + (yesno == std::string("on")) || + (yesno == std::string("1"))) { + obj->enable(fid); + return COLVARS_OK; + } else if ((yesno == std::string("no")) || + (yesno == std::string("off")) || + (yesno == std::string("0"))) { + // TODO disable() function does not exist yet, + // dependencies will not be resolved + // obj->disable(fid); + obj->set_enabled(fid, false); + return COLVARS_OK; + } + } + result = "Syntax error\n" + help_string(); + return COLVARSCRIPT_ERROR; + } + } + } + + result = "Syntax error\n" + help_string(); + return COLVARSCRIPT_ERROR; +} + + std::string colvarscript::help_string() { std::string buf; @@ -459,6 +546,7 @@ Input and output:\n\ load -- load a state file (requires configuration)\n\ save -- save a state file (requires configuration)\n\ update -- recalculate colvars and biases\n\ + addenergy -- add to the total bias energy\n\ printframe -- return a summary of the current frame\n\ printframelabels -- return labels to annotate printframe's output\n"; @@ -478,12 +566,17 @@ Accessing collective variables:\n\ colvar addforce -- apply given force on colvar \n\ colvar getconfig -- return config string of colvar \n\ colvar cvcflags -- enable or disable cvcs according to 0/1 flags\n\ + colvar get -- get the value of the colvar feature \n\ + colvar set -- set the value of the colvar feature \n\ \n\ Accessing biases:\n\ bias energy -- return the current energy of bias \n\ bias update -- recalculate bias \n\ bias delete -- delete bias \n\ - bias getconfig -- return config string of bias \n"; + bias getconfig -- return config string of bias \n\ + bias get -- get the value of the bias feature \n\ + bias set -- set the value of the bias feature \n\ +"; return buf; } diff --git a/lib/colvars/colvarscript.h b/lib/colvars/colvarscript.h index bfb8381e3b..46b1ddd203 100644 --- a/lib/colvars/colvarscript.h +++ b/lib/colvars/colvarscript.h @@ -51,6 +51,10 @@ private: /// Run subcommands on bias int proc_bias(int argc, char const *argv[]); + /// Run subcommands on base colvardeps object (colvar, bias, ...) + int proc_features(colvardeps *obj, + int argc, char const *argv[]); + /// Builds and return a short help std::string help_string(void); }; diff --git a/src/USER-COLVARS/colvarproxy_lammps.cpp b/src/USER-COLVARS/colvarproxy_lammps.cpp index 7320263ba7..89453ded9b 100644 --- a/src/USER-COLVARS/colvarproxy_lammps.cpp +++ b/src/USER-COLVARS/colvarproxy_lammps.cpp @@ -352,12 +352,17 @@ int colvarproxy_lammps::smp_enabled() int colvarproxy_lammps::smp_colvars_loop() { colvarmodule *cv = this->colvars; + colvarproxy_lammps *proxy = (colvarproxy_lammps *) cv->proxy; #pragma omp parallel for - for (size_t i = 0; i < cv->colvars_smp.size(); i++) { + for (size_t i = 0; i < cv->variables_active_smp()->size(); i++) { + colvar *x = (*(cv->variables_active_smp()))[i]; + int x_item = (*(cv->variables_active_smp_items()))[i]; if (cvm::debug()) { - cvm::log("Calculating colvar \""+cv->colvars_smp[i]->name+"\" on thread "+cvm::to_str(smp_thread_id())+"\n"); + cvm::log("["+cvm::to_str(proxy->smp_thread_id())+"/"+cvm::to_str(proxy->smp_num_threads())+ + "]: calc_colvars_items_smp(), i = "+cvm::to_str(i)+", cv = "+ + x->name+", cvc = "+cvm::to_str(x_item)+"\n"); } - cv->colvars_smp[i]->calc_cvcs(cv->colvars_smp_items[i], 1); + x->calc_cvcs(x_item, 1); } return cvm::get_error(); } @@ -367,11 +372,13 @@ int colvarproxy_lammps::smp_biases_loop() { colvarmodule *cv = this->colvars; #pragma omp parallel for - for (size_t i = 0; i < cv->biases.size(); i++) { + for (size_t i = 0; i < cv->biases_active()->size(); i++) { + colvarbias *b = (*(cv->biases_active()))[i]; if (cvm::debug()) { - cvm::log("Calculating bias \""+cv->biases[i]->name+"\" on thread "+cvm::to_str(smp_thread_id())+"\n"); + cvm::log("Calculating bias \""+b->name+"\" on thread "+ + cvm::to_str(smp_thread_id())+"\n"); } - cv->biases[i]->update(); + b->update(); } return cvm::get_error(); } diff --git a/src/USER-COLVARS/colvarproxy_lammps.h b/src/USER-COLVARS/colvarproxy_lammps.h index c0b4ea20fe..ad63eb2f9e 100644 --- a/src/USER-COLVARS/colvarproxy_lammps.h +++ b/src/USER-COLVARS/colvarproxy_lammps.h @@ -29,7 +29,7 @@ #endif #ifndef COLVARPROXY_VERSION -#define COLVARPROXY_VERSION "2016-12-27" +#define COLVARPROXY_VERSION "2017-01-09" #endif /* struct for packed data communication of coordinates and forces. */