Update Colvars library to version 2019-04-26

The following is list of relevant issues fixed and improvements:

Fix forces and missing output of runtime histogram for histogramRestraint
https://github.com/Colvars/colvars/pull/246

Use fix_modify to add configuration to Colvars:
https://github.com/Colvars/colvars/pull/216

Fix componentCoeff and name not working with orientationAngle components:
https://github.com/Colvars/colvars/issues/213

Fix 1-timestep offset with extendedLagrangian:
https://github.com/Colvars/colvars/pull/210

Changes to improve compiler support:
https://github.com/Colvars/colvars/pull/203

Fix ignored anisotropic cutoff3 for groupCoordNum:
https://github.com/Colvars/colvars/pull/202

New dipoleMagnitude variable:
https://github.com/Colvars/colvars/pull/198

Parser improvements:
https://github.com/Colvars/colvars/pull/196
This commit is contained in:
Giacomo Fiorin 2019-04-30 09:50:12 -04:00
parent 0005ee3e93
commit 7e00acce53
45 changed files with 2378 additions and 1328 deletions

View File

@ -98,6 +98,16 @@ fix to add the energy change from the biasing force added by the fix
to the system's potential energy as part of "thermodynamic
output"_thermo_style.html.
The {fix_modify configfile <config file>} option allows to add settings
from an additional config file to the colvars module. This option can
only be used, after the system has been initialized with a "run"_run.html
command.
The {fix_modify config <quoted string>} option allows to add settings
from inline strings. Those have to fit on a single line when enclosed
in a pair of double quotes ("), or can span multiple lines when bracketed
by a pair of triple double quotes (""", like python embedded documentation).
This fix computes a global scalar which can be accessed by various
"output commands"_Howto_output.html. The scalar is the cumulative
energy change due to this fix. The scalar value calculated by this

View File

@ -24,12 +24,13 @@ colvar::colvar()
{
runave_os = NULL;
prev_timestep = -1;
prev_timestep = -1L;
after_restart = false;
kinetic_energy = 0.0;
potential_energy = 0.0;
init_cv_requires();
description = "uninitialized colvar";
init_dependencies();
}
@ -193,7 +194,7 @@ int colvar::init(std::string const &conf)
{
bool homogeneous = is_enabled(f_cv_linear);
for (i = 0; i < cvcs.size(); i++) {
if ((std::fabs(cvcs[i]->sup_coeff) - 1.0) > 1.0e-10) {
if ((cvm::fabs(cvcs[i]->sup_coeff) - 1.0) > 1.0e-10) {
homogeneous = false;
}
}
@ -224,7 +225,7 @@ int colvar::init(std::string const &conf)
// Allow scripted/custom functions to be defined as periodic
if ( (is_enabled(f_cv_scripted) || is_enabled(f_cv_custom_function)) && is_enabled(f_cv_scalar) ) {
if (get_keyval(conf, "period", period, 0.)) {
set_enabled(f_cv_periodic, true);
enable(f_cv_periodic);
get_keyval(conf, "wrapAround", wrap_center, 0.);
}
}
@ -471,7 +472,7 @@ int colvar::init_grid_parameters(std::string const &conf)
if (get_keyval(conf, "lowerWallConstant", lower_wall_k, 0.0,
parse_silent)) {
cvm::log("Reading legacy options lowerWall and lowerWallConstant: "
"consider using a harmonicWalls restraint.\n");
"consider using a harmonicWalls restraint\n(caution: force constant would then be scaled by width^2).\n");
lower_wall.type(value());
if (!get_keyval(conf, "lowerWall", lower_wall, lower_boundary)) {
cvm::log("Warning: lowerWall will need to be "
@ -485,7 +486,7 @@ int colvar::init_grid_parameters(std::string const &conf)
if (get_keyval(conf, "upperWallConstant", upper_wall_k, 0.0,
parse_silent)) {
cvm::log("Reading legacy options upperWall and upperWallConstant: "
"consider using a harmonicWalls restraint.\n");
"consider using a harmonicWalls restraint\n(caution: force constant would then be scaled by width^2).\n");
upper_wall.type(value());
if (!get_keyval(conf, "upperWall", upper_wall, upper_boundary)) {
cvm::log("Warning: upperWall will need to be "
@ -562,13 +563,13 @@ int colvar::init_extended_Lagrangian(std::string const &conf)
get_keyval_feature(this, conf, "extendedLagrangian", f_cv_extended_Lagrangian, false);
if (is_enabled(f_cv_extended_Lagrangian)) {
cvm::real temp, tolerance, period;
cvm::real temp, tolerance, extended_period;
cvm::log("Enabling the extended Lagrangian term for colvar \""+
this->name+"\".\n");
xr.type(value());
vr.type(value());
x_ext.type(value());
v_ext.type(value());
fr.type(value());
const bool found = get_keyval(conf, "extendedTemp", temp, cvm::temperature());
@ -590,11 +591,11 @@ int colvar::init_extended_Lagrangian(std::string const &conf)
ext_force_k = cvm::boltzmann() * temp / (tolerance * tolerance);
cvm::log("Computed extended system force constant: " + cvm::to_str(ext_force_k) + " [E]/U^2");
get_keyval(conf, "extendedTimeConstant", period, 200.0);
if (period <= 0.0) {
get_keyval(conf, "extendedTimeConstant", extended_period, 200.0);
if (extended_period <= 0.0) {
cvm::error("Error: \"extendedTimeConstant\" must be positive.\n", INPUT_ERROR);
}
ext_mass = (cvm::boltzmann() * temp * period * period)
ext_mass = (cvm::boltzmann() * temp * extended_period * extended_period)
/ (4.0 * PI * PI * tolerance * tolerance);
cvm::log("Computed fictitious mass: " + cvm::to_str(ext_mass) + " [E]/(U/fs)^2 (U: colvar unit)");
@ -615,7 +616,7 @@ int colvar::init_extended_Lagrangian(std::string const &conf)
enable(f_cv_Langevin);
ext_gamma *= 1.0e-3; // correct as long as input is required in ps-1 and cvm::dt() is in fs
// Adjust Langevin sigma for slow time step if time_step_factor != 1
ext_sigma = std::sqrt(2.0 * cvm::boltzmann() * temp * ext_gamma * ext_mass / (cvm::dt() * cvm::real(time_step_factor)));
ext_sigma = cvm::sqrt(2.0 * cvm::boltzmann() * temp * ext_gamma * ext_mass / (cvm::dt() * cvm::real(time_step_factor)));
}
}
@ -761,6 +762,8 @@ int colvar::init_components(std::string const &conf)
"weighted by inverse power", "distanceInv");
error_code |= init_components_type<distance_pairs>(conf, "N1xN2-long vector "
"of pairwise distances", "distancePairs");
error_code |= init_components_type<dipole_magnitude>(conf, "dipole magnitude",
"dipoleMagnitude");
error_code |= init_components_type<coordnum>(conf, "coordination "
"number", "coordNum");
error_code |= init_components_type<selfcoordnum>(conf, "self-coordination "
@ -831,22 +834,25 @@ void colvar::build_atom_list(void)
for (size_t i = 0; i < cvcs.size(); i++) {
for (size_t j = 0; j < cvcs[i]->atom_groups.size(); j++) {
cvm::atom_group &ag = *(cvcs[i]->atom_groups[j]);
cvm::atom_group const &ag = *(cvcs[i]->atom_groups[j]);
for (size_t k = 0; k < ag.size(); k++) {
temp_id_list.push_back(ag[k].id);
}
if (ag.is_enabled(f_ag_fitting_group) && ag.is_enabled(f_ag_fit_gradients)) {
cvm::atom_group const &fg = *(ag.fitting_group);
for (size_t k = 0; k < fg.size(); k++) {
temp_id_list.push_back(fg[k].id);
}
}
}
}
temp_id_list.sort();
temp_id_list.unique();
// atom_ids = std::vector<int> (temp_id_list.begin(), temp_id_list.end());
unsigned int id_i = 0;
std::list<int>::iterator li;
for (li = temp_id_list.begin(); li != temp_id_list.end(); ++li) {
atom_ids[id_i] = *li;
id_i++;
atom_ids.push_back(*li);
}
temp_id_list.clear();
@ -934,16 +940,153 @@ int colvar::parse_analysis(std::string const &conf)
}
void colvar::setup() {
// loop over all components to reset masses of all groups
for (size_t i = 0; i < cvcs.size(); i++) {
for (size_t ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
cvm::atom_group &atoms = *(cvcs[i]->atom_groups[ig]);
atoms.setup();
atoms.reset_mass(name,i,ig);
atoms.read_positions();
int colvar::init_dependencies() {
size_t i;
if (features().size() == 0) {
for (i = 0; i < f_cv_ntot; i++) {
modify_features().push_back(new feature);
}
init_feature(f_cv_active, "active", f_type_dynamic);
// Do not require f_cvc_active in children, as some components may be disabled
// Colvars must be either a linear combination, or scalar (and polynomial) or scripted/custom
require_feature_alt(f_cv_active, f_cv_scalar, f_cv_linear, f_cv_scripted, f_cv_custom_function);
init_feature(f_cv_awake, "awake", f_type_static);
require_feature_self(f_cv_awake, f_cv_active);
init_feature(f_cv_gradient, "gradient", f_type_dynamic);
require_feature_children(f_cv_gradient, f_cvc_gradient);
init_feature(f_cv_collect_gradient, "collect gradient", f_type_dynamic);
require_feature_self(f_cv_collect_gradient, f_cv_gradient);
require_feature_self(f_cv_collect_gradient, f_cv_scalar);
// The following exlusion could be lifted by implementing the feature
exclude_feature_self(f_cv_collect_gradient, f_cv_scripted);
require_feature_children(f_cv_collect_gradient, f_cvc_explicit_gradient);
init_feature(f_cv_fdiff_velocity, "velocity from finite differences", f_type_dynamic);
// System force: either trivial (spring force); through extended Lagrangian, or calculated explicitly
init_feature(f_cv_total_force, "total force", f_type_dynamic);
require_feature_alt(f_cv_total_force, f_cv_extended_Lagrangian, f_cv_total_force_calc);
// Deps for explicit total force calculation
init_feature(f_cv_total_force_calc, "total force calculation", f_type_dynamic);
require_feature_self(f_cv_total_force_calc, f_cv_scalar);
require_feature_self(f_cv_total_force_calc, f_cv_linear);
require_feature_children(f_cv_total_force_calc, f_cvc_inv_gradient);
require_feature_self(f_cv_total_force_calc, f_cv_Jacobian);
init_feature(f_cv_Jacobian, "Jacobian derivative", f_type_dynamic);
require_feature_self(f_cv_Jacobian, f_cv_scalar);
require_feature_self(f_cv_Jacobian, f_cv_linear);
require_feature_children(f_cv_Jacobian, f_cvc_Jacobian);
init_feature(f_cv_hide_Jacobian, "hide Jacobian force", f_type_user);
require_feature_self(f_cv_hide_Jacobian, f_cv_Jacobian); // can only hide if calculated
init_feature(f_cv_extended_Lagrangian, "extended Lagrangian", f_type_user);
require_feature_self(f_cv_extended_Lagrangian, f_cv_scalar);
require_feature_self(f_cv_extended_Lagrangian, f_cv_gradient);
init_feature(f_cv_Langevin, "Langevin dynamics", f_type_user);
require_feature_self(f_cv_Langevin, f_cv_extended_Lagrangian);
init_feature(f_cv_linear, "linear", f_type_static);
init_feature(f_cv_scalar, "scalar", f_type_static);
init_feature(f_cv_output_energy, "output energy", f_type_user);
init_feature(f_cv_output_value, "output value", f_type_user);
init_feature(f_cv_output_velocity, "output velocity", f_type_user);
require_feature_self(f_cv_output_velocity, f_cv_fdiff_velocity);
init_feature(f_cv_output_applied_force, "output applied force", f_type_user);
init_feature(f_cv_output_total_force, "output total force", f_type_user);
require_feature_self(f_cv_output_total_force, f_cv_total_force);
init_feature(f_cv_subtract_applied_force, "subtract applied force from total force", f_type_user);
require_feature_self(f_cv_subtract_applied_force, f_cv_total_force);
init_feature(f_cv_lower_boundary, "lower boundary", f_type_user);
require_feature_self(f_cv_lower_boundary, f_cv_scalar);
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_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);
init_feature(f_cv_runave, "running average", f_type_user);
init_feature(f_cv_corrfunc, "correlation function", f_type_user);
init_feature(f_cv_scripted, "scripted", f_type_user);
init_feature(f_cv_custom_function, "custom function", f_type_user);
exclude_feature_self(f_cv_custom_function, f_cv_scripted);
init_feature(f_cv_periodic, "periodic", f_type_static);
require_feature_self(f_cv_periodic, f_cv_scalar);
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);
// because total forces are obtained from the previous time step,
// we cannot (currently) have colvar values and total forces for the same timestep
init_feature(f_cv_multiple_ts, "multiple timestep colvar", f_type_static);
exclude_feature_self(f_cv_multiple_ts, f_cv_total_force_calc);
// check that everything is initialized
for (i = 0; i < colvardeps::f_cv_ntot; i++) {
if (is_not_set(i)) {
cvm::error("Uninitialized feature " + cvm::to_str(i) + " in " + description);
}
}
}
// Initialize feature_states for each instance
feature_states.reserve(f_cv_ntot);
for (i = 0; i < f_cv_ntot; i++) {
feature_states.push_back(feature_state(true, false));
// Most features are available, so we set them so
// and list exceptions below
}
feature_states[f_cv_fdiff_velocity].available =
cvm::main()->proxy->simulation_running();
return COLVARS_OK;
}
void colvar::setup()
{
// loop over all components to update masses and charges of all groups
for (size_t i = 0; i < cvcs.size(); i++) {
for (size_t ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
cvm::atom_group *atoms = cvcs[i]->atom_groups[ig];
atoms->setup();
atoms->print_properties(name, i, ig);
atoms->read_positions();
}
}
}
std::vector<std::vector<int> > colvar::get_atom_lists()
{
std::vector<std::vector<int> > lists;
for (size_t i = 0; i < cvcs.size(); i++) {
std::vector<std::vector<int> > li = cvcs[i]->get_atom_lists();
lists.insert(lists.end(), li.begin(), li.end());
}
return lists;
}
@ -953,8 +1096,8 @@ colvar::~colvar()
// because the children are cvcs and will be deleted
// just below
// Clear references to this colvar's cvcs as children
// for dependency purposes
// Clear references to this colvar's cvcs as children
// for dependency purposes
remove_all_children();
for (std::vector<cvc *>::reverse_iterator ci = cvcs.rbegin();
@ -1231,7 +1374,6 @@ int colvar::calc_cvc_gradients(int first_cvc, size_t num_cvcs)
int colvar::collect_cvc_gradients()
{
size_t i;
if (is_enabled(f_cv_collect_gradient)) {
// Collect the atomic gradients inside colvar object
for (unsigned int a = 0; a < atomic_gradients.size(); a++) {
@ -1239,34 +1381,7 @@ int colvar::collect_cvc_gradients()
}
for (i = 0; i < cvcs.size(); i++) {
if (!cvcs[i]->is_enabled()) continue;
// Coefficient: d(a * x^n) = a * n * x^(n-1) * dx
cvm::real coeff = (cvcs[i])->sup_coeff * cvm::real((cvcs[i])->sup_np) *
cvm::integer_power((cvcs[i])->value().real_value, (cvcs[i])->sup_np-1);
for (size_t j = 0; j < cvcs[i]->atom_groups.size(); j++) {
cvm::atom_group &ag = *(cvcs[i]->atom_groups[j]);
// If necessary, apply inverse rotation to get atomic
// gradient in the laboratory frame
if (ag.b_rotate) {
cvm::rotation const rot_inv = ag.rot.inverse();
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);
}
} else {
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 * ag[k].grad;
}
}
}
cvcs[i]->collect_gradients(atom_ids, atomic_gradients);
}
}
return COLVARS_OK;
@ -1391,20 +1506,20 @@ 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) {
xr = x;
vr.reset(); // (already 0; added for clarity)
x_ext = x;
v_ext.reset(); // (already 0; added for clarity)
}
// Special case of a repeated timestep (eg. multiple NAMD "run" statements)
// revert values of the extended coordinate and velocity prior to latest integration
if (cvm::step_relative() == prev_timestep) {
xr = prev_xr;
vr = prev_vr;
if (cvm::proxy->simulation_running() && cvm::step_relative() == prev_timestep) {
x_ext = prev_x_ext;
v_ext = prev_v_ext;
}
// report the restraint center as "value"
x_reported = xr;
v_reported = vr;
x_reported = x_ext;
v_reported = v_ext;
// the "total force" with the extended Lagrangian is
// calculated in update_forces_energy() below
@ -1458,77 +1573,86 @@ cvm::real colvar::update_forces_energy()
// extended variable if there is one
if (is_enabled(f_cv_extended_Lagrangian)) {
if (cvm::debug()) {
cvm::log("Updating extended-Lagrangian degree of freedom.\n");
}
if (prev_timestep > -1) {
// Keep track of slow timestep to integrate MTS colvars
// the colvar checks the interval after waking up twice
int n_timesteps = cvm::step_relative() - prev_timestep;
if (n_timesteps != 0 && n_timesteps != time_step_factor) {
cvm::error("Error: extended-Lagrangian " + description + " has timeStepFactor " +
cvm::to_str(time_step_factor) + ", but was activated after " + cvm::to_str(n_timesteps) +
" steps at timestep " + cvm::to_str(cvm::step_absolute()) + " (relative step: " +
cvm::to_str(cvm::step_relative()) + ").\n" +
"Make sure that this colvar is requested by biases at multiples of timeStepFactor.\n");
return 0.;
if (cvm::proxy->simulation_running()) {
// Only integrate the extended equations of motion in running MD simulations
if (cvm::debug()) {
cvm::log("Updating extended-Lagrangian degree of freedom.\n");
}
}
// Integrate with slow timestep (if time_step_factor != 1)
cvm::real dt = cvm::dt() * cvm::real(time_step_factor);
if (prev_timestep > -1) {
// Keep track of slow timestep to integrate MTS colvars
// the colvar checks the interval after waking up twice
int n_timesteps = cvm::step_relative() - prev_timestep;
if (n_timesteps != 0 && n_timesteps != time_step_factor) {
cvm::error("Error: extended-Lagrangian " + description + " has timeStepFactor " +
cvm::to_str(time_step_factor) + ", but was activated after " + cvm::to_str(n_timesteps) +
" steps at timestep " + cvm::to_str(cvm::step_absolute()) + " (relative step: " +
cvm::to_str(cvm::step_relative()) + ").\n" +
"Make sure that this colvar is requested by biases at multiples of timeStepFactor.\n");
return 0.;
}
}
colvarvalue f_ext(fr.type()); // force acting on the extended variable
f_ext.reset();
// Integrate with slow timestep (if time_step_factor != 1)
cvm::real dt = cvm::dt() * cvm::real(time_step_factor);
// the total force is applied to the fictitious mass, while the
// atoms only feel the harmonic force + wall force
// fr: bias force on extended variable (without harmonic spring), for output in trajectory
// 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 (fb_actual will be added just below)
fr = f;
// External force has been scaled for a 1-timestep impulse, scale it back because we will
// integrate it with the colvar's own timestep factor
f_ext = f / cvm::real(time_step_factor);
f_ext += (-0.5 * ext_force_k) * this->dist2_lgrad(xr, x);
f = (-0.5 * ext_force_k) * this->dist2_rgrad(xr, x);
// Coupling force is a slow force, to be applied to atomic coords impulse-style
f *= cvm::real(time_step_factor);
colvarvalue f_ext(fr.type()); // force acting on the extended variable
f_ext.reset();
if (is_enabled(f_cv_subtract_applied_force)) {
// Report a "system" force without the biases on this colvar
// that is, just the spring force
ft_reported = (-0.5 * ext_force_k) * this->dist2_lgrad(xr, x);
// the total force is applied to the fictitious mass, while the
// atoms only feel the harmonic force + wall force
// fr: bias force on extended variable (without harmonic spring), for output in trajectory
// 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 (fb_actual will be added just below)
fr = f;
// External force has been scaled for a 1-timestep impulse, scale it back because we will
// integrate it with the colvar's own timestep factor
f_ext = f / cvm::real(time_step_factor);
f_ext += (-0.5 * ext_force_k) * this->dist2_lgrad(x_ext, x);
f = (-0.5 * ext_force_k) * this->dist2_rgrad(x_ext, x);
// Coupling force is a slow force, to be applied to atomic coords impulse-style
f *= cvm::real(time_step_factor);
if (is_enabled(f_cv_subtract_applied_force)) {
// Report a "system" force without the biases on this colvar
// that is, just the spring force
ft_reported = (-0.5 * ext_force_k) * this->dist2_lgrad(x_ext, x);
} else {
// The total force acting on the extended variable is f_ext
// This will be used in the next timestep
ft_reported = f_ext;
}
// backup in case we need to revert this integration timestep
// if the same MD timestep is re-run
prev_x_ext = x_ext;
prev_v_ext = v_ext;
// leapfrog: starting from x_i, f_i, v_(i-1/2)
v_ext += (0.5 * dt) * f_ext / ext_mass;
// Because of leapfrog, kinetic energy at time i is approximate
kinetic_energy = 0.5 * ext_mass * v_ext * v_ext;
potential_energy = 0.5 * ext_force_k * this->dist2(x_ext, x);
// leap to v_(i+1/2)
if (is_enabled(f_cv_Langevin)) {
v_ext -= dt * ext_gamma * v_ext;
colvarvalue rnd(x);
rnd.set_random();
v_ext += dt * ext_sigma * rnd / ext_mass;
}
v_ext += (0.5 * dt) * f_ext / ext_mass;
x_ext += dt * v_ext;
x_ext.apply_constraints();
this->wrap(x_ext);
} else {
// The total force acting on the extended variable is f_ext
// This will be used in the next timestep
ft_reported = f_ext;
// If this is a postprocessing run (eg. in VMD), the extended DOF
// is equal to the actual coordinate
x_ext = x;
}
// backup in case we need to revert this integration timestep
// if the same MD timestep is re-run
prev_xr = xr;
prev_vr = vr;
// leapfrog: starting from x_i, f_i, v_(i-1/2)
vr += (0.5 * dt) * f_ext / ext_mass;
// Because of leapfrog, kinetic energy at time i is approximate
kinetic_energy = 0.5 * ext_mass * vr * vr;
potential_energy = 0.5 * ext_force_k * this->dist2(xr, x);
// leap to v_(i+1/2)
if (is_enabled(f_cv_Langevin)) {
vr -= dt * ext_gamma * vr;
colvarvalue rnd(x);
rnd.set_random();
vr += dt * ext_sigma * rnd / ext_mass;
}
vr += (0.5 * dt) * f_ext / ext_mass;
xr += dt * vr;
xr.apply_constraints();
this->wrap(xr);
// Report extended value
x_reported = x_ext;
}
// Now adding the force on the actual colvar (for those biases that
@ -1730,7 +1854,7 @@ int colvar::update_cvc_config(std::vector<std::string> const &confs)
// ******************** METRIC FUNCTIONS ********************
// Use the metrics defined by \link cvc \endlink objects
// Use the metrics defined by \link colvar::cvc \endlink objects
bool colvar::periodic_boundaries(colvarvalue const &lb, colvarvalue const &ub) const
@ -1742,7 +1866,7 @@ bool colvar::periodic_boundaries(colvarvalue const &lb, colvarvalue const &ub) c
}
if (period > 0.0) {
if ( ((std::sqrt(this->dist2(lb, ub))) / this->width)
if ( ((cvm::sqrt(this->dist2(lb, ub))) / this->width)
< 1.0E-10 ) {
return true;
}
@ -1792,21 +1916,21 @@ colvarvalue colvar::dist2_rgrad(colvarvalue const &x1,
}
}
void colvar::wrap(colvarvalue &x) const
void colvar::wrap(colvarvalue &x_unwrapped) const
{
if ( !is_enabled(f_cv_periodic) ) {
if (!is_enabled(f_cv_periodic)) {
return;
}
if ( is_enabled(f_cv_scripted) || is_enabled(f_cv_custom_function) ) {
// Scripted functions do their own wrapping, as cvcs might not be periodic
cvm::real shift = std::floor((x.real_value - wrap_center) / period + 0.5);
x.real_value -= shift * period;
cvm::real shift = cvm::floor((x_unwrapped.real_value - wrap_center) /
period + 0.5);
x_unwrapped.real_value -= shift * period;
} else {
cvcs[0]->wrap(x);
cvcs[0]->wrap(x_unwrapped);
}
return;
}
@ -1852,15 +1976,15 @@ std::istream & colvar::read_restart(std::istream &is)
if (is_enabled(f_cv_extended_Lagrangian)) {
if ( !(get_keyval(conf, "extended_x", xr,
if ( !(get_keyval(conf, "extended_x", x_ext,
colvarvalue(x.type()), colvarparse::parse_silent)) &&
!(get_keyval(conf, "extended_v", vr,
!(get_keyval(conf, "extended_v", v_ext,
colvarvalue(x.type()), colvarparse::parse_silent)) ) {
cvm::log("Error: restart file does not contain "
"\"extended_x\" or \"extended_v\" for the colvar \""+
name+"\", but you requested \"extendedLagrangian\".\n");
}
x_reported = xr;
x_reported = x_ext;
} else {
x_reported = x;
}
@ -1875,7 +1999,7 @@ std::istream & colvar::read_restart(std::istream &is)
}
if (is_enabled(f_cv_extended_Lagrangian)) {
v_reported = vr;
v_reported = v_ext;
} else {
v_reported = v_fdiff;
}
@ -1901,8 +2025,8 @@ std::istream & colvar::read_traj(std::istream &is)
}
if (is_enabled(f_cv_extended_Lagrangian)) {
is >> xr;
x_reported = xr;
is >> x_ext;
x_reported = x_ext;
} else {
x_reported = x;
}
@ -1913,8 +2037,8 @@ std::istream & colvar::read_traj(std::istream &is)
is >> v_fdiff;
if (is_enabled(f_cv_extended_Lagrangian)) {
is >> vr;
v_reported = vr;
is >> v_ext;
v_reported = v_ext;
} else {
v_reported = v_fdiff;
}
@ -1955,11 +2079,11 @@ std::ostream & colvar::write_restart(std::ostream &os) {
os << " extended_x "
<< std::setprecision(cvm::cv_prec)
<< std::setw(cvm::cv_width)
<< xr << "\n"
<< x_ext << "\n"
<< " extended_v "
<< std::setprecision(cvm::cv_prec)
<< std::setw(cvm::cv_width)
<< vr << "\n";
<< v_ext << "\n";
}
os << "}\n\n";
@ -2190,6 +2314,7 @@ int colvar::calc_acf()
acf_x_history_p = acf_x_history.begin();
break;
case acf_notset:
default:
break;
}
@ -2222,6 +2347,7 @@ int colvar::calc_acf()
history_incr(acf_x_history, acf_x_history_p);
break;
case acf_notset:
default:
break;
}
@ -2257,7 +2383,7 @@ void colvar::calc_vel_acf(std::list<colvarvalue> &v_list,
void colvar::calc_coor_acf(std::list<colvarvalue> &x_list,
colvarvalue const &x)
colvarvalue const &x_now)
{
// same as above but for coordinates
if (x_list.size() >= acf_length+acf_offset) {
@ -2269,7 +2395,7 @@ void colvar::calc_coor_acf(std::list<colvarvalue> &x_list,
*(acf_i++) += x.norm2();
colvarvalue::inner_opt(x, xs_i, x_list.end(), acf_i);
colvarvalue::inner_opt(x_now, xs_i, x_list.end(), acf_i);
acf_nframes++;
}
@ -2277,7 +2403,7 @@ void colvar::calc_coor_acf(std::list<colvarvalue> &x_list,
void colvar::calc_p2coor_acf(std::list<colvarvalue> &x_list,
colvarvalue const &x)
colvarvalue const &x_now)
{
// same as above but with second order Legendre polynomial instead
// of just the scalar product
@ -2291,7 +2417,7 @@ void colvar::calc_p2coor_acf(std::list<colvarvalue> &x_list,
// value of P2(0) = 1
*(acf_i++) += 1.0;
colvarvalue::p2leg_opt(x, xs_i, x_list.end(), acf_i);
colvarvalue::p2leg_opt(x_now, xs_i, x_list.end(), acf_i);
acf_nframes++;
}
@ -2316,6 +2442,9 @@ int colvar::write_acf(std::ostream &os)
case acf_p2coor:
os << "Coordinate (2nd Legendre poly)";
break;
case acf_notset:
default:
break;
}
if (acf_colvar_name == name) {
@ -2420,7 +2549,7 @@ int colvar::calc_runave()
<< std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
<< runave << " "
<< std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
<< std::sqrt(runave_variance) << "\n";
<< cvm::sqrt(runave_variance) << "\n";
}
history_add_value(runave_length, *x_history_p, x);

View File

@ -92,7 +92,7 @@ public:
static std::vector<feature *> cv_features;
/// \brief Implementation of the feature list accessor for colvar
virtual const std::vector<feature *> &features()
virtual const std::vector<feature *> &features() const
{
return cv_features;
}
@ -133,7 +133,7 @@ protected:
Here:
S(x(t)) = x
s(t) = xr
s(t) = x_ext
DS = Ds = delta
*/
@ -170,13 +170,13 @@ protected:
// Options for extended_lagrangian
/// Restraint center
colvarvalue xr;
colvarvalue x_ext;
/// Previous value of the restraint center;
colvarvalue prev_xr;
colvarvalue prev_x_ext;
/// Velocity of the restraint center
colvarvalue vr;
colvarvalue v_ext;
/// Previous velocity of the restraint center
colvarvalue prev_vr;
colvarvalue prev_v_ext;
/// Mass of the restraint center
cvm::real ext_mass;
/// Restraint force constant
@ -273,6 +273,9 @@ public:
/// Init output flags
int init_output_flags(std::string const &conf);
/// \brief Initialize dependency tree
virtual int init_dependencies();
private:
/// Parse the CVC configuration for all components of a certain type
template<typename def_class_name> int init_components_type(std::string const &conf,
@ -373,7 +376,7 @@ protected:
void update_active_cvc_square_norm();
/// \brief Absolute timestep number when this colvar was last updated
int prev_timestep;
cvm::step_number prev_timestep;
public:
@ -383,32 +386,32 @@ public:
/// \brief Return the number of CVC objects with an active flag (as set by update_cvc_flags)
inline size_t num_active_cvcs() const { return n_active_cvcs; }
/// \brief Use the internal metrics (as from \link cvc
/// \brief Use the internal metrics (as from \link colvar::cvc
/// \endlink objects) to calculate square distances and gradients
///
/// Handles correctly symmetries and periodic boundary conditions
cvm::real dist2(colvarvalue const &x1,
colvarvalue const &x2) const;
/// \brief Use the internal metrics (as from \link cvc
/// \brief Use the internal metrics (as from \link colvar::cvc
/// \endlink objects) to calculate square distances and gradients
///
/// Handles correctly symmetries and periodic boundary conditions
colvarvalue dist2_lgrad(colvarvalue const &x1,
colvarvalue const &x2) const;
/// \brief Use the internal metrics (as from \link cvc
/// \brief Use the internal metrics (as from \link colvar::cvc
/// \endlink objects) to calculate square distances and gradients
///
/// Handles correctly symmetries and periodic boundary conditions
colvarvalue dist2_rgrad(colvarvalue const &x1,
colvarvalue const &x2) const;
/// \brief Use the internal metrics (as from \link cvc
/// \brief Use the internal metrics (as from \link colvar::cvc
/// \endlink objects) to wrap a value into a standard interval
///
/// Handles correctly symmetries and periodic boundary conditions
void wrap(colvarvalue &x) const;
void wrap(colvarvalue &x_unwrapped) const;
/// Read the analysis tasks
@ -546,6 +549,7 @@ public:
class polar_phi;
class distance_inv;
class distance_pairs;
class dipole_magnitude;
class angle;
class dipole_angle;
class dihedral;
@ -574,7 +578,7 @@ public:
protected:
/// \brief Array of \link cvc \endlink objects
/// \brief Array of \link colvar::cvc \endlink objects
std::vector<cvc *> cvcs;
/// \brief Flags to enable or disable cvcs at next colvar evaluation
@ -619,6 +623,9 @@ public:
inline size_t n_components() const {
return cvcs.size();
}
/// \brief Get vector of vectors of atom IDs for all atom groups
virtual std::vector<std::vector<int> > get_atom_lists();
};
inline cvm::real const & colvar::force_constant() const
@ -655,6 +662,8 @@ inline colvarvalue const & colvar::total_force() const
inline void colvar::add_bias_force(colvarvalue const &force)
{
check_enabled(f_cv_gradient,
std::string("applying a force to the variable \""+name+"\""));
if (cvm::debug()) {
cvm::log("Adding biasing force "+cvm::to_str(force)+" to colvar \""+name+"\".\n");
}

View File

@ -33,24 +33,24 @@ namespace UIestimator {
public:
n_matrix() {}
n_matrix(const std::vector<double> & lowerboundary, // lowerboundary of x
const std::vector<double> & upperboundary, // upperboundary of
const std::vector<double> & width, // width of x
const int y_size) { // size of y, for example, ysize=7, then when x=1, the distribution of y in [-2,4] is considered
n_matrix(const std::vector<double> & lowerboundary_input, // lowerboundary of x
const std::vector<double> & upperboundary_input, // upperboundary of
const std::vector<double> & width_input, // width of x
const int y_size_input) { // size of y, for example, ysize=7, then when x=1, the distribution of y in [-2,4] is considered
int i;
this->lowerboundary = lowerboundary;
this->upperboundary = upperboundary;
this->width = width;
this->dimension = lowerboundary.size();
this->y_size = y_size; // keep in mind the internal (spare) matrix is stored in diagonal form
this->y_total_size = int(std::pow(double(y_size), double(dimension)) + EPSILON);
this->lowerboundary = lowerboundary_input;
this->upperboundary = upperboundary_input;
this->width = width_input;
this->dimension = lowerboundary_input.size();
this->y_size = y_size_input; // keep in mind the internal (spare) matrix is stored in diagonal form
this->y_total_size = int(cvm::pow(double(y_size_input), double(dimension)) + EPSILON);
// the range of the matrix is [lowerboundary, upperboundary]
x_total_size = 1;
for (i = 0; i < dimension; i++) {
x_size.push_back(int((upperboundary[i] - lowerboundary[i]) / width[i] + EPSILON));
x_size.push_back(int((upperboundary_input[i] - lowerboundary_input[i]) / width_input[i] + EPSILON));
x_total_size *= x_size[i];
}
@ -89,9 +89,10 @@ namespace UIestimator {
std::vector<int> temp; // this vector is used in convert_x and convert_y to save computational resource
int i, j;
int convert_x(const std::vector<double> & x) { // convert real x value to its interal index
int i, j;
for (i = 0; i < dimension; i++) {
temp[i] = int((x[i] - lowerboundary[i]) / width[i] + EPSILON);
}
@ -121,7 +122,7 @@ namespace UIestimator {
int index = 0;
for (i = 0; i < dimension; i++) {
if (i + 1 < dimension)
index += temp[i] * int(std::pow(double(y_size), double(dimension - i - 1)) + EPSILON);
index += temp[i] * int(cvm::pow(double(y_size), double(dimension - i - 1)) + EPSILON);
else
index += temp[i];
}
@ -139,19 +140,19 @@ namespace UIestimator {
public:
n_vector() {}
n_vector(const std::vector<double> & lowerboundary, // lowerboundary of x
const std::vector<double> & upperboundary, // upperboundary of
const std::vector<double> & width, // width of x
const int y_size, // size of y, for example, ysize=7, then when x=1, the distribution of y in [-2,4] is considered
n_vector(const std::vector<double> & lowerboundary_input, // lowerboundary of x
const std::vector<double> & upperboundary_input, // upperboundary of
const std::vector<double> & width_input, // width of x
const int y_size_input, // size of y, for example, ysize=7, then when x=1, the distribution of y in [-2,4] is considered
const T & default_value) { // the default value of T
this->width = width;
this->dimension = lowerboundary.size();
this->width = width_input;
this->dimension = lowerboundary_input.size();
x_total_size = 1;
for (int i = 0; i < dimension; i++) {
this->lowerboundary.push_back(lowerboundary[i] - (y_size - 1) / 2 * width[i] - EPSILON);
this->upperboundary.push_back(upperboundary[i] + (y_size - 1) / 2 * width[i] + EPSILON);
this->lowerboundary.push_back(lowerboundary_input[i] - (y_size_input - 1) / 2 * width_input[i] - EPSILON);
this->upperboundary.push_back(upperboundary_input[i] + (y_size_input - 1) / 2 * width_input[i] + EPSILON);
x_size.push_back(int((this->upperboundary[i] - this->lowerboundary[i]) / this->width[i] + EPSILON));
x_total_size *= x_size[i];
@ -215,26 +216,26 @@ namespace UIestimator {
UIestimator() {}
//called when (re)start an eabf simulation
UIestimator(const std::vector<double> & lowerboundary,
const std::vector<double> & upperboundary,
const std::vector<double> & width,
const std::vector<double> & krestr, // force constant in eABF
const std::string & output_filename, // the prefix of output files
const int output_freq,
const bool restart, // whether restart from a .count and a .grad file
const std::vector<std::string> & input_filename, // the prefixes of input files
const double temperature) {
UIestimator(const std::vector<double> & lowerboundary_input,
const std::vector<double> & upperboundary_input,
const std::vector<double> & width_input,
const std::vector<double> & krestr_input, // force constant in eABF
const std::string & output_filename_input, // the prefix of output files
const int output_freq_input,
const bool restart_input, // whether restart from a .count and a .grad file
const std::vector<std::string> & input_filename_input, // the prefixes of input files
const double temperature_input) {
// initialize variables
this->lowerboundary = lowerboundary;
this->upperboundary = upperboundary;
this->width = width;
this->krestr = krestr;
this->output_filename = output_filename;
this->output_freq = output_freq;
this->restart = restart;
this->input_filename = input_filename;
this->temperature = temperature;
this->lowerboundary = lowerboundary_input;
this->upperboundary = upperboundary_input;
this->width = width_input;
this->krestr = krestr_input;
this->output_filename = output_filename_input;
this->output_freq = output_freq_input;
this->restart = restart_input;
this->input_filename = input_filename_input;
this->temperature = temperature_input;
int i, j;
@ -300,7 +301,7 @@ namespace UIestimator {
~UIestimator() {}
// called from MD engine every step
bool update(const int step, std::vector<double> x, std::vector<double> y) {
bool update(cvm::step_number step, std::vector<double> x, std::vector<double> y) {
int i;
@ -431,7 +432,7 @@ namespace UIestimator {
loop_flag_y[k] = loop_flag_x[k] - HALF_Y_SIZE * width[k];
}
int j = 0;
j = 0;
while (j >= 0) {
norm += distribution_x_y.get_value(loop_flag_x, loop_flag_y);
for (k = 0; k < dimension; k++) {
@ -672,7 +673,7 @@ namespace UIestimator {
}
// read input files
void read_inputfiles(const std::vector<std::string> input_filename)
void read_inputfiles(const std::vector<std::string> filename)
{
char sharp;
double nothing;
@ -683,11 +684,11 @@ namespace UIestimator {
std::vector<double> position_temp(dimension, 0);
std::vector<double> grad_temp(dimension, 0);
int count_temp = 0;
for (i = 0; i < int(input_filename.size()); i++) {
for (i = 0; i < int(filename.size()); i++) {
int size = 1 , size_temp = 0;
std::string count_filename = input_filename[i] + ".UI.count";
std::string grad_filename = input_filename[i] + ".UI.grad";
std::string count_filename = filename[i] + ".UI.count";
std::string grad_filename = filename[i] + ".UI.grad";
std::ifstream count_file(count_filename.c_str(), std::ios::in);
std::ifstream grad_file(grad_filename.c_str(), std::ios::in);

View File

@ -22,7 +22,7 @@ cvm::atom::atom()
index = -1;
id = -1;
mass = 1.0;
charge = 1.0;
charge = 0.0;
reset_data();
}
@ -107,6 +107,8 @@ cvm::atom_group::~atom_group()
delete fitting_group;
fitting_group = NULL;
}
cvm::main()->unregister_named_atom_group(this);
}
@ -183,10 +185,7 @@ int cvm::atom_group::init()
// These may be overwritten by parse(), if a name is provided
atoms.clear();
// TODO: check with proxy whether atom forces etc are available
init_ag_requires();
init_dependencies();
index = -1;
b_dummy = false;
@ -207,8 +206,67 @@ int cvm::atom_group::init()
}
int cvm::atom_group::init_dependencies() {
size_t i;
// Initialize static array once and for all
if (features().size() == 0) {
for (i = 0; i < f_ag_ntot; i++) {
modify_features().push_back(new feature);
}
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, "fitting group", f_type_static);
init_feature(f_ag_explicit_gradient, "explicit atom gradient", f_type_dynamic);
init_feature(f_ag_fit_gradients, "fit gradients", f_type_user);
require_feature_self(f_ag_fit_gradients, f_ag_explicit_gradient);
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
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);
require_feature_self(f_ag_scalable, f_ag_scalable_com);
// check that everything is initialized
for (i = 0; i < colvardeps::f_ag_ntot; i++) {
if (is_not_set(i)) {
cvm::error("Uninitialized feature " + cvm::to_str(i) + " in " + description);
}
}
}
// Initialize feature_states for each instance
// default as unavailable, not enabled
feature_states.reserve(f_ag_ntot);
for (i = 0; i < colvardeps::f_ag_ntot; i++) {
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;
// f_ag_scalable_com is provided by the CVC iff it is COM-based
feature_states[f_ag_scalable_com].available = false;
// TODO make f_ag_scalable depend on f_ag_scalable_com (or something else)
feature_states[f_ag_scalable].available = true;
feature_states[f_ag_fit_gradients].available = true;
feature_states[f_ag_fitting_group].available = true;
feature_states[f_ag_explicit_gradient].available = true;
return COLVARS_OK;
}
int cvm::atom_group::setup()
{
if (atoms_ids.size() == 0) {
atoms_ids.reserve(atoms.size());
for (cvm::atom_iter ai = atoms.begin(); ai != atoms.end(); ai++) {
atoms_ids.push_back(ai->id);
}
}
for (cvm::atom_iter ai = atoms.begin(); ai != atoms.end(); ai++) {
ai->update_mass();
ai->update_charge();
@ -237,15 +295,6 @@ void cvm::atom_group::update_total_mass()
}
void cvm::atom_group::reset_mass(std::string &name, int i, int j)
{
update_total_mass();
cvm::log("Re-initialized atom group "+name+":"+cvm::to_str(i)+"/"+
cvm::to_str(j)+". "+ cvm::to_str(atoms_ids.size())+
" atoms: total mass = "+cvm::to_str(total_mass)+".\n");
}
void cvm::atom_group::update_total_charge()
{
if (b_dummy) {
@ -264,6 +313,19 @@ void cvm::atom_group::update_total_charge()
}
void cvm::atom_group::print_properties(std::string const &colvar_name,
int i, int j)
{
if (cvm::proxy->updated_masses() && cvm::proxy->updated_charges()) {
cvm::log("Re-initialized atom group for variable \""+colvar_name+"\":"+
cvm::to_str(i)+"/"+
cvm::to_str(j)+". "+ cvm::to_str(atoms_ids.size())+
" atoms: total mass = "+cvm::to_str(total_mass)+
", total charge = "+cvm::to_str(total_charge)+".\n");
}
}
int cvm::atom_group::parse(std::string const &group_conf)
{
cvm::log("Initializing atom group \""+key+"\".\n");
@ -450,10 +512,21 @@ int cvm::atom_group::parse(std::string const &group_conf)
if (cvm::debug())
cvm::log("Done initializing atom group \""+key+"\".\n");
cvm::log("Atom group \""+key+"\" defined, "+
cvm::to_str(atoms_ids.size())+" atoms initialized: total mass = "+
cvm::to_str(total_mass)+", total charge = "+
cvm::to_str(total_charge)+".\n");
{
std::string init_msg;
init_msg.append("Atom group \""+key+"\" defined with "+
cvm::to_str(atoms_ids.size())+" atoms requested");
if ((cvm::proxy)->updated_masses()) {
init_msg.append(": total mass = "+
cvm::to_str(total_mass));
if ((cvm::proxy)->updated_charges()) {
init_msg.append(", total charge = "+
cvm::to_str(total_charge));
}
}
init_msg.append(".\n");
cvm::log(init_msg);
}
if (b_print_atom_ids) {
cvm::log("Internal definition of the atom group:\n");
@ -464,7 +537,7 @@ int cvm::atom_group::parse(std::string const &group_conf)
}
int cvm::atom_group::add_atoms_of_group(atom_group const * ag)
int cvm::atom_group::add_atoms_of_group(atom_group const *ag)
{
std::vector<int> const &source_ids = ag->atoms_ids;
@ -696,6 +769,7 @@ int cvm::atom_group::parse_fitting_options(std::string const &group_conf)
return INPUT_ERROR;
}
}
enable(f_ag_fitting_group);
}
atom_group *group_for_fit = fitting_group ? fitting_group : this;
@ -800,24 +874,24 @@ int cvm::atom_group::create_sorted_ids()
// Sort the internal IDs
std::list<int> sorted_atoms_ids_list;
for (size_t i = 0; i < this->size(); i++) {
for (size_t i = 0; i < atoms_ids.size(); i++) {
sorted_atoms_ids_list.push_back(atoms_ids[i]);
}
sorted_atoms_ids_list.sort();
sorted_atoms_ids_list.unique();
if (sorted_atoms_ids_list.size() != this->size()) {
if (sorted_atoms_ids_list.size() != atoms_ids.size()) {
return cvm::error("Error: duplicate atom IDs in atom group? (found " +
cvm::to_str(sorted_atoms_ids_list.size()) +
" unique atom IDs instead of " +
cvm::to_str(this->size()) + ").\n", BUG_ERROR);
cvm::to_str(atoms_ids.size()) + ").\n", BUG_ERROR);
}
// Compute map between sorted and unsorted elements
sorted_atoms_ids.resize(this->size());
sorted_atoms_ids_map.resize(this->size());
sorted_atoms_ids.resize(atoms_ids.size());
sorted_atoms_ids_map.resize(atoms_ids.size());
std::list<int>::iterator lsii = sorted_atoms_ids_list.begin();
size_t ii = 0;
for ( ; ii < this->size(); lsii++, ii++) {
for ( ; ii < atoms_ids.size(); lsii++, ii++) {
sorted_atoms_ids[ii] = *lsii;
size_t const pos = std::find(atoms_ids.begin(), atoms_ids.end(), *lsii) -
atoms_ids.begin();
@ -1038,15 +1112,15 @@ int cvm::atom_group::calc_center_of_mass()
}
int cvm::atom_group::calc_dipole(cvm::atom_pos const &com)
int cvm::atom_group::calc_dipole(cvm::atom_pos const &dipole_center)
{
if (b_dummy) {
cvm::error("Error: trying to compute the dipole of an empty group.\n", INPUT_ERROR);
return COLVARS_ERROR;
return cvm::error("Error: trying to compute the dipole "
"of a dummy group.\n", INPUT_ERROR);
}
dip.reset();
for (cvm::atom_const_iter ai = this->begin(); ai != this->end(); ai++) {
dip += ai->charge * (ai->pos - com);
dip += ai->charge * (ai->pos - dipole_center);
}
return COLVARS_OK;
}
@ -1056,13 +1130,12 @@ void cvm::atom_group::set_weighted_gradient(cvm::rvector const &grad)
{
if (b_dummy) return;
if (is_enabled(f_ag_scalable)) {
scalar_com_gradient = grad;
return;
}
scalar_com_gradient = grad;
for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) {
ai->grad = (ai->mass/total_mass) * grad;
if (!is_enabled(f_ag_scalable)) {
for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) {
ai->grad = (ai->mass/total_mass) * grad;
}
}
}

View File

@ -17,7 +17,7 @@
/// \brief Stores numeric id, mass and all mutable data for an atom,
/// mostly used by a \link cvc \endlink
/// mostly used by a \link colvar::cvc \endlink
///
/// This class may be used to keep atomic data such as id, mass,
/// position and collective variable derivatives) altogether.
@ -63,7 +63,7 @@ public:
/// from the \link colvarvalue \endlink class), which is also the
/// most frequent case. For more complex types of \link
/// colvarvalue \endlink objects, atomic gradients should be
/// defined within the specific \link cvc \endlink
/// defined within the specific \link colvar::cvc \endlink
/// implementation
cvm::rvector grad;
@ -100,13 +100,19 @@ public:
/// Get the latest value of the mass
inline void update_mass()
{
mass = (cvm::proxy)->get_atom_mass(index);
colvarproxy *p = cvm::proxy;
if (p->updated_masses()) {
mass = p->get_atom_mass(index);
}
}
/// Get the latest value of the charge
inline void update_charge()
{
charge = (cvm::proxy)->get_atom_charge(index);
colvarproxy *p = cvm::proxy;
if (p->updated_charges()) {
charge = p->get_atom_charge(index);
}
}
/// Get the current position
@ -145,7 +151,7 @@ public:
/// \brief Group of \link atom \endlink objects, mostly used by a
/// \link cvc \endlink object to gather all atomic data
/// \link colvar::cvc \endlink object to gather all atomic data
class colvarmodule::atom_group
: public colvarparse, public colvardeps
{
@ -174,6 +180,9 @@ public:
/// \brief Set default values for common flags
int init();
/// \brief Initialize dependency tree
virtual int init_dependencies();
/// \brief Update data required to calculate cvc's
int setup();
@ -198,16 +207,16 @@ public:
/// \brief Remove an atom object from this group
int remove_atom(cvm::atom_iter ai);
/// \brief Re-initialize the total mass of a group.
/// \brief Print the updated the total mass and charge of a group.
/// This is needed in case the hosting MD code has an option to
/// change atom masses after their initialization.
void reset_mass(std::string &name, int i, int j);
void print_properties(std::string const &colvar_name, int i, int j);
/// \brief Implementation of the feature list for atom group
static std::vector<feature *> ag_features;
/// \brief Implementation of the feature list accessor for atom group
virtual const std::vector<feature *> &features()
virtual const std::vector<feature *> &features() const
{
return ag_features;
}
@ -347,15 +356,19 @@ public:
/// Total mass of the atom group
cvm::real total_mass;
/// Update the total mass of the atom group
void update_total_mass();
/// Total charge of the atom group
cvm::real total_charge;
/// Update the total mass of the group
void update_total_charge();
/// \brief Don't apply any force on this group (use its coordinates
/// only to calculate a colvar)
bool noforce;
bool noforce;
/// \brief Get the current positions
void read_positions();
@ -423,20 +436,32 @@ public:
/// \brief Calculate the center of mass of the atomic positions, assuming that
/// they are already pbc-wrapped
int calc_center_of_mass();
private:
/// \brief Center of mass
cvm::atom_pos com;
/// \brief The derivative of a scalar variable with respect to the COM
// TODO for scalable calculations of more complex variables (e.g. rotation),
// use a colvarvalue of vectors to hold the entire derivative
cvm::rvector scalar_com_gradient;
public:
/// \brief Return the center of mass of the atomic positions
/// \brief Return the center of mass (COM) of the atomic positions
inline cvm::atom_pos center_of_mass() const
{
return com;
}
/// \brief Return previously gradient of scalar variable with respect to the
/// COM
inline cvm::rvector center_of_mass_scalar_gradient() const
{
return scalar_com_gradient;
}
/// \brief Return a copy of the current atom positions, shifted by a constant vector
std::vector<cvm::atom_pos> positions_shifted(cvm::rvector const &shift) const;
@ -444,10 +469,15 @@ public:
std::vector<cvm::rvector> velocities() const;
///\brief Calculate the dipole of the atom group around the specified center
int calc_dipole(cvm::atom_pos const &com);
int calc_dipole(cvm::atom_pos const &dipole_center);
private:
/// Dipole moment of the atom group
cvm::rvector dip;
public:
///\brief Return the (previously calculated) dipole of the atom group
inline cvm::rvector dipole() const
{

View File

@ -17,15 +17,14 @@
colvarbias::colvarbias(char const *key)
: bias_type(to_lower_cppstr(key))
{
init_cvb_requires();
description = "uninitialized " + cvm::to_str(key) + " bias";
init_dependencies();
rank = 1;
has_data = false;
b_output_energy = false;
reset();
state_file_step = 0;
description = "uninitialized " + cvm::to_str(key) + " bias";
state_file_step = 0L;
}
@ -76,6 +75,7 @@ int colvarbias::init(std::string const &conf)
cvm::error("Error: no collective variables specified.\n", INPUT_ERROR);
return INPUT_ERROR;
}
} else {
cvm::log("Reinitializing bias \""+name+"\".\n");
}
@ -98,6 +98,70 @@ int colvarbias::init(std::string const &conf)
}
int colvarbias::init_dependencies() {
int i;
if (features().size() == 0) {
for (i = 0; i < f_cvb_ntot; i++) {
modify_features().push_back(new feature);
}
init_feature(f_cvb_active, "active", f_type_dynamic);
require_feature_children(f_cvb_active, f_cv_active);
init_feature(f_cvb_awake, "awake", f_type_static);
require_feature_self(f_cvb_awake, f_cvb_active);
init_feature(f_cvb_apply_force, "apply force", f_type_user);
require_feature_children(f_cvb_apply_force, f_cv_gradient);
init_feature(f_cvb_get_total_force, "obtain total force", f_type_dynamic);
require_feature_children(f_cvb_get_total_force, f_cv_total_force);
init_feature(f_cvb_output_acc_work, "output accumulated work", f_type_user);
require_feature_self(f_cvb_output_acc_work, f_cvb_apply_force);
init_feature(f_cvb_history_dependent, "history-dependent", f_type_static);
init_feature(f_cvb_time_dependent, "time-dependent", f_type_static);
init_feature(f_cvb_scalar_variables, "require scalar variables", f_type_static);
require_feature_children(f_cvb_scalar_variables, f_cv_scalar);
init_feature(f_cvb_calc_pmf, "calculate a PMF", f_type_static);
init_feature(f_cvb_calc_ti_samples, "calculate TI samples", f_type_dynamic);
require_feature_self(f_cvb_calc_ti_samples, f_cvb_get_total_force);
require_feature_children(f_cvb_calc_ti_samples, f_cv_grid);
init_feature(f_cvb_write_ti_samples, "write TI samples ", f_type_user);
require_feature_self(f_cvb_write_ti_samples, f_cvb_calc_ti_samples);
init_feature(f_cvb_write_ti_pmf, "write TI PMF", f_type_user);
require_feature_self(f_cvb_write_ti_pmf, f_cvb_calc_ti_samples);
// check that everything is initialized
for (i = 0; i < colvardeps::f_cvb_ntot; i++) {
if (is_not_set(i)) {
cvm::error("Uninitialized feature " + cvm::to_str(i) + " in " + description);
}
}
}
// Initialize feature_states for each instance
feature_states.reserve(f_cvb_ntot);
for (i = 0; i < f_cvb_ntot; i++) {
feature_states.push_back(feature_state(true, false));
// Most features are available, so we set them so
// and list exceptions below
}
// only compute TI samples when deriving from colvarbias_ti
feature_states[f_cvb_calc_ti_samples].available = false;
return COLVARS_OK;
}
int colvarbias::reset()
{
bias_energy = 0.0;
@ -217,6 +281,9 @@ int colvarbias::update()
void colvarbias::communicate_forces()
{
if (! is_enabled(f_cvb_apply_force)) {
return;
}
size_t i = 0;
for (i = 0; i < num_variables(); i++) {
if (cvm::debug()) {
@ -345,7 +412,8 @@ std::istream & colvarbias::read_state(std::istream &is)
(set_state_params(conf) != COLVARS_OK) ) {
cvm::error("Error: in reading state configuration for \""+bias_type+"\" bias \""+
this->name+"\" at position "+
cvm::to_str(is.tellg())+" in stream.\n", INPUT_ERROR);
cvm::to_str(static_cast<size_t>(is.tellg()))+
" in stream.\n", INPUT_ERROR);
is.clear();
is.seekg(start_pos, std::ios::beg);
is.setstate(std::ios::failbit);
@ -355,7 +423,8 @@ std::istream & colvarbias::read_state(std::istream &is)
if (!read_state_data(is)) {
cvm::error("Error: in reading state data for \""+bias_type+"\" bias \""+
this->name+"\" at position "+
cvm::to_str(is.tellg())+" in stream.\n", INPUT_ERROR);
cvm::to_str(static_cast<size_t>(is.tellg()))+
" in stream.\n", INPUT_ERROR);
is.clear();
is.seekg(start_pos, std::ios::beg);
is.setstate(std::ios::failbit);
@ -365,7 +434,8 @@ std::istream & colvarbias::read_state(std::istream &is)
if (brace != "}") {
cvm::error("Error: corrupt restart information for \""+bias_type+"\" bias \""+
this->name+"\": no matching brace at position "+
cvm::to_str(is.tellg())+" in stream.\n");
cvm::to_str(static_cast<size_t>(is.tellg()))+
" in stream.\n");
is.setstate(std::ios::failbit);
}
@ -381,7 +451,8 @@ std::istream & colvarbias::read_state_data_key(std::istream &is, char const *key
!(key_in == to_lower_cppstr(std::string(key))) ) {
cvm::error("Error: in reading restart configuration for "+
bias_type+" bias \""+this->name+"\" at position "+
cvm::to_str(is.tellg())+" in stream.\n", INPUT_ERROR);
cvm::to_str(static_cast<size_t>(is.tellg()))+
" in stream.\n", INPUT_ERROR);
is.clear();
is.seekg(start_pos, std::ios::beg);
is.setstate(std::ios::failbit);
@ -640,7 +711,7 @@ int colvarbias_ti::write_output_files()
cvm::proxy->close_output_stream(ti_count_file_name);
}
std::string const ti_grad_file_name(ti_output_prefix+".ti.grad");
std::string const ti_grad_file_name(ti_output_prefix+".ti.force");
os = cvm::proxy->output_stream(ti_grad_file_name);
if (os) {
ti_avg_forces->write_multicol(*os);

View File

@ -96,6 +96,9 @@ public:
/// \brief Parse config string and (re)initialize
virtual int init(std::string const &conf);
/// \brief Initialize dependency tree
virtual int init_dependencies();
/// \brief Set to zero all mutable data
virtual int reset();
@ -181,7 +184,7 @@ public:
static std::vector<feature *> cvb_features;
/// \brief Implementation of the feature list accessor for colvarbias
virtual const std::vector<feature *> &features()
virtual const std::vector<feature *> &features() const
{
return cvb_features;
}
@ -220,7 +223,7 @@ protected:
bool has_data;
/// \brief Step number read from the last state file
size_t state_file_step;
cvm::step_number state_file_step;
};

View File

@ -191,10 +191,10 @@ int colvarbias_abf::init(std::string const &conf)
// Projected ABF
get_keyval(conf, "pABFintegrateFreq", pabf_freq, 0);
// Parameters for integrating initial (and final) gradient data
get_keyval(conf, "integrateInitSteps", integrate_initial_steps, 1e4);
get_keyval(conf, "integrateInitMaxIterations", integrate_initial_iterations, 1e4);
get_keyval(conf, "integrateInitTol", integrate_initial_tol, 1e-6);
// for updating the integrated PMF on the fly
get_keyval(conf, "integrateSteps", integrate_steps, 100);
get_keyval(conf, "integrateMaxIterations", integrate_iterations, 100);
get_keyval(conf, "integrateTol", integrate_tol, 1e-4);
}
} else {
@ -366,10 +366,10 @@ int colvarbias_abf::update()
if ( b_integrate ) {
if ( pabf_freq && cvm::step_relative() % pabf_freq == 0 ) {
cvm::real err;
int iter = pmf->integrate(integrate_steps, integrate_tol, err);
if ( iter == integrate_steps ) {
int iter = pmf->integrate(integrate_iterations, integrate_tol, err);
if ( iter == integrate_iterations ) {
cvm::log("Warning: PMF integration did not converge to " + cvm::to_str(integrate_tol)
+ " in " + cvm::to_str(integrate_steps)
+ " in " + cvm::to_str(integrate_iterations)
+ " steps. Residual error: " + cvm::to_str(err));
}
pmf->set_zero_minimum(); // TODO: do this only when necessary
@ -597,7 +597,7 @@ void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool app
if (b_integrate) {
// Do numerical integration (to high precision) and output a PMF
cvm::real err;
pmf->integrate(integrate_initial_steps, integrate_initial_tol, err);
pmf->integrate(integrate_initial_iterations, integrate_initial_tol, err);
pmf->set_zero_minimum();
std::string pmf_out_name = prefix + ".pmf";
@ -661,7 +661,7 @@ void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool app
// Do numerical integration (to high precision) and output a PMF
cvm::real err;
czar_pmf->set_div();
czar_pmf->integrate(integrate_initial_steps, integrate_initial_tol, err);
czar_pmf->integrate(integrate_initial_iterations, integrate_initial_tol, err);
czar_pmf->set_zero_minimum();
std::string czar_pmf_out_name = prefix + ".czar.pmf";

View File

@ -27,9 +27,13 @@ class colvarbias_abf : public colvarbias {
public:
/// Constructor for ABF bias
colvarbias_abf(char const *key);
/// Initializer for ABF bias
virtual int init(std::string const &conf);
/// Default destructor for ABF bias
virtual ~colvarbias_abf();
/// Per-timestep update of ABF bias
virtual int update();
private:
@ -40,11 +44,17 @@ private:
/// Base filename(s) for reading previous gradient data (replaces data from restart file)
std::vector<std::string> input_prefix;
/// Adapt the bias at each time step (as opposed to keeping it constant)?
bool update_bias;
/// Use normalized definition of PMF for distance functions? (flat at long distances)
/// by including the Jacobian term separately of the recorded PMF
bool hide_Jacobian;
/// Integrate gradients into a PMF on output
bool b_integrate;
/// Number of samples per bin before applying the full biasing force
size_t full_samples;
/// Number of samples per bin before applying a scaled-down biasing force
size_t min_samples;
/// frequency for updating output files
int output_freq;
@ -52,6 +62,7 @@ private:
bool b_history_files;
/// Write CZAR output file for stratified eABF (.zgrad)
bool b_czar_window_file;
/// Number of timesteps between recording data in history files (if non-zero)
size_t history_freq;
/// Umbrella Integration estimator of free energy from eABF
UIestimator::UIestimator eabf_UI;
@ -63,25 +74,30 @@ private:
/// Frequency for updating pABF PMF (if zero, pABF is not used)
int pabf_freq;
/// Max number of CG iterations for integrating PMF at startup and for file output
int integrate_initial_steps;
int integrate_initial_iterations;
/// Tolerance for integrating PMF at startup and for file output
cvm::real integrate_initial_tol;
/// Max number of CG iterations for integrating PMF at on-the-fly pABF updates
int integrate_steps;
int integrate_iterations;
/// Tolerance for integrating PMF at on-the-fly pABF updates
cvm::real integrate_tol;
/// Cap the biasing force to be applied?
/// Cap the biasing force to be applied? (option maxForce)
bool cap_force;
/// Maximum force to be applied
std::vector<cvm::real> max_force;
// Frequency for updating 2D gradients
int integrate_freq;
// Internal data and methods
std::vector<int> bin, force_bin, z_bin;
gradient_t system_force, applied_force;
/// Current bin in sample grid
std::vector<int> bin;
/// Current bin in force grid
std::vector<int> force_bin;
/// Cuurent bin in "actual" coordinate, when running extended Lagrangian dynamics
std::vector<int> z_bin;
/// Measured instantaneous system force
gradient_t system_force;
/// n-dim grid of free energy gradients
colvar_grid_gradient *gradients;
@ -118,7 +134,7 @@ private:
// shared ABF
bool shared_on;
size_t shared_freq;
int shared_last_step;
cvm::step_number shared_last_step;
// Share between replicas -- may be called independently of update
virtual int replica_share();

View File

@ -37,7 +37,7 @@ protected:
std::string out_name, out_name_dx;
size_t output_freq;
/// If one or more of the variables are \link type_vector \endlink, treat them as arrays of this length
/// If one or more of the variables are \link colvarvalue::type_vector \endlink, treat them as arrays of this length
size_t colvar_array_size;
/// If colvar_array_size is larger than 1, weigh each one by this number before accumulating the histogram
std::vector<cvm::real> weights;

View File

@ -11,7 +11,6 @@
#include <sstream>
#include <fstream>
#include <iomanip>
#include <cmath>
#include <algorithm>
// used to set the absolute path of a replica file
@ -39,6 +38,8 @@ colvarbias_meta::colvarbias_meta(char const *key)
new_hills_begin = hills.end();
hills_traj_os = NULL;
replica_hills_os = NULL;
ebmeta_equil_steps = 0L;
}
@ -61,7 +62,7 @@ int colvarbias_meta::init(std::string const &conf)
enable(f_cvb_history_dependent);
}
get_keyval(conf, "hillWidth", hill_width, std::sqrt(2.0 * PI) / 2.0);
get_keyval(conf, "hillWidth", hill_width, cvm::sqrt(2.0 * PI) / 2.0);
cvm::log("Half-widths of the Gaussian hills (sigma's):\n");
for (size_t i = 0; i < num_variables(); i++) {
cvm::log(variables(i)->name+std::string(": ")+
@ -201,6 +202,7 @@ int colvarbias_meta::init_ebmeta_params(std::string const &conf)
}
target_dist = new colvar_grid_scalar();
target_dist->init_from_colvars(colvars);
std::string target_dist_file;
get_keyval(conf, "targetdistfile", target_dist_file);
std::ifstream targetdiststream(target_dist_file.c_str());
target_dist->read_multicol(targetdiststream);
@ -221,9 +223,9 @@ int colvarbias_meta::init_ebmeta_params(std::string const &conf)
}
// normalize target distribution and multiply by effective volume = exp(differential entropy)
target_dist->multiply_constant(1.0/target_dist->integral());
cvm::real volume = std::exp(target_dist->entropy());
cvm::real volume = cvm::exp(target_dist->entropy());
target_dist->multiply_constant(volume);
get_keyval(conf, "ebMetaEquilSteps", ebmeta_equil_steps, 0);
get_keyval(conf, "ebMetaEquilSteps", ebmeta_equil_steps, ebmeta_equil_steps);
}
return COLVARS_OK;
@ -291,7 +293,7 @@ colvarbias_meta::create_hill(colvarbias_meta::hill const &h)
// need to be computed analytically when the colvar returns
// off-grid
cvm::real const min_dist = hills_energy->bin_distance_from_boundaries(h.centers, true);
if (min_dist < (3.0 * std::floor(hill_width)) + 1.0) {
if (min_dist < (3.0 * cvm::floor(hill_width)) + 1.0) {
hills_off_grid.push_back(h);
}
}
@ -387,7 +389,7 @@ int colvarbias_meta::update_grid_params()
// first of all, expand the grids, if specified
bool changed_grids = false;
int const min_buffer =
(3 * (size_t) std::floor(hill_width)) + 1;
(3 * (size_t) cvm::floor(hill_width)) + 1;
std::vector<int> new_sizes(hills_energy->sizes());
std::vector<colvarvalue> new_lower_boundaries(hills_energy->lower_boundaries);
@ -492,9 +494,9 @@ int colvarbias_meta::update_bias()
if (ebmeta) {
hills_scale *= 1.0/target_dist->value(target_dist->get_colvars_index());
if(cvm::step_absolute() <= long(ebmeta_equil_steps)) {
if(cvm::step_absolute() <= ebmeta_equil_steps) {
cvm::real const hills_lambda =
(cvm::real(long(ebmeta_equil_steps) - cvm::step_absolute())) /
(cvm::real(ebmeta_equil_steps - cvm::step_absolute())) /
(cvm::real(ebmeta_equil_steps));
hills_scale = hills_lambda + (1-hills_lambda)*hills_scale;
}
@ -508,7 +510,7 @@ int colvarbias_meta::update_bias()
} else {
calc_hills(new_hills_begin, hills.end(), hills_energy_sum_here);
}
hills_scale *= std::exp(-1.0*hills_energy_sum_here/(bias_temperature*cvm::boltzmann()));
hills_scale *= cvm::exp(-1.0*hills_energy_sum_here/(bias_temperature*cvm::boltzmann()));
}
switch (comm) {
@ -710,7 +712,7 @@ void colvarbias_meta::calc_hills(colvarbias_meta::hill_iter h_first,
// set it to zero if the exponent is more negative than log(1.0E-05)
h->value(0.0);
} else {
h->value(std::exp(-0.5*cv_sqdev));
h->value(cvm::exp(-0.5*cv_sqdev));
}
energy += h->energy();
}
@ -904,7 +906,7 @@ void colvarbias_meta::recount_hills_off_grid(colvarbias_meta::hill_iter h_first
for (hill_iter h = h_first; h != h_last; h++) {
cvm::real const min_dist = hills_energy->bin_distance_from_boundaries(h->centers, true);
if (min_dist < (3.0 * std::floor(hill_width)) + 1.0) {
if (min_dist < (3.0 * cvm::floor(hill_width)) + 1.0) {
hills_off_grid.push_back(*h);
}
}
@ -1427,8 +1429,8 @@ std::istream & colvarbias_meta::read_hill(std::istream &is)
return is;
}
size_t h_it;
get_keyval(data, "step", h_it, 0, parse_silent);
cvm::step_number h_it;
get_keyval(data, "step", h_it, 0L, parse_silent);
if (h_it <= state_file_step) {
if (cvm::debug())
cvm::log("Skipping a hill older than the state file for metadynamics bias \""+
@ -1457,7 +1459,7 @@ std::istream & colvarbias_meta::read_hill(std::istream &is)
std::vector<cvm::real> h_widths(num_variables());
get_keyval(data, "widths", h_widths,
std::vector<cvm::real>(num_variables(), (std::sqrt(2.0 * PI) / 2.0)),
std::vector<cvm::real>(num_variables(), (cvm::sqrt(2.0 * PI) / 2.0)),
parse_silent);
std::string h_replica = "";
@ -1482,7 +1484,7 @@ std::istream & colvarbias_meta::read_hill(std::istream &is)
// be computed analytically
cvm::real const min_dist =
hills_energy->bin_distance_from_boundaries((hills.back()).centers, true);
if (min_dist < (3.0 * std::floor(hill_width)) + 1.0) {
if (min_dist < (3.0 * cvm::floor(hill_width)) + 1.0) {
hills_off_grid.push_back(hills.back());
}
}

View File

@ -19,8 +19,8 @@
#include "colvargrid.h"
/// Metadynamics bias (implementation of \link colvarbias \endlink)
class colvarbias_meta
: public virtual colvarbias,
class colvarbias_meta
: public virtual colvarbias,
public virtual colvarbias_ti
{
@ -174,12 +174,14 @@ protected:
/// \brief Biasing temperature in well-tempered metadynamics
cvm::real bias_temperature;
// EBmeta parameters
/// Ensemble-biased metadynamics (EBmeta) flag
bool ebmeta;
/// Target distribution for EBmeta
colvar_grid_scalar* target_dist;
std::string target_dist_file;
cvm::real target_dist_volume;
size_t ebmeta_equil_steps;
/// Number of equilibration steps for EBmeta
cvm::step_number ebmeta_equil_steps;
/// \brief Try to read the restart information by allocating new
@ -285,7 +287,7 @@ public:
friend class colvarbias_meta;
/// Time step at which this hill was added
size_t it;
cvm::step_number it;
/// Identity of the replica who added this hill (only in multiple replica simulations)
std::string replica;
@ -296,9 +298,9 @@ public:
/// replica (optional) Identity of the replica which creates the
/// hill
inline hill(cvm::real const &W_in,
std::vector<colvar *> &cv,
cvm::real const &hill_width,
std::string const &replica_in = "")
std::vector<colvar *> &cv,
cvm::real const &hill_width,
std::string const &replica_in = "")
: sW(1.0),
W(W_in),
centers(cv.size()),
@ -325,11 +327,11 @@ public:
/// weight Weight of the hill \param centers Center of the hill
/// \param widths Width of the hill around centers \param replica
/// (optional) Identity of the replica which creates the hill
inline hill(size_t const &it_in,
cvm::real const &W_in,
std::vector<colvarvalue> const &centers_in,
std::vector<cvm::real> const &widths_in,
std::string const &replica_in = "")
inline hill(cvm::step_number const &it_in,
cvm::real const &W_in,
std::vector<colvarvalue> const &centers_in,
std::vector<cvm::real> const &widths_in,
std::string const &replica_in = "")
: sW(1.0),
W(W_in),
centers(centers_in),

View File

@ -7,8 +7,6 @@
// If you wish to distribute your changes, please submit them to the
// Colvars repository at GitHub.
#include <cmath>
#include "colvarmodule.h"
#include "colvarproxy.h"
#include "colvarvalue.h"
@ -179,7 +177,7 @@ int colvarbias_restraint_k::change_configuration(std::string const &conf)
colvarbias_restraint_moving::colvarbias_restraint_moving(char const *key)
{
target_nstages = 0;
target_nsteps = 0;
target_nsteps = 0L;
stage = 0;
acc_work = 0.0;
b_chg_centers = false;
@ -241,8 +239,8 @@ int colvarbias_restraint_moving::set_state_params(std::string const &conf)
{
if (b_chg_centers || b_chg_force_k) {
if (target_nstages) {
if (!get_keyval(conf, "stage", stage))
cvm::error("Error: current stage is missing from the restart.\n");
get_keyval(conf, "stage", stage, stage,
colvarparse::parse_restart | colvarparse::parse_required);
}
}
return COLVARS_OK;
@ -436,13 +434,13 @@ int colvarbias_restraint_centers_moving::set_state_params(std::string const &con
colvarbias_restraint::set_state_params(conf);
if (b_chg_centers) {
// cvm::log ("Reading the updated restraint centers from the restart.\n");
if (!get_keyval(conf, "centers", colvar_centers))
cvm::error("Error: restraint centers are missing from the restart.\n");
if (is_enabled(f_cvb_output_acc_work)) {
if (!get_keyval(conf, "accumulatedWork", acc_work))
cvm::error("Error: accumulatedWork is missing from the restart.\n");
}
get_keyval(conf, "centers", colvar_centers, colvar_centers,
colvarparse::parse_restart | colvarparse::parse_required);
}
if (is_enabled(f_cvb_output_acc_work)) {
get_keyval(conf, "accumulatedWork", acc_work, acc_work,
colvarparse::parse_restart | colvarparse::parse_required);
}
return COLVARS_OK;
@ -563,7 +561,7 @@ int colvarbias_restraint_k_moving::update()
lambda = 0.0;
}
force_k = starting_force_k + (target_force_k - starting_force_k)
* std::pow(lambda, force_k_exp);
* cvm::pow(lambda, force_k_exp);
cvm::log("Restraint " + this->name + ", stage " + cvm::to_str(stage)
+ " : lambda = " + cvm::to_str(lambda)
+ ", k = " + cvm::to_str(force_k));
@ -585,7 +583,7 @@ int colvarbias_restraint_k_moving::update()
for (size_t i = 0; i < num_variables(); i++) {
dU_dk += d_restraint_potential_dk(i);
}
restraint_FE += force_k_exp * std::pow(lambda, force_k_exp - 1.0)
restraint_FE += force_k_exp * cvm::pow(lambda, force_k_exp - 1.0)
* (target_force_k - starting_force_k) * dU_dk;
}
@ -608,7 +606,7 @@ int colvarbias_restraint_k_moving::update()
lambda = cvm::real(stage) / cvm::real(target_nstages);
}
force_k = starting_force_k + (target_force_k - starting_force_k)
* std::pow(lambda, force_k_exp);
* cvm::pow(lambda, force_k_exp);
cvm::log("Restraint " + this->name + ", stage " + cvm::to_str(stage)
+ " : lambda = " + cvm::to_str(lambda)
+ ", k = " + cvm::to_str(force_k));
@ -622,7 +620,7 @@ int colvarbias_restraint_k_moving::update()
lambda = cvm::real(cvm::step_absolute()) / cvm::real(target_nsteps);
cvm::real const force_k_old = force_k;
force_k = starting_force_k + (target_force_k - starting_force_k)
* std::pow(lambda, force_k_exp);
* cvm::pow(lambda, force_k_exp);
force_k_incr = force_k - force_k_old;
}
}
@ -672,13 +670,13 @@ int colvarbias_restraint_k_moving::set_state_params(std::string const &conf)
colvarbias_restraint::set_state_params(conf);
if (b_chg_force_k) {
// cvm::log ("Reading the updated force constant from the restart.\n");
if (!get_keyval(conf, "forceConstant", force_k, force_k))
cvm::error("Error: force constant is missing from the restart.\n");
if (is_enabled(f_cvb_output_acc_work)) {
if (!get_keyval(conf, "accumulatedWork", acc_work))
cvm::error("Error: accumulatedWork is missing from the restart.\n");
}
get_keyval(conf, "forceConstant", force_k, force_k,
colvarparse::parse_restart | colvarparse::parse_required);
}
if (is_enabled(f_cvb_output_acc_work)) {
get_keyval(conf, "accumulatedWork", acc_work, acc_work,
colvarparse::parse_restart | colvarparse::parse_required);
}
return COLVARS_OK;
@ -719,7 +717,8 @@ std::istream & colvarbias_restraint::read_state(std::istream &is)
(set_state_params(conf) != COLVARS_OK) ) {
cvm::error("Error: in reading state configuration for \""+bias_type+"\" bias \""+
this->name+"\" at position "+
cvm::to_str(is.tellg())+" in stream.\n", INPUT_ERROR);
cvm::to_str(static_cast<size_t>(is.tellg()))+
" in stream.\n", INPUT_ERROR);
is.clear();
is.seekg(start_pos, std::ios::beg);
is.setstate(std::ios::failbit);
@ -729,7 +728,8 @@ std::istream & colvarbias_restraint::read_state(std::istream &is)
if (!read_state_data(is)) {
cvm::error("Error: in reading state data for \""+bias_type+"\" bias \""+
this->name+"\" at position "+
cvm::to_str(is.tellg())+" in stream.\n", INPUT_ERROR);
cvm::to_str(static_cast<size_t>(is.tellg()))+
" in stream.\n", INPUT_ERROR);
is.clear();
is.seekg(start_pos, std::ios::beg);
is.setstate(std::ios::failbit);
@ -740,7 +740,7 @@ std::istream & colvarbias_restraint::read_state(std::istream &is)
cvm::log("brace = "+brace+"\n");
cvm::error("Error: corrupt restart information for \""+bias_type+"\" bias \""+
this->name+"\": no matching brace at position "+
cvm::to_str(is.tellg())+" in stream.\n");
cvm::to_str(static_cast<size_t>(is.tellg()))+" in stream.\n");
is.setstate(std::ios::failbit);
}
@ -787,11 +787,11 @@ int colvarbias_restraint_harmonic::init(std::string const &conf)
colvarbias_restraint_k_moving::init(conf);
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 / (variables(i)->width * variables(i)->width))+
" according to the specified width.\n");
cvm::real const w = variables(i)->width;
cvm::log("The force constant for colvar \""+variables(i)->name+
"\" will be rescaled to "+
cvm::to_str(force_k/(w*w))+
" according to the specified width ("+cvm::to_str(w)+").\n");
}
return COLVARS_OK;
@ -1014,7 +1014,7 @@ int colvarbias_restraint_harmonic_walls::init(std::string const &conf)
INPUT_ERROR);
return INPUT_ERROR;
}
force_k = std::sqrt(lower_wall_k * upper_wall_k);
force_k = cvm::sqrt(lower_wall_k * upper_wall_k);
// transform the two constants to relative values using gemetric mean as ref
// to preserve force_k if provided as single parameter
// (allow changing both via force_k)
@ -1037,25 +1037,21 @@ int colvarbias_restraint_harmonic_walls::init(std::string const &conf)
if (lower_walls.size() > 0) {
for (i = 0; i < num_variables(); i++) {
if (variables(i)->width != 1.0)
cvm::log("The lower wall force constant for colvar \""+
variables(i)->name+
"\" will be rescaled to "+
cvm::to_str(lower_wall_k * force_k /
(variables(i)->width * variables(i)->width))+
" according to the specified width.\n");
cvm::real const w = variables(i)->width;
cvm::log("The lower wall force constant for colvar \""+
variables(i)->name+"\" will be rescaled to "+
cvm::to_str(lower_wall_k * force_k / (w*w))+
" according to the specified width ("+cvm::to_str(w)+").\n");
}
}
if (upper_walls.size() > 0) {
for (i = 0; i < num_variables(); i++) {
if (variables(i)->width != 1.0)
cvm::log("The upper wall force constant for colvar \""+
variables(i)->name+
"\" will be rescaled to "+
cvm::to_str(upper_wall_k * force_k /
(variables(i)->width * variables(i)->width))+
" according to the specified width.\n");
cvm::real const w = variables(i)->width;
cvm::log("The upper wall force constant for colvar \""+
variables(i)->name+"\" will be rescaled to "+
cvm::to_str(upper_wall_k * force_k / (w*w))+
" according to the specified width ("+cvm::to_str(w)+").\n");
}
}
@ -1225,11 +1221,11 @@ int colvarbias_restraint_linear::init(std::string const &conf)
INPUT_ERROR);
return INPUT_ERROR;
}
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 / variables(i)->width)+
" according to the specified width.\n");
cvm::real const w = variables(i)->width;
cvm::log("The force constant for colvar \""+variables(i)->name+
"\" will be rescaled to "+
cvm::to_str(force_k / w)+
" according to the specified width ("+cvm::to_str(w)+").\n");
}
return COLVARS_OK;
@ -1367,6 +1363,7 @@ colvarbias_restraint_histogram::colvarbias_restraint_histogram(char const *key)
int colvarbias_restraint_histogram::init(std::string const &conf)
{
colvarbias::init(conf);
enable(f_cvb_apply_force);
get_keyval(conf, "lowerBoundary", lower_boundary, lower_boundary);
get_keyval(conf, "upperBoundary", upper_boundary, upper_boundary);
@ -1390,7 +1387,7 @@ int colvarbias_restraint_histogram::init(std::string const &conf)
cvm::real const nbins = (upper_boundary - lower_boundary) / width;
int const nbins_round = (int)(nbins);
if (std::fabs(nbins - cvm::real(nbins_round)) > 1.0E-10) {
if (cvm::fabs(nbins - cvm::real(nbins_round)) > 1.0E-10) {
cvm::log("Warning: grid interval ("+
cvm::to_str(lower_boundary, cvm::cv_width, cvm::cv_prec)+" - "+
cvm::to_str(upper_boundary, cvm::cv_width, cvm::cv_prec)+
@ -1440,7 +1437,7 @@ int colvarbias_restraint_histogram::init(std::string const &conf)
}
}
cvm::real const ref_integral = ref_p.sum() * width;
if (std::fabs(ref_integral - 1.0) > 1.0e-03) {
if (cvm::fabs(ref_integral - 1.0) > 1.0e-03) {
cvm::log("Reference distribution not normalized, normalizing to unity.\n");
ref_p /= ref_integral;
}
@ -1471,7 +1468,7 @@ int colvarbias_restraint_histogram::update()
vector_size += variables(icv)->value().size();
}
cvm::real const norm = 1.0/(std::sqrt(2.0*PI)*gaussian_width*vector_size);
cvm::real const norm = 1.0/(cvm::sqrt(2.0*PI)*gaussian_width*vector_size);
// calculate the histogram
p.reset();
@ -1482,7 +1479,7 @@ int colvarbias_restraint_histogram::update()
size_t igrid;
for (igrid = 0; igrid < p.size(); igrid++) {
cvm::real const x_grid = (lower_boundary + (igrid+0.5)*width);
p[igrid] += norm * std::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
p[igrid] += norm * cvm::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
(2.0 * gaussian_width * gaussian_width));
}
} else if (cv.type() == colvarvalue::type_vector) {
@ -1492,7 +1489,7 @@ int colvarbias_restraint_histogram::update()
size_t igrid;
for (igrid = 0; igrid < p.size(); igrid++) {
cvm::real const x_grid = (lower_boundary + (igrid+0.5)*width);
p[igrid] += norm * std::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
p[igrid] += norm * cvm::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
(2.0 * gaussian_width * gaussian_width));
}
}
@ -1523,7 +1520,7 @@ int colvarbias_restraint_histogram::update()
for (igrid = 0; igrid < p.size(); igrid++) {
cvm::real const x_grid = (lower_boundary + (igrid+0.5)*width);
force += force_k_cv * p_diff[igrid] *
norm * std::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
norm * cvm::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
(2.0 * gaussian_width * gaussian_width)) *
(-1.0 * (x_grid - cv_value) / (gaussian_width * gaussian_width));
}
@ -1536,7 +1533,7 @@ int colvarbias_restraint_histogram::update()
for (igrid = 0; igrid < p.size(); igrid++) {
cvm::real const x_grid = (lower_boundary + (igrid+0.5)*width);
force += force_k_cv * p_diff[igrid] *
norm * std::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
norm * cvm::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
(2.0 * gaussian_width * gaussian_width)) *
(-1.0 * (x_grid - cv_value) / (gaussian_width * gaussian_width));
}
@ -1550,7 +1547,7 @@ int colvarbias_restraint_histogram::update()
}
std::ostream & colvarbias_restraint_histogram::write_restart(std::ostream &os)
int colvarbias_restraint_histogram::write_output_files()
{
if (b_write_histogram) {
std::string file_name(cvm::output_prefix()+"."+this->name+".hist.dat");
@ -1558,6 +1555,9 @@ std::ostream & colvarbias_restraint_histogram::write_restart(std::ostream &os)
*os << "# " << cvm::wrap_string(variables(0)->name, cvm::cv_width)
<< " " << "p(" << cvm::wrap_string(variables(0)->name, cvm::cv_width-3)
<< ")\n";
os->setf(std::ios::fixed, std::ios::floatfield);
size_t igrid;
for (igrid = 0; igrid < p.size(); igrid++) {
cvm::real const x_grid = (lower_boundary + (igrid+1)*width);
@ -1572,13 +1572,7 @@ std::ostream & colvarbias_restraint_histogram::write_restart(std::ostream &os)
}
cvm::proxy->close_output_stream(file_name);
}
return os;
}
std::istream & colvarbias_restraint_histogram::read_restart(std::istream &is)
{
return is;
return COLVARS_OK;
}

View File

@ -132,7 +132,7 @@ protected:
/// \brief Number of steps required to reach the target force constant
/// or restraint centers
long target_nsteps;
cvm::step_number target_nsteps;
/// \brief Accumulated work (computed when outputAccumulatedWork == true)
cvm::real acc_work;
@ -328,8 +328,7 @@ public:
virtual int update();
virtual std::istream & read_restart(std::istream &is);
virtual std::ostream & write_restart(std::ostream &os);
virtual int write_output_files();
virtual std::ostream & write_traj_label(std::ostream &os);
virtual std::ostream & write_traj(std::ostream &os);

View File

@ -20,7 +20,8 @@ colvar::cvc::cvc()
b_periodic(false),
b_try_scalable(true)
{
init_cvc_requires();
description = "uninitialized colvar component";
init_dependencies();
sup_coeff = 1.0;
period = 0.0;
wrap_center = 0.0;
@ -33,7 +34,8 @@ colvar::cvc::cvc(std::string const &conf)
b_periodic(false),
b_try_scalable(true)
{
init_cvc_requires();
description = "uninitialized colvar component";
init_dependencies();
sup_coeff = 1.0;
period = 0.0;
wrap_center = 0.0;
@ -176,6 +178,100 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf,
}
int colvar::cvc::init_dependencies() {
size_t i;
// Initialize static array once and for all
if (features().size() == 0) {
for (i = 0; i < colvardeps::f_cvc_ntot; i++) {
modify_features().push_back(new feature);
}
init_feature(f_cvc_active, "active", f_type_dynamic);
// The dependency below may become useful if we use dynamic atom groups
// require_feature_children(f_cvc_active, f_ag_active);
init_feature(f_cvc_scalar, "scalar", f_type_static);
init_feature(f_cvc_gradient, "gradient", f_type_dynamic);
init_feature(f_cvc_explicit_gradient, "explicit gradient", f_type_static);
require_feature_children(f_cvc_explicit_gradient, f_ag_explicit_gradient);
init_feature(f_cvc_inv_gradient, "inverse gradient", f_type_dynamic);
require_feature_self(f_cvc_inv_gradient, f_cvc_gradient);
init_feature(f_cvc_debug_gradient, "debug gradient", f_type_user);
require_feature_self(f_cvc_debug_gradient, f_cvc_gradient);
require_feature_self(f_cvc_debug_gradient, f_cvc_explicit_gradient);
init_feature(f_cvc_Jacobian, "Jacobian derivative", f_type_dynamic);
require_feature_self(f_cvc_Jacobian, f_cvc_inv_gradient);
init_feature(f_cvc_com_based, "depends on group centers of mass", f_type_static);
init_feature(f_cvc_pbc_minimum_image, "use minimum-image distances with PBCs", f_type_user);
// Compute total force on first site only to avoid unwanted
// coupling to other colvars (see e.g. Ciccotti et al., 2005)
init_feature(f_cvc_one_site_total_force, "compute total force from one group", f_type_user);
require_feature_self(f_cvc_one_site_total_force, f_cvc_com_based);
init_feature(f_cvc_scalable, "scalable calculation", f_type_static);
require_feature_self(f_cvc_scalable, f_cvc_scalable_com);
init_feature(f_cvc_scalable_com, "scalable calculation of centers of mass", f_type_static);
require_feature_self(f_cvc_scalable_com, f_cvc_com_based);
// 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);
// require_feature_children(f_cvc_scalable_com, f_ag_scalable_com);
// check that everything is initialized
for (i = 0; i < colvardeps::f_cvc_ntot; i++) {
if (is_not_set(i)) {
cvm::error("Uninitialized feature " + cvm::to_str(i) + " in " + description);
}
}
}
// Initialize feature_states for each instance
// 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++) {
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;
// CVCs are enabled from the start - get disabled based on flags
enable(f_cvc_active);
// feature_states[f_cvc_active].enabled = true;
// Explicit gradients are implemented in mosts CVCs. Exceptions must be specified explicitly.
// feature_states[f_cvc_explicit_gradient].enabled = true;
enable(f_cvc_explicit_gradient);
// Use minimum-image distances by default
// feature_states[f_cvc_pbc_minimum_image].enabled = true;
enable(f_cvc_pbc_minimum_image);
// Features that are implemented by default if their requirements are
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;
return COLVARS_OK;
}
int colvar::cvc::setup()
{
description = "cvc " + name;
@ -192,6 +288,7 @@ colvar::cvc::~cvc()
}
}
void colvar::cvc::read_data()
{
size_t ig;
@ -214,6 +311,66 @@ void colvar::cvc::read_data()
}
std::vector<std::vector<int> > colvar::cvc::get_atom_lists()
{
std::vector<std::vector<int> > lists;
std::vector<cvm::atom_group *>::iterator agi = atom_groups.begin();
for ( ; agi != atom_groups.end(); ++agi) {
(*agi)->create_sorted_ids();
lists.push_back((*agi)->sorted_ids());
if ((*agi)->is_enabled(f_ag_fitting_group) && (*agi)->is_enabled(f_ag_fit_gradients)) {
cvm::atom_group &fg = *((*agi)->fitting_group);
fg.create_sorted_ids();
lists.push_back(fg.sorted_ids());
}
}
return lists;
}
void colvar::cvc::collect_gradients(std::vector<int> const &atom_ids, std::vector<cvm::rvector> &atomic_gradients)
{
// Coefficient: d(a * x^n) = a * n * x^(n-1) * dx
cvm::real coeff = sup_coeff * cvm::real(sup_np) *
cvm::integer_power(value().real_value, sup_np-1);
for (size_t j = 0; j < atom_groups.size(); j++) {
cvm::atom_group &ag = *(atom_groups[j]);
// If necessary, apply inverse rotation to get atomic
// gradient in the laboratory frame
if (ag.b_rotate) {
cvm::rotation const rot_inv = ag.rot.inverse();
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);
}
} else {
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 * ag[k].grad;
}
}
if (ag.is_enabled(f_ag_fitting_group) && ag.is_enabled(f_ag_fit_gradients)) {
cvm::atom_group const &fg = *(ag.fitting_group);
for (size_t k = 0; k < fg.size(); k++) {
size_t a = std::lower_bound(atom_ids.begin(), atom_ids.end(),
fg[k].id) - atom_ids.begin();
// fit gradients are in the unrotated (simulation) frame
atomic_gradients[a] += coeff * fg.fit_gradients[k];
}
}
}
}
void colvar::cvc::calc_force_invgrads()
{
cvm::error("Error: calculation of inverse gradients is not implemented "
@ -306,8 +463,8 @@ void colvar::cvc::debug_gradients()
cvm::log("dx(interp) = "+cvm::to_str(dx_pred,
21, 14)+"\n");
cvm::log("|dx(actual) - dx(interp)|/|dx(actual)| = "+
cvm::to_str(std::fabs(x_1 - x_0 - dx_pred) /
std::fabs(x_1 - x_0), 12, 5)+"\n");
cvm::to_str(cvm::fabs(x_1 - x_0 - dx_pred) /
cvm::fabs(x_1 - x_0), 12, 5)+"\n");
}
}
@ -341,8 +498,8 @@ void colvar::cvc::debug_gradients()
cvm::log("dx(interp) = "+cvm::to_str (dx_pred,
21, 14)+"\n");
cvm::log ("|dx(actual) - dx(interp)|/|dx(actual)| = "+
cvm::to_str(std::fabs (x_1 - x_0 - dx_pred) /
std::fabs (x_1 - x_0),
cvm::to_str(cvm::fabs (x_1 - x_0 - dx_pred) /
cvm::fabs (x_1 - x_0),
12, 5)+
".\n");
}
@ -378,7 +535,7 @@ colvarvalue colvar::cvc::dist2_rgrad(colvarvalue const &x1,
}
void colvar::cvc::wrap(colvarvalue &x) const
void colvar::cvc::wrap(colvarvalue &x_unwrapped) const
{
return;
}

View File

@ -27,12 +27,12 @@
/// \brief Colvar component (base class for collective variables)
///
/// A \link cvc \endlink object (or an object of a
/// A \link colvar::cvc \endlink object (or an object of a
/// cvc-derived class) implements the calculation of a collective
/// variable, its gradients and any other related physical quantities
/// that depend on microscopic degrees of freedom.
///
/// No restriction is set to what kind of calculation a \link cvc \endlink
/// No restriction is set to what kind of calculation a \link colvar::cvc \endlink
/// object performs (usually an analytical function of atomic coordinates).
/// The only constraints are that: \par
///
@ -42,9 +42,9 @@
/// alike, and allows an automatic selection of the applicable algorithms.
///
/// - The object provides an implementation \link apply_force() \endlink to
/// apply forces to atoms. Typically, one or more \link cvm::atom_group
/// apply forces to atoms. Typically, one or more \link colvarmodule::atom_group
/// \endlink objects are used, but this is not a requirement for as long as
/// the \link cvc \endlink object communicates with the simulation program.
/// the \link colvar::cvc \endlink object communicates with the simulation program.
///
/// <b> If you wish to implement a new collective variable component, you
/// should write your own class by inheriting directly from \link
@ -75,9 +75,9 @@ public:
/// \brief Description of the type of collective variable
///
/// Normally this string is set by the parent \link colvar \endlink
/// object within its constructor, when all \link cvc \endlink
/// object within its constructor, when all \link colvar::cvc \endlink
/// objects are initialized; therefore the main "config string"
/// constructor does not need to define it. If a \link cvc
/// constructor does not need to define it. If a \link colvar::cvc
/// \endlink is initialized and/or a different constructor is used,
/// this variable definition should be set within the constructor.
std::string function_type;
@ -109,6 +109,9 @@ public:
/// cvc \endlink
virtual int init(std::string const &conf);
/// \brief Initialize dependency tree
virtual int init_dependencies();
/// \brief Within the constructor, make a group parse its own
/// options from the provided configuration string
/// Returns reference to new group
@ -122,7 +125,7 @@ public:
/// \brief After construction, set data related to dependency handling
int setup();
/// \brief Default constructor (used when \link cvc \endlink
/// \brief Default constructor (used when \link colvar::cvc \endlink
/// objects are declared within other ones)
cvc();
@ -133,7 +136,7 @@ public:
static std::vector<feature *> cvc_features;
/// \brief Implementation of the feature list accessor for colvar
virtual const std::vector<feature *> &features()
virtual const std::vector<feature *> &features() const
{
return cvc_features;
}
@ -148,6 +151,9 @@ public:
cvc_features.clear();
}
/// \brief Get vector of vectors of atom IDs for all atom groups
virtual std::vector<std::vector<int> > get_atom_lists();
/// \brief Obtain data needed for the calculation for the backend
virtual void read_data();
@ -164,6 +170,10 @@ public:
/// \brief Calculate finite-difference gradients alongside the analytical ones, for each Cartesian component
virtual void debug_gradients();
/// \brief Calculate atomic gradients and add them to the corresponding item in gradient vector
/// May be overridden by CVCs that do not store their gradients in the classic way, see dihedPC
virtual void collect_gradients(std::vector<int> const &atom_ids, std::vector<cvm::rvector> &atomic_gradients);
/// \brief Calculate the total force from the system using the
/// inverse atomic gradients
virtual void calc_force_invgrads();
@ -237,7 +247,7 @@ public:
colvarvalue const &x2) const;
/// \brief Wrap value (for periodic/symmetric cvcs)
virtual void wrap(colvarvalue &x) const;
virtual void wrap(colvarvalue &x_unwrapped) const;
/// \brief Pointers to all atom groups, to let colvars collect info
/// e.g. atomic gradients
@ -246,7 +256,7 @@ public:
/// \brief Store a pointer to new atom group, and list as child for dependencies
inline void register_atom_group(cvm::atom_group *ag) {
atom_groups.push_back(ag);
add_child((colvardeps *) ag);
add_child(ag);
}
/// \brief Whether or not this CVC will be computed in parallel whenever possible
@ -415,7 +425,7 @@ public:
virtual colvarvalue dist2_rgrad(colvarvalue const &x1,
colvarvalue const &x2) const;
/// \brief Redefined to make use of the user-provided period
virtual void wrap(colvarvalue &x) const;
virtual void wrap(colvarvalue &x_unwrapped) const;
};
@ -474,7 +484,7 @@ public:
virtual colvarvalue dist2_rgrad(colvarvalue const &x1,
colvarvalue const &x2) const;
/// Redefined to handle the 2*PI periodicity
virtual void wrap(colvarvalue &x) const;
virtual void wrap(colvarvalue &x_unwrapped) const;
};
@ -559,6 +569,35 @@ public:
/// \brief Colvar component: dipole magnitude of a molecule
class colvar::dipole_magnitude
: public colvar::cvc
{
protected:
/// Dipole atom group
cvm::atom_group *atoms;
cvm::atom_pos dipoleV;
public:
/// Initialize by parsing the configuration
dipole_magnitude (std::string const &conf);
dipole_magnitude (cvm::atom const &a1);
dipole_magnitude();
virtual inline ~dipole_magnitude() {}
virtual void calc_value();
virtual void calc_gradients();
//virtual void calc_force_invgrads();
//virtual void calc_Jacobian_derivative();
virtual void apply_force (colvarvalue const &force);
virtual cvm::real dist2 (colvarvalue const &x1,
colvarvalue const &x2) const;
virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
colvarvalue const &x2) const;
virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
colvarvalue const &x2) const;
};
/// \brief Colvar component: Radius of gyration of an atom group
/// (colvarvalue::type_scalar type, range [0:*))
class colvar::gyration
@ -818,7 +857,7 @@ public:
virtual colvarvalue dist2_rgrad(colvarvalue const &x1,
colvarvalue const &x2) const;
/// Redefined to handle the 2*PI periodicity
virtual void wrap(colvarvalue &x) const;
virtual void wrap(colvarvalue &x_unwrapped) const;
};
@ -1002,7 +1041,7 @@ public:
cvm::atom const &donor,
cvm::real r0, int en, int ed);
h_bond();
virtual ~h_bond();
virtual ~h_bond() {}
virtual void calc_value();
virtual void calc_gradients();
virtual void apply_force(colvarvalue const &force);
@ -1090,6 +1129,8 @@ public:
virtual ~alpha_angles();
void calc_value();
void calc_gradients();
/// Re-implementation of cvc::collect_gradients() to carry over atomic gradients of sub-cvcs
void collect_gradients(std::vector<int> const &atom_ids, std::vector<cvm::rvector> &atomic_gradients);
void apply_force(colvarvalue const &force);
virtual cvm::real dist2(colvarvalue const &x1,
colvarvalue const &x2) const;
@ -1120,6 +1161,8 @@ public:
virtual ~dihedPC();
void calc_value();
void calc_gradients();
/// Re-implementation of cvc::collect_gradients() to carry over atomic gradients of sub-cvcs
void collect_gradients(std::vector<int> const &atom_ids, std::vector<cvm::rvector> &atomic_gradients);
void apply_force(colvarvalue const &force);
virtual cvm::real dist2(colvarvalue const &x1,
colvarvalue const &x2) const;
@ -1159,6 +1202,7 @@ public:
orientation(std::string const &conf);
orientation();
virtual int init(std::string const &conf);
virtual ~orientation() {}
virtual void calc_value();
virtual void calc_gradients();
@ -1183,6 +1227,7 @@ public:
orientation_angle(std::string const &conf);
orientation_angle();
virtual int init(std::string const &conf);
virtual ~orientation_angle() {}
virtual void calc_value();
virtual void calc_gradients();
@ -1207,6 +1252,7 @@ public:
orientation_proj(std::string const &conf);
orientation_proj();
virtual int init(std::string const &conf);
virtual ~orientation_proj() {}
virtual void calc_value();
virtual void calc_gradients();
@ -1234,6 +1280,7 @@ public:
tilt(std::string const &conf);
tilt();
virtual int init(std::string const &conf);
virtual ~tilt() {}
virtual void calc_value();
virtual void calc_gradients();
@ -1261,6 +1308,7 @@ public:
spin_angle(std::string const &conf);
spin_angle();
virtual int init(std::string const &conf);
virtual ~spin_angle() {}
virtual void calc_value();
virtual void calc_gradients();
@ -1275,7 +1323,7 @@ public:
virtual colvarvalue dist2_rgrad(colvarvalue const &x1,
colvarvalue const &x2) const;
/// Redefined to handle the 2*PI periodicity
virtual void wrap(colvarvalue &x) const;
virtual void wrap(colvarvalue &x_unwrapped) const;
};

View File

@ -11,9 +11,6 @@
#include "colvar.h"
#include "colvarcomp.h"
#include <cmath>
colvar::angle::angle(std::string const &conf)
: cvc(conf)
@ -77,14 +74,14 @@ void colvar::angle::calc_value()
cvm::real const cos_theta = (r21*r23)/(r21l*r23l);
x.real_value = (180.0/PI) * std::acos(cos_theta);
x.real_value = (180.0/PI) * cvm::acos(cos_theta);
}
void colvar::angle::calc_gradients()
{
cvm::real const cos_theta = (r21*r23)/(r21l*r23l);
cvm::real const dxdcos = -1.0 / std::sqrt(1.0 - cos_theta*cos_theta);
cvm::real const dxdcos = -1.0 / cvm::sqrt(1.0 - cos_theta*cos_theta);
dxdr1 = (180.0/PI) * dxdcos *
(1.0/r21l) * ( r23/r23l + (-1.0) * cos_theta * r21/r21l );
@ -126,7 +123,7 @@ void colvar::angle::calc_Jacobian_derivative()
// det(J) = (2 pi) r^2 * sin(theta)
// hence Jd = cot(theta)
const cvm::real theta = x.real_value * PI / 180.0;
jd = PI / 180.0 * (theta != 0.0 ? std::cos(theta) / std::sin(theta) : 0.0);
jd = PI / 180.0 * (theta != 0.0 ? cvm::cos(theta) / cvm::sin(theta) : 0.0);
}
@ -202,7 +199,7 @@ void colvar::dipole_angle::calc_value()
cvm::real const cos_theta = (r21*r23)/(r21l*r23l);
x.real_value = (180.0/PI) * std::acos(cos_theta);
x.real_value = (180.0/PI) * cvm::acos(cos_theta);
}
//to be implemented
@ -212,7 +209,7 @@ void colvar::dipole_angle::calc_value()
void colvar::dipole_angle::calc_gradients()
{
cvm::real const cos_theta = (r21*r23)/(r21l*r23l);
cvm::real const dxdcos = -1.0 / std::sqrt(1.0 - cos_theta*cos_theta);
cvm::real const dxdcos = -1.0 / cvm::sqrt(1.0 - cos_theta*cos_theta);
dxdr1 = (180.0/PI) * dxdcos *
(1.0/r21l)* (r23/r23l + (-1.0) * cos_theta * r21/r21l );
@ -346,7 +343,7 @@ void colvar::dihedral::calc_value()
cvm::real const cos_phi = n1 * n2;
cvm::real const sin_phi = n1 * r34 * r23.norm();
x.real_value = (180.0/PI) * std::atan2(sin_phi, cos_phi);
x.real_value = (180.0/PI) * cvm::atan2(sin_phi, cos_phi);
this->wrap(x);
}
@ -368,7 +365,7 @@ void colvar::dihedral::calc_gradients()
rB = 1.0/rB;
B *= rB;
if (std::fabs(sin_phi) > 0.1) {
if (cvm::fabs(sin_phi) > 0.1) {
rA = 1.0/rA;
A *= rA;
cvm::rvector const dcosdA = rA*(cos_phi*A-B);
@ -440,8 +437,8 @@ void colvar::dihedral::calc_force_invgrads()
cvm::real const dot1 = u23 * u12;
cvm::real const dot4 = u23 * u34;
cvm::real const fact1 = d12 * std::sqrt(1.0 - dot1 * dot1);
cvm::real const fact4 = d34 * std::sqrt(1.0 - dot4 * dot4);
cvm::real const fact1 = d12 * cvm::sqrt(1.0 - dot1 * dot1);
cvm::real const fact4 = d34 * cvm::sqrt(1.0 - dot4 * dot4);
group1->read_total_forces();
if (is_enabled(f_cvc_one_site_total_force)) {
@ -508,19 +505,17 @@ colvarvalue colvar::dihedral::dist2_rgrad(colvarvalue const &x1,
}
void colvar::dihedral::wrap(colvarvalue &x) const
void colvar::dihedral::wrap(colvarvalue &x_unwrapped) const
{
if ((x.real_value - wrap_center) >= 180.0) {
x.real_value -= 360.0;
if ((x_unwrapped.real_value - wrap_center) >= 180.0) {
x_unwrapped.real_value -= 360.0;
return;
}
if ((x.real_value - wrap_center) < -180.0) {
x.real_value += 360.0;
if ((x_unwrapped.real_value - wrap_center) < -180.0) {
x_unwrapped.real_value += 360.0;
return;
}
return;
}
@ -548,8 +543,8 @@ void colvar::polar_theta::calc_value()
cvm::rvector pos = atoms->center_of_mass();
r = atoms->center_of_mass().norm();
// Internal values of theta and phi are radians
theta = (r > 0.) ? std::acos(pos.z / r) : 0.;
phi = std::atan2(pos.y, pos.x);
theta = (r > 0.) ? cvm::acos(pos.z / r) : 0.;
phi = cvm::atan2(pos.y, pos.x);
x.real_value = (180.0/PI) * theta;
}
@ -560,9 +555,9 @@ void colvar::polar_theta::calc_gradients()
atoms->set_weighted_gradient(cvm::rvector(0., 0., 0.));
else
atoms->set_weighted_gradient(cvm::rvector(
(180.0/PI) * std::cos(theta) * std::cos(phi) / r,
(180.0/PI) * std::cos(theta) * std::sin(phi) / r,
(180.0/PI) * -std::sin(theta) / r));
(180.0/PI) * cvm::cos(theta) * cvm::cos(phi) / r,
(180.0/PI) * cvm::cos(theta) * cvm::sin(phi) / r,
(180.0/PI) * -cvm::sin(theta) / r));
}
@ -602,8 +597,8 @@ void colvar::polar_phi::calc_value()
cvm::rvector pos = atoms->center_of_mass();
r = atoms->center_of_mass().norm();
// Internal values of theta and phi are radians
theta = (r > 0.) ? std::acos(pos.z / r) : 0.;
phi = std::atan2(pos.y, pos.x);
theta = (r > 0.) ? cvm::acos(pos.z / r) : 0.;
phi = cvm::atan2(pos.y, pos.x);
x.real_value = (180.0/PI) * phi;
}
@ -611,8 +606,8 @@ void colvar::polar_phi::calc_value()
void colvar::polar_phi::calc_gradients()
{
atoms->set_weighted_gradient(cvm::rvector(
(180.0/PI) * -std::sin(phi) / (r*std::sin(theta)),
(180.0/PI) * std::cos(phi) / (r*std::sin(theta)),
(180.0/PI) * -cvm::sin(phi) / (r*cvm::sin(theta)),
(180.0/PI) * cvm::cos(phi) / (r*cvm::sin(theta)),
0.));
}
@ -653,15 +648,15 @@ colvarvalue colvar::polar_phi::dist2_rgrad(colvarvalue const &x1,
}
void colvar::polar_phi::wrap(colvarvalue &x) const
void colvar::polar_phi::wrap(colvarvalue &x_unwrapped) const
{
if ((x.real_value - wrap_center) >= 180.0) {
x.real_value -= 360.0;
if ((x_unwrapped.real_value - wrap_center) >= 180.0) {
x_unwrapped.real_value -= 360.0;
return;
}
if ((x.real_value - wrap_center) < -180.0) {
x.real_value += 360.0;
if ((x_unwrapped.real_value - wrap_center) < -180.0) {
x_unwrapped.real_value += 360.0;
return;
}

View File

@ -7,8 +7,6 @@
// If you wish to distribute your changes, please submit them to the
// Colvars repository at GitHub.
#include <cmath>
#include "colvarmodule.h"
#include "colvarparse.h"
#include "colvaratoms.h"
@ -102,6 +100,12 @@ colvar::coordnum::coordnum(std::string const &conf)
group1 = parse_group(conf, "group1");
group2 = parse_group(conf, "group2");
if (group1 == NULL || group2 == NULL) {
cvm::error("Error: failed to initialize atom groups.\n",
INPUT_ERROR);
return;
}
if (int atom_number = cvm::atom_group::overlap(*group1, *group2)) {
cvm::error("Error: group1 and group2 share a common atom (number: " +
cvm::to_str(atom_number) + ")\n", INPUT_ERROR);
@ -408,12 +412,6 @@ colvar::h_bond::h_bond()
}
colvar::h_bond::~h_bond()
{
delete atom_groups[0];
}
void colvar::h_bond::calc_value()
{
int const flags = coordnum::ef_null;
@ -655,8 +653,6 @@ colvar::groupcoordnum::groupcoordnum()
void colvar::groupcoordnum::calc_value()
{
cvm::rvector const r0_vec(0.0); // TODO enable the flag?
// create fake atoms to hold the com coordinates
cvm::atom group1_com_atom;
cvm::atom group2_com_atom;
@ -680,8 +676,6 @@ void colvar::groupcoordnum::calc_value()
void colvar::groupcoordnum::calc_gradients()
{
cvm::rvector const r0_vec(0.0); // TODO enable the flag?
cvm::atom group1_com_atom;
cvm::atom group2_com_atom;
group1_com_atom.pos = group1->center_of_mass();

View File

@ -7,8 +7,6 @@
// If you wish to distribute your changes, please submit them to the
// Colvars repository at GitHub.
#include <cmath>
#include "colvarmodule.h"
#include "colvarvalue.h"
#include "colvarparse.h"
@ -102,7 +100,7 @@ colvar::distance_vec::distance_vec(std::string const &conf)
{
function_type = "distance_vec";
enable(f_cvc_com_based);
enable(f_cvc_implicit_gradient);
disable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_3vector);
}
@ -112,7 +110,7 @@ colvar::distance_vec::distance_vec()
{
function_type = "distance_vec";
enable(f_cvc_com_based);
enable(f_cvc_implicit_gradient);
disable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_3vector);
}
@ -320,7 +318,7 @@ cvm::real colvar::distance_z::dist2(colvarvalue const &x1,
{
cvm::real diff = x1.real_value - x2.real_value;
if (b_periodic) {
cvm::real shift = std::floor(diff/period + 0.5);
cvm::real shift = cvm::floor(diff/period + 0.5);
diff -= shift * period;
}
return diff * diff;
@ -332,7 +330,7 @@ colvarvalue colvar::distance_z::dist2_lgrad(colvarvalue const &x1,
{
cvm::real diff = x1.real_value - x2.real_value;
if (b_periodic) {
cvm::real shift = std::floor(diff/period + 0.5);
cvm::real shift = cvm::floor(diff/period + 0.5);
diff -= shift * period;
}
return 2.0 * diff;
@ -344,22 +342,23 @@ colvarvalue colvar::distance_z::dist2_rgrad(colvarvalue const &x1,
{
cvm::real diff = x1.real_value - x2.real_value;
if (b_periodic) {
cvm::real shift = std::floor(diff/period + 0.5);
cvm::real shift = cvm::floor(diff/period + 0.5);
diff -= shift * period;
}
return (-2.0) * diff;
}
void colvar::distance_z::wrap(colvarvalue &x) const
void colvar::distance_z::wrap(colvarvalue &x_unwrapped) const
{
if (!b_periodic) {
// don't wrap if the period has not been set
return;
}
cvm::real shift = std::floor((x.real_value - wrap_center) / period + 0.5);
x.real_value -= shift * period;
cvm::real shift =
cvm::floor((x_unwrapped.real_value - wrap_center) / period + 0.5);
x_unwrapped.real_value -= shift * period;
return;
}
@ -481,7 +480,7 @@ colvar::distance_dir::distance_dir(std::string const &conf)
{
function_type = "distance_dir";
enable(f_cvc_com_based);
enable(f_cvc_implicit_gradient);
disable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_unit3vector);
}
@ -491,7 +490,7 @@ colvar::distance_dir::distance_dir()
{
function_type = "distance_dir";
enable(f_cvc_com_based);
enable(f_cvc_implicit_gradient);
disable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_unit3vector);
}
@ -629,7 +628,7 @@ void colvar::distance_inv::calc_value()
}
x.real_value *= 1.0 / cvm::real(group1->size() * group2->size());
x.real_value = std::pow(x.real_value, -1.0/cvm::real(exponent));
x.real_value = cvm::pow(x.real_value, -1.0/cvm::real(exponent));
cvm::real const dxdsum = (-1.0/(cvm::real(exponent))) *
cvm::integer_power(x.real_value, exponent+1) /
@ -671,7 +670,7 @@ colvar::distance_pairs::distance_pairs(std::string const &conf)
group2 = parse_group(conf, "group2");
x.type(colvarvalue::type_vector);
enable(f_cvc_implicit_gradient);
disable(f_cvc_explicit_gradient);
x.vector1d_value.resize(group1->size() * group2->size());
}
@ -679,7 +678,7 @@ colvar::distance_pairs::distance_pairs(std::string const &conf)
colvar::distance_pairs::distance_pairs()
{
function_type = "distance_pairs";
enable(f_cvc_implicit_gradient);
disable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_vector);
}
@ -747,6 +746,63 @@ void colvar::distance_pairs::apply_force(colvarvalue const &force)
colvar::dipole_magnitude::dipole_magnitude(std::string const &conf)
: cvc(conf)
{
function_type = "dipole_magnitude";
atoms = parse_group(conf, "atoms");
init_total_force_params(conf);
x.type(colvarvalue::type_scalar);
}
colvar::dipole_magnitude::dipole_magnitude(cvm::atom const &a1)
{
atoms = new cvm::atom_group(std::vector<cvm::atom>(1, a1));
register_atom_group(atoms);
x.type(colvarvalue::type_scalar);
}
colvar::dipole_magnitude::dipole_magnitude()
{
function_type = "dipole_magnitude";
x.type(colvarvalue::type_scalar);
}
void colvar::dipole_magnitude::calc_value()
{
cvm::atom_pos const atomsCom = atoms->center_of_mass();
atoms->calc_dipole(atomsCom);
dipoleV = atoms->dipole();
x.real_value = dipoleV.norm();
}
void colvar::dipole_magnitude::calc_gradients()
{
cvm::real const aux1 = atoms->total_charge/atoms->total_mass;
cvm::atom_pos const dipVunit = dipoleV.unit();
for (cvm::atom_iter ai = atoms->begin(); ai != atoms->end(); ai++) {
ai->grad = (ai->charge - aux1*ai->mass) * dipVunit;
}
}
void colvar::dipole_magnitude::apply_force(colvarvalue const &force)
{
if (!atoms->noforce) {
atoms->apply_colvar_force(force.real_value);
}
}
simple_scalar_dist_functions(dipole_magnitude)
colvar::gyration::gyration(std::string const &conf)
: cvc(conf)
{
@ -782,7 +838,7 @@ void colvar::gyration::calc_value()
for (cvm::atom_iter ai = atoms->begin(); ai != atoms->end(); ai++) {
x.real_value += (ai->pos).norm2();
}
x.real_value = std::sqrt(x.real_value / cvm::real(atoms->size()));
x.real_value = cvm::sqrt(x.real_value / cvm::real(atoms->size()));
}
@ -1029,7 +1085,7 @@ void colvar::rmsd::calc_value()
x.real_value += ((*atoms)[ia].pos - ref_pos[ia]).norm2();
}
x.real_value /= cvm::real(atoms->size()); // MSD
x.real_value = std::sqrt(x.real_value);
x.real_value = cvm::sqrt(x.real_value);
}
@ -1405,7 +1461,7 @@ void colvar::eigenvector::calc_Jacobian_derivative()
}
}
jd.real_value = sum * std::sqrt(eigenvec_invnorm2);
jd.real_value = sum * cvm::sqrt(eigenvec_invnorm2);
}
@ -1436,7 +1492,7 @@ colvar::cartesian::cartesian(std::string const &conf)
}
x.type(colvarvalue::type_vector);
enable(f_cvc_implicit_gradient);
disable(f_cvc_explicit_gradient);
x.vector1d_value.resize(atoms->size() * axes.size());
}

View File

@ -7,8 +7,6 @@
// If you wish to distribute your changes, please submit them to the
// Colvars repository at GitHub.
#include <cmath>
#include "colvarmodule.h"
#include "colvarvalue.h"
#include "colvarparse.h"
@ -27,7 +25,7 @@ colvar::alpha_angles::alpha_angles(std::string const &conf)
cvm::log("Initializing alpha_angles object.\n");
function_type = "alpha_angles";
enable(f_cvc_implicit_gradient);
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
std::string segment_id;
@ -118,7 +116,7 @@ colvar::alpha_angles::alpha_angles()
: cvc()
{
function_type = "alpha_angles";
enable(f_cvc_implicit_gradient);
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
}
@ -133,6 +131,8 @@ colvar::alpha_angles::~alpha_angles()
delete hb.back();
hb.pop_back();
}
// Our references to atom groups have become invalid now that children cvcs are deleted
atom_groups.clear();
}
@ -191,6 +191,58 @@ void colvar::alpha_angles::calc_gradients()
}
void colvar::alpha_angles::collect_gradients(std::vector<int> const &atom_ids, std::vector<cvm::rvector> &atomic_gradients)
{
cvm::real cvc_coeff = sup_coeff * cvm::real(sup_np) * cvm::integer_power(value().real_value, sup_np-1);
if (theta.size()) {
cvm::real const theta_norm = (1.0-hb_coeff) / cvm::real(theta.size());
for (size_t i = 0; i < theta.size(); i++) {
cvm::real const t = ((theta[i])->value().real_value-theta_ref)/theta_tol;
cvm::real const f = ( (1.0 - (t*t)) /
(1.0 - (t*t*t*t)) );
cvm::real const dfdt =
1.0/(1.0 - (t*t*t*t)) *
( (-2.0 * t) + (-1.0*f)*(-4.0 * (t*t*t)) );
// Coeficient of this CVC's gradient in the colvar gradient, times coefficient of this
// angle's gradient in the CVC's gradient
cvm::real const coeff = cvc_coeff * theta_norm * dfdt * (1.0/theta_tol);
for (size_t j = 0; j < theta[i]->atom_groups.size(); j++) {
cvm::atom_group &ag = *(theta[i]->atom_groups[j]);
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 * ag[k].grad;
}
}
}
}
if (hb.size()) {
cvm::real const hb_norm = hb_coeff / cvm::real(hb.size());
for (size_t i = 0; i < hb.size(); i++) {
// Coeficient of this CVC's gradient in the colvar gradient, times coefficient of this
// hbond's gradient in the CVC's gradient
cvm::real const coeff = cvc_coeff * 0.5 * hb_norm;
for (size_t j = 0; j < hb[i]->atom_groups.size(); j++) {
cvm::atom_group &ag = *(hb[i]->atom_groups[j]);
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 * ag[k].grad;
}
}
}
}
}
void colvar::alpha_angles::apply_force(colvarvalue const &force)
{
@ -242,7 +294,8 @@ colvar::dihedPC::dihedPC(std::string const &conf)
cvm::log("Initializing dihedral PC object.\n");
function_type = "dihedPC";
enable(f_cvc_implicit_gradient);
// Supported through references to atom groups of children cvcs
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
std::string segment_id;
@ -372,7 +425,8 @@ colvar::dihedPC::dihedPC()
: cvc()
{
function_type = "dihedPC";
enable(f_cvc_implicit_gradient);
// Supported through references to atom groups of children cvcs
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
}
@ -383,6 +437,8 @@ colvar::dihedPC::~dihedPC()
delete theta.back();
theta.pop_back();
}
// Our references to atom groups have become invalid now that children cvcs are deleted
atom_groups.clear();
}
@ -392,8 +448,8 @@ void colvar::dihedPC::calc_value()
for (size_t i = 0; i < theta.size(); i++) {
theta[i]->calc_value();
cvm::real const t = (PI / 180.) * theta[i]->value().real_value;
x.real_value += coeffs[2*i ] * std::cos(t)
+ coeffs[2*i+1] * std::sin(t);
x.real_value += coeffs[2*i ] * cvm::cos(t)
+ coeffs[2*i+1] * cvm::sin(t);
}
}
@ -406,12 +462,35 @@ void colvar::dihedPC::calc_gradients()
}
void colvar::dihedPC::collect_gradients(std::vector<int> const &atom_ids, std::vector<cvm::rvector> &atomic_gradients)
{
cvm::real cvc_coeff = sup_coeff * cvm::real(sup_np) * cvm::integer_power(value().real_value, sup_np-1);
for (size_t i = 0; i < theta.size(); i++) {
cvm::real const t = (PI / 180.) * theta[i]->value().real_value;
cvm::real const dcosdt = - (PI / 180.) * cvm::sin(t);
cvm::real const dsindt = (PI / 180.) * cvm::cos(t);
// Coeficient of this dihedPC's gradient in the colvar gradient, times coefficient of this
// dihedral's gradient in the dihedPC's gradient
cvm::real const coeff = cvc_coeff * (coeffs[2*i] * dcosdt + coeffs[2*i+1] * dsindt);
for (size_t j = 0; j < theta[i]->atom_groups.size(); j++) {
cvm::atom_group &ag = *(theta[i]->atom_groups[j]);
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 * ag[k].grad;
}
}
}
}
void colvar::dihedPC::apply_force(colvarvalue const &force)
{
for (size_t i = 0; i < theta.size(); i++) {
cvm::real const t = (PI / 180.) * theta[i]->value().real_value;
cvm::real const dcosdt = - (PI / 180.) * std::sin(t);
cvm::real const dsindt = (PI / 180.) * std::cos(t);
cvm::real const dcosdt = - (PI / 180.) * cvm::sin(t);
cvm::real const dsindt = (PI / 180.) * cvm::cos(t);
theta[i]->apply_force((coeffs[2*i ] * dcosdt +
coeffs[2*i+1] * dsindt) * force);

View File

@ -7,8 +7,6 @@
// If you wish to distribute your changes, please submit them to the
// Colvars repository at GitHub.
#include <cmath>
#include "colvarmodule.h"
#include "colvarvalue.h"
#include "colvarparse.h"
@ -18,21 +16,27 @@
colvar::orientation::orientation(std::string const &conf)
: cvc(conf)
: cvc()
{
function_type = "orientation";
atoms = parse_group(conf, "atoms");
enable(f_cvc_implicit_gradient);
disable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_quaternion);
init(conf);
}
int colvar::orientation::init(std::string const &conf)
{
int error_code = cvc::init(conf);
atoms = parse_group(conf, "atoms");
ref_pos.reserve(atoms->size());
if (get_keyval(conf, "refPositions", ref_pos, ref_pos)) {
cvm::log("Using reference positions from input file.\n");
if (ref_pos.size() != atoms->size()) {
cvm::error("Error: reference positions do not "
"match the number of requested atoms.\n");
return;
return cvm::error("Error: reference positions do not "
"match the number of requested atoms.\n", INPUT_ERROR);
}
}
@ -46,9 +50,8 @@ colvar::orientation::orientation(std::string const &conf)
// use PDB flags if column is provided
bool found = get_keyval(conf, "refPositionsColValue", file_col_value, 0.0);
if (found && file_col_value==0.0) {
cvm::error("Error: refPositionsColValue, "
"if provided, must be non-zero.\n");
return;
return cvm::error("Error: refPositionsColValue, "
"if provided, must be non-zero.\n", INPUT_ERROR);
}
}
@ -59,9 +62,8 @@ colvar::orientation::orientation(std::string const &conf)
}
if (!ref_pos.size()) {
cvm::error("Error: must define a set of "
"reference coordinates.\n");
return;
return cvm::error("Error: must define a set of "
"reference coordinates.\n", INPUT_ERROR);
}
@ -85,6 +87,7 @@ colvar::orientation::orientation(std::string const &conf)
rot.request_group2_gradients(atoms->size());
}
return error_code;
}
@ -92,7 +95,7 @@ colvar::orientation::orientation()
: cvc()
{
function_type = "orientation";
enable(f_cvc_implicit_gradient);
disable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_quaternion);
}
@ -158,10 +161,18 @@ colvarvalue colvar::orientation::dist2_rgrad(colvarvalue const &x1,
colvar::orientation_angle::orientation_angle(std::string const &conf)
: orientation(conf)
: orientation()
{
function_type = "orientation_angle";
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
init(conf);
}
int colvar::orientation_angle::init(std::string const &conf)
{
return orientation::init(conf);
}
@ -169,6 +180,7 @@ colvar::orientation_angle::orientation_angle()
: orientation()
{
function_type = "orientation_angle";
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
}
@ -180,9 +192,9 @@ void colvar::orientation_angle::calc_value()
rot.calc_optimal_rotation(ref_pos, atoms->positions_shifted(-1.0 * atoms_cog));
if ((rot.q).q0 >= 0.0) {
x.real_value = (180.0/PI) * 2.0 * std::acos((rot.q).q0);
x.real_value = (180.0/PI) * 2.0 * cvm::acos((rot.q).q0);
} else {
x.real_value = (180.0/PI) * 2.0 * std::acos(-1.0 * (rot.q).q0);
x.real_value = (180.0/PI) * 2.0 * cvm::acos(-1.0 * (rot.q).q0);
}
}
@ -191,7 +203,7 @@ void colvar::orientation_angle::calc_gradients()
{
cvm::real const dxdq0 =
( ((rot.q).q0 * (rot.q).q0 < 1.0) ?
((180.0 / PI) * (-2.0) / std::sqrt(1.0 - ((rot.q).q0 * (rot.q).q0))) :
((180.0 / PI) * (-2.0) / cvm::sqrt(1.0 - ((rot.q).q0 * (rot.q).q0))) :
0.0 );
for (size_t ia = 0; ia < atoms->size(); ia++) {
@ -214,10 +226,18 @@ simple_scalar_dist_functions(orientation_angle)
colvar::orientation_proj::orientation_proj(std::string const &conf)
: orientation(conf)
: orientation()
{
function_type = "orientation_proj";
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
init(conf);
}
int colvar::orientation_proj::init(std::string const &conf)
{
return orientation::init(conf);
}
@ -225,6 +245,7 @@ colvar::orientation_proj::orientation_proj()
: orientation()
{
function_type = "orientation_proj";
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
}
@ -261,18 +282,28 @@ simple_scalar_dist_functions(orientation_proj)
colvar::tilt::tilt(std::string const &conf)
: orientation(conf)
: orientation()
{
function_type = "tilt";
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
init(conf);
}
int colvar::tilt::init(std::string const &conf)
{
int error_code = COLVARS_OK;
error_code |= orientation::init(conf);
get_keyval(conf, "axis", axis, cvm::rvector(0.0, 0.0, 1.0));
if (axis.norm2() != 1.0) {
axis /= axis.norm();
cvm::log("Normalizing rotation axis to "+cvm::to_str(axis)+".\n");
}
x.type(colvarvalue::type_scalar);
return error_code;
}
@ -280,6 +311,7 @@ colvar::tilt::tilt()
: orientation()
{
function_type = "tilt";
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
}
@ -322,20 +354,30 @@ simple_scalar_dist_functions(tilt)
colvar::spin_angle::spin_angle(std::string const &conf)
: orientation(conf)
: orientation()
{
function_type = "spin_angle";
period = 360.0;
b_periodic = true;
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
init(conf);
}
int colvar::spin_angle::init(std::string const &conf)
{
int error_code = COLVARS_OK;
error_code |= orientation::init(conf);
get_keyval(conf, "axis", axis, cvm::rvector(0.0, 0.0, 1.0));
if (axis.norm2() != 1.0) {
axis /= axis.norm();
cvm::log("Normalizing rotation axis to "+cvm::to_str(axis)+".\n");
}
period = 360.0;
b_periodic = true;
x.type(colvarvalue::type_scalar);
return error_code;
}
@ -345,6 +387,7 @@ colvar::spin_angle::spin_angle()
function_type = "spin_angle";
period = 360.0;
b_periodic = true;
enable(f_cvc_explicit_gradient);
x.type(colvarvalue::type_scalar);
}
@ -410,15 +453,15 @@ colvarvalue colvar::spin_angle::dist2_rgrad(colvarvalue const &x1,
}
void colvar::spin_angle::wrap(colvarvalue &x) const
void colvar::spin_angle::wrap(colvarvalue &x_unwrapped) const
{
if ((x.real_value - wrap_center) >= 180.0) {
x.real_value -= 360.0;
if ((x_unwrapped.real_value - wrap_center) >= 180.0) {
x_unwrapped.real_value -= 360.0;
return;
}
if ((x.real_value - wrap_center) < -180.0) {
x.real_value += 360.0;
if ((x_unwrapped.real_value - wrap_center) < -180.0) {
x_unwrapped.real_value += 360.0;
return;
}

View File

@ -122,12 +122,7 @@ 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
{
int res;
size_t i, j;
@ -143,8 +138,7 @@ int colvardeps::enable(int feature_id,
if (fs->enabled) {
if (!(dry_run || toplevel)) {
// This is a dependency
// Prevent disabling this feature as long
// This is a dependency: prevent disabling this feature as long
// as requirement is enabled
fs->ref_count++;
if (cvm::debug())
@ -173,7 +167,10 @@ int colvardeps::enable(int feature_id,
if (!toplevel && !is_dynamic(feature_id)) {
if (!dry_run) {
cvm::log(feature_type_descr + " feature \"" + f->description
+ "\" may not be enabled as a dependency in " + description + ".\n");
+ "\" cannot be enabled automatically in " + description + ".");
if (is_user(feature_id)) {
cvm::log("Try setting it manually.\n");
}
}
return COLVARS_ERROR;
}
@ -354,6 +351,7 @@ int colvardeps::disable(int feature_id) {
return COLVARS_OK;
}
int colvardeps::decr_ref_count(int feature_id) {
int &rc = feature_states[feature_id].ref_count;
feature *f = features()[feature_id];
@ -379,324 +377,52 @@ int colvardeps::decr_ref_count(int feature_id) {
return COLVARS_OK;
}
void colvardeps::init_feature(int feature_id, const char *description, feature_type type) {
modify_features()[feature_id]->description = description;
void colvardeps::init_feature(int feature_id, const char *description_in, feature_type type) {
modify_features()[feature_id]->description = description_in;
modify_features()[feature_id]->type = type;
}
// 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); \
features()[g]->requires_exclude.push_back(f)
#define f_req_children(f, g) features()[f]->requires_children.push_back(g)
#define f_req_alt2(f, g, h) features()[f]->requires_alt.push_back(std::vector<int>(2));\
features()[f]->requires_alt.back()[0] = g; \
features()[f]->requires_alt.back()[1] = h
#define f_req_alt3(f, g, h, i) features()[f]->requires_alt.push_back(std::vector<int>(3));\
features()[f]->requires_alt.back()[0] = g; \
features()[f]->requires_alt.back()[1] = h; \
features()[f]->requires_alt.back()[2] = i
#define f_req_alt4(f, g, h, i, j) features()[f]->requires_alt.push_back(std::vector<int>(4));\
features()[f]->requires_alt.back()[0] = g; \
features()[f]->requires_alt.back()[1] = h; \
features()[f]->requires_alt.back()[2] = i; \
features()[f]->requires_alt.back()[3] = j
void colvardeps::init_cvb_requires() {
int i;
if (features().size() == 0) {
for (i = 0; i < f_cvb_ntot; i++) {
modify_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_awake, "awake", f_type_static);
f_req_self(f_cvb_awake, f_cvb_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_type_dynamic);
f_req_children(f_cvb_get_total_force, f_cv_total_force);
init_feature(f_cvb_output_acc_work, "output accumulated work", f_type_user);
f_req_self(f_cvb_output_acc_work, f_cvb_apply_force);
init_feature(f_cvb_history_dependent, "history-dependent", f_type_static);
init_feature(f_cvb_time_dependent, "time-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);
init_feature(f_cvb_calc_ti_samples, "calculate TI samples", f_type_dynamic);
f_req_self(f_cvb_calc_ti_samples, f_cvb_get_total_force);
f_req_children(f_cvb_calc_ti_samples, f_cv_grid);
init_feature(f_cvb_write_ti_samples, "write TI samples ", f_type_user);
f_req_self(f_cvb_write_ti_samples, f_cvb_calc_ti_samples);
init_feature(f_cvb_write_ti_pmf, "write TI PMF", f_type_user);
f_req_self(f_cvb_write_ti_pmf, f_cvb_calc_ti_samples);
}
// Initialize feature_states for each instance
feature_states.reserve(f_cvb_ntot);
for (i = 0; i < f_cvb_ntot; i++) {
feature_states.push_back(feature_state(true, false));
// Most features are available, so we set them so
// and list exceptions below
}
// only compute TI samples when deriving from colvarbias_ti
feature_states[f_cvb_calc_ti_samples].available = false;
// Shorthand functions for describing dependencies
void colvardeps::require_feature_self(int f, int g) {
features()[f]->requires_self.push_back(g);
}
void colvardeps::init_cv_requires() {
size_t i;
if (features().size() == 0) {
for (i = 0; i < f_cv_ntot; i++) {
modify_features().push_back(new feature);
}
init_feature(f_cv_active, "active", f_type_dynamic);
// Do not require f_cvc_active in children, as some components may be disabled
// Colvars must be either a linear combination, or scalar (and polynomial) or scripted/custom
f_req_alt4(f_cv_active, f_cv_scalar, f_cv_linear, f_cv_scripted, f_cv_custom_function);
init_feature(f_cv_awake, "awake", f_type_static);
f_req_self(f_cv_awake, f_cv_active);
init_feature(f_cv_gradient, "gradient", f_type_dynamic);
f_req_children(f_cv_gradient, f_cvc_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);
// The following exlusion could be lifted by implementing the feature
f_req_exclude(f_cv_collect_gradient, f_cv_scripted);
init_feature(f_cv_fdiff_velocity, "velocity from finite differences", f_type_dynamic);
// System force: either trivial (spring force); through extended Lagrangian, or calculated explicitly
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
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);
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);
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
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);
init_feature(f_cv_Langevin, "Langevin dynamics", f_type_user);
f_req_self(f_cv_Langevin, f_cv_extended_Lagrangian);
init_feature(f_cv_linear, "linear", f_type_static);
init_feature(f_cv_scalar, "scalar", f_type_static);
init_feature(f_cv_output_energy, "output energy", f_type_user);
init_feature(f_cv_output_value, "output value", f_type_user);
init_feature(f_cv_output_velocity, "output velocity", f_type_user);
f_req_self(f_cv_output_velocity, f_cv_fdiff_velocity);
init_feature(f_cv_output_applied_force, "output applied force", f_type_user);
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);
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);
init_feature(f_cv_lower_boundary, "lower boundary", f_type_user);
f_req_self(f_cv_lower_boundary, f_cv_scalar);
init_feature(f_cv_upper_boundary, "upper boundary", f_type_user);
f_req_self(f_cv_upper_boundary, f_cv_scalar);
init_feature(f_cv_grid, "grid", f_type_dynamic);
f_req_self(f_cv_grid, f_cv_lower_boundary);
f_req_self(f_cv_grid, f_cv_upper_boundary);
init_feature(f_cv_runave, "running average", f_type_user);
init_feature(f_cv_corrfunc, "correlation function", f_type_user);
init_feature(f_cv_scripted, "scripted", f_type_user);
init_feature(f_cv_custom_function, "custom function", f_type_user);
f_req_exclude(f_cv_custom_function, f_cv_scripted);
init_feature(f_cv_periodic, "periodic", f_type_static);
f_req_self(f_cv_periodic, f_cv_scalar);
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);
// because total forces are obtained from the previous time step,
// we cannot (currently) have colvar values and total forces for the same timestep
init_feature(f_cv_multiple_ts, "multiple timestep colvar");
f_req_exclude(f_cv_multiple_ts, f_cv_total_force_calc);
}
// Initialize feature_states for each instance
feature_states.reserve(f_cv_ntot);
for (i = 0; i < f_cv_ntot; i++) {
feature_states.push_back(feature_state(true, false));
// Most features are available, so we set them so
// and list exceptions below
}
feature_states[f_cv_fdiff_velocity].available =
cvm::main()->proxy->simulation_running();
// Ensure that exclusions are symmetric
void colvardeps::exclude_feature_self(int f, int g) {
features()[f]->requires_exclude.push_back(g);
features()[g]->requires_exclude.push_back(f);
}
void colvardeps::init_cvc_requires() {
size_t i;
// Initialize static array once and for all
if (features().size() == 0) {
for (i = 0; i < colvardeps::f_cvc_ntot; i++) {
modify_features().push_back(new feature);
}
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);
init_feature(f_cvc_scalar, "scalar", f_type_static);
init_feature(f_cvc_gradient, "gradient", f_type_dynamic);
init_feature(f_cvc_implicit_gradient, "implicit gradient", f_type_static);
f_req_children(f_cvc_implicit_gradient, f_ag_implicit_gradient);
init_feature(f_cvc_inv_gradient, "inverse gradient", f_type_dynamic);
f_req_self(f_cvc_inv_gradient, f_cvc_gradient);
init_feature(f_cvc_debug_gradient, "debug gradient", f_type_user);
f_req_self(f_cvc_debug_gradient, f_cvc_gradient);
f_req_exclude(f_cvc_debug_gradient, f_cvc_implicit_gradient);
init_feature(f_cvc_Jacobian, "Jacobian derivative", f_type_dynamic);
f_req_self(f_cvc_Jacobian, f_cvc_inv_gradient);
init_feature(f_cvc_com_based, "depends on group centers of mass", f_type_static);
// init_feature(f_cvc_pbc_minimum_image, "use minimum-image distances with PBCs", f_type_user);
// Compute total force on first site only to avoid unwanted
// coupling to other colvars (see e.g. Ciccotti et al., 2005)
init_feature(f_cvc_one_site_total_force, "compute total force from one group", f_type_user);
f_req_self(f_cvc_one_site_total_force, f_cvc_com_based);
init_feature(f_cvc_scalable, "scalable calculation", f_type_static);
f_req_self(f_cvc_scalable, f_cvc_scalable_com);
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);
// TODO only enable this when f_ag_scalable can be turned on for a pre-initialized group
// f_req_children(f_cvc_scalable, f_ag_scalable);
// f_req_children(f_cvc_scalable_com, f_ag_scalable_com);
}
// Initialize feature_states for each instance
// 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++) {
bool avail = is_dynamic(i) ? false : true;
feature_states.push_back(feature_state(avail, false));
}
// CVCs are enabled from the start - get disabled based on flags
feature_states[f_cvc_active].enabled = true;
// 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;
// Use minimum-image distances by default
feature_states[f_cvc_pbc_minimum_image].enabled = true;
// Features that are implemented by default if their requirements are
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;
void colvardeps::require_feature_children(int f, int g) {
features()[f]->requires_children.push_back(g);
}
void colvardeps::init_ag_requires() {
size_t i;
// Initialize static array once and for all
if (features().size() == 0) {
for (i = 0; i < f_ag_ntot; i++) {
modify_features().push_back(new feature);
}
void colvardeps::require_feature_alt(int f, int g, int h) {
features()[f]->requires_alt.push_back(std::vector<int>(2));
features()[f]->requires_alt.back()[0] = g;
features()[f]->requires_alt.back()[1] = h;
}
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_implicit_gradient, "implicit atom gradient", f_type_dynamic);
init_feature(f_ag_fit_gradients, "fit gradients", f_type_user);
f_req_exclude(f_ag_fit_gradients, f_ag_implicit_gradient);
init_feature(f_ag_atom_forces, "atomic forces", f_type_dynamic);
void colvardeps::require_feature_alt(int f, int g, int h, int i) {
features()[f]->requires_alt.push_back(std::vector<int>(3));
features()[f]->requires_alt.back()[0] = g;
features()[f]->requires_alt.back()[1] = h;
features()[f]->requires_alt.back()[2] = i;
}
// 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
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);
// 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)
}
// Initialize feature_states for each instance
// default as unavailable, not enabled
feature_states.reserve(f_ag_ntot);
for (i = 0; i < colvardeps::f_ag_ntot; i++) {
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;
// f_ag_scalable_com is provided by the CVC iff it is COM-based
feature_states[f_ag_scalable_com].available = false;
// TODO make f_ag_scalable depend on f_ag_scalable_com (or something else)
feature_states[f_ag_scalable].available = true;
feature_states[f_ag_fit_gradients].available = true;
feature_states[f_ag_implicit_gradient].available = true;
void colvardeps::require_feature_alt(int f, int g, int h, int i, int j) {
features()[f]->requires_alt.push_back(std::vector<int>(4));
features()[f]->requires_alt.back()[0] = g;
features()[f]->requires_alt.back()[1] = h;
features()[f]->requires_alt.back()[2] = i;
features()[f]->requires_alt.back()[3] = j;
}
@ -720,7 +446,7 @@ void colvardeps::print_state() {
void colvardeps::add_child(colvardeps *child) {
children.push_back(child);
child->parents.push_back((colvardeps *)this);
child->parents.push_back(this);
// Solve dependencies of already enabled parent features
// in the new child

View File

@ -23,7 +23,11 @@
/// 3. Static features are static properties of the object, determined
/// programatically at initialization time.
///
/// In all classes, feature 0 is active. When an object is inactivated
/// The following diagram summarizes the dependency tree at the bias, colvar, and colvarcomp levels.
/// Isolated and atom group features are not shown to save space.
/// @image html deps_2019.svg
///
/// In all classes, feature 0 is `active`. When an object is inactivated
/// all its children dependencies are dereferenced (free_children_deps)
/// While the object is inactive, no dependency solving is done on children
/// it is done when the object is activated back (restore_children_deps)
@ -72,7 +76,6 @@ protected:
/// Unused by lower-level objects (cvcs and atom groups)
int time_step_factor;
private:
/// List of the states of all features
std::vector<feature_state> feature_states;
@ -89,14 +92,14 @@ public:
inline int get_time_step_factor() const {return time_step_factor;}
/// 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);
void init_feature(int feature_id, const char *description, feature_type type);
/// Describes a feature and its dependencies
/// used in a static array within each subclass
class feature {
public:
feature() {}
feature() : type(f_type_not_set) {}
~feature() {}
std::string description; // Set by derived object initializer
@ -126,6 +129,7 @@ public:
feature_type type;
};
inline bool is_not_set(int id) { return features()[id]->type == f_type_not_set; }
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; }
@ -135,7 +139,7 @@ public:
// with a non-static array
// Intermediate classes (colvarbias and colvarcomp, which are also base classes)
// implement this as virtual to allow overriding
virtual const std::vector<feature *>&features() = 0;
virtual const std::vector<feature *> &features() const = 0;
virtual std::vector<feature *>&modify_features() = 0;
void add_child(colvardeps *child);
@ -188,10 +192,12 @@ protected:
public:
/// enable a feature and recursively solve its dependencies
/// for proper reference counting, one should not add
/// spurious calls to enable()
/// dry_run is set to true to recursively test if a feature is available, without enabling it
/// Enable a feature and recursively solve its dependencies.
/// For accurate reference counting, do not add spurious calls to enable()
/// \param dry_run Recursively test if a feature is available, without enabling it
/// \param 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 enable(int f, bool dry_run = false, bool toplevel = true);
/// Disable a feature, decrease the reference count of its dependencies
@ -318,8 +324,8 @@ public:
f_cvc_active,
f_cvc_scalar,
f_cvc_gradient,
/// \brief CVC doesn't calculate and store explicit atom gradients
f_cvc_implicit_gradient,
/// \brief CVC calculates and stores explicit atom gradients
f_cvc_explicit_gradient,
f_cvc_inv_gradient,
/// \brief If enabled, calc_gradients() will call debug_gradients() for every group needed
f_cvc_debug_gradient,
@ -341,7 +347,7 @@ public:
/// ie. not using refpositionsgroup
// f_ag_min_msd_fit,
/// \brief Does not have explicit atom gradients from parent CVC
f_ag_implicit_gradient,
f_ag_explicit_gradient,
f_ag_fit_gradients,
f_ag_atom_forces,
f_ag_scalable,
@ -349,13 +355,39 @@ public:
f_ag_ntot
};
void init_cvb_requires();
void init_cv_requires();
void init_cvc_requires();
void init_ag_requires();
/// Initialize dependency tree for object of a derived class
virtual int init_dependencies() = 0;
/// Make feature f require feature g within the same object
void require_feature_self(int f, int g);
/// Make features f and g mutually exclusive within the same object
void exclude_feature_self(int f, int g);
/// Make feature f require feature g within children
void require_feature_children(int f, int g);
/// Make feature f require either g or h within the same object
void require_feature_alt(int f, int g, int h);
/// Make feature f require any of g, h, or i within the same object
void require_feature_alt(int f, int g, int h, int i);
/// Make feature f require any of g, h, i, or j within the same object
void require_feature_alt(int f, int g, int h, int i, int j);
/// \brief print all enabled features and those of children, for debugging
void print_state();
/// \brief Check that a feature is enabled, raising BUG_ERROR if not
inline void check_enabled(int f, std::string const &reason) const
{
if (! is_enabled(f)) {
cvm::error("Error: "+reason+" requires that the feature \""+
features()[f]->description+"\" is active.\n", BUG_ERROR);
}
}
};
#endif

View File

@ -109,7 +109,7 @@ cvm::real colvar_grid_scalar::entropy() const
{
cvm::real sum = 0.0;
for (size_t i = 0; i < nt; i++) {
sum += -1.0 * data[i] * std::log(data[i]);
sum += -1.0 * data[i] * cvm::logn(data[i]);
}
cvm::real bin_volume = 1.0;
for (size_t id = 0; id < widths.size(); id++) {

View File

@ -12,7 +12,6 @@
#include <iostream>
#include <iomanip>
#include <cmath>
#include "colvar.h"
#include "colvarmodule.h"
@ -53,7 +52,7 @@ protected:
std::vector<colvar *> cv;
/// Do we request actual value (for extended-system colvars)?
std::vector<bool> actual_value;
std::vector<bool> use_actual_value;
/// Get the low-level index corresponding to an index
inline size_t address(std::vector<int> const &ix) const
@ -136,8 +135,8 @@ public:
inline void request_actual_value(bool b = true)
{
size_t i;
for (i = 0; i < actual_value.size(); i++) {
actual_value[i] = b;
for (i = 0; i < use_actual_value.size(); i++) {
use_actual_value[i] = b;
}
}
@ -215,7 +214,7 @@ public:
mult(g.mult),
data(),
cv(g.cv),
actual_value(g.actual_value),
use_actual_value(g.use_actual_value),
lower_boundaries(g.lower_boundaries),
upper_boundaries(g.upper_boundaries),
periodic(g.periodic),
@ -290,13 +289,13 @@ public:
periodic.push_back(cv[i]->periodic_boundaries());
// By default, get reported colvar value (for extended Lagrangian colvars)
actual_value.push_back(false);
use_actual_value.push_back(false);
// except if a colvar is specified twice in a row
// then the first instance is the actual value
// For histograms of extended-system coordinates
if (i > 0 && cv[i-1] == cv[i]) {
actual_value[i-1] = true;
use_actual_value[i-1] = true;
}
if (margin) {
@ -319,8 +318,7 @@ public:
return this->setup();
}
int init_from_boundaries(T const &t = T(),
size_t const &mult_i = 1)
int init_from_boundaries()
{
if (cvm::debug()) {
cvm::log("Configuring grid dimensions from colvars boundaries.\n");
@ -337,7 +335,7 @@ public:
lower_boundaries[i].real_value ) / widths[i];
int nbins_round = (int)(nbins+0.5);
if (std::fabs(nbins - cvm::real(nbins_round)) > 1.0E-10) {
if (cvm::fabs(nbins - cvm::real(nbins_round)) > 1.0E-10) {
cvm::log("Warning: grid interval("+
cvm::to_str(lower_boundaries[i], cvm::cv_width, cvm::cv_prec)+" - "+
cvm::to_str(upper_boundaries[i], cvm::cv_width, cvm::cv_prec)+
@ -392,20 +390,20 @@ public:
/// \brief Report the bin corresponding to the current value of variable i
inline int current_bin_scalar(int const i) const
{
return value_to_bin_scalar(actual_value[i] ? cv[i]->actual_value() : cv[i]->value(), i);
return value_to_bin_scalar(use_actual_value[i] ? cv[i]->actual_value() : cv[i]->value(), i);
}
/// \brief Report the bin corresponding to the current value of variable i
/// and assign first or last bin if out of boundaries
inline int current_bin_scalar_bound(int const i) const
{
return value_to_bin_scalar_bound(actual_value[i] ? cv[i]->actual_value() : cv[i]->value(), i);
return value_to_bin_scalar_bound(use_actual_value[i] ? cv[i]->actual_value() : cv[i]->value(), i);
}
/// \brief Report the bin corresponding to the current value of item iv in variable i
inline int current_bin_scalar(int const i, int const iv) const
{
return value_to_bin_scalar(actual_value[i] ?
return value_to_bin_scalar(use_actual_value[i] ?
cv[i]->actual_value().vector1d_value[iv] :
cv[i]->value().vector1d_value[iv], i);
}
@ -414,14 +412,14 @@ public:
/// the provided value is in
inline int value_to_bin_scalar(colvarvalue const &value, const int i) const
{
return (int) std::floor( (value.real_value - lower_boundaries[i].real_value) / widths[i] );
return (int) cvm::floor( (value.real_value - lower_boundaries[i].real_value) / widths[i] );
}
/// \brief Use the lower boundary and the width to report which bin
/// the provided value is in and assign first or last bin if out of boundaries
inline int value_to_bin_scalar_bound(colvarvalue const &value, const int i) const
{
int bin_index = std::floor( (value.real_value - lower_boundaries[i].real_value) / widths[i] );
int bin_index = cvm::floor( (value.real_value - lower_boundaries[i].real_value) / widths[i] );
if (bin_index < 0) bin_index=0;
if (bin_index >=int(nx[i])) bin_index=int(nx[i])-1;
return (int) bin_index;
@ -432,7 +430,7 @@ public:
colvarvalue const &new_offset,
cvm::real const &new_width) const
{
return (int) std::floor( (value.real_value - new_offset.real_value) / new_width );
return (int) cvm::floor( (value.real_value - new_offset.real_value) / new_width );
}
/// \brief Use the two boundaries and the width to report the
@ -611,8 +609,8 @@ public:
if (periodic[i]) continue;
cvm::real dl = std::sqrt(cv[i]->dist2(values[i], lower_boundaries[i])) / widths[i];
cvm::real du = std::sqrt(cv[i]->dist2(values[i], upper_boundaries[i])) / widths[i];
cvm::real dl = cvm::sqrt(cv[i]->dist2(values[i], lower_boundaries[i])) / widths[i];
cvm::real du = cvm::sqrt(cv[i]->dist2(values[i], upper_boundaries[i])) / widths[i];
if (values[i].real_value < lower_boundaries[i])
dl *= -1.0;
@ -841,7 +839,7 @@ public:
if (nd < lower_boundaries.size()) nd = lower_boundaries.size();
if (! actual_value.size()) actual_value.assign(nd, false);
if (! use_actual_value.size()) use_actual_value.assign(nd, false);
if (! periodic.size()) periodic.assign(nd, false);
if (! widths.size()) widths.assign(nd, 1.0);
@ -849,7 +847,7 @@ public:
if (old_nx.size()) {
for (size_t i = 0; i < nd; i++) {
if ( (old_nx[i] != nx[i]) ||
(std::sqrt(cv[i]->dist2(old_lb[i],
(cvm::sqrt(cv[i]->dist2(old_lb[i],
lower_boundaries[i])) > 1.0E-10) ) {
new_params = true;
}
@ -874,11 +872,11 @@ public:
void check_consistency()
{
for (size_t i = 0; i < nd; i++) {
if ( (std::sqrt(cv[i]->dist2(cv[i]->lower_boundary,
if ( (cvm::sqrt(cv[i]->dist2(cv[i]->lower_boundary,
lower_boundaries[i])) > 1.0E-10) ||
(std::sqrt(cv[i]->dist2(cv[i]->upper_boundary,
(cvm::sqrt(cv[i]->dist2(cv[i]->upper_boundary,
upper_boundaries[i])) > 1.0E-10) ||
(std::sqrt(cv[i]->dist2(cv[i]->width,
(cvm::sqrt(cv[i]->dist2(cv[i]->width,
widths[i])) > 1.0E-10) ) {
cvm::error("Error: restart information for a grid is "
"inconsistent with that of its colvars.\n");
@ -896,11 +894,11 @@ public:
// we skip dist2(), because periodicities and the like should
// matter: boundaries should be EXACTLY the same (otherwise,
// map_grid() should be used)
if ( (std::fabs(other_grid.lower_boundaries[i] -
if ( (cvm::fabs(other_grid.lower_boundaries[i] -
lower_boundaries[i]) > 1.0E-10) ||
(std::fabs(other_grid.upper_boundaries[i] -
(cvm::fabs(other_grid.upper_boundaries[i] -
upper_boundaries[i]) > 1.0E-10) ||
(std::fabs(other_grid.widths[i] -
(cvm::fabs(other_grid.widths[i] -
widths[i]) > 1.0E-10) ||
(data.size() != other_grid.data.size()) ) {
cvm::error("Error: inconsistency between "
@ -1036,11 +1034,11 @@ public:
std::istream & read_multicol(std::istream &is, bool add = false)
{
// Data in the header: nColvars, then for each
// xiMin, dXi, nPoints, periodic
// xiMin, dXi, nPoints, periodic flag
std::string hash;
cvm::real lower, width, x;
size_t n, periodic;
size_t n, periodic_flag;
bool remap;
std::vector<T> new_value;
std::vector<int> nx_read;
@ -1053,7 +1051,8 @@ public:
if ( !(is >> hash) || (hash != "#") ) {
cvm::error("Error reading grid at position "+
cvm::to_str(is.tellg())+" in stream(read \"" + hash + "\")\n");
cvm::to_str(static_cast<size_t>(is.tellg()))+
" in stream(read \"" + hash + "\")\n");
return is;
}
@ -1075,15 +1074,16 @@ public:
for (size_t i = 0; i < nd; i++ ) {
if ( !(is >> hash) || (hash != "#") ) {
cvm::error("Error reading grid at position "+
cvm::to_str(is.tellg())+" in stream(read \"" + hash + "\")\n");
cvm::to_str(static_cast<size_t>(is.tellg()))+
" in stream(read \"" + hash + "\")\n");
return is;
}
is >> lower >> width >> nx_read[i] >> periodic;
is >> lower >> width >> nx_read[i] >> periodic_flag;
if ( (std::fabs(lower - lower_boundaries[i].real_value) > 1.0e-10) ||
(std::fabs(width - widths[i] ) > 1.0e-10) ||
if ( (cvm::fabs(lower - lower_boundaries[i].real_value) > 1.0e-10) ||
(cvm::fabs(width - widths[i] ) > 1.0e-10) ||
(nx_read[i] != nx[i]) ) {
cvm::log("Warning: reading from different grid definition (colvar "
+ cvm::to_str(i+1) + "); remapping data on new grid.\n");
@ -1246,7 +1246,7 @@ public:
if (A0 * A1 == 0) {
return 0.; // can't handle empty bins
} else {
return (std::log((cvm::real)A1) - std::log((cvm::real)A0))
return (cvm::logn((cvm::real)A1) - cvm::logn((cvm::real)A0))
/ (widths[n] * 2.);
}
} else if (ix[n] > 0 && ix[n] < nx[n]-1) { // not an edge
@ -1258,7 +1258,7 @@ public:
if (A0 * A1 == 0) {
return 0.; // can't handle empty bins
} else {
return (std::log((cvm::real)A1) - std::log((cvm::real)A0))
return (cvm::logn((cvm::real)A1) - cvm::logn((cvm::real)A0))
/ (widths[n] * 2.);
}
} else {
@ -1271,8 +1271,8 @@ public:
if (A0 * A1 * A2 == 0) {
return 0.; // can't handle empty bins
} else {
return (-1.5 * std::log((cvm::real)A0) + 2. * std::log((cvm::real)A1)
- 0.5 * std::log((cvm::real)A2)) * increment / widths[n];
return (-1.5 * cvm::logn((cvm::real)A0) + 2. * cvm::logn((cvm::real)A1)
- 0.5 * cvm::logn((cvm::real)A2)) * increment / widths[n];
}
}
}

View File

@ -28,6 +28,8 @@
colvarmodule::colvarmodule(colvarproxy *proxy_in)
{
depth_s = 0;
log_level_ = 10;
cv_traj_os = NULL;
if (proxy == NULL) {
@ -152,12 +154,12 @@ int colvarmodule::read_config_string(std::string const &config_str)
{
cvm::log(cvm::line_marker);
cvm::log("Reading new configuration:\n");
std::istringstream config_s(config_str);
std::istringstream new_config_s(config_str);
// strip the comments away
std::string conf = "";
std::string line;
while (parse->read_config_line(config_s, line)) {
while (parse->read_config_line(new_config_s, line)) {
// Delete lines that contain only white space after removing comments
if (line.find_first_not_of(colvarparse::white_space) != std::string::npos)
conf.append(line+"\n");
@ -255,13 +257,16 @@ int colvarmodule::append_new_config(std::string const &new_conf)
int colvarmodule::parse_global_params(std::string const &conf)
{
colvarmodule *cvm = cvm::main();
// TODO document and then echo this keyword
parse->get_keyval(conf, "logLevel", log_level_, log_level_,
colvarparse::parse_silent);
{
std::string index_file_name;
size_t pos = 0;
while (parse->key_lookup(conf, "indexFile", &index_file_name, &pos)) {
cvm->read_index_file(index_file_name.c_str());
cvm::log("# indexFile = \""+index_file_name+"\"\n");
read_index_file(index_file_name.c_str());
index_file_name.clear();
}
}
@ -580,6 +585,24 @@ cvm::atom_group *colvarmodule::atom_group_by_name(std::string const &name)
}
void colvarmodule::register_named_atom_group(atom_group *ag) {
named_atom_groups.push_back(ag);
}
void colvarmodule::unregister_named_atom_group(cvm::atom_group *ag)
{
for (std::vector<cvm::atom_group *>::iterator agi = named_atom_groups.begin();
agi != named_atom_groups.end();
agi++) {
if (*agi == ag) {
named_atom_groups.erase(agi);
break;
}
}
}
int colvarmodule::change_configuration(std::string const &bias_name,
std::string const &conf)
{
@ -1034,9 +1057,6 @@ int colvarmodule::analyze()
cvm::log("colvarmodule::analyze(), step = "+cvm::to_str(it)+".\n");
}
if (cvm::step_relative() == 0)
cvm::log("Performing analysis.\n");
// perform colvar-specific analysis
for (std::vector<colvar *>::iterator cvi = variables_active()->begin();
cvi != variables_active()->end();
@ -1089,7 +1109,6 @@ int colvarmodule::end_of_step()
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<colvar *>::iterator cvi = variables()->begin();
cvi != variables()->end(); cvi++) {
(*cvi)->setup();
@ -1248,13 +1267,13 @@ std::istream & colvarmodule::read_restart(std::istream &is)
std::string restart_conf;
if (is >> colvarparse::read_block("configuration", restart_conf)) {
parse->get_keyval(restart_conf, "step",
it_restart, (size_t) 0,
colvarparse::parse_silent);
it_restart, static_cast<step_number>(0),
colvarparse::parse_restart);
it = it_restart;
std::string restart_version;
parse->get_keyval(restart_conf, "version",
restart_version, std::string(""),
colvarparse::parse_silent);
colvarparse::parse_restart);
if (restart_version.size() && (restart_version != std::string(COLVARS_VERSION))) {
cvm::log("This state file was generated with version "+restart_version+"\n");
}
@ -1600,14 +1619,16 @@ std::ostream & colvarmodule::write_traj(std::ostream &os)
}
void cvm::log(std::string const &message)
void cvm::log(std::string const &message, int min_log_level)
{
if (cvm::log_level() < min_log_level) return;
// allow logging when the module is not fully initialized
size_t const d = (cvm::main() != NULL) ? depth() : 0;
if (d > 0)
if (d > 0) {
proxy->log((std::string(2*d, ' '))+message);
else
} else {
proxy->log(message);
}
}
@ -1915,14 +1936,190 @@ int cvm::replica_comm_send(char* msg_data, int msg_len, int dest_rep)
template<typename T> std::string _to_str(T const &x,
size_t width, size_t prec)
{
std::ostringstream os;
if (width) os.width(width);
if (prec) {
os.setf(std::ios::scientific, std::ios::floatfield);
os.precision(prec);
}
os << x;
return os.str();
}
template<typename T> std::string _to_str_vector(std::vector<T> const &x,
size_t width, size_t prec)
{
if (!x.size()) return std::string("");
std::ostringstream os;
if (prec) {
os.setf(std::ios::scientific, std::ios::floatfield);
}
os << "{ ";
if (width) os.width(width);
if (prec) os.precision(prec);
os << x[0];
for (size_t i = 1; i < x.size(); i++) {
os << ", ";
if (width) os.width(width);
if (prec) os.precision(prec);
os << x[i];
}
os << " }";
return os.str();
}
std::string colvarmodule::to_str(std::string const &x)
{
return std::string("\"")+x+std::string("\"");
}
std::string colvarmodule::to_str(char const *x)
{
return std::string("\"")+std::string(x)+std::string("\"");
}
std::string colvarmodule::to_str(bool x)
{
return (x ? "on" : "off");
}
std::string colvarmodule::to_str(int const &x,
size_t width, size_t prec)
{
return _to_str<int>(x, width, prec);
}
std::string colvarmodule::to_str(size_t const &x,
size_t width, size_t prec)
{
return _to_str<size_t>(x, width, prec);
}
std::string colvarmodule::to_str(long int const &x,
size_t width, size_t prec)
{
return _to_str<long int>(x, width, prec);
}
std::string colvarmodule::to_str(step_number const &x,
size_t width, size_t prec)
{
return _to_str<step_number>(x, width, prec);
}
std::string colvarmodule::to_str(cvm::real const &x,
size_t width, size_t prec)
{
return _to_str<cvm::real>(x, width, prec);
}
std::string colvarmodule::to_str(cvm::rvector const &x,
size_t width, size_t prec)
{
return _to_str<cvm::rvector>(x, width, prec);
}
std::string colvarmodule::to_str(cvm::quaternion const &x,
size_t width, size_t prec)
{
return _to_str<cvm::quaternion>(x, width, prec);
}
std::string colvarmodule::to_str(colvarvalue const &x,
size_t width, size_t prec)
{
return _to_str<colvarvalue>(x, width, prec);
}
std::string colvarmodule::to_str(cvm::vector1d<cvm::real> const &x,
size_t width, size_t prec)
{
return _to_str< cvm::vector1d<cvm::real> >(x, width, prec);
}
std::string colvarmodule::to_str(cvm::matrix2d<cvm::real> const &x,
size_t width, size_t prec)
{
return _to_str< cvm::matrix2d<cvm::real> >(x, width, prec);
}
std::string colvarmodule::to_str(std::vector<int> const &x,
size_t width, size_t prec)
{
return _to_str_vector<int>(x, width, prec);
}
std::string colvarmodule::to_str(std::vector<size_t> const &x,
size_t width, size_t prec)
{
return _to_str_vector<size_t>(x, width, prec);
}
std::string colvarmodule::to_str(std::vector<long int> const &x,
size_t width, size_t prec)
{
return _to_str_vector<long int>(x, width, prec);
}
std::string colvarmodule::to_str(std::vector<cvm::real> const &x,
size_t width, size_t prec)
{
return _to_str_vector<cvm::real>(x, width, prec);
}
std::string colvarmodule::to_str(std::vector<cvm::rvector> const &x,
size_t width, size_t prec)
{
return _to_str_vector<cvm::rvector>(x, width, prec);
}
std::string colvarmodule::to_str(std::vector<cvm::quaternion> const &x,
size_t width, size_t prec)
{
return _to_str_vector<cvm::quaternion>(x, width, prec);
}
std::string colvarmodule::to_str(std::vector<colvarvalue> const &x,
size_t width, size_t prec)
{
return _to_str_vector<colvarvalue>(x, width, prec);
}
std::string colvarmodule::to_str(std::vector<std::string> const &x,
size_t width, size_t prec)
{
return _to_str_vector<std::string>(x, width, prec);
}
std::string cvm::wrap_string(std::string const &s, size_t nchars)
{
if (!s.size()) {
return std::string(nchars, ' ');
} else {
return ( (s.size() <= nchars) ?
(s+std::string(nchars-s.size(), ' ')) :
(std::string(s, 0, nchars)) );
}
}
// shared pointer to the proxy object
colvarproxy *colvarmodule::proxy = NULL;
// static runtime data
cvm::real colvarmodule::debug_gradients_step_size = 1.0e-07;
int colvarmodule::errorCode = 0;
long colvarmodule::it = 0;
long colvarmodule::it_restart = 0;
int colvarmodule::log_level_ = 10;
cvm::step_number colvarmodule::it = 0;
cvm::step_number colvarmodule::it_restart = 0;
size_t colvarmodule::restart_out_freq = 0;
size_t colvarmodule::cv_traj_freq = 0;
bool colvarmodule::use_scripted_forces = false;

View File

@ -10,6 +10,8 @@
#ifndef COLVARMODULE_H
#define COLVARMODULE_H
#include <cmath>
#include "colvars_version.h"
#ifndef COLVARS_DEBUG
@ -55,6 +57,7 @@ class colvar;
class colvarbias;
class colvarproxy;
class colvarscript;
class colvarvalue;
/// \brief Collective variables module (main class)
@ -88,10 +91,16 @@ public:
// TODO colvarscript should be unaware of colvarmodule's internals
friend class colvarscript;
/// Use a 64-bit integer to store the step number
typedef long long step_number;
/// Defining an abstract real number allows to switch precision
typedef double real;
/// Override std::pow with a product for n integer
// Math functions
/// Override the STL pow() with a product for n integer
static inline real integer_power(real const &x, int const n)
{
// Original code: math_special.h in LAMMPS
@ -105,8 +114,68 @@ public:
return (n > 0) ? yy : 1.0/yy;
}
/// Residue identifier
typedef int residue_id;
/// Reimplemented to work around MS compiler issues
static inline real pow(real const &x, real const &y)
{
return ::pow(static_cast<double>(x), static_cast<double>(y));
}
/// Reimplemented to work around MS compiler issues
static inline real floor(real const &x)
{
return ::floor(static_cast<double>(x));
}
/// Reimplemented to work around MS compiler issues
static inline real fabs(real const &x)
{
return ::fabs(static_cast<double>(x));
}
/// Reimplemented to work around MS compiler issues
static inline real sqrt(real const &x)
{
return ::sqrt(static_cast<double>(x));
}
/// Reimplemented to work around MS compiler issues
static inline real sin(real const &x)
{
return ::sin(static_cast<double>(x));
}
/// Reimplemented to work around MS compiler issues
static inline real cos(real const &x)
{
return ::cos(static_cast<double>(x));
}
/// Reimplemented to work around MS compiler issues
static inline real acos(real const &x)
{
return ::acos(static_cast<double>(x));
}
/// Reimplemented to work around MS compiler issues
static inline real atan2(real const &x, real const &y)
{
return ::atan2(static_cast<double>(x), static_cast<double>(y));
}
/// Reimplemented to work around MS compiler issues
static inline real exp(real const &x)
{
return ::exp(static_cast<double>(x));
}
/// Reimplemented to work around MS compiler issues. Note: log() is
/// currently defined as the text logging function, but this can be changed
/// at a later time
static inline real logn(real const &x)
{
return ::log(static_cast<double>(x));
}
class rvector;
template <class T> class vector1d;
@ -114,6 +183,10 @@ public:
class quaternion;
class rotation;
/// Residue identifier
typedef int residue_id;
/// \brief Atom position (different type name from rvector, to make
/// possible future PBC-transparent implementations)
typedef rvector atom_pos;
@ -150,19 +223,19 @@ public:
/// Current step number
static long it;
static step_number it;
/// Starting step number for this run
static long it_restart;
static step_number it_restart;
/// Return the current step number from the beginning of this run
static inline long step_relative()
static inline step_number step_relative()
{
return it - it_restart;
}
/// Return the current step number from the beginning of the whole
/// calculation
static inline long step_absolute()
static inline step_number step_absolute()
{
return it;
}
@ -203,9 +276,10 @@ private:
std::vector<atom_group *> named_atom_groups;
public:
/// Register a named atom group into named_atom_groups
inline void register_named_atom_group(atom_group * ag) {
named_atom_groups.push_back(ag);
}
void register_named_atom_group(atom_group *ag);
/// Remove a named atom group from named_atom_groups
void unregister_named_atom_group(atom_group *ag);
/// Array of collective variables
std::vector<colvar *> *variables();
@ -254,8 +328,7 @@ public:
/// \brief How many objects are configured yet?
size_t size() const;
/// \brief Constructor \param config_name Configuration file name
/// \param restart_name (optional) Restart file name
/// \brief Constructor
colvarmodule(colvarproxy *proxy);
/// Destructor
@ -265,6 +338,7 @@ public:
int reset();
/// Open a config file, load its contents, and pass it to config_string()
/// \param config_file_name Configuration file name
int read_config_file(char const *config_file_name);
/// \brief Parse a config string assuming it is a complete configuration
@ -431,26 +505,92 @@ public:
long traj_read_begin,
long traj_read_end);
/// Quick conversion of an object to a string
template<typename T> static std::string to_str(T const &x,
size_t const &width = 0,
size_t const &prec = 0);
/// Quick conversion of a vector of objects to a string
template<typename T> static std::string to_str(std::vector<T> const &x,
size_t const &width = 0,
size_t const &prec = 0);
/// Convert to string for output purposes
static std::string to_str(char const *s);
/// Convert to string for output purposes
static std::string to_str(std::string const &s);
/// Convert to string for output purposes
static std::string to_str(bool x);
/// Convert to string for output purposes
static std::string to_str(int const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(size_t const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(long int const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(step_number const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(real const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(rvector const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(quaternion const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(colvarvalue const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(vector1d<real> const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(matrix2d<real> const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(std::vector<int> const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(std::vector<size_t> const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(std::vector<long int> const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(std::vector<real> const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(std::vector<rvector> const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(std::vector<quaternion> const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(std::vector<colvarvalue> const &x,
size_t width = 0, size_t prec = 0);
/// Convert to string for output purposes
static std::string to_str(std::vector<std::string> const &x,
size_t width = 0, size_t prec = 0);
/// Reduce the number of characters in a string
static inline std::string wrap_string(std::string const &s,
size_t const &nchars)
{
if (!s.size())
return std::string(nchars, ' ');
else
return ( (s.size() <= size_t(nchars)) ?
(s+std::string(nchars-s.size(), ' ')) :
(std::string(s, 0, nchars)) );
}
static std::string wrap_string(std::string const &s,
size_t nchars);
/// Number of characters to represent a time step
static size_t const it_width;
@ -485,7 +625,9 @@ public:
static void request_total_force();
/// Print a message to the main log
static void log(std::string const &message);
/// \param message Message to print
/// \param min_log_level Only print if cvm::log_level() >= min_log_level
static void log(std::string const &message, int min_log_level = 10);
/// Print a message to the main log and exit with error code
static int fatal_error(std::string const &message);
@ -493,6 +635,50 @@ public:
/// Print a message to the main log and set global error code
static int error(std::string const &message, int code = COLVARS_ERROR);
private:
/// Level of logging requested by the user
static int log_level_;
public:
/// Level of logging requested by the user
static inline int log_level()
{
return log_level_;
}
/// Level at which initialization messages are logged
static inline int log_init_messages()
{
return 1;
}
/// Level at which a keyword's user-provided value is logged
static inline int log_user_params()
{
return 2;
}
/// Level at which a keyword's default value is logged
static inline int log_default_params()
{
return 3;
}
/// Level at which output-file operations are logged
static inline int log_output_files()
{
return 4;
}
/// Level at which input-file operations (configuration, state) are logged
static inline int log_input_files()
{
return 5;
}
// Replica exchange commands.
static bool replica_enabled();
static int replica_index();
@ -630,41 +816,4 @@ std::ostream & operator << (std::ostream &os, cvm::rvector const &v);
std::istream & operator >> (std::istream &is, cvm::rvector &v);
template<typename T> std::string cvm::to_str(T const &x,
size_t const &width,
size_t const &prec) {
std::ostringstream os;
if (width) os.width(width);
if (prec) {
os.setf(std::ios::scientific, std::ios::floatfield);
os.precision(prec);
}
os << x;
return os.str();
}
template<typename T> std::string cvm::to_str(std::vector<T> const &x,
size_t const &width,
size_t const &prec) {
if (!x.size()) return std::string("");
std::ostringstream os;
if (prec) {
os.setf(std::ios::scientific, std::ios::floatfield);
}
os << "{ ";
if (width) os.width(width);
if (prec) os.precision(prec);
os << x[0];
for (size_t i = 1; i < x.size(); i++) {
os << ", ";
if (width) os.width(width);
if (prec) os.precision(prec);
os << x[i];
}
os << " }";
return os.str();
}
#endif

View File

@ -10,6 +10,7 @@
#include <sstream>
#include <iostream>
#include <algorithm>
#include "colvarmodule.h"
#include "colvarvalue.h"
@ -20,15 +21,21 @@
char const * const colvarparse::white_space = " \t";
// definition of single-value keyword parsers
namespace {
template<typename TYPE> bool colvarparse::_get_keyval_scalar_(std::string const &conf,
char const *key,
TYPE &value,
TYPE const &def_value,
Parse_Mode const parse_mode)
// Avoid having to put the bool assignment in the template :-(
void set_bool(void *p, bool val)
{
bool *v = reinterpret_cast<bool *>(p);
*v = val;
}
}
bool colvarparse::get_key_string_value(std::string const &conf,
char const *key, std::string &data)
{
std::string data;
bool b_found = false, b_found_any = false;
size_t save_pos = 0, found_count = 0;
@ -48,29 +55,163 @@ template<typename TYPE> bool colvarparse::_get_keyval_scalar_(std::string const
std::string(key)+"\".\n", INPUT_ERROR);
}
return b_found_any;
}
template<typename TYPE>
void colvarparse::mark_key_set_user(std::string const &key_str,
TYPE const &value,
Parse_Mode const &parse_mode)
{
key_set_modes[to_lower_cppstr(key_str)] = key_set_user;
if (parse_mode & parse_echo) {
cvm::log("# "+key_str+" = "+cvm::to_str(value)+"\n",
cvm::log_user_params());
}
}
template<typename TYPE>
void colvarparse::mark_key_set_default(std::string const &key_str,
TYPE const &def_value,
Parse_Mode const &parse_mode)
{
key_set_modes[to_lower_cppstr(key_str)] = key_set_default;
if (parse_mode & parse_echo_default) {
cvm::log("# "+key_str+" = "+cvm::to_str(def_value)+
" [default]\n", cvm::log_default_params());
}
}
void colvarparse::error_key_required(std::string const &key_str,
Parse_Mode const &parse_mode)
{
if (key_already_set(key_str)) {
return;
}
if (parse_mode & parse_restart) {
cvm::error("Error: keyword \""+key_str+
"\" is missing from the restart.\n", INPUT_ERROR);
} else {
cvm::error("Error: keyword \""+key_str+
"\" is required.\n", INPUT_ERROR);
}
}
template<typename TYPE>
int colvarparse::_get_keyval_scalar_value_(std::string const &key_str,
std::string const &data,
TYPE &value,
TYPE const &def_value)
{
std::istringstream is(data);
size_t value_count = 0;
TYPE x(def_value);
while (is >> x) {
value = x;
value_count++;
}
if (value_count == 0) {
return cvm::error("Error: in parsing \""+
key_str+"\".\n", INPUT_ERROR);
}
if (value_count > 1) {
return cvm::error("Error: multiple values "
"are not allowed for keyword \""+
key_str+"\".\n", INPUT_ERROR);
}
return COLVARS_OK;
}
template<>
int colvarparse::_get_keyval_scalar_value_(std::string const &key_str,
std::string const &data,
bool &value,
bool const &def_value)
{
if ( (data == std::string("on")) ||
(data == std::string("yes")) ||
(data == std::string("true")) ) {
set_bool(reinterpret_cast<void *>(&value), true);
} else if ( (data == std::string("off")) ||
(data == std::string("no")) ||
(data == std::string("false")) ) {
set_bool(reinterpret_cast<void *>(&value), false);
} else {
return cvm::error("Error: boolean values only are allowed "
"for \""+key_str+"\".\n", INPUT_ERROR);
}
return COLVARS_OK;
}
template<typename TYPE>
int colvarparse::_get_keyval_scalar_novalue_(std::string const &key_str,
TYPE &value,
Parse_Mode const &parse_mode)
{
return cvm::error("Error: improper or missing value "
"for \""+key_str+"\".\n", INPUT_ERROR);
}
template<>
int colvarparse::_get_keyval_scalar_novalue_(std::string const &key_str,
bool &value,
Parse_Mode const &parse_mode)
{
set_bool(reinterpret_cast<void *>(&value), true);
mark_key_set_user<bool>(key_str, value, parse_mode);
return COLVARS_OK;
}
template<typename TYPE>
bool colvarparse::_get_keyval_scalar_(std::string const &conf,
char const *key,
TYPE &value,
TYPE const &def_value,
Parse_Mode const &parse_mode)
{
std::string const key_str(key);
std::string data;
bool const b_found_any = get_key_string_value(conf, key, data);
if (data.size()) {
std::istringstream is(data);
TYPE x(def_value);
if (is >> x) {
value = x;
_get_keyval_scalar_value_<TYPE>(key_str, data, value, def_value);
mark_key_set_user<TYPE>(key_str, value, parse_mode);
} else { // No string value
if (b_found_any) {
_get_keyval_scalar_novalue_<TYPE>(key_str, value, parse_mode);
} else {
cvm::error("Error: in parsing \""+
std::string(key)+"\".\n", INPUT_ERROR);
}
if (parse_mode != parse_silent) {
cvm::log("# "+std::string(key)+" = "+
cvm::to_str(value)+"\n");
}
} else {
if (b_found_any) {
cvm::error("Error: improper or missing value "
"for \""+std::string(key)+"\".\n", INPUT_ERROR);
}
value = def_value;
if (parse_mode != parse_silent) {
cvm::log("# "+std::string(key)+" = "+
cvm::to_str(def_value)+" [default]\n");
if (parse_mode & parse_required) {
if (cvm::debug()) {
cvm::log("get_keyval, parse_required = "+cvm::to_str(parse_mode & parse_required)+
"\n");
}
error_key_required(key_str, parse_mode);
return false;
}
if ( (parse_mode & parse_override) || !(key_already_set(key)) ) {
value = def_value;
mark_key_set_default<TYPE>(key_str, value, parse_mode);
}
}
}
@ -78,96 +219,17 @@ template<typename TYPE> bool colvarparse::_get_keyval_scalar_(std::string const
}
bool colvarparse::_get_keyval_scalar_string_(std::string const &conf,
char const *key,
std::string &value,
std::string const &def_value,
Parse_Mode const parse_mode)
template<typename TYPE>
bool colvarparse::_get_keyval_vector_(std::string const &conf,
char const *key,
std::vector<TYPE> &values,
std::vector<TYPE> const &def_values,
Parse_Mode const &parse_mode)
{
std::string const key_str(key);
std::string data;
bool b_found = false, b_found_any = false;
size_t save_pos = 0, found_count = 0;
do {
std::string data_this = "";
b_found = key_lookup(conf, key, &data_this, &save_pos);
if (b_found) {
if (!b_found_any)
b_found_any = true;
found_count++;
data = data_this;
}
} while (b_found);
if (found_count > 1) {
cvm::error("Error: found more than one instance of \""+
std::string(key)+"\".\n", INPUT_ERROR);
}
if (data.size()) {
std::istringstream is(data);
size_t data_count = 0;
std::string x(def_value);
while (is >> x) {
value = x;
data_count++;
}
if (data_count == 0)
cvm::error("Error: in parsing \""+
std::string(key)+"\".\n", INPUT_ERROR);
if (data_count > 1) {
cvm::error("Error: multiple values "
"are not allowed for keyword \""+
std::string(key)+"\".\n", INPUT_ERROR);
}
if (parse_mode != parse_silent) {
cvm::log("# "+std::string(key)+" = \""+
cvm::to_str(value)+"\"\n");
}
} else {
if (b_found_any) {
cvm::error("Error: improper or missing value "
"for \""+std::string(key)+"\".\n", INPUT_ERROR);
}
value = def_value;
if (parse_mode != parse_silent) {
cvm::log("# "+std::string(key)+" = \""+
cvm::to_str(def_value)+"\" [default]\n");
}
}
return b_found_any;
}
// multiple-value keyword parsers
template<typename TYPE> bool colvarparse::_get_keyval_vector_(std::string const &conf,
char const *key,
std::vector<TYPE> &values,
std::vector<TYPE> const &def_values,
Parse_Mode const parse_mode)
{
std::string data;
bool b_found = false, b_found_any = false;
size_t save_pos = 0, found_count = 0;
do {
std::string data_this = "";
b_found = key_lookup(conf, key, &data_this, &save_pos);
if (b_found) {
if (!b_found_any)
b_found_any = true;
found_count++;
data = data_this;
}
} while (b_found);
if (found_count > 1) {
cvm::error("Error: found more than one instance of \""+
std::string(key)+"\".\n", INPUT_ERROR);
}
bool const b_found_any = get_key_string_value(conf, key, data);
if (data.size()) {
std::istringstream is(data);
@ -175,10 +237,11 @@ template<typename TYPE> bool colvarparse::_get_keyval_vector_(std::string const
if (values.size() == 0) {
std::vector<TYPE> x;
if (def_values.size())
if (def_values.size()) {
x = def_values;
else
} else {
x.assign(1, TYPE());
}
for (size_t i = 0;
( is >> x[ ((i<x.size()) ? i : x.size()-1) ] );
@ -195,29 +258,39 @@ template<typename TYPE> bool colvarparse::_get_keyval_vector_(std::string const
values[i] = x;
} else {
cvm::error("Error: in parsing \""+
std::string(key)+"\".\n", INPUT_ERROR);
key_str+"\".\n", INPUT_ERROR);
}
}
}
if (parse_mode != parse_silent) {
cvm::log("# "+std::string(key)+" = "+
cvm::to_str(values)+"\n");
}
mark_key_set_user< std::vector<TYPE> >(key_str, values, parse_mode);
} else {
if (b_found_any) {
cvm::error("Error: improper or missing values for \""+
std::string(key)+"\".\n", INPUT_ERROR);
}
key_str+"\".\n", INPUT_ERROR);
} else {
for (size_t i = 0; i < values.size(); i++)
values[i] = def_values[ (i > def_values.size()) ? 0 : i ];
if ((values.size() > 0) && (values.size() != def_values.size())) {
cvm::error("Error: the number of default values for \""+
key_str+"\" is different from the number of "
"current values.\n", BUG_ERROR);
}
if (parse_mode & parse_required) {
error_key_required(key_str, parse_mode);
return false;
}
if ( (parse_mode & parse_override) || !(key_already_set(key)) ) {
for (size_t i = 0; i < values.size(); i++) {
values[i] = def_values[i];
}
mark_key_set_default< std::vector<TYPE> >(key_str, def_values,
parse_mode);
}
if (parse_mode != parse_silent) {
cvm::log("# "+std::string(key)+" = "+
cvm::to_str(def_values)+" [default]\n");
}
}
@ -255,13 +328,22 @@ bool colvarparse::get_keyval(std::string const &conf,
return _get_keyval_scalar_<long>(conf, key, value, def_value, parse_mode);
}
bool colvarparse::get_keyval(std::string const &conf,
char const *key,
cvm::step_number &value,
cvm::step_number const &def_value,
Parse_Mode const parse_mode)
{
return _get_keyval_scalar_<cvm::step_number>(conf, key, value, def_value, parse_mode);
}
bool colvarparse::get_keyval(std::string const &conf,
char const *key,
std::string &value,
std::string const &def_value,
Parse_Mode const parse_mode)
{
return _get_keyval_scalar_string_(conf, key, value, def_value, parse_mode);
return _get_keyval_scalar_<std::string>(conf, key, value, def_value, parse_mode);
}
bool colvarparse::get_keyval(std::string const &conf,
@ -300,66 +382,13 @@ bool colvarparse::get_keyval(std::string const &conf,
return _get_keyval_scalar_<colvarvalue>(conf, key, value, def_value, parse_mode);
}
bool colvarparse::get_keyval(std::string const &conf,
char const *key,
bool &value,
bool const &def_value,
Parse_Mode const parse_mode)
{
std::string data;
bool b_found = false, b_found_any = false;
size_t save_pos = 0, found_count = 0;
do {
std::string data_this = "";
b_found = key_lookup(conf, key, &data_this, &save_pos);
if (b_found) {
if (!b_found_any)
b_found_any = true;
found_count++;
data = data_this;
}
} while (b_found);
if (found_count > 1) {
cvm::error("Error: found more than one instance of \""+
std::string(key)+"\".\n", INPUT_ERROR);
}
if (data.size()) {
if ( (data == std::string("on")) ||
(data == std::string("yes")) ||
(data == std::string("true")) ) {
value = true;
} else if ( (data == std::string("off")) ||
(data == std::string("no")) ||
(data == std::string("false")) ) {
value = false;
} else
cvm::error("Error: boolean values only are allowed "
"for \""+std::string(key)+"\".\n", INPUT_ERROR);
if (parse_mode != parse_silent) {
cvm::log("# "+std::string(key)+" = "+
(value ? "on" : "off")+"\n");
}
} else {
if (b_found_any) {
if (parse_mode != parse_silent) {
cvm::log("# "+std::string(key)+" = on\n");
}
value = true;
} else {
value = def_value;
if (parse_mode != parse_silent) {
cvm::log("# "+std::string(key)+" = "+
(def_value ? "on" : "off")+" [default]\n");
}
}
}
return b_found_any;
return _get_keyval_scalar_<bool>(conf, key, value, def_value, parse_mode);
}
@ -440,15 +469,27 @@ bool colvarparse::get_keyval(std::string const &conf,
void colvarparse::add_keyword(char const *key)
{
for (std::list<std::string>::iterator ki = allowed_keywords.begin();
ki != allowed_keywords.end(); ki++) {
if (to_lower_cppstr(std::string(key)) == *ki)
return;
std::string const key_str_lower(to_lower_cppstr(std::string(key)));
if (key_set_modes.find(key_str_lower) != key_set_modes.end()) {
return;
}
// not found in the list
// if (cvm::debug())
// cvm::log("Registering a new keyword, \""+std::string (key)+"\".\n");
allowed_keywords.push_back(to_lower_cppstr(std::string(key)));
key_set_modes[key_str_lower] = key_not_set;
allowed_keywords.push_back(key_str_lower);
}
bool colvarparse::key_already_set(std::string const &key_str)
{
std::string const key_str_lower(to_lower_cppstr(key_str));
if (key_set_modes.find(key_str_lower) == key_set_modes.end()) {
return false;
}
return (key_set_modes[key_str_lower] > 0);
}
@ -457,6 +498,10 @@ void colvarparse::strip_values(std::string &conf)
size_t offset = 0;
data_begin_pos.sort();
data_end_pos.sort();
std::list<size_t>::iterator data_begin_pos_last = std::unique(data_begin_pos.begin(), data_begin_pos.end());
data_begin_pos.erase(data_begin_pos_last, data_begin_pos.end());
std::list<size_t>::iterator data_end_pos_last = std::unique(data_end_pos.begin(), data_end_pos.end());
data_end_pos.erase(data_end_pos_last, data_end_pos.end());
std::list<size_t>::iterator data_begin = data_begin_pos.begin();
std::list<size_t>::iterator data_end = data_end_pos.begin();
@ -464,28 +509,16 @@ void colvarparse::strip_values(std::string &conf)
for ( ; (data_begin != data_begin_pos.end()) &&
(data_end != data_end_pos.end()) ;
data_begin++, data_end++) {
// std::cerr << "data_begin, data_end "
// << *data_begin << ", " << *data_end
// << "\n";
size_t const nchars = *data_end-*data_begin;
// std::cerr << "conf[data_begin:data_end] = \""
// << std::string (conf, *data_begin - offset, nchars)
// << "\"\n";
conf.erase(*data_begin - offset, nchars);
offset += nchars;
// std::cerr << ("Stripped config = \"\n"+conf+"\"\n");
}
}
void colvarparse::clear_keyword_registry()
{
key_set_modes.clear();
allowed_keywords.clear();
data_begin_pos.clear();
data_end_pos.clear();

View File

@ -12,6 +12,7 @@
#include <cstring>
#include <string>
#include <map>
#include "colvarmodule.h"
#include "colvarvalue.h"
@ -24,35 +25,9 @@
/// need to parse input inherit from this
class colvarparse {
protected:
/// \brief List of legal keywords for this object: this is updated
/// by each call to colvarparse::get_keyval() or
/// colvarparse::key_lookup()
std::list<std::string> allowed_keywords;
/// \brief List of delimiters for the values of each keyword in the
/// configuration string; all keywords will be stripped of their
/// values before the keyword check is performed
std::list<size_t> data_begin_pos;
/// \brief List of delimiters for the values of each keyword in the
/// configuration string; all keywords will be stripped of their
/// values before the keyword check is performed
std::list<size_t> data_end_pos;
/// \brief Add a new valid keyword to the list
void add_keyword(char const *key);
/// \brief Remove all the values from the config string
void strip_values(std::string &conf);
/// \brief Configuration string of the object (includes comments)
std::string config_string;
public:
/// Default constructor
inline colvarparse()
{
init();
@ -88,14 +63,23 @@ public:
/// How a keyword is parsed in a string
enum Parse_Mode {
/// \brief(default) Read the first instance of a keyword (if
/// any), report its value, and print a warning when there is more
/// than one
parse_normal,
/// \brief Like parse_normal, but don't send any message to the log
/// (useful e.g. in restart files when such messages are very
/// numerous and redundant)
parse_silent
/// Zero for all flags
parse_null = 0,
/// Print the value of a keyword if it is given
parse_echo = (1<<1),
/// Print the default value of a keyword, if it is NOT given
parse_echo_default = (1<<2),
/// Do not print the keyword
parse_silent = 0,
/// Raise error if the keyword is not provided
parse_required = (1<<16),
/// Successive calls to get_keyval() will override the previous values
/// when the keyword is not given any more
parse_override = (1<<17),
/// The call is being executed from a read_restart() function
parse_restart = (1<<18),
/// Alias for old default behavior (should be phased out)
parse_normal = (1<<2) | (1<<1) | (1<<17)
};
/// \brief Check that all the keywords within "conf" are in the list
@ -146,6 +130,11 @@ public:
long &value,
long const &def_value = 0,
Parse_Mode const parse_mode = parse_normal);
bool get_keyval(std::string const &conf,
char const *key,
cvm::step_number &value,
cvm::step_number const &def_value = 0,
Parse_Mode const parse_mode = parse_normal);
bool get_keyval(std::string const &conf,
char const *key,
std::string &value,
@ -219,23 +208,57 @@ public:
protected:
// Templates
template<typename TYPE> bool _get_keyval_scalar_(std::string const &conf,
char const *key,
TYPE &value,
TYPE const &def_value,
Parse_Mode const parse_mode);
bool _get_keyval_scalar_string_(std::string const &conf,
char const *key,
std::string &value,
std::string const &def_value,
Parse_Mode const parse_mode);
/// Get the string value of a keyword, and save it for later parsing
bool get_key_string_value(std::string const &conf,
char const *key, std::string &data);
template<typename TYPE> bool _get_keyval_vector_(std::string const &conf,
char const *key,
std::vector<TYPE> &values,
std::vector<TYPE> const &def_values,
Parse_Mode const parse_mode);
/// Template for single-value keyword parsers
template<typename TYPE>
bool _get_keyval_scalar_(std::string const &conf,
char const *key,
TYPE &value,
TYPE const &def_value,
Parse_Mode const &parse_mode);
/// Template for multiple-value keyword parsers
template<typename TYPE>
bool _get_keyval_vector_(std::string const &conf,
char const *key,
std::vector<TYPE> &values,
std::vector<TYPE> const &def_values,
Parse_Mode const &parse_mode);
/// Extract the value of a variable from a string
template<typename TYPE>
int _get_keyval_scalar_value_(std::string const &key_str,
std::string const &data,
TYPE &value,
TYPE const &def_value);
/// Handle the case where the user provides a keyword without value
template<typename TYPE>
int _get_keyval_scalar_novalue_(std::string const &key_str,
TYPE &value,
Parse_Mode const &parse_mode);
/// Record that the keyword has just been user-defined
template<typename TYPE>
void mark_key_set_user(std::string const &key_str,
TYPE const &value,
Parse_Mode const &parse_mode);
/// Record that the keyword has just been set to its default value
template<typename TYPE>
void mark_key_set_default(std::string const &key_str,
TYPE const &def_value,
Parse_Mode const &parse_mode);
/// Raise error condition due to the keyword being required!
void error_key_required(std::string const &key_str,
Parse_Mode const &parse_mode);
/// True if the keyword has been set already
bool key_already_set(std::string const &key_str);
public:
@ -286,7 +309,7 @@ public:
size_t *save_pos = NULL);
/// \brief Reads a configuration line, adds it to config_string, and returns
/// the stream \param is Input stream \param s String that will hold the
/// the stream \param is Input stream \param line String that will hold the
/// configuration line, with comments stripped
std::istream & read_config_line(std::istream &is, std::string &line);
@ -299,7 +322,51 @@ public:
/// from this position
static int check_braces(std::string const &conf, size_t const start_pos);
protected:
/// \brief List of legal keywords for this object: this is updated
/// by each call to colvarparse::get_keyval() or
/// colvarparse::key_lookup()
std::list<std::string> allowed_keywords;
/// How a keyword has been set
enum key_set_mode {
key_not_set = 0,
key_set_user = 1,
key_set_default = 2
};
/// Track which keywords have been already set, and how
std::map<std::string, key_set_mode> key_set_modes;
/// \brief List of delimiters for the values of each keyword in the
/// configuration string; all keywords will be stripped of their
/// values before the keyword check is performed
std::list<size_t> data_begin_pos;
/// \brief List of delimiters for the values of each keyword in the
/// configuration string; all keywords will be stripped of their
/// values before the keyword check is performed
std::list<size_t> data_end_pos;
/// \brief Add a new valid keyword to the list
void add_keyword(char const *key);
/// \brief Remove all the values from the config string
void strip_values(std::string &conf);
/// \brief Configuration string of the object (includes comments)
std::string config_string;
};
/// Bitwise OR between two Parse_mode flags
inline colvarparse::Parse_Mode operator | (colvarparse::Parse_Mode const &mode1,
colvarparse::Parse_Mode const &mode2)
{
return static_cast<colvarparse::Parse_Mode>(static_cast<int>(mode1) |
static_cast<int>(mode2));
}
#endif

View File

@ -60,7 +60,7 @@ bool colvarproxy_system::total_forces_same_step() const
inline int round_to_integer(cvm::real x)
{
return std::floor(x+0.5);
return cvm::floor(x+0.5);
}
@ -129,7 +129,10 @@ cvm::rvector colvarproxy_system::position_distance(cvm::atom_pos const &pos1,
colvarproxy_atoms::colvarproxy_atoms() {}
colvarproxy_atoms::colvarproxy_atoms()
{
updated_masses_ = updated_charges_ = false;
}
colvarproxy_atoms::~colvarproxy_atoms()
@ -544,7 +547,7 @@ int colvarproxy_script::run_colvar_gradient_callback(
colvarproxy_tcl::colvarproxy_tcl()
{
_tcl_interp = NULL;
tcl_interp_ = NULL;
}
@ -573,7 +576,7 @@ char const *colvarproxy_tcl::tcl_obj_to_str(unsigned char *obj)
int colvarproxy_tcl::tcl_run_force_callback()
{
#if defined(COLVARS_TCL)
Tcl_Interp *const tcl_interp = reinterpret_cast<Tcl_Interp *>(_tcl_interp);
Tcl_Interp *const tcl_interp = reinterpret_cast<Tcl_Interp *>(tcl_interp_);
std::string cmd = std::string("calc_colvar_forces ")
+ cvm::to_str(cvm::step_absolute());
int err = Tcl_Eval(tcl_interp, cmd.c_str());
@ -596,7 +599,7 @@ int colvarproxy_tcl::tcl_run_colvar_callback(
{
#if defined(COLVARS_TCL)
Tcl_Interp *const tcl_interp = reinterpret_cast<Tcl_Interp *>(_tcl_interp);
Tcl_Interp *const tcl_interp = reinterpret_cast<Tcl_Interp *>(tcl_interp_);
size_t i;
std::string cmd = std::string("calc_") + name;
for (i = 0; i < cvc_values.size(); i++) {
@ -633,7 +636,7 @@ int colvarproxy_tcl::tcl_run_colvar_gradient_callback(
{
#if defined(COLVARS_TCL)
Tcl_Interp *const tcl_interp = reinterpret_cast<Tcl_Interp *>(_tcl_interp);
Tcl_Interp *const tcl_interp = reinterpret_cast<Tcl_Interp *>(tcl_interp_);
size_t i;
std::string cmd = std::string("calc_") + name + "_gradient";
for (i = 0; i < cvc_values.size(); i++) {

View File

@ -29,7 +29,7 @@
///
/// To interface to a new MD engine, the simplest solution is to derive a new
/// class from \link colvarproxy \endlink. Currently implemented are: \link
/// colvarproxy_lammps, \endlink, \link colvarproxy_namd, \endlink, \link
/// colvarproxy_lammps \endlink, \link colvarproxy_namd \endlink, \link
/// colvarproxy_vmd \endlink.
@ -227,11 +227,15 @@ public:
inline std::vector<cvm::real> *modify_atom_masses()
{
// assume that we are requesting masses to change them
updated_masses_ = true;
return &atoms_masses;
}
inline std::vector<cvm::real> *modify_atom_charges()
{
// assume that we are requesting charges to change them
updated_charges_ = true;
return &atoms_charges;
}
@ -250,6 +254,18 @@ public:
return &atoms_new_colvar_forces;
}
/// Record whether masses have been updated
inline bool updated_masses() const
{
return updated_masses_;
}
/// Record whether masses have been updated
inline bool updated_charges() const
{
return updated_charges_;
}
protected:
/// \brief Array of 0-based integers used to uniquely associate atoms
@ -268,6 +284,9 @@ protected:
/// \brief Forces applied from colvars, to be communicated to the MD integrator
std::vector<cvm::rvector> atoms_new_colvar_forces;
/// Whether the masses and charges have been updated from the host code
bool updated_masses_, updated_charges_;
/// Used by all init_atom() functions: create a slot for an atom not
/// requested yet; returns the index in the arrays
int add_atom_slot(int atom_id);
@ -522,7 +541,7 @@ public:
protected:
/// Pointer to Tcl interpreter object
void *_tcl_interp;
void *tcl_interp_;
/// Set Tcl pointers
virtual void init_tcl_pointers();

View File

@ -1,5 +1,5 @@
#ifndef COLVARS_VERSION
#define COLVARS_VERSION "2018-11-16"
#define COLVARS_VERSION "2019-04-26"
// 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

View File

@ -137,6 +137,10 @@ int colvarscript::run(int objc, unsigned char *const objv[])
if (cmd == "update") {
error_code |= proxy->update_input();
if (error_code) {
result += "Error updating the Colvars module.\n";
return error_code;
}
error_code |= colvars->calc();
error_code |= proxy->update_output();
if (error_code) {
@ -273,6 +277,10 @@ int colvarscript::run(int objc, unsigned char *const objv[])
int colvarscript::proc_colvar(colvar *cv, int objc, unsigned char *const objv[]) {
if (objc < 3) {
result = "Missing arguments";
return COLVARSCRIPT_ERROR;
}
std::string const subcmd(obj_to_str(objv[2]));
if (subcmd == "value") {
@ -323,6 +331,47 @@ int colvarscript::proc_colvar(colvar *cv, int objc, unsigned char *const objv[])
return COLVARS_OK;
}
if (subcmd == "getatomgroups") {
std::vector<std::vector<int> > lists = cv->get_atom_lists();
std::vector<std::vector<int> >::iterator li = lists.begin();
for ( ; li != lists.end(); ++li) {
result += "{";
std::vector<int>::iterator lj = (*li).begin();
for ( ; lj != (*li).end(); ++lj) {
result += cvm::to_str(*lj);
result += " ";
}
result += "} ";
}
return COLVARS_OK;
}
if (subcmd == "getatomids") {
std::vector<int>::iterator li = cv->atom_ids.begin();
for ( ; li != cv->atom_ids.end(); ++li) {
result += cvm::to_str(*li);
result += " ";
}
return COLVARS_OK;
}
if (subcmd == "getgradients") {
std::vector<cvm::rvector>::iterator li = cv->atomic_gradients.begin();
for ( ; li != cv->atomic_gradients.end(); ++li) {
result += "{";
int j;
for (j = 0; j < 3; ++j) {
result += cvm::to_str((*li)[j]);
result += " ";
}
result += "} ";
}
return COLVARS_OK;
}
if (subcmd == "getappliedforce") {
result = (cv->applied_force()).to_simple_string();
return COLVARS_OK;
@ -410,6 +459,10 @@ int colvarscript::proc_colvar(colvar *cv, int objc, unsigned char *const objv[])
int colvarscript::proc_bias(colvarbias *b, int objc, unsigned char *const objv[]) {
if (objc < 3) {
result = "Missing arguments";
return COLVARSCRIPT_ERROR;
}
std::string const subcmd(obj_to_str(objv[2]));
if (subcmd == "energy") {

View File

@ -191,8 +191,9 @@ inline static colvarbias *colvarbias_obj(void *pobj)
#ifdef COLVARSCRIPT_CPP
#define CVSCRIPT_COMM_FN(COMM,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \
int CVSCRIPT_COMM_FNAME(COMM)(void *pobj, \
int objc, unsigned char *const objv[]) \
extern "C" int CVSCRIPT_COMM_FNAME(COMM)(void *pobj, \
int objc, \
unsigned char *const objv[]) \
{ \
colvarscript *script = colvarscript_obj(); \
script->clear_results(); \

View File

@ -19,6 +19,8 @@ bool colvarmodule::rotation::monitor_crossings = false;
cvm::real colvarmodule::rotation::crossing_threshold = 1.0E-02;
namespace {
/// Numerical recipes diagonalization
static int jacobi(cvm::real **a, cvm::real *d, cvm::real **v, int *nrot);
@ -28,6 +30,7 @@ static int eigsrt(cvm::real *d, cvm::real **v);
/// Transpose the matrix
static int transpose(cvm::real **v);
}
std::string cvm::rvector::to_simple_string() const
@ -245,13 +248,11 @@ cvm::quaternion::position_derivative_inner(cvm::rvector const &pos,
// Seok C, Dill KA. Using quaternions to calculate RMSD. J Comput
// Chem. 25(15):1849-57 (2004) DOI: 10.1002/jcc.20110 PubMed: 15376254
void colvarmodule::rotation::build_matrix(std::vector<cvm::atom_pos> const &pos1,
std::vector<cvm::atom_pos> const &pos2,
cvm::matrix2d<cvm::real> &S)
void colvarmodule::rotation::build_correlation_matrix(
std::vector<cvm::atom_pos> const &pos1,
std::vector<cvm::atom_pos> const &pos2)
{
// build the correlation matrix
C.resize(3, 3);
C.reset();
size_t i;
for (i = 0; i < pos1.size(); i++) {
C.xx() += pos1[i].x * pos2[i].x;
@ -264,7 +265,11 @@ void colvarmodule::rotation::build_matrix(std::vector<cvm::atom_pos> const &pos1
C.zy() += pos1[i].z * pos2[i].y;
C.zz() += pos1[i].z * pos2[i].z;
}
}
void colvarmodule::rotation::compute_overlap_matrix()
{
// build the "overlap" matrix, whose eigenvectors are stationary
// points of the RMSD in the space of rotations
S[0][0] = C.xx() + C.yy() + C.zz();
@ -286,37 +291,38 @@ void colvarmodule::rotation::build_matrix(std::vector<cvm::atom_pos> const &pos1
}
void colvarmodule::rotation::diagonalize_matrix(cvm::matrix2d<cvm::real> &S,
cvm::vector1d<cvm::real> &S_eigval,
cvm::matrix2d<cvm::real> &S_eigvec)
void colvarmodule::rotation::diagonalize_matrix(
cvm::matrix2d<cvm::real> &m,
cvm::vector1d<cvm::real> &eigval,
cvm::matrix2d<cvm::real> &eigvec)
{
S_eigval.resize(4);
S_eigval.reset();
S_eigvec.resize(4,4);
S_eigvec.reset();
eigval.resize(4);
eigval.reset();
eigvec.resize(4, 4);
eigvec.reset();
// diagonalize
int jac_nrot = 0;
if (jacobi(S.c_array(), S_eigval.c_array(), S_eigvec.c_array(), &jac_nrot) !=
if (jacobi(m.c_array(), eigval.c_array(), eigvec.c_array(), &jac_nrot) !=
COLVARS_OK) {
cvm::error("Too many iterations in routine jacobi.\n"
"This is usually the result of an ill-defined set of atoms for "
"rotational alignment (RMSD, rotateReference, etc).\n");
}
eigsrt(S_eigval.c_array(), S_eigvec.c_array());
eigsrt(eigval.c_array(), eigvec.c_array());
// jacobi saves eigenvectors by columns
transpose(S_eigvec.c_array());
transpose(eigvec.c_array());
// normalize eigenvectors
for (size_t ie = 0; ie < 4; ie++) {
cvm::real norm2 = 0.0;
size_t i;
for (i = 0; i < 4; i++) {
norm2 += S_eigvec[ie][i] * S_eigvec[ie][i];
norm2 += eigvec[ie][i] * eigvec[ie][i];
}
cvm::real const norm = std::sqrt(norm2);
cvm::real const norm = cvm::sqrt(norm2);
for (i = 0; i < 4; i++) {
S_eigvec[ie][i] /= norm;
eigvec[ie][i] /= norm;
}
}
}
@ -324,23 +330,26 @@ void colvarmodule::rotation::diagonalize_matrix(cvm::matrix2d<cvm::real> &S,
// Calculate the rotation, plus its derivatives
void colvarmodule::rotation::calc_optimal_rotation(std::vector<cvm::atom_pos> const &pos1,
std::vector<cvm::atom_pos> const &pos2)
void colvarmodule::rotation::calc_optimal_rotation(
std::vector<cvm::atom_pos> const &pos1,
std::vector<cvm::atom_pos> const &pos2)
{
S.resize(4,4);
C.resize(3, 3);
C.reset();
build_correlation_matrix(pos1, pos2);
S.resize(4, 4);
S.reset();
compute_overlap_matrix();
build_matrix(pos1, pos2, S);
S_backup.resize(4,4);
S_backup.resize(4, 4);
S_backup = S;
if (b_debug_gradients) {
cvm::log("S = "+cvm::to_str(cvm::to_str(S_backup), cvm::cv_width, cvm::cv_prec)+"\n");
cvm::log("S = "+cvm::to_str(S_backup, cvm::cv_width, cvm::cv_prec)+"\n");
}
diagonalize_matrix(S, S_eigval, S_eigvec);
// eigenvalues and eigenvectors
cvm::real const L0 = S_eigval[0];
cvm::real const L1 = S_eigval[1];
@ -524,7 +533,7 @@ void colvarmodule::rotation::calc_optimal_rotation(std::vector<cvm::atom_pos> co
dq0_2[3][comp] * colvarmodule::debug_gradients_step_size);
cvm::log( "|(l_0+dl_0) - l_0^new|/l_0 = "+
cvm::to_str(std::fabs(L0+DL0 - L0_new)/L0, cvm::cv_width, cvm::cv_prec)+
cvm::to_str(cvm::fabs(L0+DL0 - L0_new)/L0, cvm::cv_width, cvm::cv_prec)+
", |(q_0+dq_0) - q_0^new| = "+
cvm::to_str((Q0+DQ0 - Q0_new).norm(), cvm::cv_width, cvm::cv_prec)+
"\n");
@ -544,6 +553,9 @@ void colvarmodule::rotation::calc_optimal_rotation(std::vector<cvm::atom_pos> co
#define n 4
namespace {
int jacobi(cvm::real **a, cvm::real *d, cvm::real **v, int *nrot)
{
int j,iq,ip,i;
@ -567,7 +579,7 @@ int jacobi(cvm::real **a, cvm::real *d, cvm::real **v, int *nrot)
sm=0.0;
for (ip=0;ip<n-1;ip++) {
for (iq=ip+1;iq<n;iq++)
sm += std::fabs(a[ip][iq]);
sm += cvm::fabs(a[ip][iq]);
}
if (sm == 0.0) {
return COLVARS_OK;
@ -578,20 +590,20 @@ int jacobi(cvm::real **a, cvm::real *d, cvm::real **v, int *nrot)
tresh=0.0;
for (ip=0;ip<n-1;ip++) {
for (iq=ip+1;iq<n;iq++) {
g=100.0*std::fabs(a[ip][iq]);
if (i > 4 && (cvm::real)(std::fabs(d[ip])+g) == (cvm::real)std::fabs(d[ip])
&& (cvm::real)(std::fabs(d[iq])+g) == (cvm::real)std::fabs(d[iq]))
g=100.0*cvm::fabs(a[ip][iq]);
if (i > 4 && (cvm::real)(cvm::fabs(d[ip])+g) == (cvm::real)cvm::fabs(d[ip])
&& (cvm::real)(cvm::fabs(d[iq])+g) == (cvm::real)cvm::fabs(d[iq]))
a[ip][iq]=0.0;
else if (std::fabs(a[ip][iq]) > tresh) {
else if (cvm::fabs(a[ip][iq]) > tresh) {
h=d[iq]-d[ip];
if ((cvm::real)(std::fabs(h)+g) == (cvm::real)std::fabs(h))
if ((cvm::real)(cvm::fabs(h)+g) == (cvm::real)cvm::fabs(h))
t=(a[ip][iq])/h;
else {
theta=0.5*h/(a[ip][iq]);
t=1.0/(std::fabs(theta)+std::sqrt(1.0+theta*theta));
t=1.0/(cvm::fabs(theta)+cvm::sqrt(1.0+theta*theta));
if (theta < 0.0) t = -t;
}
c=1.0/std::sqrt(1+t*t);
c=1.0/cvm::sqrt(1+t*t);
s=t*c;
tau=s/(1.0+c);
h=t*a[ip][iq];
@ -663,5 +675,7 @@ int transpose(cvm::real **v)
return COLVARS_OK;
}
}
#undef n
#undef ROTATE

View File

@ -10,7 +10,6 @@
#ifndef COLVARTYPES_H
#define COLVARTYPES_H
#include <cmath>
#include <vector>
#include "colvarmodule.h"
@ -220,7 +219,7 @@ public:
inline cvm::real norm() const
{
return std::sqrt(this->norm2());
return cvm::sqrt(this->norm2());
}
inline cvm::real sum() const
@ -801,7 +800,7 @@ public:
inline cvm::real norm() const
{
return std::sqrt(this->norm2());
return cvm::sqrt(this->norm2());
}
inline cvm::rvector unit() const
@ -1008,17 +1007,17 @@ public:
cvm::real theta_in,
cvm::real psi_in)
{
q0 = ( (std::cos(phi_in/2.0)) * (std::cos(theta_in/2.0)) * (std::cos(psi_in/2.0)) +
(std::sin(phi_in/2.0)) * (std::sin(theta_in/2.0)) * (std::sin(psi_in/2.0)) );
q0 = ( (cvm::cos(phi_in/2.0)) * (cvm::cos(theta_in/2.0)) * (cvm::cos(psi_in/2.0)) +
(cvm::sin(phi_in/2.0)) * (cvm::sin(theta_in/2.0)) * (cvm::sin(psi_in/2.0)) );
q1 = ( (std::sin(phi_in/2.0)) * (std::cos(theta_in/2.0)) * (std::cos(psi_in/2.0)) -
(std::cos(phi_in/2.0)) * (std::sin(theta_in/2.0)) * (std::sin(psi_in/2.0)) );
q1 = ( (cvm::sin(phi_in/2.0)) * (cvm::cos(theta_in/2.0)) * (cvm::cos(psi_in/2.0)) -
(cvm::cos(phi_in/2.0)) * (cvm::sin(theta_in/2.0)) * (cvm::sin(psi_in/2.0)) );
q2 = ( (std::cos(phi_in/2.0)) * (std::sin(theta_in/2.0)) * (std::cos(psi_in/2.0)) +
(std::sin(phi_in/2.0)) * (std::cos(theta_in/2.0)) * (std::sin(psi_in/2.0)) );
q2 = ( (cvm::cos(phi_in/2.0)) * (cvm::sin(theta_in/2.0)) * (cvm::cos(psi_in/2.0)) +
(cvm::sin(phi_in/2.0)) * (cvm::cos(theta_in/2.0)) * (cvm::sin(psi_in/2.0)) );
q3 = ( (std::cos(phi_in/2.0)) * (std::cos(theta_in/2.0)) * (std::sin(psi_in/2.0)) -
(std::sin(phi_in/2.0)) * (std::sin(theta_in/2.0)) * (std::cos(psi_in/2.0)) );
q3 = ( (cvm::cos(phi_in/2.0)) * (cvm::cos(theta_in/2.0)) * (cvm::sin(psi_in/2.0)) -
(cvm::sin(phi_in/2.0)) * (cvm::sin(theta_in/2.0)) * (cvm::cos(psi_in/2.0)) );
}
/// \brief Default constructor
@ -1115,7 +1114,7 @@ public:
/// Norm of the quaternion
inline cvm::real norm() const
{
return std::sqrt(this->norm2());
return cvm::sqrt(this->norm2());
}
/// Return the conjugate quaternion
@ -1177,7 +1176,7 @@ public:
}
/// \brief Provides the quaternion product. \b NOTE: for the inner
/// product use: \code h.inner (q); \endcode
/// product use: `h.inner (q);`
friend inline cvm::quaternion operator * (cvm::quaternion const &h,
cvm::quaternion const &q)
{
@ -1263,7 +1262,7 @@ public:
cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 +
this->q2*Q2.q2 + this->q3*Q2.q3;
cvm::real const omega = std::acos( (cos_omega > 1.0) ? 1.0 :
cvm::real const omega = cvm::acos( (cos_omega > 1.0) ? 1.0 :
( (cos_omega < -1.0) ? -1.0 : cos_omega) );
// get the minimum distance: x and -x are the same quaternion
@ -1278,11 +1277,11 @@ public:
inline cvm::quaternion dist2_grad(cvm::quaternion const &Q2) const
{
cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 + this->q2*Q2.q2 + this->q3*Q2.q3;
cvm::real const omega = std::acos( (cos_omega > 1.0) ? 1.0 :
cvm::real const omega = cvm::acos( (cos_omega > 1.0) ? 1.0 :
( (cos_omega < -1.0) ? -1.0 : cos_omega) );
cvm::real const sin_omega = std::sin(omega);
cvm::real const sin_omega = cvm::sin(omega);
if (std::fabs(sin_omega) < 1.0E-14) {
if (cvm::fabs(sin_omega) < 1.0E-14) {
// return a null 4d vector
return cvm::quaternion(0.0, 0.0, 0.0, 0.0);
}
@ -1338,14 +1337,16 @@ public:
/// \brief Perform gradient tests
bool b_debug_gradients;
/// \brief Positions to superimpose: the rotation should brings pos1
/// into pos2
std::vector<cvm::atom_pos> pos1, pos2;
/// Correlation matrix C (3, 3)
cvm::rmatrix C;
/// Overlap matrix S (4, 4)
cvm::matrix2d<cvm::real> S;
/// Eigenvalues of S
cvm::vector1d<cvm::real> S_eigval;
/// Eigenvectors of S
cvm::matrix2d<cvm::real> S_eigvec;
/// Used for debugging gradients
@ -1404,8 +1405,8 @@ public:
: b_debug_gradients(false)
{
cvm::rvector const axis_n = axis.unit();
cvm::real const sina = std::sin(angle/2.0);
q = cvm::quaternion(std::cos(angle/2.0),
cvm::real const sina = cvm::sin(angle/2.0);
q = cvm::quaternion(cvm::cos(angle/2.0),
sina * axis_n.x, sina * axis_n.y, sina * axis_n.z);
}
@ -1437,7 +1438,7 @@ public:
inline cvm::real spin_angle(cvm::rvector const &axis) const
{
cvm::rvector const q_vec = q.get_vector();
cvm::real alpha = (180.0/PI) * 2.0 * std::atan2(axis * q_vec, q.q0);
cvm::real alpha = (180.0/PI) * 2.0 * cvm::atan2(axis * q_vec, q.q0);
while (alpha > 180.0) alpha -= 360;
while (alpha < -180.0) alpha += 360;
return alpha;
@ -1473,9 +1474,9 @@ public:
{
cvm::rvector const q_vec = q.get_vector();
cvm::real const alpha =
(180.0/PI) * 2.0 * std::atan2(axis * q_vec, q.q0);
(180.0/PI) * 2.0 * cvm::atan2(axis * q_vec, q.q0);
cvm::real const cos_spin_2 = std::cos(alpha * (PI/180.0) * 0.5);
cvm::real const cos_spin_2 = cvm::cos(alpha * (PI/180.0) * 0.5);
cvm::real const cos_theta_2 = ( (cos_spin_2 != 0.0) ?
(q.q0 / cos_spin_2) :
(0.0) );
@ -1489,7 +1490,7 @@ public:
cvm::rvector const q_vec = q.get_vector();
cvm::real const iprod = axis * q_vec;
cvm::real const cos_spin_2 = std::cos(std::atan2(iprod, q.q0));
cvm::real const cos_spin_2 = cvm::cos(cvm::atan2(iprod, q.q0));
if (q.q0 != 0.0) {
@ -1529,15 +1530,17 @@ protected:
/// eigenvalue crossing)
cvm::quaternion q_old;
/// Build the overlap matrix S (used by calc_optimal_rotation())
void build_matrix(std::vector<cvm::atom_pos> const &pos1,
std::vector<cvm::atom_pos> const &pos2,
cvm::matrix2d<cvm::real> &S);
/// Build the correlation matrix C (used by calc_optimal_rotation())
void build_correlation_matrix(std::vector<cvm::atom_pos> const &pos1,
std::vector<cvm::atom_pos> const &pos2);
/// Diagonalize the overlap matrix S (used by calc_optimal_rotation())
void diagonalize_matrix(cvm::matrix2d<cvm::real> &S,
cvm::vector1d<cvm::real> &S_eigval,
cvm::matrix2d<cvm::real> &S_eigvec);
/// Compute the overlap matrix S (used by calc_optimal_rotation())
void compute_overlap_matrix();
/// Diagonalize a given matrix m (used by calc_optimal_rotation())
static void diagonalize_matrix(cvm::matrix2d<cvm::real> &m,
cvm::vector1d<cvm::real> &eigval,
cvm::matrix2d<cvm::real> &eigvec);
};

View File

@ -144,10 +144,10 @@ void colvarvalue::apply_constraints()
case colvarvalue::type_quaternionderiv:
break;
case colvarvalue::type_unit3vector:
rvector_value /= std::sqrt(rvector_value.norm2());
rvector_value /= cvm::sqrt(rvector_value.norm2());
break;
case colvarvalue::type_quaternion:
quaternion_value /= std::sqrt(quaternion_value.norm2());
quaternion_value /= cvm::sqrt(quaternion_value.norm2());
break;
case colvarvalue::type_vector:
if (elem_types.size() > 0) {
@ -579,7 +579,7 @@ colvarvalue colvarvalue::dist2_grad(colvarvalue const &x2) const
cvm::rvector const &v1 = this->rvector_value;
cvm::rvector const &v2 = x2.rvector_value;
cvm::real const cos_t = v1 * v2;
cvm::real const sin_t = std::sqrt(1.0 - cos_t*cos_t);
cvm::real const sin_t = cvm::sqrt(1.0 - cos_t*cos_t);
return colvarvalue( 2.0 * sin_t *
cvm::rvector((-1.0) * sin_t * v2.x +
cos_t/sin_t * (v1.x - cos_t*v2.x),
@ -630,7 +630,7 @@ colvarvalue const colvarvalue::interpolate(colvarvalue const &x1,
break;
case colvarvalue::type_unit3vector:
case colvarvalue::type_quaternion:
if (interp.norm()/std::sqrt(d2) < 1.0e-6) {
if (interp.norm()/cvm::sqrt(d2) < 1.0e-6) {
cvm::error("Error: interpolation between "+cvm::to_str(x1)+" and "+
cvm::to_str(x2)+" with lambda = "+cvm::to_str(lambda)+
" is undefined: result = "+cvm::to_str(interp)+"\n",

View File

@ -17,22 +17,22 @@
/// \brief Value of a collective variable: this is a metatype which
/// can be set at runtime. By default it is set to be a scalar
/// number, and can be treated as such in all operations (this is
/// done by most \link cvc \endlink implementations).
/// done by most \link colvar::cvc \endlink implementations).
///
/// \link colvarvalue \endlink allows \link colvar \endlink to be
/// treat different data types. By default, a \link colvarvalue
/// \endlink variable is a scalar number. To use it as
/// another type, declare and initialize it as
/// \code colvarvalue x(colvarvalue::type_xxx)\endcode, use \link x.type
/// (colvarvalue::type_xxx) \endlink at a later stage, or if unset,
/// assign the type with \code x = y; \endcode, provided y is correctly set.
/// `colvarvalue x(colvarvalue::type_xxx)`, use `x.type (colvarvalue::type_xxx)`
/// at a later stage, or if unset,
/// assign the type with `x = y;`, provided y is correctly set.
///
/// All operators (either unary or binary) on a \link
/// colvarvalue \endlink object performs one or more checks on the
/// \link Type \endlink, except when reading from a stream, when there is no way to
/// detect the \link Type \endlink. To use \code is >> x; \endcode x \b MUST
/// detect the \link Type \endlink. To use `is >> x;` x \b MUST
/// already have a type correcly set up for properly parsing the
/// stream. No problem of course with the output streams: \code os << x; \endcode
/// stream. No problem of course with the output streams: `os << x;`
///
/// \em Note \em on \em performance: to avoid type checks in a long array of \link
/// colvarvalue \endlink objects, use one of the existing "_opt" functions or implement a new one
@ -159,7 +159,7 @@ public:
/// \brief If the variable has constraints (e.g. unitvector or
/// quaternion), transform it to satisfy them; this function needs
/// to be called only when the \link colvarvalue \endlink
/// is calculated outside of \link cvc \endlink objects
/// is calculated outside of \link colvar::cvc \endlink objects
void apply_constraints();
/// Get the current type
@ -184,7 +184,7 @@ public:
/// Norm of this colvarvalue
inline cvm::real norm() const
{
return std::sqrt(this->norm2());
return cvm::sqrt(this->norm2());
}
/// Sum of the components of this colvarvalue (if more than one dimension)
@ -728,7 +728,7 @@ inline cvm::real colvarvalue::dist2(colvarvalue const &x2) const
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
// angle between (*this) and x2 is the distance
return std::acos(this->rvector_value * x2.rvector_value) * std::acos(this->rvector_value * x2.rvector_value);
return cvm::acos(this->rvector_value * x2.rvector_value) * cvm::acos(this->rvector_value * x2.rvector_value);
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
// angle between (*this) and x2 is the distance, the quaternion

View File

@ -153,18 +153,29 @@ void colvarproxy_lammps::init(const char *conf_file)
if (_lmp->update->ntimestep != 0) {
cvm::log("Setting initial step number from LAMMPS: "+
cvm::to_str(_lmp->update->ntimestep)+"\n");
colvars->it = colvars->it_restart = _lmp->update->ntimestep;
colvars->it = colvars->it_restart =
static_cast<cvm::step_number>(_lmp->update->ntimestep);
}
if (cvm::debug()) {
log("atoms_ids = "+cvm::to_str(atoms_ids)+"\n");
log("atoms_ncopies = "+cvm::to_str(atoms_ncopies)+"\n");
log("atoms_positions = "+cvm::to_str(atoms_positions)+"\n");
log(cvm::line_marker);
log("Info: done initializing the colvars proxy object.\n");
cvm::log("atoms_ids = "+cvm::to_str(atoms_ids)+"\n");
cvm::log("atoms_ncopies = "+cvm::to_str(atoms_ncopies)+"\n");
cvm::log("atoms_positions = "+cvm::to_str(atoms_positions)+"\n");
cvm::log(cvm::line_marker);
cvm::log("Info: done initializing the colvars proxy object.\n");
}
}
void colvarproxy_lammps::add_config_file(const char *conf_file)
{
colvars->read_config_file(conf_file);
}
void colvarproxy_lammps::add_config_string(const std::string &conf)
{
colvars->read_config_string(conf);
}
colvarproxy_lammps::~colvarproxy_lammps()
{
delete _random;
@ -185,7 +196,7 @@ int colvarproxy_lammps::setup()
double colvarproxy_lammps::compute()
{
if (cvm::debug()) {
log(std::string(cvm::line_marker)+
cvm::log(std::string(cvm::line_marker)+
"colvarproxy_lammps step no. "+
cvm::to_str(_lmp->update->ntimestep)+" [first - last = "+
cvm::to_str(_lmp->update->beginstep)+" - "+
@ -238,20 +249,20 @@ double colvarproxy_lammps::compute()
bias_energy = 0.0;
if (cvm::debug()) {
log("atoms_ids = "+cvm::to_str(atoms_ids)+"\n");
log("atoms_ncopies = "+cvm::to_str(atoms_ncopies)+"\n");
log("atoms_positions = "+cvm::to_str(atoms_positions)+"\n");
log("atoms_new_colvar_forces = "+cvm::to_str(atoms_new_colvar_forces)+"\n");
cvm::log("atoms_ids = "+cvm::to_str(atoms_ids)+"\n");
cvm::log("atoms_ncopies = "+cvm::to_str(atoms_ncopies)+"\n");
cvm::log("atoms_positions = "+cvm::to_str(atoms_positions)+"\n");
cvm::log("atoms_new_colvar_forces = "+cvm::to_str(atoms_new_colvar_forces)+"\n");
}
// call the collective variable module
colvars->calc();
if (cvm::debug()) {
log("atoms_ids = "+cvm::to_str(atoms_ids)+"\n");
log("atoms_ncopies = "+cvm::to_str(atoms_ncopies)+"\n");
log("atoms_positions = "+cvm::to_str(atoms_positions)+"\n");
log("atoms_new_colvar_forces = "+cvm::to_str(atoms_new_colvar_forces)+"\n");
cvm::log("atoms_ids = "+cvm::to_str(atoms_ids)+"\n");
cvm::log("atoms_ncopies = "+cvm::to_str(atoms_ncopies)+"\n");
cvm::log("atoms_positions = "+cvm::to_str(atoms_positions)+"\n");
cvm::log("atoms_new_colvar_forces = "+cvm::to_str(atoms_new_colvar_forces)+"\n");
}
return bias_energy;

View File

@ -103,6 +103,11 @@ class colvarproxy_lammps : public colvarproxy {
// Write files expected from Colvars (called by post_run())
void write_output_files();
// read additional config from file
void add_config_file(char const *config_filename);
// read additional config from string
void add_config_string(const std::string &config);
// implementation of pure methods from base class
public:

View File

@ -1,5 +1,5 @@
#ifndef COLVARPROXY_VERSION
#define COLVARPROXY_VERSION "2018-08-29"
#define COLVARPROXY_VERSION "2019-04-09"
// 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

View File

@ -480,6 +480,31 @@ void FixColvars::one_time_init()
/* ---------------------------------------------------------------------- */
int FixColvars::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"configfile") == 0) {
if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (me == 0) {
if (! proxy)
error->one(FLERR,"Cannot use fix_modify before initialization");
proxy->add_config_file(arg[1]);
}
return 2;
} else if (strcmp(arg[0],"config") == 0) {
if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (me == 0) {
if (! proxy)
error->one(FLERR,"Cannot use fix_modify before initialization");
std::string conf(arg[1]);
proxy->add_config_string(conf);
}
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
void FixColvars::setup(int vflag)
{
const tagint * const tag = atom->tag;

View File

@ -50,6 +50,7 @@ class FixColvars : public Fix {
virtual int setmask();
virtual void init();
virtual void setup(int);
virtual int modify_param(int, char **);
virtual void min_setup(int vflag) {setup(vflag);};
virtual void min_post_force(int);
virtual void post_force(int);