Update Colvars library to version 2020-01-27
One new feature (arithmetic path variables) and several smaller enhancements
or bugfixes.
Fix error check when loading an old state file
https://github.com/Colvars/colvars/pull/317
Get default values for grid boundaries when available
https://github.com/Colvars/colvars/pull/310
Allow redefining existing index groups (warn when this happens)
https://github.com/Colvars/colvars/pull/302
Simplified replica communication syntax in metadynamics
https://github.com/Colvars/colvars/pull/301
Obtain the bias_energy for ABF biases
https://github.com/Colvars/colvars/pull/294
Fix reading path file with vector CVCs
https://github.com/Colvars/colvars/pull/288
Fix segfault at deleting CVBasedPath
https://github.com/Colvars/colvars/pull/286
Parrinello's (arithmetic) pathCV in CV space
https://github.com/Colvars/colvars/pull/274
Fix race condition when starting a bundle of walkers
https://github.com/Colvars/colvars/pull/279
This commit is contained in:
@ -2,7 +2,7 @@
|
||||
|
||||
// This file is part of the Collective Variables module (Colvars).
|
||||
// The original version of Colvars and its updates are located at:
|
||||
// https://github.com/colvars/colvars
|
||||
// https://github.com/Colvars/colvars
|
||||
// Please update all Colvars source files before making any changes.
|
||||
// If you wish to distribute your changes, please submit them to the
|
||||
// Colvars repository at GitHub.
|
||||
@ -29,6 +29,10 @@ colvar::colvar()
|
||||
kinetic_energy = 0.0;
|
||||
potential_energy = 0.0;
|
||||
|
||||
#ifdef LEPTON
|
||||
dev_null = 0.0;
|
||||
#endif
|
||||
|
||||
description = "uninitialized colvar";
|
||||
init_dependencies();
|
||||
}
|
||||
@ -194,23 +198,32 @@ int colvar::init(std::string const &conf)
|
||||
{
|
||||
bool homogeneous = is_enabled(f_cv_linear);
|
||||
for (i = 0; i < cvcs.size(); i++) {
|
||||
if ((cvm::fabs(cvcs[i]->sup_coeff) - 1.0) > 1.0e-10) {
|
||||
if (cvm::fabs(cvm::fabs(cvcs[i]->sup_coeff) - 1.0) > 1.0e-10) {
|
||||
homogeneous = false;
|
||||
}
|
||||
}
|
||||
set_enabled(f_cv_homogeneous, homogeneous);
|
||||
}
|
||||
|
||||
// A single-component variable almost concides with its CVC object
|
||||
if ((cvcs.size() == 1) && is_enabled(f_cv_homogeneous)) {
|
||||
if ( !is_enabled(f_cv_scripted) && !is_enabled(f_cv_custom_function) &&
|
||||
(cvm::fabs(cvcs[0]->sup_coeff - 1.0) < 1.0e-10) &&
|
||||
(cvcs[0]->sup_np == 1) ) {
|
||||
enable(f_cv_single_cvc);
|
||||
}
|
||||
}
|
||||
|
||||
// Colvar is deemed periodic if:
|
||||
// - it is homogeneous
|
||||
// - all cvcs are periodic
|
||||
// - all cvcs have the same period
|
||||
if (is_enabled(f_cv_homogeneous) && cvcs[0]->b_periodic) { // TODO make this a CVC feature
|
||||
if (is_enabled(f_cv_homogeneous) && cvcs[0]->is_enabled(f_cvc_periodic)) {
|
||||
bool b_periodic = true;
|
||||
period = cvcs[0]->period;
|
||||
wrap_center = cvcs[0]->wrap_center;
|
||||
for (i = 1; i < cvcs.size(); i++) {
|
||||
if (!cvcs[i]->b_periodic || cvcs[i]->period != period) {
|
||||
if (!cvcs[i]->is_enabled(f_cvc_periodic) || cvcs[i]->period != period) {
|
||||
b_periodic = false;
|
||||
period = 0.0;
|
||||
cvm::log("Warning: although one component is periodic, this colvar will "
|
||||
@ -296,13 +309,13 @@ int colvar::init(std::string const &conf)
|
||||
#ifdef LEPTON
|
||||
int colvar::init_custom_function(std::string const &conf)
|
||||
{
|
||||
std::string expr;
|
||||
std::string expr, expr_in; // expr_in is a buffer to remember expr after unsuccessful parsing
|
||||
std::vector<Lepton::ParsedExpression> pexprs;
|
||||
Lepton::ParsedExpression pexpr;
|
||||
size_t pos = 0; // current position in config string
|
||||
double *ref;
|
||||
|
||||
if (!key_lookup(conf, "customFunction", &expr, &pos)) {
|
||||
if (!key_lookup(conf, "customFunction", &expr_in, &pos)) {
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
@ -310,6 +323,7 @@ int colvar::init_custom_function(std::string const &conf)
|
||||
cvm::log("This colvar uses a custom function.\n");
|
||||
|
||||
do {
|
||||
expr = expr_in;
|
||||
if (cvm::debug())
|
||||
cvm::log("Parsing expression \"" + expr + "\".\n");
|
||||
try {
|
||||
@ -337,8 +351,7 @@ int colvar::init_custom_function(std::string const &conf)
|
||||
// To keep the same workflow, we use a pointer to a double here
|
||||
// that will receive CVC values - even though none was allocated by Lepton
|
||||
ref = &dev_null;
|
||||
if (cvm::debug())
|
||||
cvm::log("Variable " + vn + " is absent from expression \"" + expr + "\".\n");
|
||||
cvm::log("Warning: Variable " + vn + " is absent from expression \"" + expr + "\".\n");
|
||||
}
|
||||
value_eval_var_refs.push_back(ref);
|
||||
}
|
||||
@ -348,7 +361,7 @@ int colvar::init_custom_function(std::string const &conf)
|
||||
cvm::error("Error compiling expression \"" + expr + "\".\n", INPUT_ERROR);
|
||||
return INPUT_ERROR;
|
||||
}
|
||||
} while (key_lookup(conf, "customFunction", &expr, &pos));
|
||||
} while (key_lookup(conf, "customFunction", &expr_in, &pos));
|
||||
|
||||
|
||||
// Now define derivative with respect to each scalar sub-component
|
||||
@ -373,8 +386,7 @@ int colvar::init_custom_function(std::string const &conf)
|
||||
catch (...) { // Variable is absent from derivative
|
||||
// To keep the same workflow, we use a pointer to a double here
|
||||
// that will receive CVC values - even though none was allocated by Lepton
|
||||
if (cvm::debug())
|
||||
cvm::log("Variable " + vvn + " is absent from derivative of \"" + expr + "\" wrt " + vn + ".\n");
|
||||
cvm::log("Warning: Variable " + vvn + " is absent from derivative of \"" + expr + "\" wrt " + vn + ".\n");
|
||||
ref = &dev_null;
|
||||
}
|
||||
grad_eval_var_refs.push_back(ref);
|
||||
@ -439,6 +451,21 @@ int colvar::init_custom_function(std::string const &conf)
|
||||
|
||||
int colvar::init_custom_function(std::string const &conf)
|
||||
{
|
||||
|
||||
std::string expr;
|
||||
size_t pos = 0;
|
||||
if (key_lookup(conf, "customFunction", &expr, &pos)) {
|
||||
std::string msg("Error: customFunction requires the Lepton library.");
|
||||
#if (__cplusplus < 201103L)
|
||||
// NOTE: this is not ideal; testing for the Lepton library's version would
|
||||
// be more accurate, but also less portable
|
||||
msg +=
|
||||
std::string(" Note also that recent versions of Lepton require C++11: "
|
||||
"please see https://colvars.github.io/README-c++11.html.");
|
||||
#endif
|
||||
return cvm::error(msg, COLVARS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
@ -449,7 +476,19 @@ int colvar::init_grid_parameters(std::string const &conf)
|
||||
{
|
||||
colvarmodule *cv = cvm::main();
|
||||
|
||||
get_keyval(conf, "width", width, 1.0);
|
||||
cvm::real default_width = width;
|
||||
|
||||
if (!key_already_set("width")) {
|
||||
// The first time, check if the CVC has a width to provide
|
||||
default_width = 1.0;
|
||||
if (is_enabled(f_cv_single_cvc) && cvcs[0]->is_enabled(f_cvc_width)) {
|
||||
cvm::real const cvc_width = cvcs[0]->get_param("width");
|
||||
default_width = cvc_width;
|
||||
}
|
||||
}
|
||||
|
||||
get_keyval(conf, "width", width, default_width);
|
||||
|
||||
if (width <= 0.0) {
|
||||
cvm::error("Error: \"width\" must be positive.\n", INPUT_ERROR);
|
||||
return INPUT_ERROR;
|
||||
@ -460,12 +499,32 @@ int colvar::init_grid_parameters(std::string const &conf)
|
||||
|
||||
if (is_enabled(f_cv_scalar)) {
|
||||
|
||||
if (is_enabled(f_cv_single_cvc)) {
|
||||
// Get the default boundaries from the component
|
||||
if (cvcs[0]->is_enabled(f_cvc_lower_boundary)) {
|
||||
enable(f_cv_lower_boundary);
|
||||
enable(f_cv_hard_lower_boundary);
|
||||
lower_boundary =
|
||||
*(reinterpret_cast<colvarvalue const *>(cvcs[0]->get_param_ptr("lowerBoundary")));
|
||||
}
|
||||
if (cvcs[0]->is_enabled(f_cvc_upper_boundary)) {
|
||||
enable(f_cv_upper_boundary);
|
||||
enable(f_cv_hard_upper_boundary);
|
||||
upper_boundary =
|
||||
*(reinterpret_cast<colvarvalue const *>(cvcs[0]->get_param_ptr("upperBoundary")));
|
||||
}
|
||||
}
|
||||
|
||||
if (get_keyval(conf, "lowerBoundary", lower_boundary, lower_boundary)) {
|
||||
enable(f_cv_lower_boundary);
|
||||
// Because this is the user's choice, we cannot assume it is a true
|
||||
// physical boundary
|
||||
disable(f_cv_hard_lower_boundary);
|
||||
}
|
||||
|
||||
if (get_keyval(conf, "upperBoundary", upper_boundary, upper_boundary)) {
|
||||
enable(f_cv_upper_boundary);
|
||||
disable(f_cv_hard_upper_boundary);
|
||||
}
|
||||
|
||||
std::string lw_conf, uw_conf;
|
||||
@ -520,12 +579,11 @@ harmonicWalls {\n\
|
||||
}
|
||||
}
|
||||
|
||||
if (is_enabled(f_cv_lower_boundary)) {
|
||||
get_keyval(conf, "hardLowerBoundary", hard_lower_boundary, false);
|
||||
}
|
||||
if (is_enabled(f_cv_upper_boundary)) {
|
||||
get_keyval(conf, "hardUpperBoundary", hard_upper_boundary, false);
|
||||
}
|
||||
get_keyval_feature(this, conf, "hardLowerBoundary", f_cv_hard_lower_boundary,
|
||||
is_enabled(f_cv_hard_lower_boundary));
|
||||
|
||||
get_keyval_feature(this, conf, "hardUpperBoundary", f_cv_hard_upper_boundary,
|
||||
is_enabled(f_cv_hard_upper_boundary));
|
||||
|
||||
// consistency checks for boundaries and walls
|
||||
if (is_enabled(f_cv_lower_boundary) && is_enabled(f_cv_upper_boundary)) {
|
||||
@ -546,7 +604,8 @@ harmonicWalls {\n\
|
||||
INPUT_ERROR);
|
||||
return INPUT_ERROR;
|
||||
}
|
||||
if (expand_boundaries && hard_lower_boundary && hard_upper_boundary) {
|
||||
if (expand_boundaries && is_enabled(f_cv_hard_lower_boundary) &&
|
||||
is_enabled(f_cv_hard_upper_boundary)) {
|
||||
cvm::error("Error: inconsistent configuration "
|
||||
"(trying to expand boundaries with both "
|
||||
"hardLowerBoundary and hardUpperBoundary enabled).\n",
|
||||
@ -568,7 +627,8 @@ int colvar::init_extended_Lagrangian(std::string const &conf)
|
||||
cvm::log("Enabling the extended Lagrangian term for colvar \""+
|
||||
this->name+"\".\n");
|
||||
|
||||
x_ext.type(value());
|
||||
// Mark x_ext as uninitialized so we can initialize it to the colvar value when updating
|
||||
x_ext.type(colvarvalue::type_notset);
|
||||
v_ext.type(value());
|
||||
fr.type(value());
|
||||
|
||||
@ -646,7 +706,7 @@ int colvar::init_output_flags(std::string const &conf)
|
||||
bool temp;
|
||||
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);
|
||||
"The two are NOT identical: see https://colvars.github.io/totalforce.html.\n", INPUT_ERROR);
|
||||
return INPUT_ERROR;
|
||||
}
|
||||
}
|
||||
@ -664,7 +724,7 @@ int colvar::init_output_flags(std::string const &conf)
|
||||
// read the configuration and set up corresponding instances, for
|
||||
// each type of component implemented
|
||||
template<typename def_class_name> int colvar::init_components_type(std::string const &conf,
|
||||
char const *def_desc,
|
||||
char const * /* def_desc */,
|
||||
char const *def_config_key)
|
||||
{
|
||||
size_t def_count = 0;
|
||||
@ -744,6 +804,7 @@ template<typename def_class_name> int colvar::init_components_type(std::string c
|
||||
int colvar::init_components(std::string const &conf)
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
size_t i = 0, j = 0;
|
||||
|
||||
error_code |= init_components_type<distance>(conf, "distance", "distance");
|
||||
error_code |= init_components_type<distance_vec>(conf, "distance vector", "distanceVec");
|
||||
@ -793,9 +854,11 @@ int colvar::init_components(std::string const &conf)
|
||||
error_code |= init_components_type<eigenvector>(conf, "eigenvector", "eigenvector");
|
||||
error_code |= init_components_type<gspath>(conf, "geometrical path collective variables (s)", "gspath");
|
||||
error_code |= init_components_type<gzpath>(conf, "geometrical path collective variables (z)", "gzpath");
|
||||
error_code |= init_components_type<linearCombination>(conf, "linear combination of other collective variables", "subColvar");
|
||||
error_code |= init_components_type<linearCombination>(conf, "linear combination of other collective variables", "linearCombination");
|
||||
error_code |= init_components_type<gspathCV>(conf, "geometrical path collective variables (s) for other CVs", "gspathCV");
|
||||
error_code |= init_components_type<gzpathCV>(conf, "geometrical path collective variables (z) for other CVs", "gzpathCV");
|
||||
error_code |= init_components_type<aspathCV>(conf, "arithmetic path collective variables (s) for other CVs", "aspathCV");
|
||||
error_code |= init_components_type<azpathCV>(conf, "arithmetic path collective variables (s) for other CVs", "azpathCV");
|
||||
|
||||
if (!cvcs.size() || (error_code != COLVARS_OK)) {
|
||||
cvm::error("Error: no valid components were provided "
|
||||
@ -804,15 +867,26 @@ int colvar::init_components(std::string const &conf)
|
||||
return INPUT_ERROR;
|
||||
}
|
||||
|
||||
// Check for uniqueness of CVC names (esp. if user-provided)
|
||||
for (i = 0; i < cvcs.size(); i++) {
|
||||
for (j = i+1; j < cvcs.size(); j++) {
|
||||
if (cvcs[i]->name == cvcs[j]->name) {
|
||||
cvm::error("Components " + cvm::to_str(i) + " and " + cvm::to_str(j) +\
|
||||
" cannot have the same name \"" + cvcs[i]->name+ "\".\n", INPUT_ERROR);
|
||||
return INPUT_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n_active_cvcs = cvcs.size();
|
||||
|
||||
cvm::log("All components initialized.\n");
|
||||
|
||||
// Store list of children cvcs for dependency checking purposes
|
||||
for (size_t i = 0; i < cvcs.size(); i++) {
|
||||
for (i = 0; i < cvcs.size(); i++) {
|
||||
add_child(cvcs[i]);
|
||||
}
|
||||
|
||||
cvm::log("All components initialized.\n");
|
||||
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
@ -921,7 +995,7 @@ int colvar::parse_analysis(std::string const &conf)
|
||||
return cvm::error("Error: collective variable \""+acf_colvar_name+
|
||||
"\" is not defined at this time.\n", INPUT_ERROR);
|
||||
}
|
||||
cv2->enable(f_cv_fdiff_velocity);
|
||||
cv2->enable(f_cv_fdiff_velocity); // Manual dependency to object of same type
|
||||
} else if (acf_type_str == to_lower_cppstr(std::string("coordinate_p2"))) {
|
||||
acf_type = acf_p2coor;
|
||||
} else {
|
||||
@ -998,6 +1072,8 @@ int colvar::init_dependencies() {
|
||||
init_feature(f_cv_Langevin, "Langevin dynamics", f_type_user);
|
||||
require_feature_self(f_cv_Langevin, f_cv_extended_Lagrangian);
|
||||
|
||||
init_feature(f_cv_single_cvc, "single component", f_type_static);
|
||||
|
||||
init_feature(f_cv_linear, "linear", f_type_static);
|
||||
|
||||
init_feature(f_cv_scalar, "scalar", f_type_static);
|
||||
@ -1023,6 +1099,12 @@ int colvar::init_dependencies() {
|
||||
init_feature(f_cv_upper_boundary, "upper boundary", f_type_user);
|
||||
require_feature_self(f_cv_upper_boundary, f_cv_scalar);
|
||||
|
||||
init_feature(f_cv_hard_lower_boundary, "hard lower boundary", f_type_user);
|
||||
require_feature_self(f_cv_hard_lower_boundary, f_cv_lower_boundary);
|
||||
|
||||
init_feature(f_cv_hard_upper_boundary, "hard upper boundary", f_type_user);
|
||||
require_feature_self(f_cv_hard_upper_boundary, f_cv_upper_boundary);
|
||||
|
||||
init_feature(f_cv_grid, "grid", f_type_dynamic);
|
||||
require_feature_self(f_cv_grid, f_cv_lower_boundary);
|
||||
require_feature_self(f_cv_grid, f_cv_upper_boundary);
|
||||
@ -1227,7 +1309,7 @@ int colvar::collect_cvc_data()
|
||||
}
|
||||
|
||||
|
||||
int colvar::check_cvc_range(int first_cvc, size_t num_cvcs)
|
||||
int colvar::check_cvc_range(int first_cvc, size_t /* num_cvcs */)
|
||||
{
|
||||
if ((first_cvc < 0) || (first_cvc >= ((int) cvcs.size()))) {
|
||||
cvm::error("Error: trying to address a component outside the "
|
||||
@ -1512,7 +1594,7 @@ int colvar::calc_colvar_properties()
|
||||
|
||||
// initialize the restraint center in the first step to the value
|
||||
// just calculated from the cvcs
|
||||
if (cvm::step_relative() == 0 && !after_restart) {
|
||||
if ((cvm::step_relative() == 0 && !after_restart) || x_ext.type() == colvarvalue::type_notset) {
|
||||
x_ext = x;
|
||||
v_ext.reset(); // (already 0; added for clarity)
|
||||
}
|
||||
@ -1859,6 +1941,59 @@ int colvar::update_cvc_config(std::vector<std::string> const &confs)
|
||||
}
|
||||
|
||||
|
||||
int colvar::cvc_param_exists(std::string const ¶m_name)
|
||||
{
|
||||
if (is_enabled(f_cv_single_cvc)) {
|
||||
return cvcs[0]->param_exists(param_name);
|
||||
}
|
||||
return cvm::error("Error: calling colvar::cvc_param_exists() for a variable "
|
||||
"with more than one component.\n", COLVARS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
cvm::real colvar::get_cvc_param(std::string const ¶m_name)
|
||||
{
|
||||
if (is_enabled(f_cv_single_cvc)) {
|
||||
return cvcs[0]->get_param(param_name);
|
||||
}
|
||||
cvm::error("Error: calling colvar::get_cvc_param() for a variable "
|
||||
"with more than one component.\n", COLVARS_NOT_IMPLEMENTED);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
void const *colvar::get_cvc_param_ptr(std::string const ¶m_name)
|
||||
{
|
||||
if (is_enabled(f_cv_single_cvc)) {
|
||||
return cvcs[0]->get_param_ptr(param_name);
|
||||
}
|
||||
cvm::error("Error: calling colvar::get_cvc_param() for a variable "
|
||||
"with more than one component.\n", COLVARS_NOT_IMPLEMENTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue const *colvar::get_cvc_param_grad(std::string const ¶m_name)
|
||||
{
|
||||
if (is_enabled(f_cv_single_cvc)) {
|
||||
return cvcs[0]->get_param_grad(param_name);
|
||||
}
|
||||
cvm::error("Error: calling colvar::get_cvc_param_grad() for a variable "
|
||||
"with more than one component.\n", COLVARS_NOT_IMPLEMENTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int colvar::set_cvc_param(std::string const ¶m_name, void const *new_value)
|
||||
{
|
||||
if (is_enabled(f_cv_single_cvc)) {
|
||||
return cvcs[0]->set_param(param_name, new_value);
|
||||
}
|
||||
return cvm::error("Error: calling colvar::set_cvc_param() for a variable "
|
||||
"with more than one component.\n", COLVARS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
// ******************** METRIC FUNCTIONS ********************
|
||||
// Use the metrics defined by \link colvar::cvc \endlink objects
|
||||
|
||||
|
||||
Reference in New Issue
Block a user