git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@12811 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp
2014-12-02 02:09:53 +00:00
parent 9c0f849594
commit c4af1cdbbd
34 changed files with 5927 additions and 4786 deletions

View File

@ -99,6 +99,7 @@ colvar::colvar (std::string const &conf)
initialize_components("distance", "distance", distance); initialize_components("distance", "distance", distance);
initialize_components("distance vector", "distanceVec", distance_vec); initialize_components("distance vector", "distanceVec", distance_vec);
initialize_components("Cartesian coordinates", "cartesian", cartesian);
initialize_components("distance vector " initialize_components("distance vector "
"direction", "distanceDir", distance_dir); "direction", "distanceDir", distance_dir);
initialize_components("distance projection " initialize_components("distance projection "
@ -107,6 +108,8 @@ colvar::colvar (std::string const &conf)
"on a plane", "distanceXY", distance_xy); "on a plane", "distanceXY", distance_xy);
initialize_components("average distance weighted by inverse power", initialize_components("average distance weighted by inverse power",
"distanceInv", distance_inv); "distanceInv", distance_inv);
initialize_components("N1xN2-long vector of pairwise distances",
"distancePairs", distance_pairs);
initialize_components("coordination " initialize_components("coordination "
"number", "coordNum", coordnum); "number", "coordNum", coordnum);
@ -159,11 +162,33 @@ colvar::colvar (std::string const &conf)
enable(task_scripted); enable(task_scripted);
cvm::log("This colvar uses scripted function \"" + scripted_function + "\"."); cvm::log("This colvar uses scripted function \"" + scripted_function + "\".");
// Only accept scalar scripted colvars std::string type_str;
// might accept other types when the infrastructure is in place get_keyval(conf, "scriptedFunctionType", type_str, "scalar");
// for derivatives of vectors wrt vectors
x.type(colvarvalue::type_scalar); x.type(colvarvalue::type_notset);
int t;
for (t = 0; t < colvarvalue::type_all; t++) {
if (type_str == colvarvalue::type_keyword(colvarvalue::Type(t))) {
x.type(colvarvalue::Type(t));
break;
}
}
if (x.type() == colvarvalue::type_notset) {
cvm::error("Could not parse scripted colvar type.");
return;
}
x_reported.type (x.type()); x_reported.type (x.type());
cvm::log(std::string("Expecting colvar value of type ")
+ colvarvalue::type_desc(x.type()));
if (x.type() == colvarvalue::type_vector) {
int size;
if (!get_keyval(conf, "scriptedFunctionVectorSize", size)) {
cvm::error("Error: no size specified for vector scripted function.");
return;
}
x.vector1d_value.resize(size);
}
// Sort array of cvcs based on values of componentExp // Sort array of cvcs based on values of componentExp
std::vector<cvc *> temp_vec; std::vector<cvc *> temp_vec;
@ -185,41 +210,39 @@ colvar::colvar (std::string const &conf)
// Build ordered list of component values that will be // Build ordered list of component values that will be
// passed to the script // passed to the script
for (j = 0; j < cvcs.size(); j++) { for (j = 0; j < cvcs.size(); j++) {
sorted_cvc_values.push_back(cvcs[j]->p_value()); sorted_cvc_values.push_back(&(cvcs[j]->value()));
} }
b_homogeneous = false;
// Scripted functions are deemed non-periodic
b_periodic = false;
period = 0.0;
b_inverse_gradients = false;
b_Jacobian_force = false;
} }
if (!tasks[task_scripted]) { if (!tasks[task_scripted]) {
// this is set false if any of the components has an exponent colvarvalue const &cvc_value = (cvcs[0])->value();
// different from 1 in the polynomial if (cvm::debug())
b_linear = true; cvm::log ("This collective variable is a "+
// these will be set to false if any of the cvcs has them false colvarvalue::type_desc(cvc_value.type())+
b_inverse_gradients = true; ((cvc_value.size() > 1) ? " with "+
b_Jacobian_force = true; cvm::to_str(cvc_value.size())+" individual components.\n" :
".\n"));
x.type(cvc_value);
x_reported.type(cvc_value);
} }
// Test whether this is a single-component variable // If using scripted biases, any colvar may receive bias forces
// Decide whether the colvar is periodic // and will need its gradient
// Used to wrap extended DOF if extendedLagrangian is on if (cvm::scripted_forces()) {
if (cvcs.size() == 1 && (cvcs[0])->sup_np == 1 enable(task_gradients);
&& (cvcs[0])->sup_coeff == 1.0
&& !tasks[task_scripted]) {
b_single_cvc = true;
b_periodic = (cvcs[0])->b_periodic;
period = (cvcs[0])->period;
// TODO write explicit wrap() function for colvars to allow for
// sup_coeff different from 1
// this->period = (cvcs[0])->period * (cvcs[0])->sup_coeff;
} else {
b_single_cvc = false;
b_periodic = false;
period = 0.0;
} }
// check the available features of each cvc // check for linear combinations
b_linear = !tasks[task_scripted];
for (i = 0; i < cvcs.size(); i++) { for (i = 0; i < cvcs.size(); i++) {
if ((cvcs[i])->b_debug_gradients) if ((cvcs[i])->b_debug_gradients)
enable(task_gradients); enable(task_gradients);
@ -237,7 +260,41 @@ colvar::colvar (std::string const &conf)
(cvcs[i])->function_type+"\" approaches zero.\n"); (cvcs[i])->function_type+"\" approaches zero.\n");
} }
} }
}
// Colvar is homogeneous iff:
// - it is not scripted
// - it is linear
// - all cvcs have coefficient 1 or -1
// i.e. sum or difference of cvcs
b_homogeneous = !tasks[task_scripted] && b_linear;
for (i = 0; i < cvcs.size(); i++) {
if ((std::fabs(cvcs[i]->sup_coeff) - 1.0) > 1.0e-10) {
b_homogeneous = false;
}
}
// Colvar is deemed periodic iff:
// - it is homogeneous
// - all cvcs are periodic
// - all cvcs have the same period
b_periodic = cvcs[0]->b_periodic && b_homogeneous;
period = cvcs[0]->period;
for (i = 1; i < cvcs.size(); i++) {
if (!cvcs[i]->b_periodic || cvcs[i]->period != period) {
b_periodic = false;
period = 0.0;
}
}
// these will be set to false if any of the cvcs has them false
b_inverse_gradients = !tasks[task_scripted];
b_Jacobian_force = !tasks[task_scripted];
// check the available features of each cvc
for (i = 0; i < cvcs.size(); i++) {
if ((cvcs[i])->b_periodic && !b_periodic) { if ((cvcs[i])->b_periodic && !b_periodic) {
cvm::log("Warning: although this component is periodic, the colvar will " cvm::log("Warning: although this component is periodic, the colvar will "
"not be treated as periodic, either because the exponent is not " "not be treated as periodic, either because the exponent is not "
@ -251,48 +308,29 @@ colvar::colvar (std::string const &conf)
if (! (cvcs[i])->b_Jacobian_derivative) if (! (cvcs[i])->b_Jacobian_derivative)
b_Jacobian_force = false; b_Jacobian_force = false;
if (!tasks[task_scripted]) { // components may have different types only for scripted functions
// If the combination of components is a scripted function, if (!tasks[task_scripted] && (colvarvalue::check_types(cvcs[i]->value(),
// the components may have different types cvcs[0]->value())) ) {
for (size_t j = i; j < cvcs.size(); j++) { cvm::error("ERROR: you are definining this collective variable "
if ( (cvcs[i])->type() != (cvcs[j])->type() ) { "by using components of different types. "
cvm::log ("ERROR: you are definining this collective variable "
"by using components of different types, \""+
colvarvalue::type_desc[(cvcs[i])->type()]+
"\" and \""+
colvarvalue::type_desc[(cvcs[j])->type()]+
"\". "
"You must use the same type in order to " "You must use the same type in order to "
" sum them together.\n"); " sum them together.\n", INPUT_ERROR);
cvm::set_error_bits(INPUT_ERROR); return;
} }
} }
}
}
if (!tasks[task_scripted]) {
colvarvalue::Type const value_type = (cvcs[0])->type();
if (cvm::debug())
cvm::log ("This collective variable is a "+
colvarvalue::type_desc[value_type]+", corresponding to "+
cvm::to_str (colvarvalue::dof_num[value_type])+
" internal degrees of freedom.\n");
x.type (value_type);
x_reported.type (value_type);
}
get_keyval(conf, "width", width, 1.0); get_keyval(conf, "width", width, 1.0);
if (width <= 0.0) { if (width <= 0.0) {
cvm::error("Error: \"width\" must be positive.\n", INPUT_ERROR); cvm::error("Error: \"width\" must be positive.\n", INPUT_ERROR);
} }
lower_boundary.type (this->type()); lower_boundary.type(value());
lower_wall.type (this->type()); lower_wall.type(value());
upper_boundary.type (this->type()); upper_boundary.type(value());
upper_wall.type (this->type()); upper_wall.type(value());
if (this->type() == colvarvalue::type_scalar) { if (value().type() == colvarvalue::type_scalar) {
if (get_keyval(conf, "lowerBoundary", lower_boundary, lower_boundary)) { if (get_keyval(conf, "lowerBoundary", lower_boundary, lower_boundary)) {
enable(task_lower_boundary); enable(task_lower_boundary);
@ -375,14 +413,14 @@ colvar::colvar (std::string const &conf)
enable(task_extended_lagrangian); enable(task_extended_lagrangian);
xr.type (this->type()); xr.type(value());
vr.type (this->type()); vr.type(value());
fr.type (this->type()); fr.type(value());
const bool found = get_keyval(conf, "extendedTemp", temp, cvm::temperature()); const bool found = get_keyval(conf, "extendedTemp", temp, cvm::temperature());
if (temp <= 0.0) { if (temp <= 0.0) {
if (found) if (found)
cvm::log ("Error: \"extendedTemp\" must be positive.\n"); cvm::error("Error: \"extendedTemp\" must be positive.\n", INPUT_ERROR);
else else
cvm::error("Error: a positive temperature must be provided, either " cvm::error("Error: a positive temperature must be provided, either "
"by enabling a thermostat, or through \"extendedTemp\".\n", "by enabling a thermostat, or through \"extendedTemp\".\n",
@ -621,7 +659,7 @@ int colvar::enable (colvar::task const &t)
cvm::log("Enabling calculation of the Jacobian force " cvm::log("Enabling calculation of the Jacobian force "
"on this colvar.\n"); "on this colvar.\n");
} }
fj.type (this->type()); fj.type(value());
break; break;
case task_system_force: case task_system_force:
@ -634,8 +672,8 @@ int colvar::enable (colvar::task const &t)
} }
cvm::request_system_force(); cvm::request_system_force();
} }
ft.type (this->type()); ft.type(value());
ft_reported.type (this->type()); ft_reported.type(value());
break; break;
case task_output_applied_force: case task_output_applied_force:
@ -646,9 +684,9 @@ int colvar::enable (colvar::task const &t)
break; break;
case task_fdiff_velocity: case task_fdiff_velocity:
x_old.type (this->type()); x_old.type(value());
v_fdiff.type (this->type()); v_fdiff.type(value());
v_reported.type (this->type()); v_reported.type(value());
break; break;
case task_output_velocity: case task_output_velocity:
@ -656,7 +694,7 @@ int colvar::enable (colvar::task const &t)
break; break;
case task_grid: case task_grid:
if (this->type() != colvarvalue::type_scalar) { if (value().type() != colvarvalue::type_scalar) {
cvm::error("Cannot calculate a grid for collective variable, \""+ cvm::error("Cannot calculate a grid for collective variable, \""+
this->name+"\", because its value is not a scalar number.\n", this->name+"\", because its value is not a scalar number.\n",
INPUT_ERROR); INPUT_ERROR);
@ -665,12 +703,12 @@ int colvar::enable (colvar::task const &t)
case task_extended_lagrangian: case task_extended_lagrangian:
enable(task_gradients); enable(task_gradients);
v_reported.type (this->type()); v_reported.type(value());
break; break;
case task_lower_boundary: case task_lower_boundary:
case task_upper_boundary: case task_upper_boundary:
if (this->type() != colvarvalue::type_scalar) { if (value().type() != colvarvalue::type_scalar) {
cvm::error("Error: this colvar is not a scalar value " cvm::error("Error: this colvar is not a scalar value "
"and cannot produce a grid.\n", "and cannot produce a grid.\n",
INPUT_ERROR); INPUT_ERROR);
@ -687,12 +725,12 @@ int colvar::enable (colvar::task const &t)
break; break;
case task_gradients: case task_gradients:
f.type (this->type()); f.type(value());
fb.type (this->type()); fb.type(value());
break; break;
case task_collect_gradients: case task_collect_gradients:
if (this->type() != colvarvalue::type_scalar) { if (value().type() != colvarvalue::type_scalar) {
cvm::error("Collecting atomic gradients for non-scalar collective variable \""+ cvm::error("Collecting atomic gradients for non-scalar collective variable \""+
this->name+"\" is not yet implemented.\n", this->name+"\" is not yet implemented.\n",
INPUT_ERROR); INPUT_ERROR);
@ -1032,8 +1070,8 @@ cvm::real colvar::update()
if (cvm::debug()) if (cvm::debug())
cvm::log("Updating colvar \""+this->name+"\".\n"); cvm::log("Updating colvar \""+this->name+"\".\n");
// set to zero the applied force // set to zero the applied force
f.type(value());
f.reset(); f.reset();
// add the biases' force, which at this point should already have // add the biases' force, which at this point should already have
@ -1044,7 +1082,11 @@ cvm::real colvar::update()
if (tasks[task_lower_wall] || tasks[task_upper_wall]) { if (tasks[task_lower_wall] || tasks[task_upper_wall]) {
// wall force // wall force
colvarvalue fw (this->type()); colvarvalue fw(value());
fw.reset();
if (cvm::debug())
cvm::log("Calculating wall forces for colvar \""+this->name+"\".\n");
// if the two walls are applied concurrently, decide which is the // if the two walls are applied concurrently, decide which is the
// closer one (on a periodic colvar, both walls may be applicable // closer one (on a periodic colvar, both walls may be applicable
@ -1148,25 +1190,28 @@ void colvar::communicate_forces()
cvm::log("Communicating forces from colvar \""+this->name+"\".\n"); cvm::log("Communicating forces from colvar \""+this->name+"\".\n");
if (tasks[task_scripted]) { if (tasks[task_scripted]) {
std::vector<colvarvalue> func_grads(cvcs.size()); std::vector<cvm::matrix2d<cvm::real> > func_grads;
for (i = 0; i < cvcs.size(); i++) {
func_grads.push_back(cvm::matrix2d<cvm::real> (x.size(),
cvcs[i]->value().size()));
}
int res = cvm::proxy->run_colvar_gradient_callback(scripted_function, sorted_cvc_values, func_grads); int res = cvm::proxy->run_colvar_gradient_callback(scripted_function, sorted_cvc_values, func_grads);
if (res != COLVARS_OK) {
if (res == COLVARS_NOT_IMPLEMENTED) { if (res == COLVARS_NOT_IMPLEMENTED) {
cvm::error("Colvar gradient scripts are not implemented."); cvm::error("Colvar gradient scripts are not implemented.");
return; } else {
}
if (res != COLVARS_OK) {
cvm::error("Error running colvar gradient script"); cvm::error("Error running colvar gradient script");
}
return; return;
} }
for (i = 0; i < cvcs.size(); i++) { for (i = 0; i < cvcs.size(); i++) {
cvm::increase_depth(); cvm::increase_depth();
// Force is scalar times colvarvalue (scalar or vector) // cvc force is colvar force times colvar/cvc Jacobian
// Note: this can only handle scalar colvars (scalar values of f) // (vector-matrix product)
// A non-scalar colvar would need the gradient to be expressed (cvcs[i])->apply_force(colvarvalue(f.as_vector() * func_grads[i],
// as an order-2 tensor cvcs[i]->value().type()));
(cvcs[i])->apply_force (f.real_value * func_grads[i]);
cvm::decrease_depth(); cvm::decrease_depth();
} }
} else if (x.type() == colvarvalue::type_scalar) { } else if (x.type() == colvarvalue::type_scalar) {
@ -1235,7 +1280,7 @@ bool colvar::periodic_boundaries() const
cvm::real colvar::dist2(colvarvalue const &x1, cvm::real colvar::dist2(colvarvalue const &x1,
colvarvalue const &x2) const colvarvalue const &x2) const
{ {
if (b_single_cvc) { if (b_homogeneous) {
return (cvcs[0])->dist2(x1, x2); return (cvcs[0])->dist2(x1, x2);
} else { } else {
return x1.dist2(x2); return x1.dist2(x2);
@ -1245,7 +1290,7 @@ cvm::real colvar::dist2 (colvarvalue const &x1,
colvarvalue colvar::dist2_lgrad(colvarvalue const &x1, colvarvalue colvar::dist2_lgrad(colvarvalue const &x1,
colvarvalue const &x2) const colvarvalue const &x2) const
{ {
if (b_single_cvc) { if (b_homogeneous) {
return (cvcs[0])->dist2_lgrad(x1, x2); return (cvcs[0])->dist2_lgrad(x1, x2);
} else { } else {
return x1.dist2_grad(x2); return x1.dist2_grad(x2);
@ -1255,7 +1300,7 @@ colvarvalue colvar::dist2_lgrad (colvarvalue const &x1,
colvarvalue colvar::dist2_rgrad(colvarvalue const &x1, colvarvalue colvar::dist2_rgrad(colvarvalue const &x1,
colvarvalue const &x2) const colvarvalue const &x2) const
{ {
if (b_single_cvc) { if (b_homogeneous) {
return (cvcs[0])->dist2_rgrad(x1, x2); return (cvcs[0])->dist2_rgrad(x1, x2);
} else { } else {
return x2.dist2_grad(x1); return x2.dist2_grad(x1);
@ -1264,7 +1309,7 @@ colvarvalue colvar::dist2_rgrad (colvarvalue const &x1,
void colvar::wrap(colvarvalue &x) const void colvar::wrap(colvarvalue &x) const
{ {
if (b_single_cvc) { if (b_homogeneous) {
(cvcs[0])->wrap(x); (cvcs[0])->wrap(x);
} }
return; return;
@ -1612,7 +1657,7 @@ int colvar::calc_acf()
colvar *cfcv = (acf_colvar_name.size() ? colvar *cfcv = (acf_colvar_name.size() ?
cvm::colvar_by_name(acf_colvar_name) : cvm::colvar_by_name(acf_colvar_name) :
this); this);
if (cfcv->type() != this->type()) { if (colvarvalue::check_types(cfcv->value(), value())) {
cvm::error("Error: correlation function between \""+cfcv->name+ cvm::error("Error: correlation function between \""+cfcv->name+
"\" and \""+this->name+"\" cannot be calculated, " "\" and \""+this->name+"\" cannot be calculated, "
"because their value types are different.\n", "because their value types are different.\n",
@ -1799,7 +1844,7 @@ void colvar::calc_runave()
{ {
if (x_history.empty()) { if (x_history.empty()) {
runave.type (x.type()); runave.type(value().type());
runave.reset(); runave.reset();
// first-step operations // first-step operations

View File

@ -31,9 +31,8 @@
/// ///
/// Please note that most of its members are \link colvarvalue /// Please note that most of its members are \link colvarvalue
/// \endlink objects, i.e. they can handle different data types /// \endlink objects, i.e. they can handle different data types
/// together, and must all be set to the same type of colvar::x by /// together, and must all be set to the same type of colvar::value()
/// using the colvarvalue::type() member function before using them /// before using them together in assignments or other operations; this is usually done
/// together in assignments or other operations; this is usually done
/// automatically in the constructor. If you add a new member of /// automatically in the constructor. If you add a new member of
/// \link colvarvalue \endlink type, you should also add its /// \link colvarvalue \endlink type, you should also add its
/// initialization line in the \link colvar \endlink constructor. /// initialization line in the \link colvar \endlink constructor.
@ -45,16 +44,13 @@ public:
/// Name /// Name
std::string name; std::string name;
/// Type of value /// \brief Current value (previously set by calc() or by read_traj())
colvarvalue::Type type() const;
/// \brief Current value (previously obtained from calc() or read_traj())
colvarvalue const & value() const; colvarvalue const & value() const;
/// \brief Current actual value (not extended DOF) /// \brief Current actual value (not extended DOF)
colvarvalue const & actual_value() const; colvarvalue const & actual_value() const;
/// \brief Current velocity (previously obtained from calc() or read_traj()) /// \brief Current velocity (previously set by calc() or by read_traj())
colvarvalue const & velocity() const; colvarvalue const & velocity() const;
/// \brief Current system force (previously obtained from calc() or /// \brief Current system force (previously obtained from calc() or
@ -83,9 +79,9 @@ public:
/// combination of \link cvc \endlink elements /// combination of \link cvc \endlink elements
bool b_linear; bool b_linear;
/// \brief True if this \link colvar \endlink is equal to /// \brief True if this \link colvar \endlink is a linear
/// its only constituent cvc /// combination of cvcs with coefficients 1 or -1
bool b_single_cvc; bool b_homogeneous;
/// \brief True if all \link cvc \endlink objects are capable /// \brief True if all \link cvc \endlink objects are capable
/// of calculating inverse gradients /// of calculating inverse gradients
@ -190,6 +186,13 @@ protected:
/// Value of the colvar /// Value of the colvar
colvarvalue x; colvarvalue x;
// TODO: implement functionality to treat these
// /// Vector of individual values from CVCs
// colvarvalue x_cvc;
// /// Jacobian matrix of individual values from CVCs
// colvarvalue dx_cvc;
/// Cached reported value (x may be manipulated) /// Cached reported value (x may be manipulated)
colvarvalue x_reported; colvarvalue x_reported;
@ -479,6 +482,7 @@ public:
class distance_z; class distance_z;
class distance_xy; class distance_xy;
class distance_inv; class distance_inv;
class distance_pairs;
class angle; class angle;
class dihedral; class dihedral;
class coordnum; class coordnum;
@ -500,6 +504,7 @@ public:
// non-scalar components // non-scalar components
class distance_vec; class distance_vec;
class distance_dir; class distance_dir;
class cartesian;
class orientation; class orientation;
protected: protected:
@ -533,11 +538,6 @@ public:
} }
}; };
inline colvarvalue::Type colvar::type() const
{
return x.type();
}
inline colvarvalue const & colvar::value() const inline colvarvalue const & colvar::value() const
{ {
@ -570,6 +570,7 @@ inline void colvar::add_bias_force (colvarvalue const &force)
inline void colvar::reset_bias_force() { inline void colvar::reset_bias_force() {
fb.type(value());
fb.reset(); fb.reset();
} }

View File

@ -83,14 +83,16 @@ colvarbias::~colvarbias()
void colvarbias::add_colvar(std::string const &cv_name) void colvarbias::add_colvar(std::string const &cv_name)
{ {
if (colvar *cvp = cvm::colvar_by_name (cv_name)) { if (colvar *cv = cvm::colvar_by_name(cv_name)) {
cvp->enable (colvar::task_gradients); cv->enable(colvar::task_gradients);
if (cvm::debug()) if (cvm::debug())
cvm::log("Applying this bias to collective variable \""+ cvm::log("Applying this bias to collective variable \""+
cvp->name+"\".\n"); cv->name+"\".\n");
colvars.push_back (cvp); colvars.push_back(cv);
colvar_forces.push_back (colvarvalue (cvp->type())); colvar_forces.push_back(colvarvalue());
cvp->biases.push_back (this); // add back-reference to this bias to colvar colvar_forces.back().type(cv->value()); // make sure each forces is initialized to zero
colvar_forces.back().reset();
cv->biases.push_back(this); // add back-reference to this bias to colvar
} else { } else {
cvm::error("Error: cannot find a colvar named \""+ cvm::error("Error: cannot find a colvar named \""+
cv_name+"\".\n"); cv_name+"\".\n");
@ -103,8 +105,7 @@ void colvarbias::communicate_forces()
for (size_t i = 0; i < colvars.size(); i++) { for (size_t i = 0; i < colvars.size(); i++) {
if (cvm::debug()) { if (cvm::debug()) {
cvm::log("Communicating a force to colvar \""+ cvm::log("Communicating a force to colvar \""+
colvars[i]->name+"\", of type \""+ colvars[i]->name+"\".\n");
colvarvalue::type_desc[colvars[i]->type()]+"\".\n");
} }
colvars[i]->add_bias_force(colvar_forces[i]); colvars[i]->add_bias_force(colvar_forces[i]);
} }
@ -128,19 +129,23 @@ cvm::real colvarbias::energy_difference(std::string const &conf)
int colvarbias::bin_num() int colvarbias::bin_num()
{ {
cvm::error("Error: bin_num() not implemented.\n"); cvm::error("Error: bin_num() not implemented.\n");
return -1; return COLVARS_NOT_IMPLEMENTED;
} }
int colvarbias::current_bin() int colvarbias::current_bin()
{ {
cvm::error("Error: current_bin() not implemented.\n"); cvm::error("Error: current_bin() not implemented.\n");
return -1; return COLVARS_NOT_IMPLEMENTED;
} }
int colvarbias::bin_count(int bin_index) int colvarbias::bin_count(int bin_index)
{ {
cvm::error("Error: bin_count() not implemented.\n"); cvm::error("Error: bin_count() not implemented.\n");
return -1; return COLVARS_NOT_IMPLEMENTED;
}
int colvarbias::replica_share()
{
cvm::error("Error: replica_share() not implemented.\n");
return COLVARS_NOT_IMPLEMENTED;
} }
std::ostream & colvarbias::write_traj_label(std::ostream &os) std::ostream & colvarbias::write_traj_label(std::ostream &os)
{ {

View File

@ -36,7 +36,7 @@ public:
//// Give the count at a given bin index. //// Give the count at a given bin index.
virtual int bin_count(int bin_index); virtual int bin_count(int bin_index);
//// Share information between replicas, whatever it may be. //// Share information between replicas, whatever it may be.
virtual void replica_share() {}; virtual int replica_share();
/// Perform analysis tasks /// Perform analysis tasks
virtual inline void analyse() {} virtual inline void analyse() {}

View File

@ -64,7 +64,7 @@ colvarbias_abf::colvarbias_abf (std::string const &conf, char const *key)
for (size_t i = 0; i < colvars.size(); i++) { for (size_t i = 0; i < colvars.size(); i++) {
if (colvars[i]->type() != colvarvalue::type_scalar) { if (colvars[i]->value().type() != colvarvalue::type_scalar) {
cvm::error("Error: ABF bias can only use scalar-type variables.\n"); cvm::error("Error: ABF bias can only use scalar-type variables.\n");
} }
@ -282,17 +282,17 @@ cvm::real colvarbias_abf::update()
return 0.0; return 0.0;
} }
void colvarbias_abf::replica_share () { int colvarbias_abf::replica_share() {
int p; int p;
if ( !cvm::replica_enabled() ) { if ( !cvm::replica_enabled() ) {
cvm::error("Error: shared ABF: No replicas.\n"); cvm::error("Error: shared ABF: No replicas.\n");
return; return COLVARS_ERROR;
} }
// We must have stored the last_gradients and last_samples. // We must have stored the last_gradients and last_samples.
if (shared_last_step < 0 ) { if (shared_last_step < 0 ) {
cvm::error("Error: shared ABF: Tried to apply shared ABF before any sampling had occurred.\n"); cvm::error("Error: shared ABF: Tried to apply shared ABF before any sampling had occurred.\n");
return; return COLVARS_ERROR;
} }
// Share gradients for shared ABF. // Share gradients for shared ABF.
@ -355,6 +355,8 @@ void colvarbias_abf::replica_share () {
last_gradients->copy_grid(*gradients); last_gradients->copy_grid(*gradients);
last_samples->copy_grid(*samples); last_samples->copy_grid(*samples);
shared_last_step = cvm::step_absolute(); shared_last_step = cvm::step_absolute();
return COLVARS_OK;
} }
void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool append) void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool append)
@ -546,7 +548,7 @@ std::istream & colvarbias_abf::read_restart (std::istream& is)
colvarbias_histogram::colvarbias_histogram(std::string const &conf, char const *key) colvarbias_histogram::colvarbias_histogram(std::string const &conf, char const *key)
: colvarbias(conf, key), : colvarbias(conf, key),
grid (NULL) grid(NULL), out_name("")
{ {
get_keyval(conf, "outputfreq", output_freq, cvm::restart_out_freq); get_keyval(conf, "outputfreq", output_freq, cvm::restart_out_freq);
@ -557,9 +559,6 @@ colvarbias_histogram::colvarbias_histogram (std::string const &conf, char const
grid = new colvar_grid_count (colvars); grid = new colvar_grid_count (colvars);
bin.assign(colvars.size(), 0); bin.assign(colvars.size(), 0);
out_name = cvm::output_prefix + "." + this->name + ".dat";
cvm::log ("Histogram will be written to file " + out_name);
cvm::log("Finished histogram setup.\n"); cvm::log("Finished histogram setup.\n");
} }
@ -582,6 +581,14 @@ cvm::real colvarbias_histogram::update()
{ {
if (cvm::debug()) cvm::log("Updating Grid bias " + this->name); if (cvm::debug()) cvm::log("Updating Grid bias " + this->name);
// At the first timestep, we need to assign out_name since
// output_prefix is unset during the constructor
if (cvm::step_relative() == 0) {
out_name = cvm::output_prefix + "." + this->name + ".dat";
cvm::log("Histogram " + this->name + " will be written to file \"" + out_name + "\"");
}
for (size_t i=0; i<colvars.size(); i++) { for (size_t i=0; i<colvars.size(); i++) {
bin[i] = grid->current_bin_scalar(i); bin[i] = grid->current_bin_scalar(i);
} }

View File

@ -64,7 +64,7 @@ private:
size_t shared_freq; size_t shared_freq;
int shared_last_step; int shared_last_step;
// Share between replicas -- may be called independently of update // Share between replicas -- may be called independently of update
virtual void replica_share(); virtual int replica_share();
// Store the last set for shared ABF // Store the last set for shared ABF
colvar_grid_gradient *last_gradients; colvar_grid_gradient *last_gradients;

View File

@ -1,8 +1,20 @@
// -*- c++ -*-
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "colvarmodule.h" #include "colvarmodule.h"
#include "colvarbias_alb.h" #include "colvarbias_alb.h"
#include "colvarbias.h" #include "colvarbias.h"
#include <stdio.h>
#include <stdlib.h> #ifdef _MSC_VER
#if _MSC_VER <= 1700
#define copysign(A,B) _copysign(A,B)
double fmax(double A, double B) { return ( A > B ? A : B ); }
double fmin(double A, double B) { return ( A < B ? A : B ); }
#endif
#endif
/* Note about nomenclature. Force constant is called a coupling /* Note about nomenclature. Force constant is called a coupling
* constant here to emphasize its changing in the code. Outwards, * constant here to emphasize its changing in the code. Outwards,
@ -31,7 +43,7 @@ colvarbias_alb::colvarbias_alb(std::string const &conf, char const *key) :
for (i = 0; i < colvars.size(); i++) { for (i = 0; i < colvars.size(); i++) {
colvar_centers[i].type (colvars[i]->type()); colvar_centers[i].type(colvars[i]->value());
//zero moments //zero moments
means[i] = ssd[i] = 0; means[i] = ssd[i] = 0;

View File

@ -1,3 +1,5 @@
// -*- c++ -*-
#ifndef COLVARBIAS_ALB_H #ifndef COLVARBIAS_ALB_H
#define COLVARBIAS_ALB_H #define COLVARBIAS_ALB_H

View File

@ -646,7 +646,7 @@ void colvarbias_meta::calc_hills (colvarbias_meta::hill_iter h_first,
{ {
std::vector<colvarvalue> curr_values(colvars.size()); std::vector<colvarvalue> curr_values(colvars.size());
for (size_t i = 0; i < colvars.size(); i++) { for (size_t i = 0; i < colvars.size(); i++) {
curr_values[i].type (colvars[i]->type()); curr_values[i].type(colvars[i]->value());
} }
if (colvar_values.size()) { if (colvar_values.size()) {
@ -689,15 +689,14 @@ void colvarbias_meta::calc_hills_force (size_t const &i,
std::vector<colvarvalue> const &values) std::vector<colvarvalue> const &values)
{ {
// Retrieve the value of the colvar // Retrieve the value of the colvar
colvarvalue x (values.size() ? values[i].type() : colvars[i]->type()); colvarvalue const x(values.size() ? values[i] : colvars[i]->value());
x = (values.size() ? values[i] : colvars[i]->value());
// do the type check only once (all colvarvalues in the hills series // do the type check only once (all colvarvalues in the hills series
// were already saved with their types matching those in the // were already saved with their types matching those in the
// colvars) // colvars)
hill_iter h; hill_iter h;
switch (colvars[i]->type()) { switch (colvars[i]->value().type()) {
case colvarvalue::type_scalar: case colvarvalue::type_scalar:
for (h = h_first; h != h_last; h++) { for (h = h_first; h != h_last; h++) {
@ -710,9 +709,9 @@ void colvarbias_meta::calc_hills_force (size_t const &i,
} }
break; break;
case colvarvalue::type_vector: case colvarvalue::type_3vector:
case colvarvalue::type_unitvector: case colvarvalue::type_unit3vector:
case colvarvalue::type_unitvectorderiv: case colvarvalue::type_unit3vectorderiv:
for (h = h_first; h != h_last; h++) { for (h = h_first; h != h_last; h++) {
if (h->value() == 0.0) continue; if (h->value() == 0.0) continue;
colvarvalue const &center = h->centers[i]; colvarvalue const &center = h->centers[i];
@ -735,8 +734,18 @@ void colvarbias_meta::calc_hills_force (size_t const &i,
} }
break; break;
case colvarvalue::type_vector:
for (h = h_first; h != h_last; h++) {
if (h->value() == 0.0) continue;
colvarvalue const &center = h->centers[i];
cvm::real const half_width = 0.5 * h->widths[i];
forces[i].vector1d_value +=
( h->weight() * h->value() * (0.5 / (half_width*half_width)) *
(colvars[i]->dist2_lgrad(x, center)).vector1d_value );
}
break;
case colvarvalue::type_notset: case colvarvalue::type_notset:
case colvarvalue::type_all:
break; break;
} }
} }
@ -1423,7 +1432,7 @@ std::istream & colvarbias_meta::read_hill (std::istream &is)
std::vector<colvarvalue> h_centers(colvars.size()); std::vector<colvarvalue> h_centers(colvars.size());
for (size_t i = 0; i < colvars.size(); i++) { for (size_t i = 0; i < colvars.size(); i++) {
h_centers[i].type ((colvars[i]->value()).type()); h_centers[i].type(colvars[i]->value());
} }
{ {
// it is safer to read colvarvalue objects one at a time; // it is safer to read colvarvalue objects one at a time;
@ -1732,3 +1741,5 @@ std::ostream & operator << (std::ostream &os, colvarbias_meta::hill const &h)
return os; return os;
} }

View File

@ -280,7 +280,7 @@ public:
replica(replica_in) replica(replica_in)
{ {
for (size_t i = 0; i < cv.size(); i++) { for (size_t i = 0; i < cv.size(); i++) {
centers[i].type (cv[i]->type()); centers[i].type(cv[i]->value());
centers[i] = cv[i]->value(); centers[i] = cv[i]->value();
widths[i] = cv[i]->width * hill_width; widths[i] = cv[i]->width * hill_width;
} }

View File

@ -13,15 +13,25 @@ colvarbias_restraint::colvarbias_restraint (std::string const &conf,
{ {
get_keyval(conf, "forceConstant", force_k, 1.0); get_keyval(conf, "forceConstant", force_k, 1.0);
{
// get the initial restraint centers // get the initial restraint centers
colvar_centers.resize(colvars.size()); colvar_centers.resize(colvars.size());
colvar_centers_raw.resize(colvars.size()); colvar_centers_raw.resize(colvars.size());
for (size_t i = 0; i < colvars.size(); i++) { size_t i;
colvar_centers[i].type (colvars[i]->type()); for (i = 0; i < colvars.size(); i++) {
colvar_centers_raw[i].type (colvars[i]->type()); colvar_centers[i].type(colvars[i]->value());
colvar_centers_raw[i].type(colvars[i]->value());
if (cvm::debug()) {
cvm::log("colvarbias_restraint: center size = "+
cvm::to_str(colvar_centers[i].vector1d_value.size())+"\n");
}
} }
if (get_keyval(conf, "centers", colvar_centers, colvar_centers)) { if (get_keyval(conf, "centers", colvar_centers, colvar_centers)) {
for (size_t i = 0; i < colvars.size(); i++) { for (i = 0; i < colvars.size(); i++) {
if (cvm::debug()) {
cvm::log("colvarbias_restraint: parsing initial centers, i = "+cvm::to_str(i)+".\n");
}
colvar_centers[i].apply_constraints(); colvar_centers[i].apply_constraints();
colvar_centers_raw[i] = colvar_centers[i]; colvar_centers_raw[i] = colvar_centers[i];
} }
@ -30,19 +40,28 @@ colvarbias_restraint::colvarbias_restraint (std::string const &conf,
cvm::error("Error: must define the initial centers of the restraints.\n"); cvm::error("Error: must define the initial centers of the restraints.\n");
} }
if (colvar_centers.size() != colvars.size()) if (colvar_centers.size() != colvars.size()) {
cvm::error("Error: number of centers does not match " cvm::error("Error: number of centers does not match "
"that of collective variables.\n"); "that of collective variables.\n");
}
}
{
if (cvm::debug()) {
cvm::log("colvarbias_restraint: parsing target centers.\n");
}
size_t i;
if (get_keyval(conf, "targetCenters", target_centers, colvar_centers)) { if (get_keyval(conf, "targetCenters", target_centers, colvar_centers)) {
b_chg_centers = true; b_chg_centers = true;
for (size_t i = 0; i < target_centers.size(); i++) { for (i = 0; i < target_centers.size(); i++) {
target_centers[i].apply_constraints(); target_centers[i].apply_constraints();
} }
} else { } else {
b_chg_centers = false; b_chg_centers = false;
target_centers.clear(); target_centers.clear();
} }
}
if (get_keyval(conf, "targetForceConstant", target_force_k, 0.0)) { if (get_keyval(conf, "targetForceConstant", target_force_k, 0.0)) {
if (b_chg_centers) if (b_chg_centers)
@ -110,7 +129,9 @@ void colvarbias_restraint::change_configuration (std::string const &conf)
get_keyval(conf, "forceConstant", force_k, force_k); get_keyval(conf, "forceConstant", force_k, force_k);
if (get_keyval(conf, "centers", colvar_centers, colvar_centers)) { if (get_keyval(conf, "centers", colvar_centers, colvar_centers)) {
for (size_t i = 0; i < colvars.size(); i++) { for (size_t i = 0; i < colvars.size(); i++) {
colvar_centers[i].type(colvars[i]->value());
colvar_centers[i].apply_constraints(); colvar_centers[i].apply_constraints();
colvar_centers_raw[i].type(colvars[i]->value());
colvar_centers_raw[i] = colvar_centers[i]; colvar_centers_raw[i] = colvar_centers[i];
} }
} }
@ -128,10 +149,11 @@ cvm::real colvarbias_restraint::energy_difference (std::string const &conf)
alt_colvar_centers.resize(colvars.size()); alt_colvar_centers.resize(colvars.size());
size_t i; size_t i;
for (i = 0; i < colvars.size(); i++) { for (i = 0; i < colvars.size(); i++) {
alt_colvar_centers[i].type (colvars[i]->type()); alt_colvar_centers[i].type(colvars[i]->value());
} }
if (get_keyval(conf, "centers", alt_colvar_centers, colvar_centers)) { if (get_keyval(conf, "centers", alt_colvar_centers, colvar_centers)) {
for (i = 0; i < colvars.size(); i++) { for (i = 0; i < colvars.size(); i++) {
colvar_centers[i].type(colvars[i]->value());
colvar_centers[i].apply_constraints(); colvar_centers[i].apply_constraints();
} }
} }
@ -177,7 +199,7 @@ cvm::real colvarbias_restraint::update()
// if we are restarting a staged calculation) // if we are restarting a staged calculation)
centers_incr.resize(colvars.size()); centers_incr.resize(colvars.size());
for (size_t i = 0; i < colvars.size(); i++) { for (size_t i = 0; i < colvars.size(); i++) {
centers_incr[i].type (colvars[i]->type()); centers_incr[i].type(colvars[i]->value());
centers_incr[i] = (target_centers[i] - colvar_centers_raw[i]) / centers_incr[i] = (target_centers[i] - colvar_centers_raw[i]) /
cvm::real( target_nstages ? (target_nstages - stage) : cvm::real( target_nstages ? (target_nstages - stage) :
(target_nsteps - cvm::step_absolute())); (target_nsteps - cvm::step_absolute()));
@ -285,6 +307,7 @@ cvm::real colvarbias_restraint::update()
// Force and energy calculation // Force and energy calculation
for (size_t i = 0; i < colvars.size(); i++) { for (size_t i = 0; i < colvars.size(); i++) {
colvar_forces[i].type(colvars[i]->value());
colvar_forces[i] = -1.0 * restraint_force(restraint_convert_k(force_k, colvars[i]->width), colvar_forces[i] = -1.0 * restraint_force(restraint_convert_k(force_k, colvars[i]->width),
colvars[i], colvars[i],
colvar_centers[i]); colvar_centers[i]);

View File

@ -90,7 +90,8 @@ void colvar::cvc::debug_gradients (cvm::atom_group &group)
cvm::rotation const rot_0 = group.rot; cvm::rotation const rot_0 = group.rot;
cvm::rotation const rot_inv = group.rot.inverse(); cvm::rotation const rot_inv = group.rot.inverse();
cvm::real const x_0 = x.real_value; cvm::real x_0 = x.real_value;
if ((x.type() == colvarvalue::type_vector) && (x.size() == 1)) x_0 = x[0];
// cvm::log("gradients = "+cvm::to_str (gradients)+"\n"); // cvm::log("gradients = "+cvm::to_str (gradients)+"\n");
@ -130,7 +131,8 @@ void colvar::cvc::debug_gradients (cvm::atom_group &group)
group.calc_apply_roto_translation(); group.calc_apply_roto_translation();
} }
calc_value(); calc_value();
cvm::real const x_1 = x.real_value; cvm::real x_1 = x.real_value;
if ((x.type() == colvarvalue::type_vector) && (x.size() == 1)) x_1 = x[0];
cvm::log("Atom "+cvm::to_str(ia)+", component "+cvm::to_str(id)+":\n"); cvm::log("Atom "+cvm::to_str(ia)+", component "+cvm::to_str(id)+":\n");
cvm::log("dx(actual) = "+cvm::to_str(x_1 - x_0, cvm::log("dx(actual) = "+cvm::to_str(x_1 - x_0,
21, 14)+"\n"); 21, 14)+"\n");

View File

@ -79,10 +79,6 @@ public:
/// this variable definition should be set within the constructor. /// this variable definition should be set within the constructor.
std::string function_type; std::string function_type;
/// \brief Type of \link colvarvalue \endlink that this cvc
/// provides
colvarvalue::Type type() const;
/// \brief Coefficient in the polynomial combination (default: 1.0) /// \brief Coefficient in the polynomial combination (default: 1.0)
cvm::real sup_coeff; cvm::real sup_coeff;
/// \brief Exponent in the polynomial combination (default: 1) /// \brief Exponent in the polynomial combination (default: 1)
@ -153,17 +149,17 @@ public:
/// \brief Return the previously calculated value /// \brief Return the previously calculated value
virtual colvarvalue value() const; virtual colvarvalue const & value() const;
/// \brief Return const pointer to the previously calculated value // /// \brief Return const pointer to the previously calculated value
virtual const colvarvalue *p_value() const; // virtual const colvarvalue *p_value() const;
/// \brief Return the previously calculated system force /// \brief Return the previously calculated system force
virtual colvarvalue system_force() const; virtual colvarvalue const & system_force() const;
/// \brief Return the previously calculated divergence of the /// \brief Return the previously calculated divergence of the
/// inverse atomic gradients /// inverse atomic gradients
virtual colvarvalue Jacobian_derivative() const; virtual colvarvalue const & Jacobian_derivative() const;
/// \brief Apply the collective variable force, by communicating the /// \brief Apply the collective variable force, by communicating the
/// atomic forces to the simulation program (\b Note: the \link ft /// atomic forces to the simulation program (\b Note: the \link ft
@ -248,27 +244,22 @@ protected:
inline colvarvalue::Type colvar::cvc::type() const inline colvarvalue const & colvar::cvc::value() const
{
return x.type();
}
inline colvarvalue colvar::cvc::value() const
{ {
return x; return x;
} }
inline const colvarvalue * colvar::cvc::p_value() const // inline const colvarvalue * colvar::cvc::p_value() const
{ // {
return &x; // return &x;
} // }
inline colvarvalue colvar::cvc::system_force() const inline colvarvalue const & colvar::cvc::system_force() const
{ {
return ft; return ft;
} }
inline colvarvalue colvar::cvc::Jacobian_derivative() const inline colvarvalue const & colvar::cvc::Jacobian_derivative() const
{ {
return jd; return jd;
} }
@ -340,7 +331,7 @@ public:
// \brief Colvar component: distance vector between centers of mass // \brief Colvar component: distance vector between centers of mass
// of two groups (\link colvarvalue::type_vector \endlink type, // of two groups (\link colvarvalue::type_3vector \endlink type,
// range (-*:*)x(-*:*)x(-*:*)) // range (-*:*)x(-*:*)x(-*:*))
class colvar::distance_vec class colvar::distance_vec
: public colvar::distance : public colvar::distance
@ -365,7 +356,7 @@ public:
/// \brief Colvar component: distance unit vector (direction) between /// \brief Colvar component: distance unit vector (direction) between
/// centers of mass of two groups (colvarvalue::type_unitvector type, /// centers of mass of two groups (colvarvalue::type_unit3vector type,
/// range [-1:1]x[-1:1]x[-1:1]) /// range [-1:1]x[-1:1]x[-1:1])
class colvar::distance_dir class colvar::distance_dir
: public colvar::distance : public colvar::distance
@ -483,6 +474,34 @@ public:
}; };
/// \brief Colvar component: N1xN2 vector of pairwise distances
/// (colvarvalue::type_vector type, range (0:*) for each component)
class colvar::distance_pairs
: public colvar::cvc
{
protected:
/// First atom group
cvm::atom_group group1;
/// Second atom group
cvm::atom_group group2;
/// Use absolute positions, ignoring PBCs when present
bool b_no_PBC;
public:
distance_pairs(std::string const &conf);
distance_pairs();
virtual inline ~distance_pairs() {}
virtual void calc_value();
virtual void calc_gradients();
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 /// \brief Colvar component: Radius of gyration of an atom group
/// (colvarvalue::type_scalar type, range [0:*)) /// (colvarvalue::type_scalar type, range [0:*))
@ -1114,6 +1133,23 @@ public:
}; };
// \brief Colvar component: flat vector of Cartesian coordinates
// Mostly useful to compute scripted colvar values
class colvar::cartesian
: public colvar::cvc
{
protected:
/// Atom group
cvm::atom_group atoms;
public:
cartesian(std::string const &conf);
cartesian();
virtual inline ~cartesian() {}
virtual void calc_value();
virtual void calc_gradients();
virtual void apply_force(colvarvalue const &force);
};
// metrics functions for cvc implementations // metrics functions for cvc implementations
@ -1326,15 +1362,34 @@ inline cvm::real colvar::distance_dir::dist2 (colvarvalue const &x1,
inline colvarvalue colvar::distance_dir::dist2_lgrad(colvarvalue const &x1, inline colvarvalue colvar::distance_dir::dist2_lgrad(colvarvalue const &x1,
colvarvalue const &x2) const colvarvalue const &x2) const
{ {
return colvarvalue ((x1.rvector_value - x2.rvector_value), colvarvalue::type_unitvector); return colvarvalue((x1.rvector_value - x2.rvector_value), colvarvalue::type_unit3vector);
} }
inline colvarvalue colvar::distance_dir::dist2_rgrad(colvarvalue const &x1, inline colvarvalue colvar::distance_dir::dist2_rgrad(colvarvalue const &x1,
colvarvalue const &x2) const colvarvalue const &x2) const
{ {
return colvarvalue ((x2.rvector_value - x1.rvector_value), colvarvalue::type_unitvector); return colvarvalue((x2.rvector_value - x1.rvector_value), colvarvalue::type_unit3vector);
} }
inline cvm::real colvar::distance_pairs::dist2(colvarvalue const &x1,
colvarvalue const &x2) const
{
return (x1.vector1d_value - x2.vector1d_value).norm2();
}
inline colvarvalue colvar::distance_pairs::dist2_lgrad(colvarvalue const &x1,
colvarvalue const &x2) const
{
return colvarvalue((x1.vector1d_value - x2.vector1d_value), colvarvalue::type_vector);
}
inline colvarvalue colvar::distance_pairs::dist2_rgrad(colvarvalue const &x1,
colvarvalue const &x2) const
{
return colvarvalue((x2.vector1d_value - x1.vector1d_value), colvarvalue::type_vector);
}
// distance between quaternions // distance between quaternions
inline cvm::real colvar::orientation::dist2(colvarvalue const &x1, inline cvm::real colvar::orientation::dist2(colvarvalue const &x1,

View File

@ -95,14 +95,14 @@ colvar::distance_vec::distance_vec (std::string const &conf)
: distance(conf) : distance(conf)
{ {
function_type = "distance_vec"; function_type = "distance_vec";
x.type (colvarvalue::type_vector); x.type(colvarvalue::type_3vector);
} }
colvar::distance_vec::distance_vec() colvar::distance_vec::distance_vec()
: distance() : distance()
{ {
function_type = "distance_vec"; function_type = "distance_vec";
x.type (colvarvalue::type_vector); x.type(colvarvalue::type_3vector);
} }
void colvar::distance_vec::calc_value() void colvar::distance_vec::calc_value()
@ -384,7 +384,7 @@ colvar::distance_dir::distance_dir (std::string const &conf)
: distance(conf) : distance(conf)
{ {
function_type = "distance_dir"; function_type = "distance_dir";
x.type (colvarvalue::type_unitvector); x.type(colvarvalue::type_unit3vector);
} }
@ -392,7 +392,7 @@ colvar::distance_dir::distance_dir()
: distance() : distance()
{ {
function_type = "distance_dir"; function_type = "distance_dir";
x.type (colvarvalue::type_unitvector); x.type(colvarvalue::type_unit3vector);
} }
@ -527,6 +527,99 @@ void colvar::distance_inv::apply_force (colvarvalue const &force)
colvar::distance_pairs::distance_pairs(std::string const &conf)
: cvc(conf)
{
function_type = "distance_pairs";
b_inverse_gradients = false;
b_Jacobian_derivative = false;
if (get_keyval(conf, "forceNoPBC", b_no_PBC, false)) {
cvm::log("Computing distance using absolute positions (not minimal-image)");
}
parse_group(conf, "group1", group1);
atom_groups.push_back(&group1);
parse_group(conf, "group2", group2);
atom_groups.push_back(&group2);
x.type(colvarvalue::type_vector);
x.vector1d_value.resize(group1.size() * group2.size());
}
colvar::distance_pairs::distance_pairs()
{
function_type = "distance_pairs";
b_inverse_gradients = false;
b_Jacobian_derivative = false;
x.type(colvarvalue::type_vector);
}
void colvar::distance_pairs::calc_value()
{
x.vector1d_value.resize(group1.size() * group2.size());
if (b_no_PBC) {
size_t i1, i2;
for (i1 = 0; i1 < group1.size(); i1++) {
for (i2 = 0; i2 < group2.size(); i2++) {
cvm::rvector const dv = group2[i2].pos - group1[i1].pos;
cvm::real const d = dv.norm();
x.vector1d_value[i1*group2.size() + i2] = d;
group1[i1].grad = -1.0 * dv.unit();
group2[i2].grad = dv.unit();
}
}
} else {
size_t i1, i2;
for (i1 = 0; i1 < group1.size(); i1++) {
for (i2 = 0; i2 < group2.size(); i2++) {
cvm::rvector const dv = cvm::position_distance(group1[i1].pos, group2[i2].pos);
cvm::real const d = dv.norm();
x.vector1d_value[i1*group2.size() + i2] = d;
group1[i1].grad = -1.0 * dv.unit();
group2[i2].grad = dv.unit();
}
}
}
}
void colvar::distance_pairs::calc_gradients()
{
// will be calculated on the fly in apply_force()
if (b_debug_gradients) {
cvm::log("Debugging gradients:\n");
debug_gradients(group1);
}
}
void colvar::distance_pairs::apply_force(colvarvalue const &force)
{
if (b_no_PBC) {
size_t i1, i2;
for (i1 = 0; i1 < group1.size(); i1++) {
for (i2 = 0; i2 < group2.size(); i2++) {
cvm::rvector const dv = group2[i2].pos - group1[i1].pos;
group1[i1].apply_force(force[i1*group2.size() + i2] * (-1.0) * dv.unit());
group2[i2].apply_force(force[i1*group2.size() + i2] * dv.unit());
}
}
} else {
size_t i1, i2;
for (i1 = 0; i1 < group1.size(); i1++) {
for (i2 = 0; i2 < group2.size(); i2++) {
cvm::rvector const dv = cvm::position_distance(group1[i1].pos, group2[i2].pos);
group1[i1].apply_force(force[i1*group2.size() + i2] * (-1.0) * dv.unit());
group2[i2].apply_force(force[i1*group2.size() + i2] * dv.unit());
}
}
}
}
colvar::gyration::gyration(std::string const &conf) colvar::gyration::gyration(std::string const &conf)
: cvc(conf) : cvc(conf)
{ {
@ -867,13 +960,13 @@ void colvar::rmsd::calc_Jacobian_derivative()
if (atoms.b_rotate) { if (atoms.b_rotate) {
// gradient of the rotation matrix // gradient of the rotation matrix
cvm::matrix2d <cvm::rvector, 3, 3> grad_rot_mat; cvm::matrix2d<cvm::rvector> grad_rot_mat(3, 3);
// gradients of products of 2 quaternion components // gradients of products of 2 quaternion components
cvm::rvector g11, g22, g33, g01, g02, g03, g12, g13, g23; cvm::rvector g11, g22, g33, g01, g02, g03, g12, g13, g23;
for (size_t ia = 0; ia < atoms.size(); ia++) { for (size_t ia = 0; ia < atoms.size(); ia++) {
// Gradient of optimal quaternion wrt current Cartesian position // Gradient of optimal quaternion wrt current Cartesian position
cvm::vector1d< cvm::rvector, 4 > &dq = atoms.rot.dQ0_1[ia]; cvm::vector1d<cvm::rvector> &dq = atoms.rot.dQ0_1[ia];
g11 = 2.0 * (atoms.rot.q)[1]*dq[1]; g11 = 2.0 * (atoms.rot.q)[1]*dq[1];
g22 = 2.0 * (atoms.rot.q)[2]*dq[2]; g22 = 2.0 * (atoms.rot.q)[2]*dq[2];
@ -1143,7 +1236,7 @@ void colvar::eigenvector::calc_force_invgrads()
void colvar::eigenvector::calc_Jacobian_derivative() void colvar::eigenvector::calc_Jacobian_derivative()
{ {
// gradient of the rotation matrix // gradient of the rotation matrix
cvm::matrix2d <cvm::rvector, 3, 3> grad_rot_mat; cvm::matrix2d<cvm::rvector> grad_rot_mat(3, 3);
cvm::quaternion &quat0 = atoms.rot.q; cvm::quaternion &quat0 = atoms.rot.q;
// gradients of products of 2 quaternion components // gradients of products of 2 quaternion components
@ -1156,7 +1249,7 @@ void colvar::eigenvector::calc_Jacobian_derivative()
// Gradient of optimal quaternion wrt current Cartesian position // Gradient of optimal quaternion wrt current Cartesian position
// trick: d(R^-1)/dx = d(R^t)/dx = (dR/dx)^t // trick: d(R^-1)/dx = d(R^t)/dx = (dR/dx)^t
// we can just transpose the derivatives of the direct matrix // we can just transpose the derivatives of the direct matrix
cvm::vector1d< cvm::rvector, 4 > &dq_1 = atoms.rot.dQ0_1[ia]; cvm::vector1d<cvm::rvector> &dq_1 = atoms.rot.dQ0_1[ia];
g11 = 2.0 * quat0[1]*dq_1[1]; g11 = 2.0 * quat0[1]*dq_1[1];
g22 = 2.0 * quat0[2]*dq_1[2]; g22 = 2.0 * quat0[2]*dq_1[2];
@ -1191,5 +1284,51 @@ void colvar::eigenvector::calc_Jacobian_derivative()
} }
colvar::cartesian::cartesian(std::string const &conf)
: cvc(conf)
{
b_inverse_gradients = false;
b_Jacobian_derivative = false;
function_type = "cartesian";
parse_group(conf, "atoms", atoms);
atom_groups.push_back(&atoms);
x.type(colvarvalue::type_vector);
x.vector1d_value.resize(atoms.size() * 3);
}
void colvar::cartesian::calc_value()
{
int ia, j;
for (ia = 0; ia < atoms.size(); ia++) {
for (j = 0; j < 3; j++) {
x.vector1d_value[3*ia + j] = atoms[ia].pos[j];
}
}
}
void colvar::cartesian::calc_gradients()
{
// we're not using the "grad" member of each
// atom object, because it only can represent the gradient of a
// scalar colvar
}
void colvar::cartesian::apply_force(colvarvalue const &force)
{
int ia, j;
if (!atoms.noforce) {
cvm::rvector f;
for (ia = 0; ia < atoms.size(); ia++) {
for (j = 0; j < 3; j++) {
f[j] = force.vector1d_value[3*ia + j];
}
atoms[ia].apply_force(f);
}
}
}

View File

@ -193,25 +193,3 @@ void colvar_grid_gradient::write_1D_integral (std::ostream &os)
// quaternion_grid::quaternion_grid (std::vector<colvar *> const &cv_i,
// std::vector<std::string> const &grid_str)
// {
// cv = cv_i;
// std::istringstream is (grid_str[0]);
// is >> grid_size;
// min.assign (3, -1.0);
// max.assign (3, 1.0);
// np.assign (3, grid_size);
// dx.assign (3, 2.0/(cvm::real (grid_size)));
// // assumes a uniform grid in the three directions; change
// // get_value() if you want to use different sizes
// cvm::log ("Allocating quaternion grid ("+cvm::to_str (np.size())+" dimensional)...");
// data.create (np, 0.0);
// cvm::log ("done.\n");
// if (cvm::debug()) cvm::log ("Grid size = "+data.size());
// }

View File

@ -30,7 +30,7 @@ protected:
std::vector<int> nxc; std::vector<int> nxc;
/// \brief Multiplicity of each datum (allow the binning of /// \brief Multiplicity of each datum (allow the binning of
/// non-scalar types) /// non-scalar types such as atomic gradients)
size_t mult; size_t mult;
/// Total number of grid points /// Total number of grid points
@ -223,7 +223,7 @@ public:
for (size_t i = 0; i < cv.size(); i++) { for (size_t i = 0; i < cv.size(); i++) {
if (cv[i]->type() != colvarvalue::type_scalar) { if (cv[i]->value().type() != colvarvalue::type_scalar) {
cvm::error("Colvar grids can only be automatically " cvm::error("Colvar grids can only be automatically "
"constructed for scalar variables. " "constructed for scalar variables. "
"ABF and histogram can not be used; metadynamics " "ABF and histogram can not be used; metadynamics "

View File

@ -1,6 +1,8 @@
/// -*- c++ -*- /// -*- c++ -*-
#include <sstream> #include <sstream>
#include <string.h>
#include "colvarmodule.h" #include "colvarmodule.h"
#include "colvarparse.h" #include "colvarparse.h"
#include "colvarproxy.h" #include "colvarproxy.h"
@ -169,7 +171,7 @@ int colvarmodule::parse_global_params (std::string const &conf)
colvarparse::parse_silent); colvarparse::parse_silent);
if (use_scripted_forces && !proxy->force_script_defined) { if (use_scripted_forces && !proxy->force_script_defined) {
cvm::fatal_error("User script for scripted colvars forces not found."); cvm::fatal_error("User script for scripted colvar forces not found.");
} }
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
@ -230,143 +232,57 @@ bool colvarmodule::check_new_bias(std::string &conf, char const *key)
return false; return false;
} }
template <class bias_type>
int colvarmodule::parse_biases_type(std::string const &conf,
char const *keyword,
size_t &bias_count)
{
std::string bias_conf = "";
size_t conf_saved_pos = 0;
while (parse->key_lookup(conf, keyword, bias_conf, conf_saved_pos)) {
if (bias_conf.size()) {
cvm::log(cvm::line_marker);
cvm::increase_depth();
biases.push_back(new bias_type(bias_conf, keyword));
if (cvm::check_new_bias(bias_conf, keyword)) {
return COLVARS_ERROR;
}
cvm::decrease_depth();
bias_count++;
} else {
cvm::error("Error: keyword \""+std::string(keyword)+"\" found without configuration.\n",
INPUT_ERROR);
return COLVARS_ERROR;
}
bias_conf = "";
}
return COLVARS_OK;
}
int colvarmodule::parse_biases(std::string const &conf) int colvarmodule::parse_biases(std::string const &conf)
{ {
if (cvm::debug()) if (cvm::debug())
cvm::log("Initializing the collective variables biases.\n"); cvm::log("Initializing the collective variables biases.\n");
{
/// initialize ABF instances /// initialize ABF instances
std::string abf_conf = ""; parse_biases_type<colvarbias_abf>(conf, "abf", n_abf_biases);
size_t abf_pos = 0;
while (parse->key_lookup (conf, "abf", abf_conf, abf_pos)) {
if (abf_conf.size()) {
cvm::log (cvm::line_marker);
cvm::increase_depth();
biases.push_back (new colvarbias_abf (abf_conf, "abf"));
if (cvm::check_new_bias(abf_conf, "abf")) {
return COLVARS_ERROR;
}
cvm::decrease_depth();
n_abf_biases++;
} else {
cvm::error("Error: \"abf\" keyword found without configuration.\n", INPUT_ERROR);
return COLVARS_ERROR;
}
abf_conf = "";
}
}
{
/// initialize harmonic restraints
std::string harm_conf = "";
size_t harm_pos = 0;
while (parse->key_lookup (conf, "harmonic", harm_conf, harm_pos)) {
if (harm_conf.size()) {
cvm::log (cvm::line_marker);
cvm::increase_depth();
biases.push_back (new colvarbias_restraint_harmonic (harm_conf, "harmonic"));
if (cvm::check_new_bias(harm_conf, "harmonic")) {
return COLVARS_ERROR;
}
cvm::decrease_depth();
n_rest_biases++;
} else {
cvm::error("Error: \"harmonic\" keyword found without configuration.\n", INPUT_ERROR);
return COLVARS_ERROR;
}
harm_conf = "";
}
}
{
/// initialize linear restraints
std::string lin_conf = "";
size_t lin_pos = 0;
while (parse->key_lookup (conf, "linear", lin_conf, lin_pos)) {
if (lin_conf.size()) {
cvm::log (cvm::line_marker);
cvm::increase_depth();
biases.push_back (new colvarbias_restraint_linear (lin_conf, "linear"));
if (cvm::check_new_bias(lin_conf, "linear")) {
return COLVARS_ERROR;
}
cvm::decrease_depth();
n_rest_biases++;
} else {
cvm::error("Error: \"linear\" keyword found without configuration.\n", INPUT_ERROR);
return COLVARS_ERROR;
}
lin_conf = "";
}
}
{
/// initialize adaptive linear biases /// initialize adaptive linear biases
std::string alb_conf = ""; parse_biases_type<colvarbias_alb>(conf, "ALB", n_rest_biases);
size_t alb_pos = 0;
while (parse->key_lookup (conf, "ALB", alb_conf, alb_pos)) {
if (alb_conf.size()) {
cvm::log (cvm::line_marker);
cvm::increase_depth();
biases.push_back (new colvarbias_alb (alb_conf, "ALB"));
if (cvm::check_new_bias(alb_conf, "ALB")) {
return COLVARS_ERROR;
}
cvm::decrease_depth();
n_rest_biases++;
} else {
cvm::error("Error: \"ALB\" keyword found without configuration.\n", INPUT_ERROR);
return COLVARS_ERROR;
}
alb_conf = "";
}
}
/// initialize harmonic restraints
parse_biases_type<colvarbias_restraint_harmonic>(conf, "harmonic", n_rest_biases);
{
/// initialize histograms /// initialize histograms
std::string histo_conf = ""; parse_biases_type<colvarbias_histogram>(conf, "histogram", n_histo_biases);
size_t histo_pos = 0;
while (parse->key_lookup (conf, "histogram", histo_conf, histo_pos)) { /// initialize linear restraints
if (histo_conf.size()) { parse_biases_type<colvarbias_restraint_linear>(conf, "linear", n_rest_biases);
cvm::log (cvm::line_marker);
cvm::increase_depth();
biases.push_back (new colvarbias_histogram (histo_conf, "histogram"));
if (cvm::check_new_bias(histo_conf, "histogram")) {
return COLVARS_ERROR;
}
cvm::decrease_depth();
n_histo_biases++;
} else {
cvm::error("Error: \"histogram\" keyword found without configuration.\n", INPUT_ERROR);
return COLVARS_ERROR;
}
histo_conf = "";
}
}
{
/// initialize metadynamics instances /// initialize metadynamics instances
std::string meta_conf = ""; parse_biases_type<colvarbias_meta>(conf, "metadynamics", n_meta_biases);
size_t meta_pos = 0;
while (parse->key_lookup (conf, "metadynamics", meta_conf, meta_pos)) {
if (meta_conf.size()) {
cvm::log (cvm::line_marker);
cvm::increase_depth();
biases.push_back (new colvarbias_meta (meta_conf, "metadynamics"));
if (cvm::check_new_bias(meta_conf, "metadynamics")) {
return COLVARS_ERROR;
}
cvm::decrease_depth();
n_meta_biases++;
} else {
cvm::error("Error: \"metadynamics\" keyword found without configuration.\n", INPUT_ERROR);
return COLVARS_ERROR;
}
meta_conf = "";
}
}
if (use_scripted_forces) { if (use_scripted_forces) {
cvm::log(cvm::line_marker); cvm::log(cvm::line_marker);
@ -375,10 +291,15 @@ int colvarmodule::parse_biases (std::string const &conf)
cvm::decrease_depth(); cvm::decrease_depth();
} }
if (biases.size() || use_scripted_forces) if (biases.size() || use_scripted_forces) {
cvm::log(cvm::line_marker); cvm::log(cvm::line_marker);
cvm::log("Collective variables biases initialized, "+ cvm::log("Collective variables biases initialized, "+
cvm::to_str(biases.size())+" in total.\n"); cvm::to_str(biases.size())+" in total.\n");
} else {
if (!use_scripted_forces) {
cvm::log("No collective variables biases were defined.\n");
}
}
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
} }
@ -448,124 +369,73 @@ cvm::real colvarmodule::energy_difference (std::string const &bias_name,
return energy_diff; return energy_diff;
} }
// For shared ABF int colvarmodule::bias_current_bin(std::string const &bias_name)
cvm::real colvarmodule::read_width(std::string const &name)
{ {
cvm::increase_depth(); cvm::increase_depth();
int found = 0; int ret;
real width = -1.0; colvarbias *b = bias_by_name(bias_name);
for (std::vector<colvar *>::iterator cvi = colvars.begin();
cvi != colvars.end(); if (b != NULL) {
cvi++) { ret = b->current_bin();
if ( (*cvi)->name == name ) {
++found;
width = (*cvi)->width;
}
}
if (found < 1) {
cvm::error ("Error: bias not found.\n");
} else if (found > 1) {
cvm::error ("Error: duplicate bias name.\n");
} else { } else {
cvm::decrease_depth(); cvm::error("Error: bias not found.\n");
} ret = COLVARS_ERROR;
return width;
} }
size_t colvarmodule::bias_current_bin (std::string const &bias_name)
{
cvm::increase_depth();
int found = 0;
size_t ret = 0; // N.B.: size_t is unsigned, so returning -1 would be a problem.
for (std::vector<colvarbias *>::iterator bi = biases.begin();
bi != biases.end();
bi++) {
if ( (*bi)->name == bias_name ) {
++found;
ret = (*bi)->current_bin ();
}
}
if (found < 1) {
cvm::error ("Error: bias not found.\n");
} else if (found > 1) {
cvm::error ("Error: duplicate bias name.\n");
} else {
cvm::decrease_depth(); cvm::decrease_depth();
}
return ret; return ret;
} }
size_t colvarmodule::bias_bin_num (std::string const &bias_name) int colvarmodule::bias_bin_num(std::string const &bias_name)
{ {
cvm::increase_depth(); cvm::increase_depth();
int found = 0; int ret;
size_t ret = 0; // N.B.: size_t is unsigned, so returning -1 would be a problem. colvarbias *b = bias_by_name(bias_name);
for (std::vector<colvarbias *>::iterator bi = biases.begin(); if (b != NULL) {
bi != biases.end(); ret = b->bin_num();
bi++) {
if ( (*bi)->name == bias_name ) {
++found;
ret = (*bi)->bin_num ();
}
}
if (found < 1) {
cvm::error ("Error: bias not found.\n");
} else if (found > 1) {
cvm::error ("Error: duplicate bias name.\n");
} else { } else {
cvm::decrease_depth(); cvm::error("Error: bias not found.\n");
ret = COLVARS_ERROR;
} }
cvm::decrease_depth();
return ret; return ret;
} }
size_t colvarmodule::bias_bin_count (std::string const &bias_name, size_t bin_index) int colvarmodule::bias_bin_count(std::string const &bias_name, size_t bin_index)
{ {
cvm::increase_depth(); cvm::increase_depth();
int found = 0; int ret;
size_t ret = 0; // N.B.: size_t is unsigned, so returning -1 would be a problem. colvarbias *b = bias_by_name(bias_name);
for (std::vector<colvarbias *>::iterator bi = biases.begin(); if (b != NULL) {
bi != biases.end(); ret = b->bin_count(bin_index);
bi++) {
if ( (*bi)->name == bias_name ) {
++found;
ret = (*bi)->bin_count (bin_index);
}
}
if (found < 1) {
cvm::error ("Error: bias not found.\n");
} else if (found > 1) {
cvm::error ("Error: duplicate bias name.\n");
} else { } else {
cvm::decrease_depth(); cvm::error("Error: bias not found.\n");
ret = COLVARS_ERROR;
} }
cvm::decrease_depth();
return ret; return ret;
} }
void colvarmodule::bias_share (std::string const &bias_name) int colvarmodule::bias_share(std::string const &bias_name)
{ {
cvm::increase_depth(); cvm::increase_depth();
int found = 0; int ret;
colvarbias *b = bias_by_name(bias_name);
for (std::vector<colvarbias *>::iterator bi = biases.begin(); if (b != NULL) {
bi != biases.end(); b->replica_share();
bi++) { ret = COLVARS_OK;
if ( (*bi)->name == bias_name ) { } else {
++found;
(*bi)->replica_share ();
}
}
if (found < 1) {
cvm::error("Error: bias not found.\n"); cvm::error("Error: bias not found.\n");
return; ret = COLVARS_ERROR;
}
if (found > 1) {
cvm::error ("Error: duplicate bias name.\n");
return;
} }
cvm::decrease_depth(); cvm::decrease_depth();
return ret;
} }
@ -706,7 +576,7 @@ int colvarmodule::calc() {
// write trajectory file, if needed // write trajectory file, if needed
if (cv_traj_freq && cv_traj_name.size()) { if (cv_traj_freq && cv_traj_name.size()) {
if (!cv_traj_os.good()) { if (!cv_traj_os.is_open()) {
open_traj_file(cv_traj_name); open_traj_file(cv_traj_name);
} }
@ -867,21 +737,10 @@ int colvarmodule::setup_output()
std::string("")); std::string(""));
if (cv_traj_freq && cv_traj_name.size()) { if (cv_traj_freq && cv_traj_name.size()) {
// open trajectory file open_traj_file(cv_traj_name);
if (cv_traj_append) {
cvm::log ("Appending to colvar trajectory file \""+cv_traj_name+
"\".\n");
cv_traj_os.open (cv_traj_name.c_str(), std::ios::app);
} else {
cvm::log ("Writing to colvar trajectory file \""+cv_traj_name+
"\".\n");
proxy->backup_file (cv_traj_name.c_str());
cv_traj_os.open (cv_traj_name.c_str(), std::ios::out);
} }
cv_traj_os.setf (std::ios::scientific, std::ios::floatfield);
}
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
} }
@ -1061,21 +920,27 @@ std::ostream & colvarmodule::write_restart (std::ostream &os)
int colvarmodule::open_traj_file(std::string const &file_name) int colvarmodule::open_traj_file(std::string const &file_name)
{ {
if (cv_traj_os.is_open()) {
return COLVARS_OK;
}
// (re)open trajectory file // (re)open trajectory file
if (cv_traj_append) { if (cv_traj_append) {
cvm::log("Appending to colvar trajectory file \""+file_name+ cvm::log("Appending to colvar trajectory file \""+file_name+
"\".\n"); "\".\n");
cv_traj_os.open(file_name.c_str(), std::ios::app); cv_traj_os.open(file_name.c_str(), std::ios::app);
} else { } else {
cvm::log ("Overwriting colvar trajectory file \""+file_name+ cvm::log("Writing to colvar trajectory file \""+file_name+
"\".\n"); "\".\n");
proxy->backup_file(file_name.c_str()); proxy->backup_file(file_name.c_str());
cv_traj_os.open(file_name.c_str(), std::ios::out); cv_traj_os.open(file_name.c_str(), std::ios::out);
} }
if (!cv_traj_os.good()) {
if (!cv_traj_os.is_open()) {
cvm::error("Error: cannot write to file \""+file_name+"\".\n", cvm::error("Error: cannot write to file \""+file_name+"\".\n",
FILE_ERROR); FILE_ERROR);
} }
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
} }
@ -1330,7 +1195,7 @@ bool colvarmodule::b_analysis = false;
cvm::real colvarmodule::rotation::crossing_threshold = 1.0E-04; cvm::real colvarmodule::rotation::crossing_threshold = 1.0E-04;
std::list<std::string> colvarmodule::index_group_names; std::list<std::string> colvarmodule::index_group_names;
std::list<std::vector<int> > colvarmodule::index_groups; std::list<std::vector<int> > colvarmodule::index_groups;
bool colvarmodule::use_scripted_forces = false;
// file name prefixes // file name prefixes
std::string colvarmodule::output_prefix = ""; std::string colvarmodule::output_prefix = "";

View File

@ -4,7 +4,7 @@
#define COLVARMODULE_H #define COLVARMODULE_H
#ifndef COLVARS_VERSION #ifndef COLVARS_VERSION
#define COLVARS_VERSION "2014-10-21" #define COLVARS_VERSION "2014-11-21"
#endif #endif
#ifndef COLVARS_DEBUG #ifndef COLVARS_DEBUG
@ -21,6 +21,7 @@
/// objects. /// objects.
// Internal method return codes // Internal method return codes
#define COLVARS_NOT_IMPLEMENTED -2
#define COLVARS_ERROR -1 #define COLVARS_ERROR -1
#define COLVARS_OK 0 #define COLVARS_OK 0
@ -80,11 +81,8 @@ public:
typedef int residue_id; typedef int residue_id;
class rvector; class rvector;
template <class T, template <class T> class vector1d;
size_t const length> class vector1d; template <class T> class matrix2d;
template <class T,
size_t const outer_length,
size_t const inner_length> class matrix2d;
class quaternion; class quaternion;
class rotation; class rotation;
@ -219,6 +217,10 @@ public:
/// Parse and initialize collective variable biases /// Parse and initialize collective variable biases
int parse_biases(std::string const &conf); int parse_biases(std::string const &conf);
/// Parse and initialize collective variable biases of a specific type
template <class bias_type>
int parse_biases_type(std::string const &conf, char const *keyword, size_t &bias_count);
/// Test error condition and keyword parsing /// Test error condition and keyword parsing
/// on error, delete new bias /// on error, delete new bias
bool check_new_bias(std::string &conf, char const *key); bool check_new_bias(std::string &conf, char const *key);
@ -273,16 +275,14 @@ public:
/// currently works for harmonic (force constant and/or centers) /// currently works for harmonic (force constant and/or centers)
real energy_difference(std::string const &bias_name, std::string const &conf); real energy_difference(std::string const &bias_name, std::string const &conf);
/// Give the bin width in the units of the colvar.
real read_width(std::string const &name);
/// Give the total number of bins for a given bias. /// Give the total number of bins for a given bias.
size_t bias_bin_num(std::string const &bias_name); int bias_bin_num(std::string const &bias_name);
/// Calculate the bin index for a given bias. /// Calculate the bin index for a given bias.
size_t bias_current_bin(std::string const &bias_name); int bias_current_bin(std::string const &bias_name);
//// Give the count at a given bin index. //// Give the count at a given bin index.
size_t bias_bin_count(std::string const &bias_name, size_t bin_index); int bias_bin_count(std::string const &bias_name, size_t bin_index);
//// Share among replicas. //// Share among replicas.
void bias_share(std::string const &bias_name); int bias_share(std::string const &bias_name);
/// Calculate collective variables and biases /// Calculate collective variables and biases
int calc(); int calc();
@ -467,7 +467,7 @@ protected:
static size_t depth; static size_t depth;
/// Use scripted colvars forces? /// Use scripted colvars forces?
bool use_scripted_forces; static bool use_scripted_forces;
public: public:
/// \brief Pointer to the proxy object, used to retrieve atomic data /// \brief Pointer to the proxy object, used to retrieve atomic data
@ -481,6 +481,8 @@ public:
/// Decrease the depth (number of indentations in the output) /// Decrease the depth (number of indentations in the output)
static void decrease_depth(); static void decrease_depth();
static inline bool scripted_forces() { return use_scripted_forces; }
}; };

View File

@ -4,18 +4,11 @@
#define COLVARPROXY_H #define COLVARPROXY_H
#ifndef COLVARPROXY_VERSION
#define COLVARPROXY_VERSION "2014-10-21"
#endif
#include "colvarmodule.h" #include "colvarmodule.h"
#include "colvarvalue.h" #include "colvarvalue.h"
// return values for the frame() routine // return values for the frame() routine
#define COLVARS_NO_SUCH_FRAME -1 #define COLVARS_NO_SUCH_FRAME -1
#define COLVARS_NOT_IMPLEMENTED -2
// forward declarations // forward declarations
class colvarscript; class colvarscript;
@ -177,7 +170,7 @@ public:
virtual int run_colvar_gradient_callback(std::string const &name, virtual int run_colvar_gradient_callback(std::string const &name,
std::vector<const colvarvalue *> const &cvcs, std::vector<const colvarvalue *> const &cvcs,
std::vector<colvarvalue> &gradient) std::vector<cvm::matrix2d<cvm::real> > &gradient)
{ return COLVARS_NOT_IMPLEMENTED; } { return COLVARS_NOT_IMPLEMENTED; }
// **************** INPUT/OUTPUT **************** // **************** INPUT/OUTPUT ****************

View File

@ -1,6 +1,9 @@
// -*- c++ -*- // -*- c++ -*-
#include <cstdlib> #include <cstdlib>
#include <stdlib.h>
#include <string.h>
#include "colvarscript.h" #include "colvarscript.h"
@ -209,14 +212,19 @@ int colvarscript::proc_colvar (int argc, char const *argv[]) {
std::string subcmd = argv[2]; std::string subcmd = argv[2];
if (subcmd == "value") { if (subcmd == "value") {
result = cvm::to_str(cv->value(), 0, cvm::cv_prec); result = (cv->value()).to_simple_string();
return COLVARSCRIPT_OK;
}
if (subcmd == "width") {
result = cvm::to_str(cv->width, 0, cvm::cv_prec);
return COLVARSCRIPT_OK; return COLVARSCRIPT_OK;
} }
if (subcmd == "update") { if (subcmd == "update") {
cv->calc(); cv->calc();
cv->update(); cv->update();
result = cvm::to_str(cv->value(), 0, cvm::cv_prec); result = (cv->value()).to_simple_string();
return COLVARSCRIPT_OK; return COLVARSCRIPT_OK;
} }
@ -234,21 +242,21 @@ int colvarscript::proc_colvar (int argc, char const *argv[]) {
if (subcmd == "addforce") { if (subcmd == "addforce") {
if (argc < 4) { if (argc < 4) {
result = "Missing parameter: force value"; result = "addforce: missing parameter: force value";
return COLVARSCRIPT_ERROR; return COLVARSCRIPT_ERROR;
} }
std::string f_str = argv[3]; std::string f_str = argv[3];
std::istringstream is(f_str); std::istringstream is(f_str);
is.width(cvm::cv_width); is.width(cvm::cv_width);
is.precision(cvm::cv_prec); is.precision(cvm::cv_prec);
colvarvalue force (cv->type()); colvarvalue force(cv->value());
force.is_derivative(); force.is_derivative();
if (!(is >> force)) { if (force.from_simple_string(is.str()) != COLVARS_OK) {
result = "Error parsing force value"; result = "addforce : error parsing force value";
return COLVARSCRIPT_ERROR; return COLVARSCRIPT_ERROR;
} }
cv->add_bias_force(force); cv->add_bias_force(force);
result = cvm::to_str(force, cvm::cv_width, cvm::cv_prec); result = force.to_simple_string();
return COLVARSCRIPT_OK; return COLVARSCRIPT_OK;
} }
@ -282,6 +290,34 @@ int colvarscript::proc_bias (int argc, char const *argv[]) {
return COLVARSCRIPT_OK; return COLVARSCRIPT_OK;
} }
// Subcommands for MW ABF
if (subcmd == "bin") {
int r = b->current_bin();
result = cvm::to_str(r);
return COLVARSCRIPT_OK;
}
if (subcmd == "binnum") {
int r = b->bin_num();
if (r < 0) {
result = "Error: calling bin_num() for bias " + b->name;
return COLVARSCRIPT_ERROR;
}
result = cvm::to_str(r);
return COLVARSCRIPT_OK;
}
if (subcmd == "share") {
int r = b->replica_share();
if (r < 0) {
result = "Error: calling replica_share() for bias " + b->name;
return COLVARSCRIPT_ERROR;
}
result = cvm::to_str(r);
return COLVARSCRIPT_OK;
}
// End commands for MW ABF
if (subcmd == "delete") { if (subcmd == "delete") {
// the bias destructor takes care of the cleanup at cvm level // the bias destructor takes care of the cleanup at cvm level
delete b; delete b;
@ -291,7 +327,16 @@ int colvarscript::proc_bias (int argc, char const *argv[]) {
} }
if (argc >= 4) { if (argc >= 4) {
// std::string param = argv[3]; std::string param = argv[3];
if (subcmd == "count") {
int index;
if (!(std::istringstream(param) >> index)) {
result = "bin_count: error parsing bin index";
return COLVARSCRIPT_ERROR;
}
result = cvm::to_str(b->bin_count(index));
return COLVARSCRIPT_OK;
}
result = "Syntax error"; result = "Syntax error";
return COLVARSCRIPT_ERROR; return COLVARSCRIPT_ERROR;

View File

@ -1,10 +1,35 @@
/// -*- c++ -*- // -*- c++ -*-
#include <stdlib.h>
#include <string.h>
#include "colvarmodule.h" #include "colvarmodule.h"
#include "colvartypes.h" #include "colvartypes.h"
#include "colvarparse.h" #include "colvarparse.h"
std::string cvm::rvector::to_simple_string() const
{
std::ostringstream os;
os.setf(std::ios::scientific, std::ios::floatfield);
os.precision(cvm::cv_prec);
os << x << " " << y << " " << z;
return os.str();
}
int cvm::rvector::from_simple_string(std::string const &s)
{
std::stringstream stream(s);
if ( !(stream >> x) ||
!(stream >> y) ||
!(stream >> z) ) {
return COLVARS_ERROR;
}
return COLVARS_OK;
}
std::ostream & operator << (std::ostream &os, colvarmodule::rvector const &v) std::ostream & operator << (std::ostream &os, colvarmodule::rvector const &v)
{ {
std::streamsize const w = os.width(); std::streamsize const w = os.width();
@ -38,7 +63,26 @@ std::istream & operator >> (std::istream &is, colvarmodule::rvector &v)
return is; return is;
} }
std::string cvm::quaternion::to_simple_string() const
{
std::ostringstream os;
os.setf(std::ios::scientific, std::ios::floatfield);
os.precision(cvm::cv_prec);
os << q0 << " " << q1 << " " << q2 << " " << q3;
return os.str();
}
int cvm::quaternion::from_simple_string(std::string const &s)
{
std::stringstream stream(s);
if ( !(stream >> q0) ||
!(stream >> q1) ||
!(stream >> q2) ||
!(stream >> q3) ) {
return COLVARS_ERROR;
}
return COLVARS_OK;
}
std::ostream & operator << (std::ostream &os, colvarmodule::quaternion const &q) std::ostream & operator << (std::ostream &os, colvarmodule::quaternion const &q)
{ {
@ -174,8 +218,6 @@ cvm::quaternion::position_derivative_inner (cvm::rvector const &pos,
// Calculate the optimal rotation between two groups, and implement it // Calculate the optimal rotation between two groups, and implement it
// as a quaternion. Uses the method documented in: Coutsias EA, // as a quaternion. Uses the method documented in: Coutsias EA,
// Seok C, Dill KA. Using quaternions to calculate RMSD. J Comput // Seok C, Dill KA. Using quaternions to calculate RMSD. J Comput
@ -183,13 +225,13 @@ cvm::quaternion::position_derivative_inner (cvm::rvector const &pos,
void colvarmodule::rotation::build_matrix(std::vector<cvm::atom_pos> const &pos1, void colvarmodule::rotation::build_matrix(std::vector<cvm::atom_pos> const &pos1,
std::vector<cvm::atom_pos> const &pos2, std::vector<cvm::atom_pos> const &pos2,
matrix2d<cvm::real, 4, 4> &S) cvm::matrix2d<cvm::real> &S)
{ {
cvm::rmatrix C;
// build the correlation matrix // build the correlation matrix
C.resize(3, 3);
C.reset(); C.reset();
for (size_t i = 0; i < pos1.size(); i++) { size_t i;
for (i = 0; i < pos1.size(); i++) {
C.xx() += pos1[i].x * pos2[i].x; C.xx() += pos1[i].x * pos2[i].x;
C.xy() += pos1[i].x * pos2[i].y; C.xy() += pos1[i].x * pos2[i].y;
C.xz() += pos1[i].x * pos2[i].z; C.xz() += pos1[i].x * pos2[i].z;
@ -219,70 +261,51 @@ void colvarmodule::rotation::build_matrix (std::vector<cvm::atom_pos> const &pos
S[3][2] = C.yz() + C.zy(); S[3][2] = C.yz() + C.zy();
S[2][3] = S[3][2]; S[2][3] = S[3][2];
S[3][3] = - C.xx() - C.yy() + C.zz(); S[3][3] = - C.xx() - C.yy() + C.zz();
// if (cvm::debug()) {
// for (size_t i = 0; i < 4; i++) {
// std::string line ("");
// for (size_t j = 0; j < 4; j++) {
// line += std::string (" S["+cvm::to_str (i)+
// "]["+cvm::to_str (j)+"] ="+cvm::to_str (S[i][j]));
// }
// cvm::log (line+"\n");
// }
// }
} }
void colvarmodule::rotation::diagonalize_matrix (matrix2d<cvm::real, 4, 4> &S, void colvarmodule::rotation::diagonalize_matrix(cvm::matrix2d<cvm::real> &S,
cvm::real S_eigval[4], cvm::vector1d<cvm::real> &S_eigval,
matrix2d<cvm::real, 4, 4> &S_eigvec) cvm::matrix2d<cvm::real> &S_eigvec)
{ {
S_eigval.resize(4);
S_eigval.reset();
S_eigvec.resize(4,4);
S_eigvec.reset();
// diagonalize // diagonalize
int jac_nrot = 0; int jac_nrot = 0;
jacobi (S, S_eigval, S_eigvec, &jac_nrot); jacobi(S.c_array(), S_eigval.c_array(), S_eigvec.c_array(), &jac_nrot);
eigsrt (S_eigval, S_eigvec); eigsrt(S_eigval.c_array(), S_eigvec.c_array());
// jacobi saves eigenvectors by columns // jacobi saves eigenvectors by columns
transpose (S_eigvec); transpose(S_eigvec.c_array());
// normalize eigenvectors // normalize eigenvectors
for (size_t ie = 0; ie < 4; ie++) { for (size_t ie = 0; ie < 4; ie++) {
cvm::real norm2 = 0.0; cvm::real norm2 = 0.0;
size_t i; size_t i;
for (i = 0; i < 4; i++) norm2 += std::pow (S_eigvec[ie][i], int (2)); for (i = 0; i < 4; i++) {
norm2 += std::pow(S_eigvec[ie][i], int(2));
}
cvm::real const norm = std::sqrt(norm2); cvm::real const norm = std::sqrt(norm2);
for (i = 0; i < 4; i++) S_eigvec[ie][i] /= norm; for (i = 0; i < 4; i++) {
S_eigvec[ie][i] /= norm;
}
} }
} }
// Calculate the rotation, plus its derivatives // Calculate the rotation, plus its derivatives
void colvarmodule::rotation::calc_optimal_rotation void colvarmodule::rotation::calc_optimal_rotation(std::vector<cvm::atom_pos> const &pos1,
(std::vector<cvm::atom_pos> const &pos1,
std::vector<cvm::atom_pos> const &pos2) std::vector<cvm::atom_pos> const &pos2)
{ {
matrix2d<cvm::real, 4, 4> S; S.resize(4,4);
matrix2d<cvm::real, 4, 4> S_backup; S.reset();
cvm::real S_eigval[4];
matrix2d<cvm::real, 4, 4> S_eigvec;
// if (cvm::debug()) {
// cvm::atom_pos cog1 (0.0, 0.0, 0.0);
// for (size_t i = 0; i < pos1.size(); i++) {
// cog1 += pos1[i];
// }
// cog1 /= cvm::real (pos1.size());
// cvm::atom_pos cog2 (0.0, 0.0, 0.0);
// for (size_t i = 0; i < pos2.size(); i++) {
// cog2 += pos2[i];
// }
// cog2 /= cvm::real (pos1.size());
// cvm::log ("calc_optimal_rotation: centers of geometry are: "+
// cvm::to_str (cog1, cvm::cv_width, cvm::cv_prec)+
// " and "+cvm::to_str (cog2, cvm::cv_width, cvm::cv_prec)+".\n");
// }
build_matrix(pos1, pos2, S); build_matrix(pos1, pos2, S);
S_backup.resize(4,4);
S_backup = S; S_backup = S;
if (cvm::debug()) { if (cvm::debug()) {
@ -294,17 +317,17 @@ void colvarmodule::rotation::calc_optimal_rotation
diagonalize_matrix(S, S_eigval, S_eigvec); diagonalize_matrix(S, S_eigval, S_eigvec);
// eigenvalues and eigenvectors // eigenvalues and eigenvectors
cvm::real const &L0 = S_eigval[0]; cvm::real const L0 = S_eigval[0];
cvm::real const &L1 = S_eigval[1]; cvm::real const L1 = S_eigval[1];
cvm::real const &L2 = S_eigval[2]; cvm::real const L2 = S_eigval[2];
cvm::real const &L3 = S_eigval[3]; cvm::real const L3 = S_eigval[3];
cvm::real const *Q0 = S_eigvec[0]; cvm::quaternion const Q0(S_eigvec[0]);
cvm::real const *Q1 = S_eigvec[1]; cvm::quaternion const Q1(S_eigvec[1]);
cvm::real const *Q2 = S_eigvec[2]; cvm::quaternion const Q2(S_eigvec[2]);
cvm::real const *Q3 = S_eigvec[3]; cvm::quaternion const Q3(S_eigvec[3]);
lambda = L0; lambda = L0;
q = cvm::quaternion (Q0); q = Q0;
if (q_old.norm2() > 0.0) { if (q_old.norm2() > 0.0) {
q.match(q_old); q.match(q_old);
@ -318,20 +341,20 @@ void colvarmodule::rotation::calc_optimal_rotation
if (cvm::debug()) { if (cvm::debug()) {
if (b_debug_gradients) { if (b_debug_gradients) {
cvm::log("L0 = "+cvm::to_str(L0, cvm::cv_width, cvm::cv_prec)+ cvm::log("L0 = "+cvm::to_str(L0, cvm::cv_width, cvm::cv_prec)+
", Q0 = "+cvm::to_str (cvm::quaternion (Q0), cvm::cv_width, cvm::cv_prec)+ ", Q0 = "+cvm::to_str(Q0, cvm::cv_width, cvm::cv_prec)+
", Q0*Q0 = "+cvm::to_str (cvm::quaternion (Q0).inner (cvm::quaternion (Q0)), cvm::cv_width, cvm::cv_prec)+ ", Q0*Q0 = "+cvm::to_str(Q0.inner(Q0), cvm::cv_width, cvm::cv_prec)+
"\n"); "\n");
cvm::log("L1 = "+cvm::to_str(L1, cvm::cv_width, cvm::cv_prec)+ cvm::log("L1 = "+cvm::to_str(L1, cvm::cv_width, cvm::cv_prec)+
", Q1 = "+cvm::to_str (cvm::quaternion (Q1), cvm::cv_width, cvm::cv_prec)+ ", Q1 = "+cvm::to_str(Q1, cvm::cv_width, cvm::cv_prec)+
", Q0*Q1 = "+cvm::to_str (cvm::quaternion (Q0).inner (cvm::quaternion (Q1)), cvm::cv_width, cvm::cv_prec)+ ", Q0*Q1 = "+cvm::to_str(Q0.inner(Q1), cvm::cv_width, cvm::cv_prec)+
"\n"); "\n");
cvm::log("L2 = "+cvm::to_str(L2, cvm::cv_width, cvm::cv_prec)+ cvm::log("L2 = "+cvm::to_str(L2, cvm::cv_width, cvm::cv_prec)+
", Q2 = "+cvm::to_str (cvm::quaternion (Q2), cvm::cv_width, cvm::cv_prec)+ ", Q2 = "+cvm::to_str(Q2, cvm::cv_width, cvm::cv_prec)+
", Q0*Q2 = "+cvm::to_str (cvm::quaternion (Q0).inner (cvm::quaternion (Q2)), cvm::cv_width, cvm::cv_prec)+ ", Q0*Q2 = "+cvm::to_str(Q0.inner(Q2), cvm::cv_width, cvm::cv_prec)+
"\n"); "\n");
cvm::log("L3 = "+cvm::to_str(L3, cvm::cv_width, cvm::cv_prec)+ cvm::log("L3 = "+cvm::to_str(L3, cvm::cv_width, cvm::cv_prec)+
", Q3 = "+cvm::to_str (cvm::quaternion (Q3), cvm::cv_width, cvm::cv_prec)+ ", Q3 = "+cvm::to_str(Q3, cvm::cv_width, cvm::cv_prec)+
", Q0*Q3 = "+cvm::to_str (cvm::quaternion (Q0).inner (cvm::quaternion (Q3)), cvm::cv_width, cvm::cv_prec)+ ", Q0*Q3 = "+cvm::to_str(Q0.inner(Q3), cvm::cv_width, cvm::cv_prec)+
"\n"); "\n");
} }
} }
@ -346,7 +369,7 @@ void colvarmodule::rotation::calc_optimal_rotation
cvm::real const &a2y = pos2[ia].y; cvm::real const &a2y = pos2[ia].y;
cvm::real const &a2z = pos2[ia].z; cvm::real const &a2z = pos2[ia].z;
matrix2d<cvm::rvector, 4, 4> &ds_1 = dS_1[ia]; cvm::matrix2d<cvm::rvector> &ds_1 = dS_1[ia];
// derivative of the S matrix // derivative of the S matrix
ds_1.reset(); ds_1.reset();
@ -368,7 +391,7 @@ void colvarmodule::rotation::calc_optimal_rotation
ds_1[3][3].set(-a2x, -a2y, a2z); ds_1[3][3].set(-a2x, -a2y, a2z);
cvm::rvector &dl0_1 = dL0_1[ia]; cvm::rvector &dl0_1 = dL0_1[ia];
vector1d<cvm::rvector, 4> &dq0_1 = dQ0_1[ia]; cvm::vector1d<cvm::rvector> &dq0_1 = dQ0_1[ia];
// matrix multiplications; derivatives of L_0 and Q_0 are // matrix multiplications; derivatives of L_0 and Q_0 are
// calculated using Hellmann-Feynman theorem (i.e. exploiting the // calculated using Hellmann-Feynman theorem (i.e. exploiting the
@ -401,7 +424,7 @@ void colvarmodule::rotation::calc_optimal_rotation
cvm::real const &a1y = pos1[ia].y; cvm::real const &a1y = pos1[ia].y;
cvm::real const &a1z = pos1[ia].z; cvm::real const &a1z = pos1[ia].z;
matrix2d<cvm::rvector, 4, 4> &ds_2 = dS_2[ia]; cvm::matrix2d<cvm::rvector> &ds_2 = dS_2[ia];
ds_2.reset(); ds_2.reset();
ds_2[0][0].set( a1x, a1y, a1z); ds_2[0][0].set( a1x, a1y, a1z);
@ -422,7 +445,7 @@ void colvarmodule::rotation::calc_optimal_rotation
ds_2[3][3].set(-a1x, -a1y, a1z); ds_2[3][3].set(-a1x, -a1y, a1z);
cvm::rvector &dl0_2 = dL0_2[ia]; cvm::rvector &dl0_2 = dL0_2[ia];
vector1d<cvm::rvector, 4> &dq0_2 = dQ0_2[ia]; cvm::vector1d<cvm::rvector> &dq0_2 = dQ0_2[ia];
dl0_2.reset(); dl0_2.reset();
for (size_t i = 0; i < 4; i++) { for (size_t i = 0; i < 4; i++) {
@ -447,9 +470,9 @@ void colvarmodule::rotation::calc_optimal_rotation
if (b_debug_gradients) { if (b_debug_gradients) {
matrix2d<cvm::real, 4, 4> S_new; cvm::matrix2d<cvm::real> S_new(4, 4);
cvm::real S_new_eigval[4]; cvm::vector1d<cvm::real> S_new_eigval(4);
matrix2d<cvm::real, 4, 4> S_new_eigvec; cvm::matrix2d<cvm::real> S_new_eigvec(4, 4);
// make an infitesimal move along each cartesian coordinate of // make an infitesimal move along each cartesian coordinate of
// this atom, and solve again the eigenvector problem // this atom, and solve again the eigenvector problem
@ -469,7 +492,7 @@ void colvarmodule::rotation::calc_optimal_rotation
diagonalize_matrix(S_new, S_new_eigval, S_new_eigvec); diagonalize_matrix(S_new, S_new_eigval, S_new_eigvec);
cvm::real const &L0_new = S_new_eigval[0]; cvm::real const &L0_new = S_new_eigval[0];
cvm::real const *Q0_new = S_new_eigvec[0]; cvm::quaternion const Q0_new(S_new_eigvec[0]);
cvm::real const DL0 = (dl0_2[comp]) * colvarmodule::debug_gradients_step_size; cvm::real const DL0 = (dl0_2[comp]) * colvarmodule::debug_gradients_step_size;
cvm::quaternion const q0(Q0); cvm::quaternion const q0(Q0);
@ -497,18 +520,21 @@ void colvarmodule::rotation::calc_optimal_rotation
h=a[k][l]; \ h=a[k][l]; \
a[i][j]=g-s*(h+g*tau); \ a[i][j]=g-s*(h+g*tau); \
a[k][l]=h+s*(g-h*tau); a[k][l]=h+s*(g-h*tau);
#define n 4 #define n 4
void jacobi(cvm::real **a, cvm::real d[], cvm::real **v, int *nrot) void jacobi(cvm::real **a, cvm::real *d, cvm::real **v, int *nrot)
{ {
int j,iq,ip,i; int j,iq,ip,i;
cvm::real tresh,theta,tau,t,sm,s,h,g,c; cvm::real tresh,theta,tau,t,sm,s,h,g,c;
std::vector<cvm::real> b (n, 0.0); cvm::vector1d<cvm::real> b(n);
std::vector<cvm::real> z (n, 0.0); cvm::vector1d<cvm::real> z(n);
for (ip=0;ip<n;ip++) { for (ip=0;ip<n;ip++) {
for (iq=0;iq<n;iq++) v[ip][iq]=0.0; for (iq=0;iq<n;iq++) {
v[ip][iq]=0.0;
}
v[ip][ip]=1.0; v[ip][ip]=1.0;
} }
for (ip=0;ip<n;ip++) { for (ip=0;ip<n;ip++) {
@ -578,7 +604,7 @@ void jacobi(cvm::real **a, cvm::real d[], cvm::real **v, int *nrot)
cvm::error("Too many iterations in routine jacobi.\n"); cvm::error("Too many iterations in routine jacobi.\n");
} }
void eigsrt(cvm::real d[], cvm::real **v) void eigsrt(cvm::real *d, cvm::real **v)
{ {
int k,j,i; int k,j,i;
cvm::real p; cvm::real p;
@ -602,8 +628,9 @@ void eigsrt(cvm::real d[], cvm::real **v)
void transpose(cvm::real **v) void transpose(cvm::real **v)
{ {
cvm::real p; cvm::real p;
for (int i=0;i<n;i++) { int i,j;
for (int j=i+1;j<n;j++) { for (i=0;i<n;i++) {
for (j=i+1;j<n;j++) {
p=v[i][j]; p=v[i][j];
v[i][j]=v[j][i]; v[i][j]=v[j][i];
v[j][i]=p; v[j][i]=p;

File diff suppressed because it is too large Load Diff

View File

@ -1,237 +1,385 @@
/// -*- c++ -*- /// -*- c++ -*-
#include <vector> #include <vector>
#include <sstream>
#include <iostream>
#include "colvarmodule.h" #include "colvarmodule.h"
#include "colvarvalue.h" #include "colvarvalue.h"
std::string const colvarvalue::type_desc[colvarvalue::type_all+1] = void colvarvalue::add_elem(colvarvalue const &x)
{ "not_set",
"scalar number",
"3-dimensional vector",
"3-dimensional unit vector",
"3-dimensional tangent vector",
"4-dimensional unit quaternion",
"4-dimensional tangent vector",
};
std::string const colvarvalue::type_keyword[colvarvalue::type_all+1] =
{ "not_set",
"scalar",
"vector",
"unit_vector",
"",
"unit_quaternion",
"",
};
size_t const colvarvalue::dof_num[ colvarvalue::type_all+1] =
{ 0, 1, 3, 2, 2, 3, 3 };
void colvarvalue::undef_op() const
{ {
cvm::error ("Error: Undefined operation on a colvar of type \""+ if (this->value_type != type_vector) {
colvarvalue::type_desc[this->value_type]+"\".\n"); cvm::error("Error: trying to set an element for a variable that is not set to be a vector.\n");
}
void colvarvalue::error_rside
(colvarvalue::Type const &vt) const
{
cvm::error("Trying to assign a colvar value with type \""+
type_desc[this->value_type]+"\" to one with type \""+
type_desc[vt]+"\".\n");
}
void colvarvalue::error_lside(colvarvalue::Type const &vt) const
{
cvm::error("Trying to use a colvar value with type \""+
type_desc[vt]+"\" as one of type \""+
type_desc[this->value_type]+"\".\n");
}
void colvarvalue::inner_opt(colvarvalue const &x,
std::vector<colvarvalue>::iterator &xv,
std::vector<colvarvalue>::iterator const &xv_end,
std::vector<cvm::real>::iterator &inner)
{
// doing type check only once, here
colvarvalue::check_types(x, *xv);
std::vector<colvarvalue>::iterator &xvi = xv;
std::vector<cvm::real>::iterator &ii = inner;
switch (x.value_type) {
case colvarvalue::type_scalar:
while (xvi != xv_end) {
*(ii++) += (xvi++)->real_value * x.real_value;
}
break;
case colvarvalue::type_vector:
case colvarvalue::type_unitvector:
case colvarvalue::type_unitvectorderiv:
while (xvi != xv_end) {
*(ii++) += (xvi++)->rvector_value * x.rvector_value;
}
break;
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
while (xvi != xv_end) {
*(ii++) += ((xvi++)->quaternion_value).cosine (x.quaternion_value);
}
break;
default:
x.undef_op();
};
}
void colvarvalue::inner_opt(colvarvalue const &x,
std::list<colvarvalue>::iterator &xv,
std::list<colvarvalue>::iterator const &xv_end,
std::vector<cvm::real>::iterator &inner)
{
// doing type check only once, here
colvarvalue::check_types(x, *xv);
std::list<colvarvalue>::iterator &xvi = xv;
std::vector<cvm::real>::iterator &ii = inner;
switch (x.value_type) {
case colvarvalue::type_scalar:
while (xvi != xv_end) {
*(ii++) += (xvi++)->real_value * x.real_value;
}
break;
case colvarvalue::type_vector:
case colvarvalue::type_unitvector:
case colvarvalue::type_unitvectorderiv:
while (xvi != xv_end) {
*(ii++) += (xvi++)->rvector_value * x.rvector_value;
}
break;
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
while (xvi != xv_end) {
*(ii++) += ((xvi++)->quaternion_value).cosine (x.quaternion_value);
}
break;
default:
x.undef_op();
};
}
void colvarvalue::p2leg_opt(colvarvalue const &x,
std::vector<colvarvalue>::iterator &xv,
std::vector<colvarvalue>::iterator const &xv_end,
std::vector<cvm::real>::iterator &inner)
{
// doing type check only once, here
colvarvalue::check_types(x, *xv);
std::vector<colvarvalue>::iterator &xvi = xv;
std::vector<cvm::real>::iterator &ii = inner;
switch (x.value_type) {
case colvarvalue::type_scalar:
cvm::error("Error: cannot calculate Legendre polynomials "
"for scalar variables.\n");
return; return;
break;
case colvarvalue::type_vector:
while (xvi != xv_end) {
cvm::real const cosine =
((xvi)->rvector_value * x.rvector_value) /
((xvi)->rvector_value.norm() * x.rvector_value.norm());
xvi++;
*(ii++) += 1.5*cosine*cosine - 0.5;
} }
break; size_t const n = vector1d_value.size();
case colvarvalue::type_unitvector: size_t const nd = num_dimensions(x.value_type);
case colvarvalue::type_unitvectorderiv: elem_types.push_back(x.value_type);
while (xvi != xv_end) { elem_indices.push_back(n);
cvm::real const cosine = (xvi++)->rvector_value * x.rvector_value; elem_sizes.push_back(nd);
*(ii++) += 1.5*cosine*cosine - 0.5; vector1d_value.resize(n + nd);
set_elem(n, x);
} }
colvarvalue const colvarvalue::get_elem(int const i_begin, int const i_end, Type const vt) const
{
if (vector1d_value.size() > 0) {
cvm::vector1d<cvm::real> const v(vector1d_value.slice(i_begin, i_end));
return colvarvalue(v, vt);
} else {
cvm::error("Error: trying to get an element from a variable that is not a vector.\n");
return colvarvalue(type_notset);
}
}
void colvarvalue::set_elem(int const i_begin, int const i_end, colvarvalue const &x)
{
if (vector1d_value.size() > 0) {
vector1d_value.sliceassign(i_begin, i_end, x.as_vector());
} else {
cvm::error("Error: trying to set an element for a variable that is not a vector.\n");
}
}
colvarvalue const colvarvalue::get_elem(int const icv) const
{
if (elem_types.size() > 0) {
return get_elem(elem_indices[icv], elem_indices[icv] + elem_sizes[icv],
elem_types[icv]);
} else {
cvm::error("Error: trying to get a colvarvalue element from a vector colvarvalue that was initialized as a plain array.\n");
return colvarvalue(type_notset);
}
}
void colvarvalue::set_elem(int const icv, colvarvalue const &x)
{
if (elem_types.size() > 0) {
check_types_assign(elem_types[icv], x.value_type);
set_elem(elem_indices[icv], elem_indices[icv] + elem_sizes[icv], x);
} else {
cvm::error("Error: trying to set a colvarvalue element for a colvarvalue that was initialized as a plain array.\n");
}
}
colvarvalue colvarvalue::inverse() const
{
switch (value_type) {
case colvarvalue::type_scalar:
return colvarvalue(1.0/real_value);
break;
case colvarvalue::type_3vector:
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
return colvarvalue(cvm::rvector(1.0/rvector_value.x,
1.0/rvector_value.y,
1.0/rvector_value.z));
break; break;
case colvarvalue::type_quaternion: case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv: case colvarvalue::type_quaternionderiv:
while (xvi != xv_end) { return colvarvalue(cvm::quaternion(1.0/quaternion_value.q0,
cvm::real const cosine = (xvi++)->quaternion_value.cosine (x.quaternion_value); 1.0/quaternion_value.q1,
*(ii++) += 1.5*cosine*cosine - 0.5; 1.0/quaternion_value.q2,
1.0/quaternion_value.q3));
break;
case colvarvalue::type_vector:
{
cvm::vector1d<cvm::real> result(vector1d_value);
if (elem_types.size() > 0) {
// if we have information about non-scalar types, use it
size_t i;
for (i = 0; i < elem_types.size(); i++) {
result.sliceassign(elem_indices[i], elem_indices[i]+elem_sizes[i],
cvm::vector1d<cvm::real>((this->get_elem(i)).inverse()));
}
} else {
size_t i;
for (i = 0; i < result.size(); i++) {
if (result[i] != 0.0) {
result = 1.0/result[i];
}
}
}
return colvarvalue(result, type_vector);
} }
break; break;
case colvarvalue::type_notset:
default: default:
x.undef_op(); undef_op();
break;
}
return colvarvalue();
}
// binary operations between two colvarvalues
colvarvalue operator + (colvarvalue const &x1,
colvarvalue const &x2)
{
colvarvalue::check_types(x1, x2);
switch (x1.value_type) {
case colvarvalue::type_scalar:
return colvarvalue(x1.real_value + x2.real_value);
case colvarvalue::type_3vector:
return colvarvalue(x1.rvector_value + x2.rvector_value);
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
return colvarvalue(x1.rvector_value + x2.rvector_value,
colvarvalue::type_unit3vector);
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
return colvarvalue(x1.quaternion_value + x2.quaternion_value);
case colvarvalue::type_vector:
return colvarvalue(x1.vector1d_value + x2.vector1d_value, colvarvalue::type_vector);
case colvarvalue::type_notset:
default:
x1.undef_op();
return colvarvalue(colvarvalue::type_notset);
}; };
} }
void colvarvalue::p2leg_opt(colvarvalue const &x,
std::list<colvarvalue>::iterator &xv, colvarvalue operator - (colvarvalue const &x1,
std::list<colvarvalue>::iterator const &xv_end, colvarvalue const &x2)
std::vector<cvm::real>::iterator &inner)
{ {
// doing type check only once, here colvarvalue::check_types(x1, x2);
colvarvalue::check_types(x, *xv);
std::list<colvarvalue>::iterator &xvi = xv; switch (x1.value_type) {
std::vector<cvm::real>::iterator &ii = inner; case colvarvalue::type_scalar:
return colvarvalue(x1.real_value - x2.real_value);
case colvarvalue::type_3vector:
return colvarvalue(x1.rvector_value - x2.rvector_value);
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
return colvarvalue(x1.rvector_value - x2.rvector_value,
colvarvalue::type_unit3vector);
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
return colvarvalue(x1.quaternion_value - x2.quaternion_value);
case colvarvalue::type_vector:
return colvarvalue(x1.vector1d_value - x2.vector1d_value, colvarvalue::type_vector);
case colvarvalue::type_notset:
default:
x1.undef_op();
return colvarvalue(colvarvalue::type_notset);
};
}
// binary operations with real numbers
colvarvalue operator * (cvm::real const &a,
colvarvalue const &x)
{
switch (x.value_type) { switch (x.value_type) {
case colvarvalue::type_scalar: case colvarvalue::type_scalar:
cvm::error("Error: cannot calculate Legendre polynomials " return colvarvalue(a * x.real_value);
"for scalar variables.\n"); case colvarvalue::type_3vector:
break; return colvarvalue(a * x.rvector_value);
case colvarvalue::type_vector: case colvarvalue::type_unit3vector:
while (xvi != xv_end) { case colvarvalue::type_unit3vectorderiv:
cvm::real const cosine = return colvarvalue(a * x.rvector_value,
((xvi)->rvector_value * x.rvector_value) / colvarvalue::type_unit3vector);
((xvi)->rvector_value.norm() * x.rvector_value.norm());
xvi++;
*(ii++) += 1.5*cosine*cosine - 0.5;
}
break;
case colvarvalue::type_unitvector:
case colvarvalue::type_unitvectorderiv:
while (xvi != xv_end) {
cvm::real const cosine = (xvi++)->rvector_value * x.rvector_value;
*(ii++) += 1.5*cosine*cosine - 0.5;
}
break;
case colvarvalue::type_quaternion: case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv: case colvarvalue::type_quaternionderiv:
while (xvi != xv_end) { return colvarvalue(a * x.quaternion_value);
cvm::real const cosine = (xvi++)->quaternion_value.cosine (x.quaternion_value); case colvarvalue::type_vector:
*(ii++) += 1.5*cosine*cosine - 0.5; return colvarvalue(x.vector1d_value * a, colvarvalue::type_vector);
} case colvarvalue::type_notset:
break;
default: default:
x.undef_op(); x.undef_op();
return colvarvalue(colvarvalue::type_notset);
}
}
colvarvalue operator * (colvarvalue const &x,
cvm::real const &a)
{
return a * x;
}
colvarvalue operator / (colvarvalue const &x,
cvm::real const &a)
{
switch (x.value_type) {
case colvarvalue::type_scalar:
return colvarvalue(x.real_value / a);
case colvarvalue::type_3vector:
return colvarvalue(x.rvector_value / a);
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
return colvarvalue(x.rvector_value / a,
colvarvalue::type_unit3vector);
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
return colvarvalue(x.quaternion_value / a);
case colvarvalue::type_vector:
return colvarvalue(x.vector1d_value / a, colvarvalue::type_vector);
case colvarvalue::type_notset:
default:
x.undef_op();
return colvarvalue(colvarvalue::type_notset);
}
}
// inner product between two colvarvalues
cvm::real operator * (colvarvalue const &x1,
colvarvalue const &x2)
{
colvarvalue::check_types(x1, x2);
switch (x1.value_type) {
case colvarvalue::type_scalar:
return (x1.real_value * x2.real_value);
case colvarvalue::type_3vector:
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
return (x1.rvector_value * x2.rvector_value);
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
// the "*" product is the quaternion product, here the inner
// member function is used instead
return (x1.quaternion_value.inner(x2.quaternion_value));
case colvarvalue::type_vector:
return (x1.vector1d_value * x2.vector1d_value);
case colvarvalue::type_notset:
default:
x1.undef_op();
return 0.0;
}; };
} }
colvarvalue colvarvalue::dist2_grad(colvarvalue const &x2) const
{
colvarvalue::check_types(*this, x2);
switch (this->value_type) {
case colvarvalue::type_scalar:
return 2.0 * (this->real_value - x2.real_value);
case colvarvalue::type_3vector:
return 2.0 * (this->rvector_value - x2.rvector_value);
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
{
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);
return colvarvalue( 2.0 * sin_t *
cvm::rvector((-1.0) * sin_t * v2.x +
cos_t/sin_t * (v1.x - cos_t*v2.x),
(-1.0) * sin_t * v2.y +
cos_t/sin_t * (v1.y - cos_t*v2.y),
(-1.0) * sin_t * v2.z +
cos_t/sin_t * (v1.z - cos_t*v2.z)
),
colvarvalue::type_unit3vector );
}
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
return this->quaternion_value.dist2_grad(x2.quaternion_value);
case colvarvalue::type_vector:
return colvarvalue(2.0 * (this->vector1d_value - x2.vector1d_value), colvarvalue::type_vector);
break;
case colvarvalue::type_notset:
default:
this->undef_op();
return colvarvalue(colvarvalue::type_notset);
};
}
std::string colvarvalue::to_simple_string() const
{
switch (type()) {
case colvarvalue::type_scalar:
return cvm::to_str(real_value, 0, cvm::cv_prec);
break;
case colvarvalue::type_3vector:
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
return rvector_value.to_simple_string();
break;
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
return quaternion_value.to_simple_string();
break;
case colvarvalue::type_vector:
return vector1d_value.to_simple_string();
break;
case colvarvalue::type_notset:
default:
undef_op();
break;
}
return std::string();
}
int colvarvalue::from_simple_string(std::string const &s)
{
switch (type()) {
case colvarvalue::type_scalar:
return ((std::istringstream(s) >> real_value)
? COLVARS_OK : COLVARS_ERROR);
break;
case colvarvalue::type_3vector:
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
return rvector_value.from_simple_string(s);
break;
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
return quaternion_value.from_simple_string(s);
break;
case colvarvalue::type_vector:
return vector1d_value.from_simple_string(s);
break;
case colvarvalue::type_notset:
default:
undef_op();
break;
}
return COLVARS_ERROR;
}
std::ostream & operator << (std::ostream &os, colvarvalue const &x) std::ostream & operator << (std::ostream &os, colvarvalue const &x)
{ {
switch (x.type()) { switch (x.type()) {
case colvarvalue::type_scalar: case colvarvalue::type_scalar:
os << x.real_value; os << x.real_value;
break; break;
case colvarvalue::type_vector: case colvarvalue::type_3vector:
case colvarvalue::type_unitvector: case colvarvalue::type_unit3vector:
case colvarvalue::type_unitvectorderiv: case colvarvalue::type_unit3vectorderiv:
os << x.rvector_value; os << x.rvector_value;
break; break;
case colvarvalue::type_quaternion: case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv: case colvarvalue::type_quaternionderiv:
os << x.quaternion_value; os << x.quaternion_value;
break; break;
case colvarvalue::type_vector:
os << x.vector1d_value;
break;
case colvarvalue::type_notset: case colvarvalue::type_notset:
os << "not set"; break; default:
os << "not set";
break;
} }
return os; return os;
} }
@ -239,7 +387,8 @@ std::ostream & operator << (std::ostream &os, colvarvalue const &x)
std::ostream & operator << (std::ostream &os, std::vector<colvarvalue> const &v) std::ostream & operator << (std::ostream &os, std::vector<colvarvalue> const &v)
{ {
for (size_t i = 0; i < v.size(); i++) { size_t i;
for (i = 0; i < v.size(); i++) {
os << v[i]; os << v[i];
} }
return os; return os;
@ -258,11 +407,11 @@ std::istream & operator >> (std::istream &is, colvarvalue &x)
case colvarvalue::type_scalar: case colvarvalue::type_scalar:
is >> x.real_value; is >> x.real_value;
break; break;
case colvarvalue::type_vector: case colvarvalue::type_3vector:
case colvarvalue::type_unitvectorderiv: case colvarvalue::type_unit3vectorderiv:
is >> x.rvector_value; is >> x.rvector_value;
break; break;
case colvarvalue::type_unitvector: case colvarvalue::type_unit3vector:
is >> x.rvector_value; is >> x.rvector_value;
x.apply_constraints(); x.apply_constraints();
break; break;
@ -273,6 +422,10 @@ std::istream & operator >> (std::istream &is, colvarvalue &x)
case colvarvalue::type_quaternionderiv: case colvarvalue::type_quaternionderiv:
is >> x.quaternion_value; is >> x.quaternion_value;
break; break;
case colvarvalue::type_vector:
is >> x.vector1d_value;
break;
case colvarvalue::type_notset:
default: default:
x.undef_op(); x.undef_op();
} }
@ -285,13 +438,16 @@ size_t colvarvalue::output_width(size_t const &real_width) const
switch (this->value_type) { switch (this->value_type) {
case colvarvalue::type_scalar: case colvarvalue::type_scalar:
return real_width; return real_width;
case colvarvalue::type_vector: case colvarvalue::type_3vector:
case colvarvalue::type_unitvector: case colvarvalue::type_unit3vector:
case colvarvalue::type_unitvectorderiv: case colvarvalue::type_unit3vectorderiv:
return cvm::rvector::output_width(real_width); return cvm::rvector::output_width(real_width);
case colvarvalue::type_quaternion: case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv: case colvarvalue::type_quaternionderiv:
return cvm::quaternion::output_width(real_width); return cvm::quaternion::output_width(real_width);
case colvarvalue::type_vector:
// note how this depends on the vector's size
return vector1d_value.output_width(real_width);
case colvarvalue::type_notset: case colvarvalue::type_notset:
default: default:
return 0; return 0;
@ -299,3 +455,186 @@ size_t colvarvalue::output_width(size_t const &real_width) const
} }
void colvarvalue::inner_opt(colvarvalue const &x,
std::vector<colvarvalue>::iterator &xv,
std::vector<colvarvalue>::iterator const &xv_end,
std::vector<cvm::real>::iterator &result)
{
// doing type check only once, here
colvarvalue::check_types(x, *xv);
std::vector<colvarvalue>::iterator &xvi = xv;
std::vector<cvm::real>::iterator &ii = result;
switch (x.value_type) {
case colvarvalue::type_scalar:
while (xvi != xv_end) {
*(ii++) += (xvi++)->real_value * x.real_value;
}
break;
case colvarvalue::type_3vector:
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
while (xvi != xv_end) {
*(ii++) += (xvi++)->rvector_value * x.rvector_value;
}
break;
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
while (xvi != xv_end) {
*(ii++) += ((xvi++)->quaternion_value).cosine(x.quaternion_value);
}
break;
case colvarvalue::type_vector:
while (xvi != xv_end) {
*(ii++) += (xvi++)->vector1d_value * x.vector1d_value;
}
break;
default:
x.undef_op();
};
}
void colvarvalue::inner_opt(colvarvalue const &x,
std::list<colvarvalue>::iterator &xv,
std::list<colvarvalue>::iterator const &xv_end,
std::vector<cvm::real>::iterator &result)
{
// doing type check only once, here
colvarvalue::check_types(x, *xv);
std::list<colvarvalue>::iterator &xvi = xv;
std::vector<cvm::real>::iterator &ii = result;
switch (x.value_type) {
case colvarvalue::type_scalar:
while (xvi != xv_end) {
*(ii++) += (xvi++)->real_value * x.real_value;
}
break;
case colvarvalue::type_3vector:
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
while (xvi != xv_end) {
*(ii++) += (xvi++)->rvector_value * x.rvector_value;
}
break;
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
while (xvi != xv_end) {
*(ii++) += ((xvi++)->quaternion_value).cosine(x.quaternion_value);
}
break;
case colvarvalue::type_vector:
while (xvi != xv_end) {
*(ii++) += (xvi++)->vector1d_value * x.vector1d_value;
}
break;
default:
x.undef_op();
};
}
void colvarvalue::p2leg_opt(colvarvalue const &x,
std::vector<colvarvalue>::iterator &xv,
std::vector<colvarvalue>::iterator const &xv_end,
std::vector<cvm::real>::iterator &result)
{
// doing type check only once, here
colvarvalue::check_types(x, *xv);
std::vector<colvarvalue>::iterator &xvi = xv;
std::vector<cvm::real>::iterator &ii = result;
switch (x.value_type) {
case colvarvalue::type_scalar:
cvm::error("Error: cannot calculate Legendre polynomials "
"for scalar variables.\n");
return;
break;
case colvarvalue::type_3vector:
while (xvi != xv_end) {
cvm::real const cosine =
((xvi)->rvector_value * x.rvector_value) /
((xvi)->rvector_value.norm() * x.rvector_value.norm());
xvi++;
*(ii++) += 1.5*cosine*cosine - 0.5;
}
break;
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
while (xvi != xv_end) {
cvm::real const cosine = (xvi++)->rvector_value * x.rvector_value;
*(ii++) += 1.5*cosine*cosine - 0.5;
}
break;
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
while (xvi != xv_end) {
cvm::real const cosine = (xvi++)->quaternion_value.cosine(x.quaternion_value);
*(ii++) += 1.5*cosine*cosine - 0.5;
}
break;
case colvarvalue::type_vector:
while (xvi != xv_end) {
cvm::real const cosine =
((xvi)->vector1d_value * x.vector1d_value) /
((xvi)->vector1d_value.norm() * x.rvector_value.norm());
xvi++;
*(ii++) += 1.5*cosine*cosine - 0.5;
}
break;
default:
x.undef_op();
};
}
void colvarvalue::p2leg_opt(colvarvalue const &x,
std::list<colvarvalue>::iterator &xv,
std::list<colvarvalue>::iterator const &xv_end,
std::vector<cvm::real>::iterator &result)
{
// doing type check only once, here
colvarvalue::check_types(x, *xv);
std::list<colvarvalue>::iterator &xvi = xv;
std::vector<cvm::real>::iterator &ii = result;
switch (x.value_type) {
case colvarvalue::type_scalar:
cvm::error("Error: cannot calculate Legendre polynomials "
"for scalar variables.\n");
break;
case colvarvalue::type_3vector:
while (xvi != xv_end) {
cvm::real const cosine =
((xvi)->rvector_value * x.rvector_value) /
((xvi)->rvector_value.norm() * x.rvector_value.norm());
xvi++;
*(ii++) += 1.5*cosine*cosine - 0.5;
}
break;
case colvarvalue::type_unit3vector:
case colvarvalue::type_unit3vectorderiv:
while (xvi != xv_end) {
cvm::real const cosine = (xvi++)->rvector_value * x.rvector_value;
*(ii++) += 1.5*cosine*cosine - 0.5;
}
break;
case colvarvalue::type_quaternion:
case colvarvalue::type_quaternionderiv:
while (xvi != xv_end) {
cvm::real const cosine = (xvi++)->quaternion_value.cosine(x.quaternion_value);
*(ii++) += 1.5*cosine*cosine - 0.5;
}
break;
default:
x.undef_op();
};
}

File diff suppressed because it is too large Load Diff