Update Colvars library to version 2024-06-04

This commit is contained in:
Giacomo Fiorin
2024-08-06 01:07:43 +02:00
parent 278accd9ea
commit 133dee9ac1
74 changed files with 7343 additions and 4676 deletions

View File

@ -19,45 +19,40 @@
colvar::cvc::cvc()
{
description = "uninitialized colvar component";
b_try_scalable = true;
sup_coeff = 1.0;
sup_np = 1;
period = 0.0;
wrap_center = 0.0;
width = 0.0;
cvc::init_dependencies();
}
colvar::cvc::cvc(std::string const &conf)
int colvar::cvc::update_description()
{
description = "uninitialized colvar component";
b_try_scalable = true;
sup_coeff = 1.0;
sup_np = 1;
period = 0.0;
wrap_center = 0.0;
width = 0.0;
init_dependencies();
colvar::cvc::init(conf);
if (name.size() > 0) {
description = "cvc \"" + name + "\"";
} else {
description = "unnamed cvc";
}
description += " of type \"" + function_type() + "\"";
return COLVARS_OK;
}
std::string colvar::cvc::function_type() const
{
if (function_types.empty()) {
return "unset";
}
return function_types.back();
}
int colvar::cvc::set_function_type(std::string const &type)
{
function_type = type;
if (function_types.size() == 0) {
function_types.push_back(function_type);
} else {
if (function_types.back() != function_type) {
function_types.push_back(function_type);
}
}
function_types.push_back(type);
update_description();
cvm::main()->cite_feature(function_types[0]+" colvar component");
for (size_t i = function_types.size()-1; i > 0; i--) {
cvm::main()->cite_feature(function_types[i]+" colvar component"+
" (derived from "+function_types[i-1]+")");
}
cvm::main()->cite_feature(function_types[0]+" colvar component");
return COLVARS_OK;
}
@ -67,6 +62,8 @@ int colvar::cvc::init(std::string const &conf)
if (cvm::debug())
cvm::log("Initializing cvc base object.\n");
int error_code = COLVARS_OK;
std::string const old_name(name);
if (name.size() > 0) {
@ -74,18 +71,14 @@ int colvar::cvc::init(std::string const &conf)
}
if (get_keyval(conf, "name", name, name)) {
if (name.size() > 0) {
description = "cvc \"" + name + "\" of type " + function_type;
} else {
description = "unnamed cvc";
}
if ((name != old_name) && (old_name.size() > 0)) {
cvm::error("Error: cannot rename component \""+old_name+
"\" after initialization (new name = \""+name+"\")",
COLVARS_INPUT_ERROR);
error_code |= cvm::error("Error: cannot rename component \"" + old_name +
"\" after initialization (new name = \"" + name + "\")",
COLVARS_INPUT_ERROR);
name = old_name;
}
}
update_description();
get_keyval(conf, "componentCoeff", sup_coeff, sup_coeff);
get_keyval(conf, "componentExp", sup_np, sup_np);
@ -102,6 +95,24 @@ int colvar::cvc::init(std::string const &conf)
register_param("period", reinterpret_cast<void *>(&period));
register_param("wrapAround", reinterpret_cast<void *>(&wrap_center));
if (period != 0.0) {
if (!is_available(f_cvc_periodic)) {
error_code |=
cvm::error("Error: invalid use of period and/or "
"wrapAround in a \"" +
function_type() + "\" component.\n" + "Period: " + cvm::to_str(period) +
" wrapAround: " + cvm::to_str(wrap_center),
COLVARS_INPUT_ERROR);
} else {
enable(f_cvc_periodic);
}
}
if ((wrap_center != 0.0) && !is_enabled(f_cvc_periodic)) {
error_code |= cvm::error("Error: wrapAround was defined for a non-periodic component.\n",
COLVARS_INPUT_ERROR);
}
get_keyval_feature(this, conf, "debugGradients",
f_cvc_debug_gradient, false, parse_silent);
@ -119,7 +130,7 @@ int colvar::cvc::init(std::string const &conf)
if (cvm::debug())
cvm::log("Done initializing cvc base object.\n");
return cvm::get_error();
return error_code;
}
@ -157,10 +168,13 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf,
char const *group_key,
bool optional)
{
cvm::atom_group *group = NULL;
int error_code = COLVARS_OK;
cvm::atom_group *group = nullptr;
std::string group_conf;
if (key_lookup(conf, group_key, &group_conf)) {
group = new cvm::atom_group(group_key);
if (b_try_scalable) {
@ -177,31 +191,42 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf,
// TODO check for other types of parallelism here
}
if (group_conf.size() == 0) {
cvm::error("Error: atom group \""+group->key+
"\" is set, but has no definition.\n",
COLVARS_INPUT_ERROR);
if (group_conf.empty()) {
error_code |= cvm::error("Error: atom group \"" + group->key + "\" has no definition.\n",
COLVARS_INPUT_ERROR);
delete group;
group = nullptr;
// Silence unused variable warning; TODO stop returning a pointer
(void) error_code;
return group;
}
cvm::increase_depth();
if (group->parse(group_conf) == COLVARS_OK) {
error_code |= group->parse(group_conf);
if (error_code != COLVARS_OK) {
error_code |=
cvm::error("Error: in definition of atom group \"" + std::string(group_key) + "\".",
COLVARS_INPUT_ERROR);
delete group;
group = nullptr;
} else {
register_atom_group(group);
}
group->check_keywords(group_conf, group_key);
if (cvm::get_error()) {
cvm::error("Error parsing definition for atom group \""+
std::string(group_key)+"\".", COLVARS_INPUT_ERROR);
error_code |= group->check_keywords(group_conf, group_key);
}
cvm::decrease_depth();
} else {
if (! optional) {
cvm::error("Error: definition for atom group \""+
std::string(group_key)+"\" not found.\n");
if (!optional) {
error_code |=
cvm::error("Error: atom group \"" + std::string(group_key) + "\" is required.\n",
COLVARS_INPUT_ERROR);
}
}
// Silence unused variable warning; TODO stop returning a pointer
(void) error_code;
return group;
}
@ -228,6 +253,8 @@ int colvar::cvc::init_dependencies() {
init_feature(f_cvc_upper_boundary, "defined_upper_boundary", f_type_static);
init_feature(f_cvc_explicit_atom_groups, "explicit_atom_groups", f_type_static);
init_feature(f_cvc_gradient, "gradient", f_type_dynamic);
init_feature(f_cvc_explicit_gradient, "explicit_gradient", f_type_static);
@ -264,6 +291,7 @@ int colvar::cvc::init_dependencies() {
init_feature(f_cvc_collect_atom_ids, "collect_atom_ids", f_type_dynamic);
require_feature_children(f_cvc_collect_atom_ids, f_ag_collect_atom_ids);
require_feature_self(f_cvc_collect_atom_ids, f_cvc_explicit_atom_groups);
// TODO only enable this when f_ag_scalable can be turned on for a pre-initialized group
// require_feature_children(f_cvc_scalable, f_ag_scalable);
@ -281,7 +309,7 @@ int colvar::cvc::init_dependencies() {
// 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++) {
for (i = feature_states.size(); i < colvardeps::f_cvc_ntot; i++) {
bool avail = is_dynamic(i) ? false : true;
feature_states.push_back(feature_state(avail, false));
}
@ -292,6 +320,8 @@ int colvar::cvc::init_dependencies() {
feature_states[f_cvc_gradient].available = true;
feature_states[f_cvc_collect_atom_ids].available = true;
feature_states[f_cvc_periodic].available = false;
// CVCs are enabled from the start - get disabled based on flags
enable(f_cvc_active);
@ -314,7 +344,7 @@ int colvar::cvc::init_dependencies() {
int colvar::cvc::setup()
{
description = "cvc " + name;
update_description();
return COLVARS_OK;
}
@ -349,6 +379,7 @@ void colvar::cvc::init_as_angle()
void colvar::cvc::init_as_periodic_angle()
{
x.type(colvarvalue::type_scalar);
provide(f_cvc_periodic);
enable(f_cvc_periodic);
period = 360.0;
init_scalar_boundaries(-180.0, 180.0);
@ -372,6 +403,7 @@ void colvar::cvc::register_atom_group(cvm::atom_group *ag)
{
atom_groups.push_back(ag);
add_child(ag);
enable(f_cvc_explicit_atom_groups);
}
@ -411,29 +443,21 @@ int colvar::cvc::set_param(std::string const &param_name,
void colvar::cvc::read_data()
{
size_t ig;
for (ig = 0; ig < atom_groups.size(); ig++) {
cvm::atom_group &atoms = *(atom_groups[ig]);
atoms.reset_atoms_data();
atoms.read_positions();
atoms.calc_required_properties();
// each atom group will take care of its own fitting_group, if defined
if (is_enabled(f_cvc_explicit_atom_groups)) {
for (auto agi = atom_groups.begin(); agi != atom_groups.end(); agi++) {
cvm::atom_group &atoms = *(*agi);
atoms.reset_atoms_data();
atoms.read_positions();
atoms.calc_required_properties();
// each atom group will take care of its own fitting_group, if defined
}
}
//// Don't try to get atom velocities, as no back-end currently implements it
// if (tasks[task_output_velocity] && !tasks[task_fdiff_velocity]) {
// for (i = 0; i < cvcs.size(); i++) {
// for (ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
// cvcs[i]->atom_groups[ig]->read_velocities();
// }
// }
// }
}
std::vector<std::vector<int> > colvar::cvc::get_atom_lists()
std::vector<std::vector<int>> colvar::cvc::get_atom_lists()
{
std::vector<std::vector<int> > lists;
std::vector<std::vector<int>> lists;
std::vector<cvm::atom_group *>::iterator agi = atom_groups.begin();
for ( ; agi != atom_groups.end(); ++agi) {
@ -462,12 +486,12 @@ void colvar::cvc::collect_gradients(std::vector<int> const &atom_ids, std::vecto
// If necessary, apply inverse rotation to get atomic
// gradient in the laboratory frame
if (ag.is_enabled(f_ag_rotate)) {
cvm::rotation const rot_inv = ag.rot.inverse();
const auto rot_inv = ag.rot.inverse().matrix();
for (size_t k = 0; k < ag.size(); k++) {
size_t a = std::lower_bound(atom_ids.begin(), atom_ids.end(),
ag[k].id) - atom_ids.begin();
atomic_gradients[a] += coeff * rot_inv.rotate(ag[k].grad);
atomic_gradients[a] += coeff * (rot_inv * ag[k].grad);
}
} else {
@ -494,7 +518,7 @@ void colvar::cvc::collect_gradients(std::vector<int> const &atom_ids, std::vecto
void colvar::cvc::calc_force_invgrads()
{
cvm::error("Error: calculation of inverse gradients is not implemented "
"for colvar components of type \""+function_type+"\".\n",
"for colvar components of type \""+function_type()+"\".\n",
COLVARS_NOT_IMPLEMENTED);
}
@ -502,7 +526,7 @@ void colvar::cvc::calc_force_invgrads()
void colvar::cvc::calc_Jacobian_derivative()
{
cvm::error("Error: calculation of inverse gradients is not implemented "
"for colvar components of type \""+function_type+"\".\n",
"for colvar components of type \""+function_type()+"\".\n",
COLVARS_NOT_IMPLEMENTED);
}
@ -515,6 +539,18 @@ void colvar::cvc::calc_fit_gradients()
}
void colvar::cvc::apply_force(colvarvalue const &cvforce)
{
if (is_enabled(f_cvc_explicit_atom_groups)) {
for (auto agi = atom_groups.begin(); agi != atom_groups.end(); agi++) {
if (!(*agi)->noforce) {
(*agi)->apply_colvar_force(cvforce);
}
}
}
}
void colvar::cvc::debug_gradients()
{
// this function should work for any scalar cvc:
@ -528,8 +564,8 @@ void colvar::cvc::debug_gradients()
cvm::atom_group *group = atom_groups[ig];
if (group->b_dummy) continue;
cvm::rotation const rot_0 = group->rot;
cvm::rotation const rot_inv = group->rot.inverse();
const auto rot_0 = group->rot.matrix();
const auto rot_inv = group->rot.inverse().matrix();
cvm::real x_0 = x.real_value;
if ((x.type() == colvarvalue::type_vector) && (x.size() == 1)) x_0 = x[0];
@ -550,7 +586,7 @@ void colvar::cvc::debug_gradients()
cvm::log((group->fitting_group ? std::string("refPosGroup") : group->key) +
"[" + cvm::to_str(j) + "] = " +
(group->is_enabled(f_ag_rotate) ?
cvm::to_str(rot_0.rotate(group_for_fit->fit_gradients[j])) :
cvm::to_str(rot_0 * (group_for_fit->fit_gradients[j])) :
cvm::to_str(group_for_fit->fit_gradients[j])));
}
}
@ -561,7 +597,7 @@ void colvar::cvc::debug_gradients()
// tests are best conducted in the unrotated (simulation) frame
cvm::rvector const atom_grad = (group->is_enabled(f_ag_rotate) ?
rot_inv.rotate((*group)[ia].grad) :
rot_inv * ((*group)[ia].grad) :
(*group)[ia].grad);
gradient_sum += atom_grad;
@ -634,34 +670,43 @@ void colvar::cvc::debug_gradients()
}
cvm::real colvar::cvc::dist2(colvarvalue const &x1,
colvarvalue const &x2) const
cvm::real colvar::cvc::dist2(colvarvalue const &x1, colvarvalue const &x2) const
{
return x1.dist2(x2);
cvm::real diff = x1.real_value - x2.real_value;
if (is_enabled(f_cvc_periodic)) {
cvm::real const shift = cvm::floor(diff / period + 0.5);
diff -= shift * period;
}
return diff * diff;
}
colvarvalue colvar::cvc::dist2_lgrad(colvarvalue const &x1,
colvarvalue const &x2) const
colvarvalue colvar::cvc::dist2_lgrad(colvarvalue const &x1, colvarvalue const &x2) const
{
return x1.dist2_grad(x2);
cvm::real diff = x1.real_value - x2.real_value;
if (is_enabled(f_cvc_periodic)) {
cvm::real const shift = cvm::floor(diff / period + 0.5);
diff -= shift * period;
}
return 2.0 * diff;
}
colvarvalue colvar::cvc::dist2_rgrad(colvarvalue const &x1,
colvarvalue const &x2) const
colvarvalue colvar::cvc::dist2_rgrad(colvarvalue const &x1, colvarvalue const &x2) const
{
return x2.dist2_grad(x1);
return cvc::dist2_lgrad(x1, x2);
}
void colvar::cvc::wrap(colvarvalue & /* x_unwrapped */) const
void colvar::cvc::wrap(colvarvalue &x_unwrapped) const
{
return;
if (is_enabled(f_cvc_periodic)) {
cvm::real const shift = cvm::floor((x_unwrapped.real_value - wrap_center) / period + 0.5);
x_unwrapped.real_value -= shift * period;
}
}
// Static members
std::vector<colvardeps::feature *> colvar::cvc::cvc_features;