Merge pull request #187 from akohlmey/colvars-update-2016-09-30

update colvars library to version 2016-09-30
This commit is contained in:
sjplimp
2016-09-30 09:21:00 -06:00
committed by GitHub
20 changed files with 728 additions and 155 deletions

View File

@ -150,7 +150,7 @@ colvar::colvar(std::string const &conf)
feature_states[f_cv_linear]->enabled = lin; feature_states[f_cv_linear]->enabled = lin;
} }
// Colvar is homogeneous iff: // Colvar is homogeneous if:
// - it is linear (hence not scripted) // - it is linear (hence not scripted)
// - all cvcs have coefficient 1 or -1 // - all cvcs have coefficient 1 or -1
// i.e. sum or difference of cvcs // i.e. sum or difference of cvcs
@ -375,28 +375,16 @@ colvar::colvar(std::string const &conf)
{ {
bool temp; bool temp;
if (get_keyval(conf, "outputSystemForce", temp, false)) { if (get_keyval(conf, "outputSystemForce", temp, false, colvarparse::parse_silent)) {
cvm::error("Colvar option outputSystemForce is deprecated.\n" cvm::error("Option outputSystemForce is deprecated: only outputTotalForce is supported instead.\n"
"Please use outputTotalForce, or outputSystemForce within an ABF bias."); "The two are NOT identical: see http://colvars.github.io/totalforce.html.\n", INPUT_ERROR);
return; return;
} }
} }
{ get_keyval_feature(this, conf, "outputTotalForce", f_cv_output_total_force, false);
bool b_output_total_force; get_keyval_feature(this, conf, "outputAppliedForce", f_cv_output_applied_force, false);
get_keyval(conf, "outputTotalForce", b_output_total_force, false); get_keyval_feature(this, conf, "subtractAppliedForce", f_cv_subtract_applied_force, false);
if (b_output_total_force) {
enable(f_cv_output_total_force);
}
}
{
bool b_output_applied_force;
get_keyval(conf, "outputAppliedForce", b_output_applied_force, false);
if (b_output_applied_force) {
enable(f_cv_output_applied_force);
}
}
// Start in active state by default // Start in active state by default
enable(f_cv_active); enable(f_cv_active);
@ -409,6 +397,8 @@ colvar::colvar(std::string const &conf)
fj.type(value()); fj.type(value());
ft.type(value()); ft.type(value());
ft_reported.type(value()); ft_reported.type(value());
f_old.type(value());
f_old.reset();
if (cvm::b_analysis) if (cvm::b_analysis)
parse_analysis(conf); parse_analysis(conf);
@ -519,6 +509,8 @@ int colvar::init_components(std::string const &conf)
"number", "coordNum"); "number", "coordNum");
error_code |= init_components_type<selfcoordnum>(conf, "self-coordination " error_code |= init_components_type<selfcoordnum>(conf, "self-coordination "
"number", "selfCoordNum"); "number", "selfCoordNum");
error_code |= init_components_type<groupcoordnum>(conf, "group-coordination "
"number", "groupCoord");
error_code |= init_components_type<angle>(conf, "angle", "angle"); error_code |= init_components_type<angle>(conf, "angle", "angle");
error_code |= init_components_type<dipole_angle>(conf, "dipole angle", "dipoleAngle"); error_code |= init_components_type<dipole_angle>(conf, "dipole angle", "dipoleAngle");
error_code |= init_components_type<dihedral>(conf, "dihedral", "dihedral"); error_code |= init_components_type<dihedral>(conf, "dihedral", "dihedral");
@ -1104,6 +1096,14 @@ int colvar::calc_colvar_properties()
} else { } else {
if (is_enabled(f_cv_subtract_applied_force)) {
// correct the total force only if it has been measured
// TODO add a specific test instead of relying on sq norm
if (ft.norm2() > 0.0) {
ft -= f_old;
}
}
x_reported = x; x_reported = x;
ft_reported = ft; ft_reported = ft;
} }
@ -1210,6 +1210,10 @@ cvm::real colvar::update_forces_energy()
x_old = x; x_old = x;
} }
if (is_enabled(f_cv_subtract_applied_force)) {
f_old = f;
}
if (cvm::debug()) if (cvm::debug())
cvm::log("Done updating colvar \""+this->name+"\".\n"); cvm::log("Done updating colvar \""+this->name+"\".\n");
return (potential_energy + kinetic_energy); return (potential_energy + kinetic_energy);
@ -1640,15 +1644,9 @@ std::ostream & colvar::write_traj(std::ostream &os)
} }
if (is_enabled(f_cv_output_applied_force)) { if (is_enabled(f_cv_output_applied_force)) {
if (is_enabled(f_cv_extended_Lagrangian)) { os << " "
os << " " << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
<< std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width) << applied_force();
<< fr;
} else {
os << " "
<< std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
<< f;
}
} }
return os; return os;

View File

@ -175,6 +175,9 @@ public:
/// (if defined) contribute to it /// (if defined) contribute to it
colvarvalue f; colvarvalue f;
/// Applied force at the previous step (to be subtracted from total force if needed)
colvarvalue f_old;
/// \brief Total force, as derived from the atomic trajectory; /// \brief Total force, as derived from the atomic trajectory;
/// should equal the system force plus \link f \endlink /// should equal the system force plus \link f \endlink
colvarvalue ft; colvarvalue ft;
@ -272,10 +275,13 @@ public:
/// \brief Calculate the quantities associated to the colvar (but not to the CVCs) /// \brief Calculate the quantities associated to the colvar (but not to the CVCs)
int calc_colvar_properties(); int calc_colvar_properties();
/// Get the current biasing force /// Get the current applied force
inline colvarvalue bias_force() const inline colvarvalue const applied_force() const
{ {
return fb; if (is_enabled(f_cv_extended_Lagrangian)) {
return fr;
}
return f;
} }
/// Set the total biasing force to zero /// Set the total biasing force to zero
@ -482,6 +488,7 @@ public:
class dihedral; class dihedral;
class coordnum; class coordnum;
class selfcoordnum; class selfcoordnum;
class groupcoordnum;
class h_bond; class h_bond;
class rmsd; class rmsd;
class orientation_angle; class orientation_angle;

View File

@ -67,7 +67,7 @@ int colvarbias_histogram::init(std::string const &conf)
if (colvar_array_size > 0) { if (colvar_array_size > 0) {
weights.assign(colvar_array_size, 1.0); weights.assign(colvar_array_size, 1.0);
get_keyval(conf, "weights", weights, weights, colvarparse::parse_silent); get_keyval(conf, "weights", weights, weights);
} }
for (i = 0; i < colvars.size(); i++) { for (i = 0; i < colvars.size(); i++) {
@ -79,7 +79,7 @@ int colvarbias_histogram::init(std::string const &conf)
{ {
std::string grid_conf; std::string grid_conf;
if (key_lookup(conf, "grid", grid_conf)) { if (key_lookup(conf, "histogramGrid", grid_conf)) {
grid->parse_params(grid_conf); grid->parse_params(grid_conf);
} }
} }

View File

@ -92,7 +92,11 @@ int colvarbias_meta::init(std::string const &conf)
get_keyval(conf, "keepHills", keep_hills, false); get_keyval(conf, "keepHills", keep_hills, false);
if (! get_keyval(conf, "writeFreeEnergyFile", dump_fes, true)) if (! get_keyval(conf, "writeFreeEnergyFile", dump_fes, true))
get_keyval(conf, "dumpFreeEnergyFile", dump_fes, true, colvarparse::parse_silent); get_keyval(conf, "dumpFreeEnergyFile", dump_fes, true, colvarparse::parse_silent);
get_keyval(conf, "saveFreeEnergyFile", dump_fes_save, false); if (get_keyval(conf, "saveFreeEnergyFile", dump_fes_save, false, colvarparse::parse_silent)) {
cvm::log("Option \"saveFreeEnergyFile\" is deprecated, "
"please use \"keepFreeEnergyFiles\" instead.");
}
get_keyval(conf, "keepFreeEnergyFiles", dump_fes_save, dump_fes_save);
hills_energy = new colvar_grid_scalar(colvars); hills_energy = new colvar_grid_scalar(colvars);
hills_energy_gradients = new colvar_grid_gradient(colvars); hills_energy_gradients = new colvar_grid_gradient(colvars);

View File

@ -612,3 +612,250 @@ cvm::real colvarbias_restraint_linear::restraint_convert_k(cvm::real k,
colvarbias_restraint_histogram::colvarbias_restraint_histogram(char const *key)
: colvarbias(key)
{
lower_boundary = 0.0;
upper_boundary = 0.0;
width = 0.0;
gaussian_width = 0.0;
}
int colvarbias_restraint_histogram::init(std::string const &conf)
{
colvarbias::init(conf);
get_keyval(conf, "lowerBoundary", lower_boundary, lower_boundary);
get_keyval(conf, "upperBoundary", upper_boundary, upper_boundary);
get_keyval(conf, "width", width, width);
if (width <= 0.0) {
cvm::error("Error: \"width\" must be positive.\n", INPUT_ERROR);
}
get_keyval(conf, "gaussianWidth", gaussian_width, 2.0 * width, colvarparse::parse_silent);
get_keyval(conf, "gaussianSigma", gaussian_width, 2.0 * width);
if (lower_boundary >= upper_boundary) {
cvm::error("Error: the upper boundary, "+
cvm::to_str(upper_boundary)+
", is not higher than the lower boundary, "+
cvm::to_str(lower_boundary)+".\n",
INPUT_ERROR);
}
cvm::real const nbins = (upper_boundary - lower_boundary) / width;
int const nbins_round = (int)(nbins);
if (std::fabs(nbins - cvm::real(nbins_round)) > 1.0E-10) {
cvm::log("Warning: grid interval ("+
cvm::to_str(lower_boundary, cvm::cv_width, cvm::cv_prec)+" - "+
cvm::to_str(upper_boundary, cvm::cv_width, cvm::cv_prec)+
") is not commensurate to its bin width ("+
cvm::to_str(width, cvm::cv_width, cvm::cv_prec)+").\n");
}
p.resize(nbins_round);
ref_p.resize(nbins_round);
p_diff.resize(nbins_round);
bool const inline_ref_p =
get_keyval(conf, "refHistogram", ref_p.data_array(), ref_p.data_array());
std::string ref_p_file;
get_keyval(conf, "refHistogramFile", ref_p_file, std::string(""));
if (ref_p_file.size()) {
if (inline_ref_p) {
cvm::error("Error: cannot specify both refHistogram and refHistogramFile at the same time.\n",
INPUT_ERROR);
} else {
std::ifstream is(ref_p_file.c_str());
std::string data_s = "";
std::string line;
while (getline_nocomments(is, line)) {
data_s.append(line+"\n");
}
if (data_s.size() == 0) {
cvm::error("Error: file \""+ref_p_file+"\" empty or unreadable.\n", FILE_ERROR);
}
is.close();
cvm::vector1d<cvm::real> data;
if (data.from_simple_string(data_s) != 0) {
cvm::error("Error: could not read histogram from file \""+ref_p_file+"\".\n");
}
if (data.size() == 2*ref_p.size()) {
// file contains both x and p(x)
size_t i;
for (i = 0; i < ref_p.size(); i++) {
ref_p[i] = data[2*i+1];
}
} else if (data.size() == ref_p.size()) {
ref_p = data;
} else {
cvm::error("Error: file \""+ref_p_file+"\" contains a histogram of different length.\n",
INPUT_ERROR);
}
}
}
cvm::real const ref_integral = ref_p.sum() * width;
if (std::fabs(ref_integral - 1.0) > 1.0e-03) {
cvm::log("Reference distribution not normalized, normalizing to unity.\n");
ref_p /= ref_integral;
}
get_keyval(conf, "writeHistogram", b_write_histogram, false);
get_keyval(conf, "forceConstant", force_k, 1.0);
return COLVARS_OK;
}
colvarbias_restraint_histogram::~colvarbias_restraint_histogram()
{
p.resize(0);
ref_p.resize(0);
p_diff.resize(0);
}
int colvarbias_restraint_histogram::update()
{
if (cvm::debug())
cvm::log("Updating the histogram restraint bias \""+this->name+"\".\n");
size_t vector_size = 0;
size_t icv;
for (icv = 0; icv < colvars.size(); icv++) {
vector_size += colvars[icv]->value().size();
}
cvm::real const norm = 1.0/(std::sqrt(2.0*PI)*gaussian_width*vector_size);
// calculate the histogram
p.reset();
for (icv = 0; icv < colvars.size(); icv++) {
colvarvalue const &cv = colvars[icv]->value();
if (cv.type() == colvarvalue::type_scalar) {
cvm::real const cv_value = cv.real_value;
size_t igrid;
for (igrid = 0; igrid < p.size(); igrid++) {
cvm::real const x_grid = (lower_boundary + (igrid+0.5)*width);
p[igrid] += norm * std::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
(2.0 * gaussian_width * gaussian_width));
}
} else if (cv.type() == colvarvalue::type_vector) {
size_t idim;
for (idim = 0; idim < cv.vector1d_value.size(); idim++) {
cvm::real const cv_value = cv.vector1d_value[idim];
size_t igrid;
for (igrid = 0; igrid < p.size(); igrid++) {
cvm::real const x_grid = (lower_boundary + (igrid+0.5)*width);
p[igrid] += norm * std::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
(2.0 * gaussian_width * gaussian_width));
}
}
} else {
// TODO
}
}
cvm::real const force_k_cv = force_k * vector_size;
// calculate the difference between current and reference
p_diff = p - ref_p;
bias_energy = 0.5 * force_k_cv * p_diff * p_diff;
// calculate the forces
for (icv = 0; icv < colvars.size(); icv++) {
colvarvalue const &cv = colvars[icv]->value();
colvarvalue &cv_force = colvar_forces[icv];
cv_force.type(cv);
cv_force.reset();
if (cv.type() == colvarvalue::type_scalar) {
cvm::real const cv_value = cv.real_value;
cvm::real &force = cv_force.real_value;
size_t igrid;
for (igrid = 0; igrid < p.size(); igrid++) {
cvm::real const x_grid = (lower_boundary + (igrid+0.5)*width);
force += force_k_cv * p_diff[igrid] *
norm * std::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
(2.0 * gaussian_width * gaussian_width)) *
(-1.0 * (x_grid - cv_value) / (gaussian_width * gaussian_width));
}
} else if (cv.type() == colvarvalue::type_vector) {
size_t idim;
for (idim = 0; idim < cv.vector1d_value.size(); idim++) {
cvm::real const cv_value = cv.vector1d_value[idim];
cvm::real &force = cv_force.vector1d_value[idim];
size_t igrid;
for (igrid = 0; igrid < p.size(); igrid++) {
cvm::real const x_grid = (lower_boundary + (igrid+0.5)*width);
force += force_k_cv * p_diff[igrid] *
norm * std::exp(-1.0 * (x_grid - cv_value) * (x_grid - cv_value) /
(2.0 * gaussian_width * gaussian_width)) *
(-1.0 * (x_grid - cv_value) / (gaussian_width * gaussian_width));
}
}
} else {
// TODO
}
}
return COLVARS_OK;
}
std::ostream & colvarbias_restraint_histogram::write_restart(std::ostream &os)
{
if (b_write_histogram) {
std::string file_name(cvm::output_prefix+"."+this->name+".hist.dat");
std::ofstream os(file_name.c_str());
os << "# " << cvm::wrap_string(colvars[0]->name, cvm::cv_width)
<< " " << "p(" << cvm::wrap_string(colvars[0]->name, cvm::cv_width-3)
<< ")\n";
size_t igrid;
for (igrid = 0; igrid < p.size(); igrid++) {
cvm::real const x_grid = (lower_boundary + (igrid+1)*width);
os << " "
<< std::setprecision(cvm::cv_prec)
<< std::setw(cvm::cv_width)
<< x_grid
<< " "
<< std::setprecision(cvm::cv_prec)
<< std::setw(cvm::cv_width)
<< p[igrid] << "\n";
}
os.close();
}
return os;
}
std::istream & colvarbias_restraint_histogram::read_restart(std::istream &is)
{
return is;
}
std::ostream & colvarbias_restraint_histogram::write_traj_label(std::ostream &os)
{
os << " ";
if (b_output_energy) {
os << " E_"
<< cvm::wrap_string(this->name, cvm::en_width-2);
}
return os;
}
std::ostream & colvarbias_restraint_histogram::write_traj(std::ostream &os)
{
os << " ";
if (b_output_energy) {
os << " "
<< std::setprecision(cvm::en_prec) << std::setw(cvm::en_width)
<< bias_energy;
}
return os;
}

View File

@ -168,4 +168,52 @@ protected:
}; };
/// Restrain the 1D histogram of a set of variables (or of a multidimensional one)
// TODO this could be reimplemented more cleanly as a derived class of both restraint and histogram
class colvarbias_restraint_histogram : public colvarbias {
public:
colvarbias_restraint_histogram(char const *key);
int init(std::string const &conf);
~colvarbias_restraint_histogram();
virtual int update();
virtual std::istream & read_restart(std::istream &is);
virtual std::ostream & write_restart(std::ostream &os);
virtual std::ostream & write_traj_label(std::ostream &os);
virtual std::ostream & write_traj(std::ostream &os);
protected:
/// Probability density
cvm::vector1d<cvm::real> p;
/// Reference probability density
cvm::vector1d<cvm::real> ref_p;
/// Difference between probability density and reference
cvm::vector1d<cvm::real> p_diff;
/// Lower boundary of the grid
cvm::real lower_boundary;
/// Upper boundary of the grid
cvm::real upper_boundary;
/// Resolution of the grid
cvm::real width;
/// Width of the Gaussians
cvm::real gaussian_width;
/// Restraint force constant
cvm::real force_k;
/// Write the histogram to a file
bool b_write_histogram;
};
#endif #endif

View File

@ -54,6 +54,21 @@ colvar::cvc::cvc(std::string const &conf)
} }
int colvar::cvc::init_total_force_params(std::string const &conf)
{
if (get_keyval_feature(this, conf, "oneSiteSystemForce",
f_cvc_one_site_total_force, is_enabled(f_cvc_one_site_total_force))) {
cvm::log("Warning: keyword \"oneSiteSystemForce\" is deprecated: "
"please use \"oneSiteTotalForce\" instead.\n");
}
if (get_keyval_feature(this, conf, "oneSiteTotalForce",
f_cvc_one_site_total_force, is_enabled(f_cvc_one_site_total_force))) {
cvm::log("Computing total force on group 1 only");
}
return COLVARS_OK;
}
cvm::atom_group *colvar::cvc::parse_group(std::string const &conf, cvm::atom_group *colvar::cvc::parse_group(std::string const &conf,
char const *group_key, char const *group_key,
bool optional) bool optional)
@ -77,8 +92,6 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf,
if (is_enabled(f_cvc_scalable)) { if (is_enabled(f_cvc_scalable)) {
cvm::log("Will enable scalable calculation for group \""+group->key+"\".\n"); cvm::log("Will enable scalable calculation for group \""+group->key+"\".\n");
} else {
cvm::log("Scalable calculation is not available for group \""+group->key+"\" with the current configuration.\n");
} }
} }

View File

@ -108,6 +108,9 @@ public:
char const *group_key, char const *group_key,
bool optional = false); bool optional = false);
/// \brief Parse options pertaining to total force calculation
virtual int init_total_force_params(std::string const &conf);
/// \brief After construction, set data related to dependency handling /// \brief After construction, set data related to dependency handling
int setup(); int setup();
@ -306,9 +309,6 @@ protected:
cvm::rvector dist_v; cvm::rvector dist_v;
/// Use absolute positions, ignoring PBCs when present /// Use absolute positions, ignoring PBCs when present
bool b_no_PBC; bool b_no_PBC;
/// Compute total force on first site only to avoid unwanted
/// coupling to other colvars (see e.g. Ciccotti et al., 2005)
bool b_1site_force;
public: public:
distance(std::string const &conf); distance(std::string const &conf);
distance(); distance();
@ -388,9 +388,6 @@ protected:
cvm::atom_group *ref2; cvm::atom_group *ref2;
/// Use absolute positions, ignoring PBCs when present /// Use absolute positions, ignoring PBCs when present
bool b_no_PBC; bool b_no_PBC;
/// Compute total force on one site only to avoid unwanted
/// coupling to other colvars (see e.g. Ciccotti et al., 2005)
bool b_1site_force;
/// Vector on which the distance vector is projected /// Vector on which the distance vector is projected
cvm::rvector axis; cvm::rvector axis;
/// Norm of the axis /// Norm of the axis
@ -854,6 +851,62 @@ public:
colvarvalue const &x2) const; colvarvalue const &x2) const;
}; };
/// \brief Colvar component: coordination number between two groups
/// (colvarvalue::type_scalar type, range [0:N1*N2])
class colvar::groupcoordnum
: public colvar::distance
{
protected:
/// \brief "Cutoff" for isotropic calculation (default)
cvm::real r0;
/// \brief "Cutoff vector" for anisotropic calculation
cvm::rvector r0_vec;
/// \brief Wheter dist/r0 or \vec{dist}*\vec{1/r0_vec} should ne be
/// used
bool b_anisotropic;
/// Integer exponent of the function numerator
int en;
/// Integer exponent of the function denominator
int ed;
public:
/// Constructor
groupcoordnum(std::string const &conf);
groupcoordnum();
virtual inline ~groupcoordnum() {}
virtual void calc_value();
virtual void calc_gradients();
virtual void apply_force(colvarvalue const &force);
template<bool b_gradients>
/// \brief Calculate a coordination number through the function
/// (1-x**n)/(1-x**m), x = |A1-A2|/r0 \param r0 "cutoff" for the
/// coordination number \param exp_num \i n exponent \param exp_den
/// \i m exponent \param A1 atom \param A2 atom
static cvm::real switching_function(cvm::real const &r0,
int const &exp_num, int const &exp_den,
cvm::atom &A1, cvm::atom &A2);
/*
template<bool b_gradients>
/// \brief Calculate a coordination number through the function
/// (1-x**n)/(1-x**m), x = |(A1-A2)*(r0_vec)^-|1 \param r0_vec
/// vector of different cutoffs in the three directions \param
/// exp_num \i n exponent \param exp_den \i m exponent \param A1
/// atom \param A2 atom
static cvm::real switching_function(cvm::rvector const &r0_vec,
int const &exp_num, int const &exp_den,
cvm::atom &A1, cvm::atom &A2);
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: hydrogen bond, defined as the product of /// \brief Colvar component: hydrogen bond, defined as the product of
/// a colvar::coordnum and 1/2*(1-cos((180-ang)/ang_tol)) /// a colvar::coordnum and 1/2*(1-cos((180-ang)/ang_tol))
/// (colvarvalue::type_scalar type, range [0:1]) /// (colvarvalue::type_scalar type, range [0:1])

View File

@ -18,9 +18,9 @@ colvar::angle::angle(std::string const &conf)
group1 = parse_group(conf, "group1"); group1 = parse_group(conf, "group1");
group2 = parse_group(conf, "group2"); group2 = parse_group(conf, "group2");
group3 = parse_group(conf, "group3"); group3 = parse_group(conf, "group3");
if (get_keyval(conf, "oneSiteSystemForce", b_1site_force, false)) {
cvm::log("Computing total force on group 1 only"); init_total_force_params(conf);
}
x.type(colvarvalue::type_scalar); x.type(colvarvalue::type_scalar);
} }
@ -33,7 +33,6 @@ colvar::angle::angle(cvm::atom const &a1,
provide(f_cvc_inv_gradient); provide(f_cvc_inv_gradient);
provide(f_cvc_Jacobian); provide(f_cvc_Jacobian);
provide(f_cvc_com_based); provide(f_cvc_com_based);
b_1site_force = false;
group1 = new cvm::atom_group(std::vector<cvm::atom>(1, a1)); group1 = new cvm::atom_group(std::vector<cvm::atom>(1, a1));
group2 = new cvm::atom_group(std::vector<cvm::atom>(1, a2)); group2 = new cvm::atom_group(std::vector<cvm::atom>(1, a2));
@ -94,7 +93,7 @@ void colvar::angle::calc_force_invgrads()
// centered on group2, which means group2 is kept fixed // centered on group2, which means group2 is kept fixed
// when propagating changes in the angle) // when propagating changes in the angle)
if (b_1site_force) { if (is_enabled(f_cvc_one_site_total_force)) {
group1->read_total_forces(); group1->read_total_forces();
cvm::real norm_fact = 1.0 / dxdr1.norm2(); cvm::real norm_fact = 1.0 / dxdr1.norm2();
ft.real_value = norm_fact * dxdr1 * group1->total_force(); ft.real_value = norm_fact * dxdr1 * group1->total_force();
@ -140,9 +139,8 @@ colvar::dipole_angle::dipole_angle(std::string const &conf)
group2 = parse_group(conf, "group2"); group2 = parse_group(conf, "group2");
group3 = parse_group(conf, "group3"); group3 = parse_group(conf, "group3");
if (get_keyval(conf, "oneSiteSystemForce", b_1site_force, false)) { init_total_force_params(conf);
cvm::log("Computing total force on group 1 only");
}
x.type(colvarvalue::type_scalar); x.type(colvarvalue::type_scalar);
} }
@ -152,7 +150,6 @@ colvar::dipole_angle::dipole_angle(cvm::atom const &a1,
cvm::atom const &a3) cvm::atom const &a3)
{ {
function_type = "dipole_angle"; function_type = "dipole_angle";
b_1site_force = false;
group1 = new cvm::atom_group(std::vector<cvm::atom>(1, a1)); group1 = new cvm::atom_group(std::vector<cvm::atom>(1, a1));
group2 = new cvm::atom_group(std::vector<cvm::atom>(1, a2)); group2 = new cvm::atom_group(std::vector<cvm::atom>(1, a2));
@ -250,14 +247,13 @@ colvar::dihedral::dihedral(std::string const &conf)
provide(f_cvc_Jacobian); provide(f_cvc_Jacobian);
provide(f_cvc_com_based); provide(f_cvc_com_based);
if (get_keyval(conf, "oneSiteSystemForce", b_1site_force, false)) {
cvm::log("Computing total force on group 1 only");
}
group1 = parse_group(conf, "group1"); group1 = parse_group(conf, "group1");
group2 = parse_group(conf, "group2"); group2 = parse_group(conf, "group2");
group3 = parse_group(conf, "group3"); group3 = parse_group(conf, "group3");
group4 = parse_group(conf, "group4"); group4 = parse_group(conf, "group4");
init_total_force_params(conf);
x.type(colvarvalue::type_scalar); x.type(colvarvalue::type_scalar);
} }
@ -422,7 +418,7 @@ void colvar::dihedral::calc_force_invgrads()
cvm::real const fact4 = d34 * std::sqrt(1.0 - dot4 * dot4); cvm::real const fact4 = d34 * std::sqrt(1.0 - dot4 * dot4);
group1->read_total_forces(); group1->read_total_forces();
if ( b_1site_force ) { if (is_enabled(f_cvc_one_site_total_force)) {
// This is only measuring the force on group 1 // This is only measuring the force on group 1
ft.real_value = PI/180.0 * fact1 * (cross1 * group1->total_force()); ft.real_value = PI/180.0 * fact1 * (cross1 * group1->total_force());
} else { } else {

View File

@ -338,3 +338,151 @@ void colvar::selfcoordnum::apply_force(colvarvalue const &force)
} }
} }
// groupcoordnum member functions
colvar::groupcoordnum::groupcoordnum(std::string const &conf)
: distance(conf), b_anisotropic(false)
{
function_type = "groupcoordnum";
x.type(colvarvalue::type_scalar);
// group1 and group2 are already initialized by distance()
if (group1->b_dummy || group2->b_dummy)
cvm::fatal_error("Error: neither group can be a dummy atom\n");
bool const b_scale = get_keyval(conf, "cutoff", r0,
cvm::real(4.0 * cvm::unit_angstrom()));
if (get_keyval(conf, "cutoff3", r0_vec,
cvm::rvector(4.0, 4.0, 4.0), parse_silent)) {
if (b_scale)
cvm::fatal_error("Error: cannot specify \"scale\" and "
"\"scale3\" at the same time.\n");
b_anisotropic = true;
// remove meaningless negative signs
if (r0_vec.x < 0.0) r0_vec.x *= -1.0;
if (r0_vec.y < 0.0) r0_vec.y *= -1.0;
if (r0_vec.z < 0.0) r0_vec.z *= -1.0;
}
get_keyval(conf, "expNumer", en, int(6) );
get_keyval(conf, "expDenom", ed, int(12));
if ( (en%2) || (ed%2) ) {
cvm::fatal_error("Error: odd exponents provided, can only use even ones.\n");
}
}
colvar::groupcoordnum::groupcoordnum()
: b_anisotropic(false)
{
function_type = "groupcoordnum";
x.type(colvarvalue::type_scalar);
}
template<bool calculate_gradients>
cvm::real colvar::groupcoordnum::switching_function(cvm::real const &r0,
int const &en,
int const &ed,
cvm::atom &A1,
cvm::atom &A2)
{
cvm::rvector const diff = cvm::position_distance(A1.pos, A2.pos);
cvm::real const l2 = diff.norm2()/(r0*r0);
// Assume en and ed are even integers, and avoid sqrt in the following
int const en2 = en/2;
int const ed2 = ed/2;
cvm::real const xn = std::pow(l2, en2);
cvm::real const xd = std::pow(l2, ed2);
cvm::real const func = (1.0-xn)/(1.0-xd);
if (calculate_gradients) {
cvm::real const dFdl2 = (1.0/(1.0-xd))*(en2*(xn/l2) - func*ed2*(xd/l2))*(-1.0);
cvm::rvector const dl2dx = (2.0/(r0*r0))*diff;
A1.grad += (-1.0)*dFdl2*dl2dx;
A2.grad += dFdl2*dl2dx;
}
return func;
}
#if 0 // AMG: I don't think there's any reason to support anisotropic,
// and I don't have those flags below in calc_value, but
// if I need them, I'll also need to uncomment this method
template<bool calculate_gradients>
cvm::real colvar::groupcoordnum::switching_function(cvm::rvector const &r0_vec,
int const &en,
int const &ed,
cvm::atom &A1,
cvm::atom &A2)
{
cvm::rvector const diff = cvm::position_distance(A1.pos, A2.pos);
cvm::rvector const scal_diff(diff.x/r0_vec.x, diff.y/r0_vec.y, diff.z/r0_vec.z);
cvm::real const l2 = scal_diff.norm2();
// Assume en and ed are even integers, and avoid sqrt in the following
int const en2 = en/2;
int const ed2 = ed/2;
cvm::real const xn = std::pow(l2, en2);
cvm::real const xd = std::pow(l2, ed2);
cvm::real const func = (1.0-xn)/(1.0-xd);
if (calculate_gradients) {
cvm::real const dFdl2 = (1.0/(1.0-xd))*(en2*(xn/l2) - func*ed2*(xd/l2))*(-1.0);
cvm::rvector const dl2dx((2.0/(r0_vec.x*r0_vec.x))*diff.x,
(2.0/(r0_vec.y*r0_vec.y))*diff.y,
(2.0/(r0_vec.z*r0_vec.z))*diff.z);
A1.grad += (-1.0)*dFdl2*dl2dx;
A2.grad += dFdl2*dl2dx;
}
return func;
}
#endif
void colvar::groupcoordnum::calc_value()
{
// create fake atoms to hold the com coordinates
cvm::atom group1_com_atom;
cvm::atom group2_com_atom;
group1_com_atom.pos = group1->center_of_mass();
group2_com_atom.pos = group2->center_of_mass();
x.real_value = coordnum::switching_function<false>(r0, en, ed,
group1_com_atom, group2_com_atom);
}
void colvar::groupcoordnum::calc_gradients()
{
cvm::atom group1_com_atom;
cvm::atom group2_com_atom;
group1_com_atom.pos = group1->center_of_mass();
group2_com_atom.pos = group2->center_of_mass();
coordnum::switching_function<true>(r0, en, ed, group1_com_atom, group2_com_atom);
group1->set_weighted_gradient(group1_com_atom.grad);
group2->set_weighted_gradient(group2_com_atom.grad);
}
void colvar::groupcoordnum::apply_force(colvarvalue const &force)
{
if (!group1->noforce)
group1->apply_colvar_force(force.real_value);
if (!group2->noforce)
group2->apply_colvar_force(force.real_value);
}

View File

@ -18,14 +18,14 @@ colvar::distance::distance(std::string const &conf)
provide(f_cvc_Jacobian); provide(f_cvc_Jacobian);
provide(f_cvc_com_based); provide(f_cvc_com_based);
group1 = parse_group(conf, "group1");
group2 = parse_group(conf, "group2");
if (get_keyval(conf, "forceNoPBC", b_no_PBC, false)) { if (get_keyval(conf, "forceNoPBC", b_no_PBC, false)) {
cvm::log("Computing distance using absolute positions (not minimal-image)"); cvm::log("Computing distance using absolute positions (not minimal-image)");
} }
if (get_keyval(conf, "oneSiteSystemForce", b_1site_force, false)) {
cvm::log("Computing total force on group 1 only"); init_total_force_params(conf);
}
group1 = parse_group(conf, "group1");
group2 = parse_group(conf, "group2");
x.type(colvarvalue::type_scalar); x.type(colvarvalue::type_scalar);
} }
@ -38,7 +38,6 @@ colvar::distance::distance()
provide(f_cvc_inv_gradient); provide(f_cvc_inv_gradient);
provide(f_cvc_Jacobian); provide(f_cvc_Jacobian);
provide(f_cvc_com_based); provide(f_cvc_com_based);
b_1site_force = false;
b_no_PBC = false; b_no_PBC = false;
x.type(colvarvalue::type_scalar); x.type(colvarvalue::type_scalar);
} }
@ -67,7 +66,7 @@ void colvar::distance::calc_gradients()
void colvar::distance::calc_force_invgrads() void colvar::distance::calc_force_invgrads()
{ {
group1->read_total_forces(); group1->read_total_forces();
if ( b_1site_force ) { if (is_enabled(f_cvc_one_site_total_force)) {
ft.real_value = -1.0 * (group1->total_force() * dist_v.unit()); ft.real_value = -1.0 * (group1->total_force() * dist_v.unit());
} else { } else {
group2->read_total_forces(); group2->read_total_forces();
@ -97,6 +96,7 @@ colvar::distance_vec::distance_vec(std::string const &conf)
: distance(conf) : distance(conf)
{ {
function_type = "distance_vec"; function_type = "distance_vec";
provide(f_cvc_com_based);
x.type(colvarvalue::type_3vector); x.type(colvarvalue::type_3vector);
} }
@ -105,6 +105,7 @@ colvar::distance_vec::distance_vec()
: distance() : distance()
{ {
function_type = "distance_vec"; function_type = "distance_vec";
provide(f_cvc_com_based);
x.type(colvarvalue::type_3vector); x.type(colvarvalue::type_3vector);
} }
@ -185,9 +186,9 @@ colvar::distance_z::distance_z(std::string const &conf)
if (get_keyval(conf, "forceNoPBC", b_no_PBC, false)) { if (get_keyval(conf, "forceNoPBC", b_no_PBC, false)) {
cvm::log("Computing distance using absolute positions (not minimal-image)"); cvm::log("Computing distance using absolute positions (not minimal-image)");
} }
if (get_keyval(conf, "oneSiteSystemForce", b_1site_force, false)) {
cvm::log("Computing total force on group \"main\" only"); init_total_force_params(conf);
}
} }
colvar::distance_z::distance_z() colvar::distance_z::distance_z()
@ -251,7 +252,7 @@ void colvar::distance_z::calc_force_invgrads()
{ {
main->read_total_forces(); main->read_total_forces();
if (fixed_axis && !b_1site_force) { if (fixed_axis && !is_enabled(f_cvc_one_site_total_force)) {
ref1->read_total_forces(); ref1->read_total_forces();
ft.real_value = 0.5 * ((main->total_force() - ref1->total_force()) * axis); ft.real_value = 0.5 * ((main->total_force() - ref1->total_force()) * axis);
} else { } else {
@ -351,7 +352,7 @@ void colvar::distance_xy::calc_force_invgrads()
{ {
main->read_total_forces(); main->read_total_forces();
if (fixed_axis && !b_1site_force) { if (fixed_axis && !is_enabled(f_cvc_one_site_total_force)) {
ref1->read_total_forces(); ref1->read_total_forces();
ft.real_value = 0.5 / x.real_value * ((main->total_force() - ref1->total_force()) * dist_v_ortho); ft.real_value = 0.5 / x.real_value * ((main->total_force() - ref1->total_force()) * dist_v_ortho);
} else { } else {
@ -382,6 +383,7 @@ colvar::distance_dir::distance_dir(std::string const &conf)
: distance(conf) : distance(conf)
{ {
function_type = "distance_dir"; function_type = "distance_dir";
provide(f_cvc_com_based);
x.type(colvarvalue::type_unit3vector); x.type(colvarvalue::type_unit3vector);
} }
@ -390,6 +392,7 @@ colvar::distance_dir::distance_dir()
: distance() : distance()
{ {
function_type = "distance_dir"; function_type = "distance_dir";
provide(f_cvc_com_based);
x.type(colvarvalue::type_unit3vector); x.type(colvarvalue::type_unit3vector);
} }
@ -461,7 +464,6 @@ colvar::distance_inv::distance_inv()
{ {
function_type = "distance_inv"; function_type = "distance_inv";
exponent = 6; exponent = 6;
b_1site_force = false;
x.type(colvarvalue::type_scalar); x.type(colvarvalue::type_scalar);
} }

View File

@ -293,6 +293,9 @@ void colvardeps::init_cv_requires() {
f_description(f_cv_output_total_force, "output total force"); f_description(f_cv_output_total_force, "output total force");
f_req_self(f_cv_output_total_force, f_cv_total_force); f_req_self(f_cv_output_total_force, f_cv_total_force);
f_description(f_cv_subtract_applied_force, "subtract applied force from total force");
f_req_self(f_cv_subtract_applied_force, f_cv_total_force);
f_description(f_cv_lower_boundary, "lower boundary"); f_description(f_cv_lower_boundary, "lower boundary");
f_req_self(f_cv_lower_boundary, f_cv_scalar); f_req_self(f_cv_lower_boundary, f_cv_scalar);
@ -376,6 +379,11 @@ void colvardeps::init_cvc_requires() {
f_description(f_cvc_com_based, "depends on group centers of mass"); f_description(f_cvc_com_based, "depends on group centers of mass");
// Compute total force on first site only to avoid unwanted
// coupling to other colvars (see e.g. Ciccotti et al., 2005)
f_description(f_cvc_one_site_total_force, "compute total collective force only from one group center");
f_req_self(f_cvc_one_site_total_force, f_cvc_com_based);
f_description(f_cvc_scalable, "scalable calculation"); f_description(f_cvc_scalable, "scalable calculation");
f_req_self(f_cvc_scalable, f_cvc_scalable_com); f_req_self(f_cvc_scalable, f_cvc_scalable_com);

View File

@ -176,6 +176,8 @@ public:
f_cv_total_force, f_cv_total_force,
/// \brief Calculate total force from atomic forces /// \brief Calculate total force from atomic forces
f_cv_total_force_calc, f_cv_total_force_calc,
/// \brief Subtract the applied force from the total force
f_cv_subtract_applied_force,
/// \brief Estimate Jacobian derivative /// \brief Estimate Jacobian derivative
f_cv_Jacobian, f_cv_Jacobian,
/// \brief Do not report the Jacobian force as part of the total force /// \brief Do not report the Jacobian force as part of the total force
@ -236,6 +238,7 @@ public:
/// \brief If enabled, calc_gradients() will call debug_gradients() for every group needed /// \brief If enabled, calc_gradients() will call debug_gradients() for every group needed
f_cvc_debug_gradient, f_cvc_debug_gradient,
f_cvc_Jacobian, f_cvc_Jacobian,
f_cvc_one_site_total_force,
f_cvc_com_based, f_cvc_com_based,
f_cvc_scalable, f_cvc_scalable,
f_cvc_scalable_com, f_cvc_scalable_com,

View File

@ -382,8 +382,8 @@ public:
inline int current_bin_scalar(int const i, int const iv) const inline int current_bin_scalar(int const i, int const iv) const
{ {
return value_to_bin_scalar(actual_value[i] ? return value_to_bin_scalar(actual_value[i] ?
cv[i]->actual_value().vector1d_value[iv] : cv[i]->actual_value().vector1d_value[iv] :
cv[i]->value().vector1d_value[iv], i); cv[i]->value().vector1d_value[iv], i);
} }
/// \brief Use the lower boundary and the width to report which bin /// \brief Use the lower boundary and the width to report which bin
@ -395,8 +395,8 @@ public:
/// \brief Same as the standard version, but uses another grid definition /// \brief Same as the standard version, but uses another grid definition
inline int value_to_bin_scalar(colvarvalue const &value, inline int value_to_bin_scalar(colvarvalue const &value,
colvarvalue const &new_offset, colvarvalue const &new_offset,
cvm::real const &new_width) const cvm::real const &new_width) const
{ {
return (int) std::floor( (value.real_value - new_offset.real_value) / new_width ); return (int) std::floor( (value.real_value - new_offset.real_value) / new_width );
} }
@ -410,22 +410,22 @@ public:
/// \brief Same as the standard version, but uses different parameters /// \brief Same as the standard version, but uses different parameters
inline colvarvalue bin_to_value_scalar(int const &i_bin, inline colvarvalue bin_to_value_scalar(int const &i_bin,
colvarvalue const &new_offset, colvarvalue const &new_offset,
cvm::real const &new_width) const cvm::real const &new_width) const
{ {
return new_offset.real_value + new_width * (0.5 + i_bin); return new_offset.real_value + new_width * (0.5 + i_bin);
} }
/// Set the value at the point with index ix /// Set the value at the point with index ix
inline void set_value(std::vector<int> const &ix, inline void set_value(std::vector<int> const &ix,
T const &t, T const &t,
size_t const &imult = 0) size_t const &imult = 0)
{ {
data[this->address(ix)+imult] = t; data[this->address(ix)+imult] = t;
has_data = true; has_data = true;
} }
/// \brief Get the change from this to other_grid /// \brief Get the change from this to other_grid
/// and store the result in this. /// and store the result in this.
/// this_grid := other_grid - this_grid /// this_grid := other_grid - this_grid
/// Grids must have the same dimensions. /// Grids must have the same dimensions.
@ -434,13 +434,13 @@ public:
if (other_grid.multiplicity() != this->multiplicity()) { if (other_grid.multiplicity() != this->multiplicity()) {
cvm::error("Error: trying to subtract two grids with " cvm::error("Error: trying to subtract two grids with "
"different multiplicity.\n"); "different multiplicity.\n");
return; return;
} }
if (other_grid.data.size() != this->data.size()) { if (other_grid.data.size() != this->data.size()) {
cvm::error("Error: trying to subtract two grids with " cvm::error("Error: trying to subtract two grids with "
"different size.\n"); "different size.\n");
return; return;
} }
@ -457,13 +457,13 @@ public:
{ {
if (other_grid.multiplicity() != this->multiplicity()) { if (other_grid.multiplicity() != this->multiplicity()) {
cvm::error("Error: trying to copy two grids with " cvm::error("Error: trying to copy two grids with "
"different multiplicity.\n"); "different multiplicity.\n");
return; return;
} }
if (other_grid.data.size() != this->data.size()) { if (other_grid.data.size() != this->data.size()) {
cvm::error("Error: trying to copy two grids with " cvm::error("Error: trying to copy two grids with "
"different size.\n"); "different size.\n");
return; return;
} }
@ -493,7 +493,7 @@ public:
/// \brief Get the binned value indexed by ix, or the first of them /// \brief Get the binned value indexed by ix, or the first of them
/// if the multiplicity is larger than 1 /// if the multiplicity is larger than 1
inline T const & value(std::vector<int> const &ix, inline T const & value(std::vector<int> const &ix,
size_t const &imult = 0) const size_t const &imult = 0) const
{ {
return data[this->address(ix) + imult]; return data[this->address(ix) + imult];
} }
@ -541,7 +541,7 @@ public:
/// boundaries; a negative number is returned if the given point is /// boundaries; a negative number is returned if the given point is
/// off-grid /// off-grid
inline cvm::real bin_distance_from_boundaries(std::vector<colvarvalue> const &values, inline cvm::real bin_distance_from_boundaries(std::vector<colvarvalue> const &values,
bool skip_hard_boundaries = false) bool skip_hard_boundaries = false)
{ {
cvm::real minimum = 1.0E+16; cvm::real minimum = 1.0E+16;
for (size_t i = 0; i < nd; i++) { for (size_t i = 0; i < nd; i++) {
@ -574,7 +574,7 @@ public:
{ {
if (other_grid.multiplicity() != this->multiplicity()) { if (other_grid.multiplicity() != this->multiplicity()) {
cvm::error("Error: trying to merge two grids with values of " cvm::error("Error: trying to merge two grids with values of "
"different multiplicity.\n"); "different multiplicity.\n");
return; return;
} }
@ -593,8 +593,8 @@ public:
for (size_t i = 0; i < nd; i++) { for (size_t i = 0; i < nd; i++) {
oix[i] = oix[i] =
value_to_bin_scalar(bin_to_value_scalar(ix[i], gb[i], gw[i]), value_to_bin_scalar(bin_to_value_scalar(ix[i], gb[i], gw[i]),
ogb[i], ogb[i],
ogw[i]); ogw[i]);
} }
if (! other_grid.index_ok(oix)) { if (! other_grid.index_ok(oix)) {
@ -614,11 +614,11 @@ public:
/// \brief Add data from another grid of the same type, AND /// \brief Add data from another grid of the same type, AND
/// identical definition (boundaries, widths) /// identical definition (boundaries, widths)
void add_grid(colvar_grid<T> const &other_grid, void add_grid(colvar_grid<T> const &other_grid,
cvm::real scale_factor = 1.0) cvm::real scale_factor = 1.0)
{ {
if (other_grid.multiplicity() != this->multiplicity()) { if (other_grid.multiplicity() != this->multiplicity()) {
cvm::error("Error: trying to sum togetehr two grids with values of " cvm::error("Error: trying to sum togetehr two grids with values of "
"different multiplicity.\n"); "different multiplicity.\n");
return; return;
} }
if (scale_factor != 1.0) if (scale_factor != 1.0)
@ -636,7 +636,7 @@ public:
/// \brief Return the value suitable for output purposes (so that it /// \brief Return the value suitable for output purposes (so that it
/// may be rescaled or manipulated without changing it permanently) /// may be rescaled or manipulated without changing it permanently)
virtual inline T value_output(std::vector<int> const &ix, virtual inline T value_output(std::vector<int> const &ix,
size_t const &imult = 0) size_t const &imult = 0)
{ {
return value(ix, imult); return value(ix, imult);
} }
@ -645,9 +645,9 @@ public:
/// into the internal representation (the two may be different, /// into the internal representation (the two may be different,
/// e.g. when using colvar_grid_count) /// e.g. when using colvar_grid_count)
virtual inline void value_input(std::vector<int> const &ix, virtual inline void value_input(std::vector<int> const &ix,
T const &t, T const &t,
size_t const &imult = 0, size_t const &imult = 0,
bool add = false) bool add = false)
{ {
if ( add ) if ( add )
data[address(ix) + imult] += t; data[address(ix) + imult] += t;
@ -737,7 +737,8 @@ public:
} }
/// Read a grid definition from a config string /// Read a grid definition from a config string
int parse_params(std::string const &conf) int parse_params(std::string const &conf,
colvarparse::Parse_Mode const parse_mode = colvarparse::parse_normal)
{ {
if (cvm::debug()) cvm::log("Reading grid configuration from string.\n"); if (cvm::debug()) cvm::log("Reading grid configuration from string.\n");
@ -746,30 +747,33 @@ public:
{ {
size_t nd_in = 0; size_t nd_in = 0;
// this is only used in state files
colvarparse::get_keyval(conf, "n_colvars", nd_in, nd, colvarparse::parse_silent); colvarparse::get_keyval(conf, "n_colvars", nd_in, nd, colvarparse::parse_silent);
if (nd_in != nd) { if (nd_in != nd) {
cvm::error("Error: trying to read data for a grid " cvm::error("Error: trying to read data for a grid "
"that contains a different number of colvars ("+ "that contains a different number of colvars ("+
cvm::to_str(nd_in)+") than the grid defined " cvm::to_str(nd_in)+") than the grid defined "
"in the configuration file("+cvm::to_str(nd)+ "in the configuration file("+cvm::to_str(nd)+
").\n"); ").\n");
return COLVARS_ERROR; return COLVARS_ERROR;
} }
} }
// underscore keywords are used in state file
colvarparse::get_keyval(conf, "lower_boundaries", colvarparse::get_keyval(conf, "lower_boundaries",
lower_boundaries, lower_boundaries, colvarparse::parse_silent); lower_boundaries, lower_boundaries, colvarparse::parse_silent);
colvarparse::get_keyval(conf, "upper_boundaries", colvarparse::get_keyval(conf, "upper_boundaries",
upper_boundaries, upper_boundaries, colvarparse::parse_silent); upper_boundaries, upper_boundaries, colvarparse::parse_silent);
// support also camel case // camel case keywords are used in config file
colvarparse::get_keyval(conf, "lowerBoundaries", colvarparse::get_keyval(conf, "lowerBoundaries",
lower_boundaries, lower_boundaries, colvarparse::parse_silent); lower_boundaries, lower_boundaries, parse_mode);
colvarparse::get_keyval(conf, "upperBoundaries", colvarparse::get_keyval(conf, "upperBoundaries",
upper_boundaries, upper_boundaries, colvarparse::parse_silent); upper_boundaries, upper_boundaries, parse_mode);
colvarparse::get_keyval(conf, "widths", widths, widths, colvarparse::parse_silent); colvarparse::get_keyval(conf, "widths", widths, widths, parse_mode);
// only used in state file
colvarparse::get_keyval(conf, "sizes", nx, nx, colvarparse::parse_silent); colvarparse::get_keyval(conf, "sizes", nx, nx, colvarparse::parse_silent);
if (nd < lower_boundaries.size()) nd = lower_boundaries.size(); if (nd < lower_boundaries.size()) nd = lower_boundaries.size();
@ -808,13 +812,13 @@ public:
{ {
for (size_t i = 0; i < nd; i++) { for (size_t i = 0; i < nd; i++) {
if ( (std::sqrt(cv[i]->dist2(cv[i]->lower_boundary, if ( (std::sqrt(cv[i]->dist2(cv[i]->lower_boundary,
lower_boundaries[i])) > 1.0E-10) || lower_boundaries[i])) > 1.0E-10) ||
(std::sqrt(cv[i]->dist2(cv[i]->upper_boundary, (std::sqrt(cv[i]->dist2(cv[i]->upper_boundary,
upper_boundaries[i])) > 1.0E-10) || upper_boundaries[i])) > 1.0E-10) ||
(std::sqrt(cv[i]->dist2(cv[i]->width, (std::sqrt(cv[i]->dist2(cv[i]->width,
widths[i])) > 1.0E-10) ) { widths[i])) > 1.0E-10) ) {
cvm::error("Error: restart information for a grid is " cvm::error("Error: restart information for a grid is "
"inconsistent with that of its colvars.\n"); "inconsistent with that of its colvars.\n");
return; return;
} }
} }
@ -830,19 +834,19 @@ public:
// matter: boundaries should be EXACTLY the same (otherwise, // matter: boundaries should be EXACTLY the same (otherwise,
// map_grid() should be used) // map_grid() should be used)
if ( (std::fabs(other_grid.lower_boundaries[i] - if ( (std::fabs(other_grid.lower_boundaries[i] -
lower_boundaries[i]) > 1.0E-10) || lower_boundaries[i]) > 1.0E-10) ||
(std::fabs(other_grid.upper_boundaries[i] - (std::fabs(other_grid.upper_boundaries[i] -
upper_boundaries[i]) > 1.0E-10) || upper_boundaries[i]) > 1.0E-10) ||
(std::fabs(other_grid.widths[i] - (std::fabs(other_grid.widths[i] -
widths[i]) > 1.0E-10) || widths[i]) > 1.0E-10) ||
(data.size() != other_grid.data.size()) ) { (data.size() != other_grid.data.size()) ) {
cvm::error("Error: inconsistency between " cvm::error("Error: inconsistency between "
"two grids that are supposed to be equal, " "two grids that are supposed to be equal, "
"aside from the data stored.\n"); "aside from the data stored.\n");
return; return;
}
} }
} }
}
/// \brief Read grid entry in restart file /// \brief Read grid entry in restart file
@ -853,7 +857,7 @@ public:
if ((is >> key) && (key == std::string("grid_parameters"))) { if ((is >> key) && (key == std::string("grid_parameters"))) {
is.seekg(start_pos, std::ios::beg); is.seekg(start_pos, std::ios::beg);
is >> colvarparse::read_block("grid_parameters", conf); is >> colvarparse::read_block("grid_parameters", conf);
parse_params(conf); parse_params(conf, colvarparse::parse_silent);
} else { } else {
cvm::log("Grid parameters are missing in the restart file, using those from the configuration.\n"); cvm::log("Grid parameters are missing in the restart file, using those from the configuration.\n");
is.seekg(start_pos, std::ios::beg); is.seekg(start_pos, std::ios::beg);
@ -871,11 +875,11 @@ public:
} }
/// \brief Write the grid data without labels, as they are /// \brief Write the grid data without labels, as they are
/// represented in memory /// represented in memory
/// \param buf_size Number of values per line /// \param buf_size Number of values per line
std::ostream & write_raw(std::ostream &os, std::ostream & write_raw(std::ostream &os,
size_t const buf_size = 3) size_t const buf_size = 3)
{ {
std::streamsize const w = os.width(); std::streamsize const w = os.width();
std::streamsize const p = os.precision(); std::streamsize const p = os.precision();
@ -935,10 +939,10 @@ public:
os << std::setw(2) << "# " << nd << "\n"; os << std::setw(2) << "# " << nd << "\n";
for (size_t i = 0; i < nd; i++) { for (size_t i = 0; i < nd; i++) {
os << "# " os << "# "
<< std::setw(10) << lower_boundaries[i] << std::setw(10) << lower_boundaries[i]
<< std::setw(10) << widths[i] << std::setw(10) << widths[i]
<< std::setw(10) << nx[i] << " " << std::setw(10) << nx[i] << " "
<< periodic[i] << "\n"; << periodic[i] << "\n";
} }
@ -951,14 +955,14 @@ public:
for (size_t i = 0; i < nd; i++) { for (size_t i = 0; i < nd; i++) {
os << " " os << " "
<< std::setw(w) << std::setprecision(p) << std::setw(w) << std::setprecision(p)
<< bin_to_value_scalar(ix[i], i); << bin_to_value_scalar(ix[i], i);
} }
os << " "; os << " ";
for (size_t imult = 0; imult < mult; imult++) { for (size_t imult = 0; imult < mult; imult++) {
os << " " os << " "
<< std::setw(w) << std::setprecision(p) << std::setw(w) << std::setprecision(p)
<< value_output(ix, imult); << value_output(ix, imult);
} }
os << "\n"; os << "\n";
} }
@ -986,7 +990,7 @@ public:
if ( !(is >> hash) || (hash != "#") ) { if ( !(is >> hash) || (hash != "#") ) {
cvm::error("Error reading grid at position "+ cvm::error("Error reading grid at position "+
cvm::to_str(is.tellg())+" in stream(read \"" + hash + "\")\n"); cvm::to_str(is.tellg())+" in stream(read \"" + hash + "\")\n");
return is; return is;
} }
@ -1008,7 +1012,7 @@ public:
for (size_t i = 0; i < nd; i++ ) { for (size_t i = 0; i < nd; i++ ) {
if ( !(is >> hash) || (hash != "#") ) { if ( !(is >> hash) || (hash != "#") ) {
cvm::error("Error reading grid at position "+ cvm::error("Error reading grid at position "+
cvm::to_str(is.tellg())+" in stream(read \"" + hash + "\")\n"); cvm::to_str(is.tellg())+" in stream(read \"" + hash + "\")\n");
return is; return is;
} }
@ -1016,10 +1020,10 @@ public:
if ( (std::fabs(lower - lower_boundaries[i].real_value) > 1.0e-10) || if ( (std::fabs(lower - lower_boundaries[i].real_value) > 1.0e-10) ||
(std::fabs(width - widths[i] ) > 1.0e-10) || (std::fabs(width - widths[i] ) > 1.0e-10) ||
(nx_read[i] != nx[i]) ) { (nx_read[i] != nx[i]) ) {
cvm::log("Warning: reading from different grid definition (colvar " cvm::log("Warning: reading from different grid definition (colvar "
+ cvm::to_str(i+1) + "); remapping data on new grid.\n"); + cvm::to_str(i+1) + "); remapping data on new grid.\n");
remap = true; remap = true;
} }
} }
@ -1063,7 +1067,6 @@ public:
/// \brief Write the grid data without labels, as they are /// \brief Write the grid data without labels, as they are
/// represented in memory /// represented in memory
/// \param buf_size Number of values per line
std::ostream & write_opendx(std::ostream &os) std::ostream & write_opendx(std::ostream &os)
{ {
// write the header // write the header
@ -1122,11 +1125,11 @@ public:
/// Constructor /// Constructor
colvar_grid_count(std::vector<int> const &nx_i, colvar_grid_count(std::vector<int> const &nx_i,
size_t const &def_count = 0); size_t const &def_count = 0);
/// Constructor from a vector of colvars /// Constructor from a vector of colvars
colvar_grid_count(std::vector<colvar *> &colvars, colvar_grid_count(std::vector<colvar *> &colvars,
size_t const &def_count = 0); size_t const &def_count = 0);
/// Increment the counter at given position /// Increment the counter at given position
inline void incr_count(std::vector<int> const &ix) inline void incr_count(std::vector<int> const &ix)
@ -1136,7 +1139,7 @@ public:
/// \brief Get the binned count indexed by ix from the newly read data /// \brief Get the binned count indexed by ix from the newly read data
inline size_t const & new_count(std::vector<int> const &ix, inline size_t const & new_count(std::vector<int> const &ix,
size_t const &imult = 0) size_t const &imult = 0)
{ {
return new_data[address(ix) + imult]; return new_data[address(ix) + imult];
} }
@ -1145,9 +1148,9 @@ public:
/// into the internal representation (it may have been rescaled or /// into the internal representation (it may have been rescaled or
/// manipulated) /// manipulated)
virtual inline void value_input(std::vector<int> const &ix, virtual inline void value_input(std::vector<int> const &ix,
size_t const &t, size_t const &t,
size_t const &imult = 0, size_t const &imult = 0,
bool add = false) bool add = false)
{ {
if (add) { if (add) {
data[address(ix)] += t; data[address(ix)] += t;
@ -1164,7 +1167,7 @@ public:
/// \brief Return the log-gradient from finite differences /// \brief Return the log-gradient from finite differences
/// on the *same* grid for dimension n /// on the *same* grid for dimension n
inline const cvm::real log_gradient_finite_diff( const std::vector<int> &ix0, inline const cvm::real log_gradient_finite_diff( const std::vector<int> &ix0,
int n = 0) int n = 0)
{ {
cvm::real A0, A1; cvm::real A0, A1;
std::vector<int> ix; std::vector<int> ix;
@ -1377,7 +1380,7 @@ public:
/// \brief Return the value of the function at ix divided by its /// \brief Return the value of the function at ix divided by its
/// number of samples (if the count grid is defined) /// number of samples (if the count grid is defined)
virtual inline cvm::real value_output(std::vector<int> const &ix, virtual inline cvm::real value_output(std::vector<int> const &ix,
size_t const &imult = 0) size_t const &imult = 0)
{ {
if (samples) if (samples)
return (samples->value(ix) > 0) ? return (samples->value(ix) > 0) ?
@ -1391,9 +1394,9 @@ public:
/// into the internal representation (it may have been rescaled or /// into the internal representation (it may have been rescaled or
/// manipulated) /// manipulated)
virtual inline void value_input(std::vector<int> const &ix, virtual inline void value_input(std::vector<int> const &ix,
cvm::real const &new_value, cvm::real const &new_value,
size_t const &imult = 0, size_t const &imult = 0,
bool add = false) bool add = false)
{ {
if (add) { if (add) {
if (samples) if (samples)

View File

@ -293,6 +293,9 @@ int colvarmodule::parse_biases(std::string const &conf)
/// initialize histograms /// initialize histograms
parse_biases_type<colvarbias_histogram>(conf, "histogram", n_histo_biases); parse_biases_type<colvarbias_histogram>(conf, "histogram", n_histo_biases);
/// initialize histogram restraints
parse_biases_type<colvarbias_restraint_histogram>(conf, "histogramRestraint", n_rest_biases);
/// initialize linear restraints /// initialize linear restraints
parse_biases_type<colvarbias_restraint_linear>(conf, "linear", n_rest_biases); parse_biases_type<colvarbias_restraint_linear>(conf, "linear", n_rest_biases);

View File

@ -4,7 +4,7 @@
#define COLVARMODULE_H #define COLVARMODULE_H
#ifndef COLVARS_VERSION #ifndef COLVARS_VERSION
#define COLVARS_VERSION "2016-09-14" #define COLVARS_VERSION "2016-09-30"
#endif #endif
#ifndef COLVARS_DEBUG #ifndef COLVARS_DEBUG

View File

@ -243,11 +243,17 @@ int colvarscript::proc_colvar(int argc, char const *argv[]) {
} }
if (subcmd == "getappliedforce") { if (subcmd == "getappliedforce") {
result = (cv->bias_force()).to_simple_string(); result = (cv->applied_force()).to_simple_string();
return COLVARS_OK; return COLVARS_OK;
} }
if (subcmd == "getsystemforce") { if (subcmd == "getsystemforce") {
// TODO warning here
result = (cv->total_force()).to_simple_string();
return COLVARS_OK;
}
if (subcmd == "gettotalforce") {
result = (cv->total_force()).to_simple_string(); result = (cv->total_force()).to_simple_string();
return COLVARS_OK; return COLVARS_OK;
} }

View File

@ -57,6 +57,12 @@ public:
} }
} }
/// Return a reference to the data
inline std::vector<T> &data_array()
{
return data;
}
inline ~vector1d() inline ~vector1d()
{ {
data.clear(); data.clear();
@ -203,6 +209,16 @@ public:
return std::sqrt(this->norm2()); return std::sqrt(this->norm2());
} }
inline cvm::real sum() const
{
cvm::real result = 0.0;
size_t i;
for (i = 0; i < this->size(); i++) {
result += (*this)[i];
}
return result;
}
/// Slicing /// Slicing
inline vector1d<T> const slice(size_t const i1, size_t const i2) const inline vector1d<T> const slice(size_t const i1, size_t const i2) const
{ {
@ -295,11 +311,23 @@ public:
{ {
std::stringstream stream(s); std::stringstream stream(s);
size_t i = 0; size_t i = 0;
while ((stream >> (*this)[i]) && (i < this->size())) { if (this->size()) {
i++; while ((stream >> (*this)[i]) && (i < this->size())) {
} i++;
if (i < this->size()) { }
return COLVARS_ERROR; if (i < this->size()) {
return COLVARS_ERROR;
}
} else {
T input;
while (stream >> input) {
if ((i % 100) == 0) {
data.reserve(data.size()+100);
}
data.resize(data.size()+1);
data[i] = input;
i++;
}
} }
return COLVARS_OK; return COLVARS_OK;
} }
@ -434,6 +462,12 @@ public:
this->clear(); this->clear();
} }
/// Return a reference to the data
inline std::vector<T> &data_array()
{
return data;
}
inline row & operator [] (size_t const i) inline row & operator [] (size_t const i)
{ {
return rows[i]; return rows[i];