diff --git a/lib/colvars/colvar.cpp b/lib/colvars/colvar.cpp
index cb10ac4f6..25ffec898 100644
--- a/lib/colvars/colvar.cpp
+++ b/lib/colvars/colvar.cpp
@@ -1,1676 +1,1676 @@
 // -*- c++ -*-
 
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 #include "colvarparse.h"
 #include "colvar.h"
 #include "colvarcomp.h"
 #include <algorithm>
 
 
 // XX TODO make the acf code handle forces as well as values and velocities
 
 
 colvar::colvar (std::string const &conf)
 {
   cvm::log ("Initializing a new collective variable.\n");
-  
+
   get_keyval (conf, "name", this->name,
               (std::string ("colvar")+cvm::to_str (cvm::colvars.size()+1)));
 
   for (std::vector<colvar *>::iterator cvi = cvm::colvars.begin();
        cvi < cvm::colvars.end();
        cvi++) {
     if ((*cvi)->name == this->name)
       cvm::fatal_error ("Error: this colvar cannot have the same name, \""+this->name+
                         "\", as another colvar.\n");
   }
 
-  // all tasks disabled by default 
+  // all tasks disabled by default
   for (size_t i = 0; i < task_ntot; i++) {
     tasks[i] = false;
   }
 
   kinetic_energy = 0.0;
   potential_energy = 0.0;
 
   // read the configuration and set up corresponding instances, for
   // each type of component implemented
 #define initialize_components(def_desc,def_config_key,def_class_name)   \
   {                                                                     \
     size_t def_count = 0;                                               \
     std::string def_conf = "";                                          \
     size_t pos = 0;                                                     \
     while ( this->key_lookup (conf,                                     \
                               def_config_key,                           \
                               def_conf,                                 \
                               pos) ) {                                  \
       if (!def_conf.size()) continue;                                   \
       cvm::log ("Initializing "                                         \
                 "a new \""+std::string (def_config_key)+"\" component"+ \
                 (cvm::debug() ? ", with configuration:\n"+def_conf      \
                  : ".\n"));                                             \
       cvm::increase_depth();                                            \
       cvc *cvcp = new colvar::def_class_name (def_conf);                \
       if (cvcp != NULL) {                                               \
         cvcs.push_back (cvcp);                                          \
         cvcp->check_keywords (def_conf, def_config_key);                \
         cvm::decrease_depth();                                          \
       } else {                                                          \
         cvm::fatal_error ("Error: in allocating component \""           \
                           def_config_key"\".\n");                       \
       }                                                                 \
       if ( (cvcp->period != 0.0) || (cvcp->wrap_center != 0.0) ) {      \
         if ( (cvcp->function_type != std::string ("distance_z")) &&     \
              (cvcp->function_type != std::string ("dihedral")) &&       \
              (cvcp->function_type != std::string ("spin_angle")) ) {    \
           cvm::fatal_error ("Error: invalid use of period and/or "      \
                             "wrapAround in a \""+                       \
                             std::string (def_config_key)+               \
                             "\" component.\n"+                          \
                             "Period: "+cvm::to_str(cvcp->period) +      \
                         " wrapAround: "+cvm::to_str(cvcp->wrap_center));\
         }                                                               \
       }                                                                 \
       if ( ! cvcs.back()->name.size())                                  \
         cvcs.back()->name = std::string (def_config_key)+               \
           (cvm::to_str (++def_count));                                  \
       if (cvm::debug())                                                 \
         cvm::log ("Done initializing a \""+                             \
                   std::string (def_config_key)+                         \
                   "\" component"+                                       \
                   (cvm::debug() ?                                       \
                    ", named \""+cvcs.back()->name+"\""                  \
                    : "")+".\n");                                        \
       def_conf = "";                                                    \
       if (cvm::debug())                                                 \
         cvm::log ("Parsed "+cvm::to_str (cvcs.size())+                  \
                   " components at this time.\n");                       \
     }                                                                   \
   }
 
 
   initialize_components ("distance",         "distance",       distance);
   initialize_components ("distance vector",  "distanceVec",    distance_vec);
   initialize_components ("distance vector "
                          "direction",        "distanceDir",    distance_dir);
   initialize_components ("distance projection "
                          "on an axis",       "distanceZ",      distance_z);
   initialize_components ("distance projection "
                          "on a plane",       "distanceXY",     distance_xy);
   initialize_components ("average distance weighted by inverse power",
                          "distanceInv", distance_inv);
 
   initialize_components ("coordination "
                          "number",           "coordNum",       coordnum);
   initialize_components ("self-coordination "
                          "number",           "selfCoordNum",   selfcoordnum);
 
   initialize_components ("angle",            "angle",          angle);
   initialize_components ("dihedral",         "dihedral",       dihedral);
 
   initialize_components ("hydrogen bond",    "hBond",          h_bond);
 
   //  initialize_components ("alpha helix",      "alphaDihedrals", alpha_dihedrals);
   initialize_components ("alpha helix",      "alpha",          alpha_angles);
 
   initialize_components ("dihedral principal "
                          "component",        "dihedralPC",     dihedPC);
 
   initialize_components ("orientation",      "orientation",    orientation);
   initialize_components ("orientation "
                          "angle",            "orientationAngle",orientation_angle);
   initialize_components ("tilt",             "tilt",           tilt);
   initialize_components ("spin angle",       "spinAngle",      spin_angle);
 
   initialize_components ("RMSD",             "rmsd",           rmsd);
 
   //  initialize_components ("logarithm of MSD", "logmsd",         logmsd);
 
   initialize_components ("radius of "
                          "gyration",         "gyration",       gyration);
   initialize_components ("moment of "
                          "inertia",          "inertia",        inertia);
   initialize_components ("moment of inertia around an axis",
                                              "inertiaZ",       inertia_z);
   initialize_components ("eigenvector",      "eigenvector",    eigenvector);
 
   if (!cvcs.size())
     cvm::fatal_error ("Error: no valid components were provided "
                       "for this collective variable.\n");
 
   cvm::log ("All components initialized.\n");
 
 
   // this is set false if any of the components has an exponent
   // different from 1 in the polynomial
   b_linear = true;
 
   // these will be set to false if any of the cvcs has them false
   b_inverse_gradients = true;
   b_Jacobian_force    = true;
 
   // Decide whether the colvar is periodic
   // Used to wrap extended DOF if extendedLagrangian is on
-  if (cvcs.size() == 1 && (cvcs[0])->b_periodic && (cvcs[0])->sup_np == 1 
+  if (cvcs.size() == 1 && (cvcs[0])->b_periodic && (cvcs[0])->sup_np == 1
                                                 && (cvcs[0])->sup_coeff == 1.0 ) {
     this->b_periodic = true;
     this->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 {
     this->b_periodic = false;
     this->period = 0.0;
   }
 
   // check the available features of each cvc
   for (size_t i = 0; i < cvcs.size(); i++) {
 
     if ((cvcs[i])->sup_np != 1) {
       if (cvm::debug() && b_linear)
         cvm::log ("Warning: You are using a non-linear polynomial "
                   "combination to define this collective variable, "
                   "some biasing methods may be unavailable.\n");
       b_linear = false;
 
       if ((cvcs[i])->sup_np < 0) {
         cvm::log ("Warning: you chose a negative exponent in the combination; "
                   "if you apply forces, the simulation may become unstable "
                   "when the component \""+
                   (cvcs[i])->function_type+"\" approaches zero.\n");
       }
     }
 
     if ((cvcs[i])->b_periodic && !b_periodic) {
         cvm::log ("Warning: although this component is periodic, the colvar will "
                   "not be treated as periodic, either because the exponent is not "
                   "1, or because multiple components are present. Make sure that "
                   "you know what you are doing!");
     }
 
     if (! (cvcs[i])->b_inverse_gradients)
       b_inverse_gradients = false;
 
     if (! (cvcs[i])->b_Jacobian_derivative)
       b_Jacobian_force = false;
 
     for (size_t j = i; j < cvcs.size(); j++) {
       if ( (cvcs[i])->type() != (cvcs[j])->type() ) {
         cvm::fatal_error ("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 "
                           " sum them together.\n");
       }
     }
   }
 
 
   {
     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);
   if (width <= 0.0)
     cvm::fatal_error ("Error: \"width\" must be positive.\n");
 
   lower_boundary.type (this->type());
   lower_wall.type     (this->type());
 
   upper_boundary.type (this->type());
   upper_wall.type     (this->type());
 
   if (this->type() == colvarvalue::type_scalar) {
 
     if (get_keyval (conf, "lowerBoundary", lower_boundary, lower_boundary)) {
       enable (task_lower_boundary);
     }
 
     get_keyval (conf, "lowerWallConstant", lower_wall_k, 0.0);
     if (lower_wall_k > 0.0) {
       get_keyval (conf, "lowerWall", lower_wall, lower_boundary);
       enable (task_lower_wall);
     }
 
     if (get_keyval (conf, "upperBoundary", upper_boundary, upper_boundary)) {
       enable (task_upper_boundary);
     }
 
     get_keyval (conf, "upperWallConstant", upper_wall_k, 0.0);
     if (upper_wall_k > 0.0) {
       get_keyval (conf, "upperWall", upper_wall, upper_boundary);
       enable (task_upper_wall);
     }
   }
 
   if (tasks[task_lower_boundary]) {
     get_keyval (conf, "hardLowerBoundary", hard_lower_boundary, false);
   }
   if (tasks[task_upper_boundary]) {
     get_keyval (conf, "hardUpperBoundary", hard_upper_boundary, false);
   }
 
   // consistency checks for boundaries and walls
   if (tasks[task_lower_boundary] && tasks[task_upper_boundary]) {
     if (lower_boundary >= upper_boundary) {
       cvm::fatal_error ("Error: the upper boundary, "+
                         cvm::to_str (upper_boundary)+
                         ", is not higher than the lower boundary, "+
                         cvm::to_str (lower_boundary)+".\n");
     }
   }
 
   if (tasks[task_lower_wall] && tasks[task_upper_wall]) {
     if (lower_wall >= upper_wall) {
       cvm::fatal_error ("Error: the upper wall, "+
                         cvm::to_str (upper_wall)+
                         ", is not higher than the lower wall, "+
                         cvm::to_str (lower_wall)+".\n");
     }
 
     if (dist2 (lower_wall, upper_wall) < 1.0E-12) {
       cvm::log ("Lower wall and upper wall are equal "
                 "in the periodic domain of the colvar: disabling walls.\n");
       disable (task_lower_wall);
       disable (task_upper_wall);
     }
   }
 
   get_keyval (conf, "expandBoundaries", expand_boundaries, false);
   if (expand_boundaries && periodic_boundaries()) {
     cvm::fatal_error ("Error: trying to expand boundaries that already "
                       "cover a whole period of a periodic colvar.\n");
   }
   if (expand_boundaries && hard_lower_boundary && hard_upper_boundary) {
     cvm::fatal_error ("Error: inconsistent configuration "
                       "(trying to expand boundaries with both "
                       "hardLowerBoundary and hardUpperBoundary enabled).\n");
   }
 
   {
     bool b_extended_lagrangian;
     get_keyval (conf, "extendedLagrangian", b_extended_lagrangian, false);
 
     if (b_extended_lagrangian) {
       cvm::real temp, tolerance, period;
 
       cvm::log ("Enabling the extended Lagrangian term for colvar \""+
                 this->name+"\".\n");
-    
+
       enable (task_extended_lagrangian);
 
       xr.type (this->type());
       vr.type (this->type());
       fr.type (this->type());
 
       const bool found = get_keyval (conf, "extendedTemp", temp, cvm::temperature());
       if (temp <= 0.0) {
         if (found)
           cvm::fatal_error ("Error: \"extendedTemp\" must be positive.\n");
         else
           cvm::fatal_error ("Error: a positive temperature must be provided, either "
                             "by enabling a thermostat, or through \"extendedTemp\".\n");
       }
 
       get_keyval (conf, "extendedFluctuation", tolerance, width);
       if (tolerance <= 0.0)
         cvm::fatal_error ("Error: \"extendedFluctuation\" must be positive.\n");
       ext_force_k = cvm::boltzmann() * temp / (tolerance * tolerance);
       cvm::log ("Computed extended system force constant: " + cvm::to_str(ext_force_k) + " kcal/mol/U^2");
 
       get_keyval (conf, "extendedTimeConstant", period, 200.0);
       if (period <= 0.0)
         cvm::fatal_error ("Error: \"extendedTimeConstant\" must be positive.\n");
       ext_mass = (cvm::boltzmann() * temp * period * period)
                  / (4.0 * PI * PI * tolerance * tolerance);
       cvm::log ("Computed fictitious mass: " + cvm::to_str(ext_mass) + " kcal/mol/(U/fs)^2   (U: colvar unit)");
 
       {
         bool b_output_energy;
         get_keyval (conf, "outputEnergy", b_output_energy, false);
         if (b_output_energy) {
           enable (task_output_energy);
         }
       }
 
       get_keyval (conf, "extendedLangevinDamping", ext_gamma, 1.0);
       if (ext_gamma < 0.0)
         cvm::fatal_error ("Error: \"extendedLangevinDamping\" may not be negative.\n");
       if (ext_gamma != 0.0) {
         enable (task_langevin);
         ext_gamma *= 1.0e-3; // convert from ps-1 to fs-1
         ext_sigma = std::sqrt(2.0 * cvm::boltzmann() * temp * ext_gamma * ext_mass / cvm::dt());
       }
     }
   }
 
   {
     bool b_output_value;
     get_keyval (conf, "outputValue", b_output_value, true);
     if (b_output_value) {
       enable (task_output_value);
     }
   }
 
   {
     bool b_output_velocity;
     get_keyval (conf, "outputVelocity", b_output_velocity, false);
     if (b_output_velocity) {
       enable (task_output_velocity);
     }
   }
 
   {
     bool b_output_system_force;
     get_keyval (conf, "outputSystemForce", b_output_system_force, false);
     if (b_output_system_force) {
       enable (task_output_system_force);
     }
   }
 
   {
     bool b_output_applied_force;
     get_keyval (conf, "outputAppliedForce", b_output_applied_force, false);
     if (b_output_applied_force) {
       enable (task_output_applied_force);
     }
   }
 
   if (cvm::b_analysis)
     parse_analysis (conf);
 
   if (cvm::debug())
     cvm::log ("Done initializing collective variable \""+this->name+"\".\n");
 }
 
 
 
 void colvar::build_atom_list (void)
 {
   // If atomic gradients are requested, build full list of atom ids from all cvcs
   std::list<int> temp_id_list;
 
   for (size_t i = 0; i < cvcs.size(); i++) {
     for (size_t j = 0; j < cvcs[i]->atom_groups.size(); j++) {
       for (size_t k = 0; k < cvcs[i]->atom_groups[j]->size(); k++) {
         temp_id_list.push_back (cvcs[i]->atom_groups[j]->at(k).id);
       }
     }
   }
 
   temp_id_list.sort();
   temp_id_list.unique();
   atom_ids = std::vector<int> (temp_id_list.begin(), temp_id_list.end());
   temp_id_list.clear();
 
   atomic_gradients.resize (atom_ids.size());
   if (atom_ids.size()) {
     if (cvm::debug())
       cvm::log ("Colvar: created atom list with " + cvm::to_str(atom_ids.size()) + " atoms.\n");
   } else {
     cvm::log ("Warning: colvar components communicated no atom IDs.\n");
   }
 }
 
 
 void colvar::parse_analysis (std::string const &conf)
 {
 
   //   if (cvm::debug())
   //     cvm::log ("Parsing analysis flags for collective variable \""+
   //               this->name+"\".\n");
 
   runave_length = 0;
   bool b_runave = false;
   if (get_keyval (conf, "runAve", b_runave) && b_runave) {
 
     enable (task_runave);
 
     get_keyval (conf, "runAveLength", runave_length, 1000);
     get_keyval (conf, "runAveStride", runave_stride, 1);
 
     if ((cvm::restart_out_freq % runave_stride) != 0)
       cvm::fatal_error ("Error: runAveStride must be commensurate with the restart frequency.\n");
 
     std::string runave_outfile;
     get_keyval (conf, "runAveOutputFile", runave_outfile,
                 std::string (cvm::output_prefix+"."+
                              this->name+".runave.traj"));
 
     size_t const this_cv_width = x.output_width (cvm::cv_width);
     runave_os.open (runave_outfile.c_str());
     runave_os << "# " << cvm::wrap_string ("step", cvm::it_width-2)
               << "  "
               << cvm::wrap_string ("running average", this_cv_width)
               << " "
               << cvm::wrap_string ("running stddev", this_cv_width)
               << "\n";
   }
 
   acf_length = 0;
   bool b_acf = false;
   if (get_keyval (conf, "corrFunc", b_acf) && b_acf) {
 
     enable (task_corrfunc);
 
     std::string acf_colvar_name;
     get_keyval (conf, "corrFuncWithColvar", acf_colvar_name, this->name);
     if (acf_colvar_name == this->name) {
       cvm::log ("Calculating auto-correlation function.\n");
     } else {
       cvm::log ("Calculating correlation function with \""+
                 this->name+"\".\n");
     }
 
     std::string acf_type_str;
     get_keyval (conf, "corrFuncType", acf_type_str, to_lower_cppstr (std::string ("velocity")));
     if (acf_type_str == to_lower_cppstr (std::string ("coordinate"))) {
       acf_type = acf_coor;
     } else if (acf_type_str == to_lower_cppstr (std::string ("velocity"))) {
       acf_type = acf_vel;
       enable (task_fdiff_velocity);
       if (acf_colvar_name.size())
         (cvm::colvar_p (acf_colvar_name))->enable (task_fdiff_velocity);
     } else if (acf_type_str == to_lower_cppstr (std::string ("coordinate_p2"))) {
       acf_type = acf_p2coor;
     } else {
       cvm::fatal_error ("Unknown type of correlation function, \""+
                         acf_type_str+"\".\n");
     }
 
     get_keyval (conf, "corrFuncOffset", acf_offset, 0);
     get_keyval (conf, "corrFuncLength", acf_length, 1000);
     get_keyval (conf, "corrFuncStride", acf_stride, 1);
 
     if ((cvm::restart_out_freq % acf_stride) != 0)
       cvm::fatal_error ("Error: corrFuncStride must be commensurate with the restart frequency.\n");
 
     get_keyval (conf, "corrFuncNormalize", acf_normalize, true);
     get_keyval (conf, "corrFuncOutputFile", acf_outfile,
                 std::string (cvm::output_prefix+"."+this->name+
                              ".corrfunc.dat"));
   }
 }
 
 
 void colvar::enable (colvar::task const &t)
 {
   switch (t) {
 
   case task_output_system_force:
     enable (task_system_force);
     break;
 
   case task_report_Jacobian_force:
     enable (task_Jacobian_force);
     enable (task_system_force);
     if (cvm::debug())
       cvm::log ("Adding the Jacobian force to the system force, "
                 "rather than applying its opposite silently.\n");
     break;
 
   case task_Jacobian_force:
     // checks below do not apply to extended-system colvars
     if ( !tasks[task_extended_lagrangian] ) {
       enable (task_gradients);
 
-      if (!b_Jacobian_force) 
+      if (!b_Jacobian_force)
         cvm::fatal_error ("Error: colvar \""+this->name+
                           "\" does not have Jacobian forces implemented.\n");
-      if (!b_linear) 
+      if (!b_linear)
         cvm::fatal_error ("Error: colvar \""+this->name+
                           "\" must be defined as a linear combination "
                           "to calculate the Jacobian force.\n");
       if (cvm::debug())
         cvm::log ("Enabling calculation of the Jacobian force "
                   "on this colvar.\n");
     }
     fj.type (this->type());
     break;
 
   case task_system_force:
     if (!tasks[task_extended_lagrangian]) {
       if (!b_inverse_gradients) {
         cvm::fatal_error ("Error: one or more of the components of "
                           "colvar \""+this->name+
                           "\" does not support system force calculation.\n");
       }
       cvm::request_system_force();
     }
     ft.type (this->type());
     ft_reported.type (this->type());
     break;
 
   case task_output_applied_force:
   case task_lower_wall:
   case task_upper_wall:
     // all of the above require gradients
     enable (task_gradients);
     break;
 
   case task_fdiff_velocity:
     x_old.type (this->type());
     v_fdiff.type (this->type());
     v_reported.type (this->type());
     break;
 
   case task_output_velocity:
     enable (task_fdiff_velocity);
     break;
 
   case task_grid:
     if (this->type() != colvarvalue::type_scalar)
       cvm::fatal_error ("Cannot calculate a grid for collective variable, \""+
                         this->name+"\", because its value is not a scalar number.\n");
     break;
 
   case task_extended_lagrangian:
     enable (task_gradients);
     v_reported.type (this->type());
     break;
 
   case task_lower_boundary:
   case task_upper_boundary:
     if (this->type() != colvarvalue::type_scalar) {
       cvm::fatal_error ("Error: this colvar is not a scalar value "
                         "and cannot produce a grid.\n");
     }
     break;
 
 
   case task_output_value:
   case task_runave:
   case task_corrfunc:
   case task_ntot:
     break;
 
   case task_gradients:
     f.type  (this->type());
     fb.type (this->type());
     break;
 
   case task_collect_gradients:
     if (this->type() != colvarvalue::type_scalar)
       cvm::fatal_error ("Collecting atomic gradients for non-scalar collective variable \""+
                         this->name+"\" is not yet implemented.\n");
     enable (task_gradients);
     if (atom_ids.size() == 0) {
       build_atom_list();
     }
     break;
   }
 
 
   tasks[t] = true;
 }
 
 
 void colvar::disable (colvar::task const &t)
 {
   // check dependencies
   switch (t) {
   case task_gradients:
     disable (task_upper_wall);
     disable (task_lower_wall);
     disable (task_output_applied_force);
     disable (task_system_force);
     disable (task_Jacobian_force);
     break;
 
   case task_system_force:
     disable (task_output_system_force);
     break;
 
   case task_Jacobian_force:
     disable (task_report_Jacobian_force);
     break;
 
   case task_fdiff_velocity:
     disable (task_output_velocity);
     break;
 
   case task_lower_boundary:
   case task_upper_boundary:
     disable (task_grid);
     break;
 
   case task_extended_lagrangian:
   case task_report_Jacobian_force:
   case task_output_value:
   case task_output_velocity:
   case task_output_applied_force:
   case task_output_system_force:
   case task_runave:
   case task_corrfunc:
   case task_grid:
   case task_lower_wall:
   case task_upper_wall:
   case task_ntot:
     break;
   }
 
   tasks[t] = false;
 }
 
 
 colvar::~colvar()
 {
   for (size_t i = 0; i < cvcs.size(); i++) {
     delete cvcs[i];
   }
-}  
+}
 
 
 
 // ******************** CALC FUNCTIONS ********************
 
 
 void colvar::calc()
 {
   if (cvm::debug())
     cvm::log ("Calculating colvar \""+this->name+"\".\n");
 
   // prepare atom groups for calculation
   if (cvm::debug())
     cvm::log ("Collecting data from atom groups.\n");
   for (size_t i = 0; i < cvcs.size(); i++) {
     for (size_t ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
       cvm::atom_group &atoms = *(cvcs[i]->atom_groups[ig]);
       atoms.reset_atoms_data();
       atoms.read_positions();
       if (atoms.b_center || atoms.b_rotate) {
         atoms.calc_apply_roto_translation();
       }
       // each atom group will take care of its own ref_pos_group, if defined
     }
   }
   if (tasks[task_output_velocity]) {
     for (size_t i = 0; i < cvcs.size(); i++) {
       for (size_t ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
         cvcs[i]->atom_groups[ig]->read_velocities();
-      }   
+      }
     }
   }
   if (tasks[task_system_force]) {
     for (size_t i = 0; i < cvcs.size(); i++) {
       for (size_t ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
         cvcs[i]->atom_groups[ig]->read_system_forces();
-      }   
+      }
     }
   }
 
   // calculate the value of the colvar
 
   if (cvm::debug())
     cvm::log ("Calculating colvar components.\n");
   x.reset();
   if (x.type() == colvarvalue::type_scalar) {
     // polynomial combination allowed
 
     for (size_t i = 0; i < cvcs.size(); i++) {
       cvm::increase_depth();
       (cvcs[i])->calc_value();
       cvm::decrease_depth();
       if (cvm::debug())
         cvm::log ("Colvar component no. "+cvm::to_str (i+1)+
                   " within colvar \""+this->name+"\" has value "+
                   cvm::to_str ((cvcs[i])->value(),
                                cvm::cv_width, cvm::cv_prec)+".\n");
       x += (cvcs[i])->sup_coeff *
         ( ((cvcs[i])->sup_np != 1) ?
           std::pow ((cvcs[i])->value().real_value, (cvcs[i])->sup_np) :
           (cvcs[i])->value().real_value );
-    } 
+    }
   } else {
     // only linear combination allowed
 
     for (size_t i = 0; i < cvcs.size(); i++) {
       cvm::increase_depth();
       (cvcs[i])->calc_value();
       cvm::decrease_depth();
       if (cvm::debug())
         cvm::log ("Colvar component no. "+cvm::to_str (i+1)+
                   " within colvar \""+this->name+"\" has value "+
                   cvm::to_str ((cvcs[i])->value(),
                                cvm::cv_width, cvm::cv_prec)+".\n");
       x += (cvcs[i])->sup_coeff * (cvcs[i])->value();
-    } 
+    }
   }
 
   if (cvm::debug())
     cvm::log ("Colvar \""+this->name+"\" has value "+
               cvm::to_str (x, cvm::cv_width, cvm::cv_prec)+".\n");
 
   if (tasks[task_gradients]) {
 
     if (cvm::debug())
       cvm::log ("Calculating gradients of colvar \""+this->name+"\".\n");
 
     for (size_t i = 0; i < cvcs.size(); i++) {
       // calculate the gradients of each component
       cvm::increase_depth();
 
       (cvcs[i])->calc_gradients();
 
       // if requested, propagate (via chain rule) the gradients above
       // to the atoms used to define the roto-translation
       for (size_t ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
-        if (cvcs[i]->atom_groups[ig]->b_fit_gradients) 
+        if (cvcs[i]->atom_groups[ig]->b_fit_gradients)
           cvcs[i]->atom_groups[ig]->calc_fit_gradients();
-      }   
+      }
 
       cvm::decrease_depth();
     }
 
     if (cvm::debug())
       cvm::log ("Done calculating gradients of colvar \""+this->name+"\".\n");
 
     if (tasks[task_collect_gradients]) {
       // Collect the atomic gradients inside colvar object
       for (int a = 0; a < atomic_gradients.size(); a++) {
         atomic_gradients[a].reset();
       }
       for (size_t i = 0; i < cvcs.size(); i++) {
         // Coefficient: d(a * x^n) = a * n * x^(n-1) * dx
         cvm::real coeff = (cvcs[i])->sup_coeff * cvm::real ((cvcs[i])->sup_np) *
           std::pow ((cvcs[i])->value().real_value, (cvcs[i])->sup_np-1);
 
         for (size_t j = 0; j < cvcs[i]->atom_groups.size(); j++) {
 
           // If necessary, apply inverse rotation to get atomic
           // gradient in the laboratory frame
           if (cvcs[i]->atom_groups[j]->b_rotate) {
             cvm::rotation const rot_inv = cvcs[i]->atom_groups[j]->rot.inverse();
 
             for (size_t k = 0; k < cvcs[i]->atom_groups[j]->size(); k++) {
               int a = std::lower_bound (atom_ids.begin(), atom_ids.end(),
                   cvcs[i]->atom_groups[j]->at(k).id) - atom_ids.begin();
               atomic_gradients[a] += coeff *
                 rot_inv.rotate (cvcs[i]->atom_groups[j]->at(k).grad);
             }
 
           } else {
 
             for (size_t k = 0; k < cvcs[i]->atom_groups[j]->size(); k++) {
               int a = std::lower_bound (atom_ids.begin(), atom_ids.end(),
                   cvcs[i]->atom_groups[j]->at(k).id) - atom_ids.begin();
-              atomic_gradients[a] += coeff * cvcs[i]->atom_groups[j]->at(k).grad; 
+              atomic_gradients[a] += coeff * cvcs[i]->atom_groups[j]->at(k).grad;
             }
           }
         }
       }
     }
   }
 
   if (tasks[task_system_force]) {
 
     if (cvm::debug())
       cvm::log ("Calculating system force of colvar \""+this->name+"\".\n");
 
     ft.reset();
 
     if(!tasks[task_extended_lagrangian] && (cvm::step_relative() > 0)) {
       // get from the cvcs the system forces from the PREVIOUS step
       for (size_t i = 0; i < cvcs.size(); i++) {
         (cvcs[i])->calc_force_invgrads();
         // linear combination is assumed
         cvm::increase_depth();
         ft += (cvcs[i])->system_force() / ((cvcs[i])->sup_coeff * cvm::real (cvcs.size()));
         cvm::decrease_depth();
       }
     }
 
     if (tasks[task_report_Jacobian_force]) {
       // add the Jacobian force to the system force, and don't apply any silent
       // correction internally: biases such as colvarbias_abf will handle it
       ft += fj;
     }
 
     if (cvm::debug())
       cvm::log ("Done calculating system force of colvar \""+this->name+"\".\n");
   }
 
   if (tasks[task_fdiff_velocity]) {
     // calculate the velocity by finite differences
     if (cvm::step_relative() == 0)
       x_old = x;
     else {
       v_fdiff = fdiff_velocity (x_old, x);
       v_reported = v_fdiff;
     }
   }
 
   if (tasks[task_extended_lagrangian]) {
 
     // initialize the restraint center in the first step to the value
     // just calculated from the cvcs
     // TODO: put it in the restart information
     if (cvm::step_relative() == 0) {
       xr = x;
       vr = 0.0; // (already 0; added for clarity)
     }
 
     // report the restraint center as "value"
     x_reported = xr;
     v_reported = vr;
     // the "system force" with the extended Lagrangian is just the
     // harmonic term acting on the extended coordinate
     // Note: this is the force for current timestep
     ft_reported = (-0.5 * ext_force_k) * this->dist2_lgrad (xr, x);
 
   } else {
 
     x_reported = x;
     ft_reported = ft;
   }
 
   if (cvm::debug())
     cvm::log ("Done calculating colvar \""+this->name+"\".\n");
 }
 
 
 cvm::real colvar::update()
 {
   if (cvm::debug())
     cvm::log ("Updating colvar \""+this->name+"\".\n");
 
 
   // set to zero the applied force
   f.reset();
 
   // add the biases' force, which at this point should already have
   // been summed over each bias using this colvar
   f += fb;
 
 
   if (tasks[task_lower_wall] || tasks[task_upper_wall]) {
 
     // wall force
     colvarvalue fw (this->type());
 
     // if the two walls are applied concurrently, decide which is the
     // closer one (on a periodic colvar, both walls may be applicable
     // at the same time)
     if ( (!tasks[task_upper_wall]) ||
          (this->dist2 (x, lower_wall) < this->dist2 (x, upper_wall)) ) {
 
       cvm::real const grad = this->dist2_lgrad (x, lower_wall);
       if (grad < 0.0) {
         fw = -0.5 * lower_wall_k * grad;
         if (cvm::debug())
           cvm::log ("Applying a lower wall force ("+
                     cvm::to_str (fw)+") to \""+this->name+"\".\n");
         f += fw;
 
       }
 
     } else {
 
       cvm::real const grad = this->dist2_lgrad (x, upper_wall);
       if (grad > 0.0) {
         fw = -0.5 * upper_wall_k * grad;
         if (cvm::debug())
           cvm::log ("Applying an upper wall force ("+
                     cvm::to_str (fw)+") to \""+this->name+"\".\n");
         f += fw;
       }
     }
   }
 
   if (tasks[task_Jacobian_force]) {
-    
+
     cvm::increase_depth();
     for (size_t i = 0; i < cvcs.size(); i++) {
       (cvcs[i])->calc_Jacobian_derivative();
     }
     cvm::decrease_depth();
 
     fj.reset();
     for (size_t i = 0; i < cvcs.size(); i++) {
       // linear combination is assumed
       fj += 1.0 / ( cvm::real (cvcs.size()) *  cvm::real ((cvcs[i])->sup_coeff) ) *
         (cvcs[i])->Jacobian_derivative();
     }
     fj *= cvm::boltzmann() * cvm::temperature();
 
     // the instantaneous Jacobian force was not included in the reported system force;
-    // instead, it is subtracted from the applied force (silent Jacobian correction) 
-    if (! tasks[task_report_Jacobian_force]) 
+    // instead, it is subtracted from the applied force (silent Jacobian correction)
+    if (! tasks[task_report_Jacobian_force])
       f -= fj;
   }
 
 
   if (tasks[task_extended_lagrangian]) {
 
     cvm::real dt = cvm::dt();
 
     // the total force is applied to the fictitious mass, while the
     // atoms only feel the harmonic force
     // fr: extended coordinate force; f: colvar force applied to atomic coordinates
     fr   = f;
     fr  += (-0.5 * ext_force_k) * this->dist2_lgrad (xr, x);
     f    = (-0.5 * ext_force_k) * this->dist2_rgrad (xr, x);
 
     // leap frog: starting from x_i, f_i, v_(i-1/2)
     vr  += (0.5 * dt) * fr / ext_mass;
     // Because of leapfrog, kinetic energy at time i is approximate
     kinetic_energy = 0.5 * ext_mass * vr * vr;
     potential_energy = 0.5 * ext_force_k * this->dist2(xr, x);
     // leap to v_(i+1/2)
     if (tasks[task_langevin]) {
       vr -= dt * ext_gamma * vr.real_value;
-      vr += dt * ext_sigma * cvm::rand_gaussian() / ext_mass; 
-    } 
-    vr  += (0.5 * dt) * fr / ext_mass; 
+      vr += dt * ext_sigma * cvm::rand_gaussian() / ext_mass;
+    }
+    vr  += (0.5 * dt) * fr / ext_mass;
     xr  += dt * vr;
     xr.apply_constraints();
     if (this->b_periodic) this->wrap (xr);
   }
 
 
   if (tasks[task_fdiff_velocity]) {
     // set it for the next step
     x_old = x;
   }
 
   if (cvm::debug())
     cvm::log ("Done updating colvar \""+this->name+"\".\n");
   return (potential_energy + kinetic_energy);
 }
 
 
 void colvar::communicate_forces()
 {
   if (cvm::debug())
-    cvm::log ("Communicating forces from colvar \""+this->name+"\".\n"); 
+    cvm::log ("Communicating forces from colvar \""+this->name+"\".\n");
 
   if (x.type() == colvarvalue::type_scalar) {
 
     for (size_t i = 0; i < cvcs.size(); i++) {
       cvm::increase_depth();
-      (cvcs[i])->apply_force (f * (cvcs[i])->sup_coeff * 
+      (cvcs[i])->apply_force (f * (cvcs[i])->sup_coeff *
                               cvm::real ((cvcs[i])->sup_np) *
                               (std::pow ((cvcs[i])->value().real_value,
                                       (cvcs[i])->sup_np-1)) );
       cvm::decrease_depth();
     }
 
   } else {
 
     for (size_t i = 0; i < cvcs.size(); i++) {
       cvm::increase_depth();
       (cvcs[i])->apply_force (f * (cvcs[i])->sup_coeff);
       cvm::decrease_depth();
     }
   }
 
   if (cvm::debug())
-    cvm::log ("Done communicating forces from colvar \""+this->name+"\".\n"); 
+    cvm::log ("Done communicating forces from colvar \""+this->name+"\".\n");
 }
 
 
 
 // ******************** METRIC FUNCTIONS ********************
 // Use the metrics defined by \link cvc \endlink objects
 
 
 bool colvar::periodic_boundaries (colvarvalue const &lb, colvarvalue const &ub) const
 {
   if ( (!tasks[task_lower_boundary]) || (!tasks[task_upper_boundary]) ) {
     cvm::fatal_error ("Error: requesting to histogram the "
                       "collective variable \""+this->name+"\", but a "
                       "pair of lower and upper boundaries must be "
                       "defined.\n");
   }
 
   if (period > 0.0) {
     if ( ((std::sqrt (this->dist2 (lb, ub))) / this->width)
          < 1.0E-10 ) {
       return true;
     }
   }
 
   return false;
 }
 
 bool colvar::periodic_boundaries() const
 {
   if ( (!tasks[task_lower_boundary]) || (!tasks[task_upper_boundary]) ) {
     cvm::fatal_error ("Error: requesting to histogram the "
                       "collective variable \""+this->name+"\", but a "
                       "pair of lower and upper boundaries must be "
                       "defined.\n");
   }
 
   return periodic_boundaries (lower_boundary, upper_boundary);
 }
 
 
 cvm::real colvar::dist2 (colvarvalue const &x1,
                          colvarvalue const &x2) const
 {
   return (cvcs[0])->dist2 (x1, x2);
 }
 
 colvarvalue colvar::dist2_lgrad (colvarvalue const &x1,
                                  colvarvalue const &x2) const
 {
   return (cvcs[0])->dist2_lgrad (x1, x2);
 }
 
 colvarvalue colvar::dist2_rgrad (colvarvalue const &x1,
                                  colvarvalue const &x2) const
 {
   return (cvcs[0])->dist2_rgrad (x1, x2);
 }
 
 cvm::real colvar::compare (colvarvalue const &x1,
                            colvarvalue const &x2) const
 {
   return (cvcs[0])->compare (x1, x2);
 }
 
 void colvar::wrap (colvarvalue &x) const
 {
   (cvcs[0])->wrap (x);
   return;
 }
 
 
 // ******************** INPUT FUNCTIONS ********************
 
 std::istream & colvar::read_restart (std::istream &is)
 {
   size_t const start_pos = is.tellg();
 
   std::string conf;
   if ( !(is >> colvarparse::read_block ("colvar", conf)) ) {
     // this is not a colvar block
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
     return is;
   }
 
   {
     std::string check_name = "";
     if ( (get_keyval (conf, "name", check_name,
                       std::string (""), colvarparse::parse_silent)) &&
          (check_name != name) )  {
       cvm::fatal_error ("Error: the state file does not match the "
                         "configuration file, at colvar \""+name+"\".\n");
     }
     if (check_name.size() == 0) {
       cvm::fatal_error ("Error: Collective variable in the "
                         "restart file without any identifier.\n");
     }
   }
 
   if ( !(get_keyval (conf, "x", x,
                      colvarvalue (x.type()), colvarparse::parse_silent)) ) {
     cvm::log ("Error: restart file does not contain "
               "the value of the colvar \""+
               name+"\" .\n");
   } else {
     cvm::log ("Restarting collective variable \""+name+"\" from value: "+
               cvm::to_str (x)+"\n");
   }
 
   if (tasks[colvar::task_extended_lagrangian]) {
 
     if ( !(get_keyval (conf, "extended_x", xr,
                        colvarvalue (x.type()), colvarparse::parse_silent)) &&
          !(get_keyval (conf, "extended_v", vr,
                        colvarvalue (x.type()), colvarparse::parse_silent)) ) {
       cvm::log ("Error: restart file does not contain "
                 "\"extended_x\" or \"extended_v\" for the colvar \""+
                 name+"\", but you requested \"extendedLagrangian\".\n");
     }
   }
 
   if (tasks[task_extended_lagrangian]) {
     x_reported = xr;
   } else {
     x_reported = x;
   }
 
   if (tasks[task_output_velocity]) {
 
     if ( !(get_keyval (conf, "v", v_fdiff,
                        colvarvalue (x.type()), colvarparse::parse_silent)) ) {
       cvm::log ("Error: restart file does not contain "
                 "the velocity for the colvar \""+
                 name+"\", but you requested \"outputVelocity\".\n");
     }
 
     if (tasks[task_extended_lagrangian]) {
       v_reported = vr;
     } else {
       v_reported = v_fdiff;
     }
   }
 
   return is;
 }
 
 
 std::istream & colvar::read_traj (std::istream &is)
 {
   size_t const start_pos = is.tellg();
 
   if (tasks[task_output_value]) {
 
     if (!(is >> x)) {
       cvm::log ("Error: in reading the value of colvar \""+
                 this->name+"\" from trajectory.\n");
       is.clear();
       is.seekg (start_pos, std::ios::beg);
       is.setstate (std::ios::failbit);
       return is;
     }
 
     if (tasks[task_extended_lagrangian]) {
       is >> xr;
       x_reported = xr;
     } else {
       x_reported = x;
     }
   }
 
   if (tasks[task_output_velocity]) {
 
     is >> v_fdiff;
 
     if (tasks[task_extended_lagrangian]) {
       is >> vr;
       v_reported = vr;
     } else {
       v_reported = v_fdiff;
     }
   }
 
   if (tasks[task_output_system_force]) {
 
     is >> ft;
 
-    if (tasks[task_extended_lagrangian]) { 
+    if (tasks[task_extended_lagrangian]) {
       is >> fr;
       ft_reported = fr;
     } else {
       ft_reported = ft;
     }
   }
 
   if (tasks[task_output_applied_force]) {
     is >> f;
   }
 
   return is;
 }
 
 
 // ******************** OUTPUT FUNCTIONS ********************
 
 std::ostream & colvar::write_restart (std::ostream &os) {
 
   os << "colvar {\n"
      << "  name " << name << "\n"
      << "  x "
      << std::setprecision (cvm::cv_prec)
      << std::setw (cvm::cv_width)
      << x << "\n";
 
   if (tasks[task_output_velocity]) {
     os << "  v "
        << std::setprecision (cvm::cv_prec)
        << std::setw (cvm::cv_width)
        << v_reported << "\n";
   }
 
   if (tasks[task_extended_lagrangian]) {
     os << "  extended_x "
        << std::setprecision (cvm::cv_prec)
        << std::setw (cvm::cv_width)
        << xr << "\n"
        << "  extended_v "
        << std::setprecision (cvm::cv_prec)
        << std::setw (cvm::cv_width)
        << vr << "\n";
   }
 
   os << "}\n\n";
 
   return os;
-}  
+}
 
 
 std::ostream & colvar::write_traj_label (std::ostream & os)
 {
   size_t const this_cv_width = x.output_width (cvm::cv_width);
 
   os << " ";
 
   if (tasks[task_output_value]) {
 
     os << " "
        << cvm::wrap_string (this->name, this_cv_width);
 
     if (tasks[task_extended_lagrangian]) {
       // restraint center
       os << " r_"
          << cvm::wrap_string (this->name, this_cv_width-2);
     }
   }
 
   if (tasks[task_output_velocity]) {
 
     os << " v_"
        << cvm::wrap_string (this->name, this_cv_width-2);
 
     if (tasks[task_extended_lagrangian]) {
       // restraint center
       os << " vr_"
          << cvm::wrap_string (this->name, this_cv_width-3);
     }
   }
 
   if (tasks[task_output_energy]) {
       os << " Ep_"
          << cvm::wrap_string (this->name, this_cv_width-3)
          << " Ek_"
          << cvm::wrap_string (this->name, this_cv_width-3);
   }
 
   if (tasks[task_output_system_force]) {
 
     os << " fs_"
        << cvm::wrap_string (this->name, this_cv_width-3);
 
     if (tasks[task_extended_lagrangian]) {
       // restraint center
       os << " fr_"
          << cvm::wrap_string (this->name, this_cv_width-3);
     }
   }
 
   if (tasks[task_output_applied_force]) {
     os << " fa_"
        << cvm::wrap_string (this->name, this_cv_width-3);
   }
 
   return os;
 }
 
 
 std::ostream & colvar::write_traj (std::ostream &os)
 {
   os << " ";
 
   if (tasks[task_output_value]) {
 
     if (tasks[task_extended_lagrangian]) {
       os << " "
          << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
          << x;
     }
 
     os << " "
        << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
        << x_reported;
   }
 
   if (tasks[task_output_velocity]) {
 
     if (tasks[task_extended_lagrangian]) {
       os << " "
          << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
          << v_fdiff;
     }
 
     os << " "
        << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
        << v_reported;
   }
 
   if (tasks[task_output_energy]) {
       os << " "
          << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
          << potential_energy
          << " "
          << kinetic_energy;
   }
 
 
   if (tasks[task_output_system_force]) {
 
     if (tasks[task_extended_lagrangian]) {
       os << " "
          << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
          << ft;
     }
 
     os << " "
        << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
        << ft_reported;
   }
 
   if (tasks[task_output_applied_force]) {
     os << " "
        << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
        << f;
   }
 
   return os;
 }
 
 void colvar::write_output_files()
 {
   if (cvm::b_analysis) {
 
     if (acf.size()) {
       cvm::log ("Writing acf to file \""+acf_outfile+"\".\n");
 
       std::ofstream acf_os (acf_outfile.c_str());
       if (! acf_os.good())
         cvm::fatal_error ("Cannot open file \""+acf_outfile+"\".\n");
       write_acf (acf_os);
       acf_os.close();
     }
 
     if (runave_os.good()) {
       runave_os.close();
     }
   }
 }
 
 
 
 // ******************** ANALYSIS FUNCTIONS ********************
 
 void colvar::analyse()
 {
   if (tasks[task_runave]) {
     calc_runave();
   }
 
   if (tasks[task_corrfunc]) {
     calc_acf();
   }
 }
 
 
 inline void history_add_value (size_t const           &history_length,
                                std::list<colvarvalue> &history,
                                colvarvalue const      &new_value)
 {
   history.push_front (new_value);
   if (history.size() > history_length)
     history.pop_back();
 }
 
 inline void history_incr (std::list< std::list<colvarvalue> >           &history,
                           std::list< std::list<colvarvalue> >::iterator &history_p)
 {
-  if ((++history_p) == history.end()) 
+  if ((++history_p) == history.end())
     history_p = history.begin();
 }
 
 
 void colvar::calc_acf()
 {
   // using here an acf_stride-long list of vectors for either
   // coordinates (acf_x_history) or velocities (acf_v_history); each vector can
   // contain up to acf_length values, which are contiguous in memory
   // representation but separated by acf_stride in the time series;
   // the pointer to each vector is changed at every step
 
   if (! (acf_x_history.size() || acf_v_history.size()) ) {
 
     // first-step operations
 
-    colvar *cfcv = (acf_colvar_name.size() ? 
+    colvar *cfcv = (acf_colvar_name.size() ?
                     cvm::colvar_p (acf_colvar_name) :
                     this);
     if (cfcv->type() != this->type())
       cvm::fatal_error ("Error: correlation function between \""+cfcv->name+
                         "\" and \""+this->name+"\" cannot be calculated, "
                         "because their value types are different.\n");
     acf_nframes = 0;
 
     cvm::log ("Colvar \""+this->name+"\": initializing ACF calculation.\n");
 
     if (acf.size() < acf_length+1)
       acf.resize (acf_length+1, 0.0);
 
     switch (acf_type) {
 
     case acf_vel:
       // allocate space for the velocities history
       for (size_t i = 0; i < acf_stride; i++) {
         acf_v_history.push_back (std::list<colvarvalue>());
       }
       acf_v_history_p = acf_v_history.begin();
       break;
 
     case acf_coor:
     case acf_p2coor:
       // allocate space for the coordinates history
       for (size_t i = 0; i < acf_stride; i++) {
         acf_x_history.push_back (std::list<colvarvalue>());
       }
       acf_x_history_p = acf_x_history.begin();
       break;
 
     default:
       break;
     }
 
   } else {
 
-    colvar *cfcv = (acf_colvar_name.size() ? 
+    colvar *cfcv = (acf_colvar_name.size() ?
                     cvm::colvar_p (acf_colvar_name) :
                     this);
 
     switch (acf_type) {
 
     case acf_vel:
 
       if (tasks[task_fdiff_velocity]) {
         // calc() should do this already, but this only happens in a
         // simulation; better do it again in case a trajectory is
         // being read
         v_reported = v_fdiff = fdiff_velocity (x_old, cfcv->value());
       }
 
       calc_vel_acf ((*acf_v_history_p), cfcv->velocity());
       // store this value in the history
       history_add_value (acf_length+acf_offset, *acf_v_history_p, cfcv->velocity());
       // if stride is larger than one, cycle among different histories
       history_incr (acf_v_history, acf_v_history_p);
       break;
 
     case acf_coor:
 
       calc_coor_acf ((*acf_x_history_p), cfcv->value());
       history_add_value (acf_length+acf_offset, *acf_x_history_p, cfcv->value());
       history_incr (acf_x_history, acf_x_history_p);
       break;
 
     case acf_p2coor:
 
       calc_p2coor_acf ((*acf_x_history_p), cfcv->value());
       history_add_value (acf_length+acf_offset, *acf_x_history_p, cfcv->value());
       history_incr (acf_x_history, acf_x_history_p);
       break;
 
     default:
       break;
     }
   }
 
   if (tasks[task_fdiff_velocity]) {
     // set it for the next step
     x_old = x;
   }
 }
 
 
 void colvar::calc_vel_acf (std::list<colvarvalue> &v_list,
                            colvarvalue const      &v)
 {
   // loop over stored velocities and add to the ACF, but only the
   // length is sufficient to hold an entire row of ACF values
   if (v_list.size() >= acf_length+acf_offset) {
     std::list<colvarvalue>::iterator  vs_i = v_list.begin();
     std::vector<cvm::real>::iterator acf_i = acf.begin();
 
     for (size_t i = 0; i < acf_offset; i++)
       vs_i++;
 
     // current vel with itself
     *(acf_i++) += v.norm2();
 
     // inner products of previous velocities with current (acf_i and
     // vs_i are updated)
-    colvarvalue::inner_opt (v, vs_i, v_list.end(), acf_i); 
+    colvarvalue::inner_opt (v, vs_i, v_list.end(), acf_i);
 
     acf_nframes++;
   }
 }
 
 
 void colvar::calc_coor_acf (std::list<colvarvalue> &x_list,
                             colvarvalue const      &x)
 {
   // same as above but for coordinates
   if (x_list.size() >= acf_length+acf_offset) {
     std::list<colvarvalue>::iterator  xs_i = x_list.begin();
     std::vector<cvm::real>::iterator acf_i = acf.begin();
 
     for (size_t i = 0; i < acf_offset; i++)
       xs_i++;
 
     *(acf_i++) += x.norm2();
 
-    colvarvalue::inner_opt (x, xs_i, x_list.end(), acf_i); 
+    colvarvalue::inner_opt (x, xs_i, x_list.end(), acf_i);
 
     acf_nframes++;
   }
 }
 
 
 void colvar::calc_p2coor_acf (std::list<colvarvalue> &x_list,
                               colvarvalue const      &x)
 {
   // same as above but with second order Legendre polynomial instead
   // of just the scalar product
   if (x_list.size() >= acf_length+acf_offset) {
     std::list<colvarvalue>::iterator  xs_i = x_list.begin();
     std::vector<cvm::real>::iterator acf_i = acf.begin();
 
     for (size_t i = 0; i < acf_offset; i++)
       xs_i++;
 
     // value of P2(0) = 1
     *(acf_i++) += 1.0;
 
-    colvarvalue::p2leg_opt (x, xs_i, x_list.end(), acf_i); 
+    colvarvalue::p2leg_opt (x, xs_i, x_list.end(), acf_i);
 
     acf_nframes++;
   }
 }
 
 
 void colvar::write_acf (std::ostream &os)
 {
   if (!acf_nframes)
     cvm::log ("Warning: ACF was not calculated (insufficient frames).\n");
   os.setf (std::ios::scientific, std::ios::floatfield);
   os << "# Autocorrelation function for collective variable \""
      << this->name << "\"\n";
   // one frame is used for normalization, the statistical sample is
   // hence decreased
   os << "# nframes = " << (acf_normalize ?
                            acf_nframes - 1 :
                            acf_nframes) << "\n";
 
   cvm::real const acf_norm = acf.front() / cvm::real (acf_nframes);
   std::vector<cvm::real>::iterator acf_i;
   size_t it = acf_offset;
   for (acf_i = acf.begin(); acf_i != acf.end(); acf_i++) {
     os << std::setw (cvm::it_width) << acf_stride * (it++) << " "
        << std::setprecision (cvm::cv_prec)
        << std::setw (cvm::cv_width)
        << ( acf_normalize ?
             (*acf_i)/(acf_norm * cvm::real (acf_nframes)) :
             (*acf_i)/(cvm::real (acf_nframes)) ) << "\n";
   }
 }
 
 
 void colvar::calc_runave()
 {
   if (!x_history.size()) {
 
     runave.type (x.type());
     runave.reset();
 
     // first-step operations
 
     if (cvm::debug())
       cvm::log ("Colvar \""+this->name+
                 "\": initializing running average calculation.\n");
 
     acf_nframes = 0;
 
     x_history.push_back (std::list<colvarvalue>());
     x_history_p = x_history.begin();
 
   } else {
 
     if ( (cvm::step_relative() % runave_stride) == 0) {
 
       if ((*x_history_p).size() >= runave_length-1) {
 
         runave = x;
         for (std::list<colvarvalue>::iterator xs_i = (*x_history_p).begin();
              xs_i != (*x_history_p).end(); xs_i++) {
           runave += (*xs_i);
         }
         runave *= 1.0 / cvm::real (runave_length);
         runave.apply_constraints();
 
         runave_variance = 0.0;
         runave_variance += this->dist2 (x, runave);
         for (std::list<colvarvalue>::iterator xs_i = (*x_history_p).begin();
              xs_i != (*x_history_p).end(); xs_i++) {
           runave_variance += this->dist2 (x, (*xs_i));
         }
         runave_variance *= 1.0 / cvm::real (runave_length-1);
 
         runave_os << std::setw (cvm::it_width) << cvm::step_relative()
                   << "  "
                   << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
                   << runave << " "
                   << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
                   << std::sqrt (runave_variance) << "\n";
       }
 
       history_add_value (runave_length, *x_history_p, x);
     }
   }
 
 }
 
 
diff --git a/lib/colvars/colvar.h b/lib/colvars/colvar.h
index c16355dd1..6466ac1bf 100644
--- a/lib/colvars/colvar.h
+++ b/lib/colvars/colvar.h
@@ -1,578 +1,578 @@
 // -*- c++ -*-
 
 #ifndef COLVAR_H
 #define COLVAR_H
 
 #include <iostream>
 #include <iomanip>
 #include <cmath>
 
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 #include "colvarparse.h"
 
 
 /// \brief A collective variable (main class); to be defined, it needs
 /// at least one object of a derived class of colvar::cvc; it
 /// calculates and returns a \link colvarvalue \endlink object
 ///
 /// This class parses the configuration, defines the behaviour and
 /// stores the value (\link colvar::x \endlink) and all related data
 /// of a collective variable.  How the value is calculated is defined
 /// in \link colvar::cvc \endlink and its derived classes.  The
 /// \link colvar \endlink object contains pointers to multiple \link
 /// colvar::cvc \endlink derived objects, which can be combined
 /// together into one collective variable.  This makes possible to
 /// implement new collective variables at runtime based on the
 /// existing ones.  Currently, this possibility is limited to a
 /// polynomial, using the coefficients cvc::sup_coeff and the
 /// exponents cvc::sup_np.  In case of non-scalar variables,
 /// only exponents equal to 1 are accepted.
 ///
 /// Please note that most of its members are \link colvarvalue
 /// \endlink objects, i.e. they can handle different data types
 /// together, and must all be set to the same type of colvar::x by
 /// using the colvarvalue::type() member function before using them
 /// together in assignments or other operations; this is usually done
 /// automatically in the constructor.  If you add a new member of
 /// \link colvarvalue \endlink type, you should also add its
 /// initialization line in the \link colvar \endlink constructor.
 
 class colvar : public colvarparse {
 
 public:
 
   /// Name
   std::string name;
 
   /// Type of value
   colvarvalue::Type type() const;
 
   /// \brief Current value (previously obtained from calc() or read_traj())
   colvarvalue const & value() const;
 
   /// \brief Current actual value (not extended DOF)
   colvarvalue const & actual_value() const;
 
   /// \brief Current velocity (previously obtained from calc() or read_traj())
   colvarvalue const & velocity() const;
 
   /// \brief Current system force (previously obtained from calc() or
   /// read_traj()).  Note: this is calculated using the atomic forces
   /// from the last simulation step.
   ///
   /// Total atom forces are read from the MD program, the total force
   /// acting on the collective variable is calculated summing those
   /// from all colvar components, the bias and walls forces are
   /// subtracted.
   colvarvalue const & system_force() const;
 
   /// \brief
 
   /// \brief Typical fluctuation amplitude for this collective
   /// variable (e.g. local width of a free energy basin)
   ///
   /// In metadynamics calculations, \link colvarbias_meta \endlink,
   /// this value is used to calculate the width of a gaussian.  In ABF
   /// calculations, \link colvarbias_abf \endlink, it is used to
   /// calculate the grid spacing in the direction of this collective
   /// variable.
   cvm::real width;
 
   /// \brief True if this \link colvar \endlink is a linear
   /// combination of \link cvc \endlink elements
   bool b_linear;
 
   /// \brief True if all \link cvc \endlink objects are capable
   /// of calculating inverse gradients
   bool b_inverse_gradients;
 
   /// \brief True if all \link cvc \endlink objects are capable
   /// of calculating Jacobian forces
   bool b_Jacobian_force;
 
   /// \brief Options controlling the behaviour of the colvar during
   /// the simulation, which are set from outside the cvcs
   enum task {
     /// \brief Gradients are calculated and temporarily stored, so
     /// that external forces can be applied
     task_gradients,
     /// \brief Collect atomic gradient data from all cvcs into vector
     /// atomic_gradients
     task_collect_gradients,
     /// \brief Calculate the velocity with finite differences
     task_fdiff_velocity,
     /// \brief The system force is calculated, projecting the atomic
     /// forces on the inverse gradients
     task_system_force,
     /// \brief The variable has a harmonic restraint around a moving
     /// center with fictitious mass; bias forces will be applied to
     /// the center
     task_extended_lagrangian,
     /// \brief The extended system coordinate undergoes Langevin
     /// dynamics
     task_langevin,
     /// \brief Output the potential and kinetic energies
     /// (for extended Lagrangian colvars only)
     task_output_energy,
     /// \brief Compute analytically the "force" arising from the
     /// geometric entropy component (for example, that from the angular
     /// states orthogonal to a distance vector)
     task_Jacobian_force,
     /// \brief Report the Jacobian force as part of the system force
     /// if disabled, apply a correction internally to cancel it
     task_report_Jacobian_force,
     /// \brief Output the value to the trajectory file (on by default)
     task_output_value,
     /// \brief Output the velocity to the trajectory file
     task_output_velocity,
     /// \brief Output the applied force to the trajectory file
     task_output_applied_force,
     /// \brief Output the system force to the trajectory file
     task_output_system_force,
     /// \brief A lower boundary is defined
     task_lower_boundary,
     /// \brief An upper boundary is defined
     task_upper_boundary,
     /// \brief Provide a discretization of the values of the colvar to
     /// be used by the biases or in analysis (needs lower and upper
     /// boundary)
     task_grid,
     /// \brief Apply a restraining potential (|x-xb|^2) to the colvar
     /// when it goes below the lower wall
     task_lower_wall,
     /// \brief Apply a restraining potential (|x-xb|^2) to the colvar
     /// when it goes above the upper wall
     task_upper_wall,
     /// \brief Compute running average
     task_runave,
     /// \brief Compute time correlation function
     task_corrfunc,
     /// \brief Number of possible tasks
     task_ntot
   };
 
   /// Tasks performed by this colvar
   bool tasks[task_ntot];
 
 protected:
 
 
   /*
     extended:
     H = H_{0} + \sum_{i} 1/2*\lambda*(S_i(x(t))-s_i(t))^2 \\
     + \sum_{i} 1/2*m_i*(ds_i(t)/dt)^2 \\
     + \sum_{t'<t} W * exp (-1/2*\sum_{i} (s_i(t')-s_i(t))^2/(\delta{}s_i)^2) \\
     + \sum_{w} (\sum_{i}c_{w,i}s_i(t) - D_w)^M/(\Sigma_w)^M
 
     normal:
     H = H_{0} + \sum_{t'<t} W * exp (-1/2*\sum_{i} (S_i(x(t'))-S_i(x(t)))^2/(\delta{}S_i)^2) \\
     + \sum_{w} (\sum_{i}c_{w,i}S_i(t) - D_w)^M/(\Sigma_w)^M
 
     output:
     H = H_{0}   (only output S(x), no forces)
 
     Here:
     S(x(t)) = x
     s(t)    = xr
     DS = Ds = delta
   */
 
 
   /// Value of the colvar
   colvarvalue x;
 
   /// Cached reported value (x may be manipulated)
   colvarvalue x_reported;
 
   /// Finite-difference velocity
   colvarvalue v_fdiff;
 
   inline colvarvalue fdiff_velocity (colvarvalue const &xold,
                                      colvarvalue const &xnew)
   {
     // using the gradient of the square distance to calculate the
     // velocity (non-scalar variables automatically taken into
     // account)
     cvm::real dt = cvm::dt();
     return ( ( (dt > 0.0) ? (1.0/dt) : 1.0 ) *
              0.5 * dist2_lgrad (xnew, xold) );
   }
 
   /// Cached reported velocity
   colvarvalue v_reported;
 
   // Options for task_extended_lagrangian
   /// Restraint center
   colvarvalue xr;
   /// Velocity of the restraint center
   colvarvalue vr;
   /// Mass of the restraint center
   cvm::real ext_mass;
   /// Restraint force constant
   cvm::real ext_force_k;
   /// Friction coefficient for Langevin extended dynamics
   cvm::real ext_gamma;
   /// Amplitude of Gaussian white noise for Langevin extended dynamics
   cvm::real ext_sigma;
-  
+
   /// \brief Harmonic restraint force
   colvarvalue fr;
 
   /// \brief Jacobian force, when task_Jacobian_force is enabled
   colvarvalue fj;
 
   /// Cached reported system force
   colvarvalue ft_reported;
 
 public:
 
 
   /// \brief Bias force; reset_bias_force() should be called before
   /// the biases are updated
   colvarvalue fb;
 
   /// \brief Total \em applied force; fr (if task_extended_lagrangian
   /// is defined), fb (if biases are applied) and the walls' forces
   /// (if defined) contribute to it
   colvarvalue f;
 
   /// \brief Total force, as derived from the atomic trajectory;
   /// should equal the total system force plus \link f \endlink
   colvarvalue ft;
 
 
   /// Period, if it is a constant
   cvm::real period;
 
   /// \brief Same as above, but also takes into account components
   /// with a variable period, such as distanceZ
   bool b_periodic;
 
 
   /// \brief Expand the boundaries of multiples of width, to keep the
   /// value always within range
   bool expand_boundaries;
 
   /// \brief Location of the lower boundary
   colvarvalue lower_boundary;
   /// \brief Location of the lower wall
   colvarvalue lower_wall;
   /// \brief Force constant for the lower boundary potential (|x-xb|^2)
   cvm::real   lower_wall_k;
   /// \brief Whether this colvar has a hard lower boundary
   bool        hard_lower_boundary;
 
   /// \brief Location of the upper boundary
   colvarvalue upper_boundary;
   /// \brief Location of the upper wall
   colvarvalue upper_wall;
   /// \brief Force constant for the upper boundary potential (|x-xb|^2)
   cvm::real   upper_wall_k;
   /// \brief Whether this colvar has a hard upper boundary
   bool        hard_upper_boundary;
 
   /// \brief Is the interval defined by the two boundaries periodic?
   bool periodic_boundaries() const;
 
   /// \brief Is the interval defined by the two boundaries periodic?
   bool periodic_boundaries (colvarvalue const &lb, colvarvalue const &ub) const;
 
 
   /// Constructor
   colvar (std::string const &conf);
 
   /// Enable the specified task
   void enable (colvar::task const &t);
 
   /// Disable the specified task
   void disable (colvar::task const &t);
 
   /// Destructor
   ~colvar();
 
 
   /// \brief Calculate the colvar value and all the other requested
   /// quantities
   void calc();
 
   /// \brief Calculate just the value, and store it in the argument
   void calc_value (colvarvalue &xn);
 
   /// Set the total biasing force to zero
   void reset_bias_force();
 
   /// Add to the total force from biases
   void add_bias_force (colvarvalue const &force);
 
   /// \brief Collect all forces on this colvar, integrate internal
   /// equations of motion of internal degrees of freedom; see also
   /// colvar::communicate_forces()
   /// return colvar energy if extended Lagrandian active
   cvm::real update();
 
   /// \brief Communicate forces (previously calculated in
   /// colvar::update()) to the external degrees of freedom
   void communicate_forces();
 
 
   /// \brief Use the internal metrics (as from \link cvc
   /// \endlink objects) to calculate square distances and gradients
   ///
   /// Handles correctly symmetries and periodic boundary conditions
   cvm::real dist2 (colvarvalue const &x1,
                    colvarvalue const &x2) const;
 
   /// \brief Use the internal metrics (as from \link cvc
   /// \endlink objects) to calculate square distances and gradients
   ///
   /// Handles correctly symmetries and periodic boundary conditions
   colvarvalue dist2_lgrad (colvarvalue const &x1,
                            colvarvalue const &x2) const;
 
   /// \brief Use the internal metrics (as from \link cvc
   /// \endlink objects) to calculate square distances and gradients
   ///
   /// Handles correctly symmetries and periodic boundary conditions
   colvarvalue dist2_rgrad (colvarvalue const &x1,
                            colvarvalue const &x2) const;
 
   /// \brief Use the internal metrics (as from \link cvc
   /// \endlink objects) to compare colvar values
   ///
   /// Handles correctly symmetries and periodic boundary conditions
   cvm::real compare (colvarvalue const &x1,
                      colvarvalue const &x2) const;
 
   /// \brief Use the internal metrics (as from \link cvc
   /// \endlink objects) to wrap a value into a standard interval
   ///
   /// Handles correctly symmetries and periodic boundary conditions
   void wrap (colvarvalue &x) const;
 
 
   /// Read the analysis tasks
   void parse_analysis (std::string const &conf);
   /// Perform analysis tasks
   void analyse();
 
 
   /// Read the value from a collective variable trajectory file
   std::istream & read_traj (std::istream &is);
   /// Output formatted values to the trajectory file
   std::ostream & write_traj (std::ostream &os);
   /// Write a label to the trajectory file (comment line)
   std::ostream & write_traj_label (std::ostream &os);
 
 
   /// Read the collective variable from a restart file
   std::istream & read_restart (std::istream &is);
   /// Write the collective variable to a restart file
   std::ostream & write_restart (std::ostream &os);
 
   /// Write output files (if defined, e.g. in analysis mode)
   void write_output_files();
 
 
 protected:
 
   /// Previous value (to calculate velocities during analysis)
   colvarvalue            x_old;
 
   /// Time series of values and velocities used in correlation
-  /// functions 
+  /// functions
   std::list< std::list<colvarvalue> > acf_x_history, acf_v_history;
   /// Time series of values and velocities used in correlation
   /// functions (pointers)x
   std::list< std::list<colvarvalue> >::iterator acf_x_history_p, acf_v_history_p;
 
   /// Time series of values and velocities used in running averages
   std::list< std::list<colvarvalue> > x_history;
   /// Time series of values and velocities used in correlation
   /// functions (pointers)x
   std::list< std::list<colvarvalue> >::iterator x_history_p;
 
   /// \brief Collective variable with which the correlation is
   /// calculated (default: itself)
   std::string            acf_colvar_name;
   /// Length of autocorrelation function (ACF)
   size_t                 acf_length;
   /// After how many steps the ACF starts
   size_t                 acf_offset;
   /// How many timesteps separate two ACF values
   size_t                 acf_stride;
   /// Number of frames for each ACF point
   size_t                 acf_nframes;
   /// Normalize the ACF to a maximum value of 1?
   bool                   acf_normalize;
   /// ACF values
   std::vector<cvm::real> acf;
   /// Name of the file to write the ACF
   std::string            acf_outfile;
 
   /// Type of autocorrelation function (ACF)
   enum acf_type_e {
     /// Unset type
     acf_notset,
     /// Velocity ACF, scalar product between v(0) and v(t)
     acf_vel,
     /// Coordinate ACF, scalar product between x(0) and x(t)
     acf_coor,
     /// \brief Coordinate ACF, second order Legendre polynomial
     /// between x(0) and x(t) (does not work with scalar numbers)
     acf_p2coor
   };
 
   /// Type of autocorrelation function (ACF)
   acf_type_e             acf_type;
 
   /// \brief Velocity ACF, scalar product between v(0) and v(t)
   void calc_vel_acf (std::list<colvarvalue> &v_history,
                      colvarvalue const      &v);
 
   /// \brief Coordinate ACF, scalar product between x(0) and x(t)
   /// (does not work with scalar numbers)
   void calc_coor_acf (std::list<colvarvalue> &x_history,
                       colvarvalue const      &x);
 
   /// \brief Coordinate ACF, second order Legendre polynomial between
   /// x(0) and x(t) (does not work with scalar numbers)
   void calc_p2coor_acf (std::list<colvarvalue> &x_history,
                         colvarvalue const      &x);
 
   /// Calculate the auto-correlation function (ACF)
   void calc_acf();
   /// Save the ACF to a file
   void write_acf (std::ostream &os);
 
   /// Length of running average series
   size_t         runave_length;
   /// Timesteps to skip between two values in the running average series
   size_t         runave_stride;
   /// Name of the file to write the running average
   std::ofstream  runave_os;
   /// Current value of the running average
   colvarvalue    runave;
   /// Current value of the square deviation from the running average
   cvm::real      runave_variance;
 
   /// Calculate the running average and its standard deviation
   void calc_runave();
 
   /// If extended Lagrangian active: colvar energies (kinetic and harmonic potential)
   cvm::real kinetic_energy;
   cvm::real potential_energy;
 public:
 
 
   // collective variable component base class
   class cvc;
 
   // currently available collective variable components
 
   // scalar colvar components
   class distance;
   class distance_z;
   class distance_xy;
   class distance_inv;
   class angle;
   class dihedral;
   class coordnum;
   class selfcoordnum;
   class h_bond;
   class rmsd;
   class orientation_angle;
   class tilt;
   class spin_angle;
   class gyration;
   class inertia;
   class inertia_z;
   class eigenvector;
   class alpha_dihedrals;
   class alpha_angles;
   class dihedPC;
 
   // non-scalar components
   class distance_vec;
   class distance_dir;
   class orientation;
 
 protected:
 
   /// \brief Array of \link cvc \endlink objects
   std::vector<cvc *> cvcs;
 
   /// \brief Initialize the sorted list of atom IDs for atoms involved
   /// in all cvcs (called when enabling task_collect_gradients)
   void build_atom_list (void);
 
 public:
   /// \brief Sorted array of (zero-based) IDs for all atoms involved
   std::vector<int> atom_ids;
 
   /// \brief Array of atomic gradients collected from all cvcs
   /// with appropriate components, rotations etc.
   /// For scalar variables only!
   std::vector<cvm::rvector> atomic_gradients;
 
   inline size_t n_components () const {
     return cvcs.size();
   }
 };
 
 
 inline colvar * cvm::colvar_p (std::string const &name)
 {
   for (std::vector<colvar *>::iterator cvi = cvm::colvars.begin();
        cvi != cvm::colvars.end();
        cvi++) {
     if ((*cvi)->name == name) {
       return (*cvi);
     }
   }
   return NULL;
 }
 
 
 inline colvarvalue::Type colvar::type() const
 {
   return x.type();
 }
 
 
 inline colvarvalue const & colvar::value() const
 {
   return x_reported;
 }
 
 
 inline colvarvalue const & colvar::actual_value() const
 {
   return x;
 }
 
 
 inline colvarvalue const & colvar::velocity() const
 {
   return v_reported;
 }
 
 
 inline colvarvalue const & colvar::system_force() const
 {
   return ft_reported;
 }
 
 
 inline void colvar::add_bias_force (colvarvalue const &force)
 {
   fb += force;
 }
 
 
 inline void colvar::reset_bias_force() {
   fb.reset();
 }
 
 #endif
 
diff --git a/lib/colvars/colvaratoms.cpp b/lib/colvars/colvaratoms.cpp
index 34b171e08..fdfb7c1e1 100644
--- a/lib/colvars/colvaratoms.cpp
+++ b/lib/colvars/colvaratoms.cpp
@@ -1,844 +1,844 @@
 #include "colvarmodule.h"
 #include "colvarparse.h"
 #include "colvaratoms.h"
 
 
 // member functions of the "atom" class depend tightly on the MD interface, and are
 // thus defined in colvarproxy_xxx.cpp
 
 // in this file only atom_group functions are defined
 
 
 // Note: "conf" is the configuration of the cvc who is using this atom group;
 // "key" is the name of the atom group (e.g. "atoms", "group1", "group2", ...)
 cvm::atom_group::atom_group (std::string const &conf,
                              char const        *key)
   : b_center (false), b_rotate (false), b_user_defined_fit (false),
     ref_pos_group (NULL),
     b_fit_gradients (false),
     noforce (false)
 {
   cvm::log ("Defining atom group \""+
             std::string (key)+"\".\n");
   // real work is done by parse
   parse (conf, key);
 }
 
 
 cvm::atom_group::atom_group (std::vector<cvm::atom> const &atoms)
-  : b_dummy (false), b_center (false), b_rotate (false), 
-    ref_pos_group (NULL), b_fit_gradients (false), 
+  : b_dummy (false), b_center (false), b_rotate (false),
+    ref_pos_group (NULL), b_fit_gradients (false),
     noforce (false)
 {
   this->reserve (atoms.size());
   for (size_t i = 0; i < atoms.size(); i++) {
     this->push_back (atoms[i]);
   }
   total_mass = 0.0;
   for (cvm::atom_iter ai = this->begin();
        ai != this->end(); ai++) {
     total_mass += ai->mass;
   }
 }
 
 
 cvm::atom_group::atom_group()
-  : b_dummy (false), b_center (false), b_rotate (false), 
-    ref_pos_group (NULL), b_fit_gradients (false), 
+  : b_dummy (false), b_center (false), b_rotate (false),
+    ref_pos_group (NULL), b_fit_gradients (false),
     noforce (false)
 {
   total_mass = 0.0;
 }
 
 
 cvm::atom_group::~atom_group()
 {
   if (ref_pos_group) {
     delete ref_pos_group;
     ref_pos_group = NULL;
   }
 }
 
 
 void cvm::atom_group::add_atom (cvm::atom const &a)
 {
   if (b_dummy) {
     cvm::fatal_error ("Error: cannot add atoms to a dummy group.\n");
   } else {
     this->push_back (a);
     total_mass += a.mass;
   }
 }
 
 
 void cvm::atom_group::parse (std::string const &conf,
                              char const        *key)
 {
   std::string group_conf;
 
   // save_delimiters is set to false for this call, because "conf" is
   // not the config string of this group, but of its parent object
   // (which has already taken care of the delimiters)
   save_delimiters = false;
   key_lookup (conf, key, group_conf, dummy_pos);
   // restoring the normal value, because we do want keywords checked
   // inside "group_conf"
   save_delimiters = true;
 
   if (group_conf.size() == 0) {
     cvm::fatal_error ("Error: atom group \""+
                       std::string (key)+"\" is set, but "
                       "has no definition.\n");
   }
 
   cvm::increase_depth();
 
   cvm::log ("Initializing atom group \""+std::string (key)+"\".\n");
 
   // whether or not to include messages in the log
   // colvarparse::Parse_Mode mode = parse_silent;
   // {
   //   bool b_verbose;
   //   get_keyval (group_conf, "verboseOutput", b_verbose, false, parse_silent);
   //   if (b_verbose) mode = parse_normal;
   // }
   colvarparse::Parse_Mode mode = parse_normal;
 
   {
     //    std::vector<int> atom_indexes;
     std::string numbers_conf = "";
     size_t pos = 0;
     std::vector<int> atom_indexes;
     while (key_lookup (group_conf, "atomNumbers", numbers_conf, pos)) {
       if (numbers_conf.size()) {
         std::istringstream is (numbers_conf);
         int ia;
         while (is >> ia) {
           atom_indexes.push_back (ia);
         }
       }
 
       if (atom_indexes.size()) {
         this->reserve (this->size()+atom_indexes.size());
         for (size_t i = 0; i < atom_indexes.size(); i++) {
           this->push_back (cvm::atom (atom_indexes[i]));
         }
       } else
         cvm::fatal_error ("Error: no numbers provided for \""
                           "atomNumbers\".\n");
 
       atom_indexes.clear();
     }
 
     std::string index_group_name;
     if (get_keyval (group_conf, "indexGroup", index_group_name)) {
       // use an index group from the index file read globally
       std::list<std::string>::iterator names_i = cvm::index_group_names.begin();
       std::list<std::vector<int> >::iterator index_groups_i = cvm::index_groups.begin();
       for ( ; names_i != cvm::index_group_names.end() ; names_i++, index_groups_i++) {
         if (*names_i == index_group_name)
           break;
       }
       if (names_i == cvm::index_group_names.end()) {
         cvm::fatal_error ("Error: could not find index group "+
                           index_group_name+" among those provided by the index file.\n");
       }
       this->reserve (index_groups_i->size());
       for (size_t i = 0; i < index_groups_i->size(); i++) {
         this->push_back (cvm::atom ((*index_groups_i)[i]));
       }
     }
   }
 
   {
     std::string range_conf = "";
     size_t pos = 0;
     while (key_lookup (group_conf, "atomNumbersRange",
                        range_conf, pos)) {
 
       if (range_conf.size()) {
         std::istringstream is (range_conf);
         int initial, final;
         char dash;
         if ( (is >> initial) && (initial > 0) &&
              (is >> dash) && (dash == '-') &&
              (is >> final) && (final > 0) ) {
           for (int anum = initial; anum <= final; anum++) {
             this->push_back (cvm::atom (anum));
           }
           range_conf = "";
           continue;
         }
       }
 
       cvm::fatal_error ("Error: no valid definition for \""
                         "atomNumbersRange\", \""+
                         range_conf+"\".\n");
     }
   }
 
   std::vector<std::string> psf_segids;
   get_keyval (group_conf, "psfSegID", psf_segids, std::vector<std::string> (), mode);
   for (std::vector<std::string>::iterator psii = psf_segids.begin();
        psii < psf_segids.end(); psii++) {
 
     if ( (psii->size() == 0) || (psii->size() > 4) ) {
       cvm::fatal_error ("Error: invalid segmend identifier provided, \""+
                         (*psii)+"\".\n");
     }
   }
 
   {
     std::string range_conf = "";
     size_t pos = 0;
     size_t range_count = 0;
     std::vector<std::string>::iterator psii = psf_segids.begin();
     while (key_lookup (group_conf, "atomNameResidueRange",
                        range_conf, pos)) {
       range_count++;
 
       if (range_count > psf_segids.size()) {
         cvm::fatal_error ("Error: more instances of \"atomNameResidueRange\" than "
                           "values of \"psfSegID\".\n");
       }
 
       std::string const &psf_segid = psf_segids.size() ? *psii : std::string ("");
 
       if (range_conf.size()) {
 
         std::istringstream is (range_conf);
         std::string atom_name;
         int initial, final;
         char dash;
         if ( (is >> atom_name) && (atom_name.size())  &&
              (is >> initial) && (initial > 0) &&
              (is >> dash) && (dash == '-') &&
              (is >> final) && (final > 0) ) {
           for (int resid = initial; resid <= final; resid++) {
             this->push_back (cvm::atom (resid, atom_name, psf_segid));
           }
           range_conf = "";
         } else {
           cvm::fatal_error ("Error: cannot parse definition for \""
                             "atomNameResidueRange\", \""+
                             range_conf+"\".\n");
         }
 
       } else {
         cvm::fatal_error ("Error: atomNameResidueRange with empty definition.\n");
       }
 
       if (psf_segid.size())
         psii++;
     }
   }
 
   {
     // read the atoms from a file
     std::string atoms_file_name;
     if (get_keyval (group_conf, "atomsFile", atoms_file_name, std::string (""), mode)) {
 
       std::string atoms_col;
       if (!get_keyval (group_conf, "atomsCol", atoms_col, std::string (""), mode)) {
         cvm::fatal_error ("Error: parameter atomsCol is required if atomsFile is set.\n");
       }
 
       double atoms_col_value;
       bool const atoms_col_value_defined = get_keyval (group_conf, "atomsColValue", atoms_col_value, 0.0, mode);
       if (atoms_col_value_defined && (!atoms_col_value))
         cvm::fatal_error ("Error: atomsColValue, "
                           "if provided, must be non-zero.\n");
 
       cvm::load_atoms (atoms_file_name.c_str(), *this, atoms_col, atoms_col_value);
     }
   }
 
-  for (std::vector<cvm::atom>::iterator a1 = this->begin(); 
+  for (std::vector<cvm::atom>::iterator a1 = this->begin();
        a1 != this->end(); a1++) {
     std::vector<cvm::atom>::iterator a2 = a1;
     ++a2;
     for ( ; a2 != this->end(); a2++) {
       if (a1->id == a2->id) {
         if (cvm::debug())
           cvm::log ("Discarding doubly counted atom with number "+
                     cvm::to_str (a1->id+1)+".\n");
         a2 = this->erase (a2);
         if (a2 == this->end())
           break;
       }
     }
   }
 
   if (get_keyval (group_conf, "dummyAtom", dummy_atom_pos, cvm::atom_pos(), mode)) {
     b_dummy = true;
     this->total_mass = 1.0;
-  } else 
+  } else
     b_dummy = false;
 
-  if (b_dummy && (this->size())) 
+  if (b_dummy && (this->size()))
     cvm::fatal_error ("Error: cannot set up group \""+
                       std::string (key)+"\" as a dummy atom "
                       "and provide it with atom definitions.\n");
 
 #if (! defined (COLVARS_STANDALONE))
   if ( (!b_dummy) && (!cvm::b_analysis) && (!(this->size())) ) {
     cvm::fatal_error ("Error: no atoms defined for atom group \""+
                       std::string (key)+"\".\n");
   }
 #endif
 
   if (!b_dummy) {
     this->total_mass = 0.0;
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       this->total_mass += ai->mass;
     }
   }
 
   if (!b_dummy) {
     bool enable_forces = true;
     // disableForces is deprecated
     if (get_keyval (group_conf, "enableForces", enable_forces, true, mode)) {
       noforce = !enable_forces;
     } else {
       get_keyval (group_conf, "disableForces", noforce, false, mode);
     }
   }
 
   // FITTING OPTIONS
 
   bool b_defined_center = get_keyval (group_conf, "centerReference", b_center, false, mode);
   bool b_defined_rotate = get_keyval (group_conf, "rotateReference", b_rotate, false, mode);
   // is the user setting explicit options?
   b_user_defined_fit = b_defined_center || b_defined_rotate;
 
   get_keyval (group_conf, "enableFitGradients", b_fit_gradients, true, mode);
 
   if (b_center || b_rotate) {
 
     if (b_dummy)
       cvm::fatal_error ("Error: centerReference or rotateReference "
                         "cannot be defined for a dummy atom.\n");
 
     if (key_lookup (group_conf, "refPositionsGroup")) {
       // instead of this group, define another group to compute the fit
       if (ref_pos_group) {
         cvm::fatal_error ("Error: the atom group \""+
                           std::string (key)+"\" has already a reference group "
                           "for the rototranslational fit, which was communicated by the "
                           "colvar component.  You should not use refPositionsGroup "
                           "in this case.\n");
       }
       cvm::log ("Within atom group \""+std::string (key)+"\":\n");
       ref_pos_group = new atom_group (group_conf, "refPositionsGroup");
     }
 
     atom_group *group_for_fit = ref_pos_group ? ref_pos_group : this;
 
     get_keyval (group_conf, "refPositions", ref_pos, ref_pos, mode);
 
     std::string ref_pos_file;
     if (get_keyval (group_conf, "refPositionsFile", ref_pos_file, std::string (""), mode)) {
 
       if (ref_pos.size()) {
         cvm::fatal_error ("Error: cannot specify \"refPositionsFile\" and "
                           "\"refPositions\" at the same time.\n");
       }
 
       std::string ref_pos_col;
       double ref_pos_col_value;
-      
+
       if (get_keyval (group_conf, "refPositionsCol", ref_pos_col, std::string (""), mode)) {
         // if provided, use PDB column to select coordinates
         bool found = get_keyval (group_conf, "refPositionsColValue", ref_pos_col_value, 0.0, mode);
         if (found && !ref_pos_col_value)
           cvm::fatal_error ("Error: refPositionsColValue, "
                             "if provided, must be non-zero.\n");
       } else {
         // if not, rely on existing atom indices for the group
         group_for_fit->create_sorted_ids();
         ref_pos.resize (group_for_fit->size());
       }
 
       cvm::load_coords (ref_pos_file.c_str(), ref_pos, group_for_fit->sorted_ids,
                         ref_pos_col, ref_pos_col_value);
     }
 
     if (ref_pos.size()) {
 
       if (b_rotate) {
         if (ref_pos.size() != group_for_fit->size())
           cvm::fatal_error ("Error: the number of reference positions provided ("+
                             cvm::to_str (ref_pos.size())+
                             ") does not match the number of atoms within \""+
                             std::string (key)+
                             "\" ("+cvm::to_str (group_for_fit->size())+
                             "): to perform a rotational fit, "+
                             "these numbers should be equal.\n");
       }
 
       // save the center of geometry of ref_pos and subtract it
       center_ref_pos();
 
     } else {
 #if (! defined (COLVARS_STANDALONE))
       cvm::fatal_error ("Error: no reference positions provided.\n");
 #endif
     }
 
     if (b_fit_gradients) {
       group_for_fit->fit_gradients.assign (group_for_fit->size(), cvm::atom_pos (0.0, 0.0, 0.0));
       rot.request_group1_gradients (group_for_fit->size());
     }
 
     if (b_rotate && !noforce) {
       cvm::log ("Warning: atom group \""+std::string (key)+
                 "\" will be aligned to a fixed orientation given by the reference positions provided.  "
                 "If the internal structure of the group changes too much (i.e. its RMSD is comparable "
                 "to its radius of gyration), the optimal rotation and its gradients may become discontinuous.  "
                 "If that happens, use refPositionsGroup (or a different definition for it if already defined) "
                 "to align the coordinates.\n");
       // initialize rot member data
       rot.request_group1_gradients (this->size());
     }
 
   }
 
   if (cvm::debug())
     cvm::log ("Done initializing atom group with name \""+
               std::string (key)+"\".\n");
 
   this->check_keywords (group_conf, key);
 
   cvm::log ("Atom group \""+std::string (key)+"\" defined, "+
             cvm::to_str (this->size())+" atoms initialized: total mass = "+
             cvm::to_str (this->total_mass)+".\n");
 
   cvm::decrease_depth();
 }
 
 
 void cvm::atom_group::create_sorted_ids (void)
 {
   // Only do the work if the vector is not yet populated
   if (sorted_ids.size())
     return;
 
   std::list<int> temp_id_list;
   for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) {
     temp_id_list.push_back (ai->id);
   }
   temp_id_list.sort();
   temp_id_list.unique();
   if (temp_id_list.size() != this->size()) {
     cvm::fatal_error ("Error: duplicate atom IDs in atom group? (found " +
                       cvm::to_str(temp_id_list.size()) +
                       " unique atom IDs instead of" +
                       cvm::to_str(this->size()) + ").\n");
   }
   sorted_ids = std::vector<int> (temp_id_list.begin(), temp_id_list.end());
   return;
 }
 
 void cvm::atom_group::center_ref_pos()
 {
   // save the center of geometry of ref_pos and then subtract it from
   // them; in this way it will be possible to use ref_pos also for
   // the rotational fit
   // This is called either by atom_group::parse or by CVCs that set
   // reference positions (eg. RMSD, eigenvector)
   ref_pos_cog = cvm::atom_pos (0.0, 0.0, 0.0);
   std::vector<cvm::atom_pos>::iterator pi = ref_pos.begin();
   for ( ; pi != ref_pos.end(); pi++) {
     ref_pos_cog += *pi;
   }
   ref_pos_cog /= (cvm::real) ref_pos.size();
   for (std::vector<cvm::atom_pos>::iterator pi = ref_pos.begin();
        pi != ref_pos.end(); pi++) {
     (*pi) -= ref_pos_cog;
   }
 }
 
 void cvm::atom_group::read_positions()
 {
   if (b_dummy) return;
 
   for (cvm::atom_iter ai = this->begin();
        ai != this->end(); ai++) {
     ai->read_position();
   }
 
   if (ref_pos_group)
     ref_pos_group->read_positions();
 }
 
 void cvm::atom_group::calc_apply_roto_translation()
 {
   atom_group *fit_group = ref_pos_group ? ref_pos_group : this;
 
   if (b_center) {
     // center on the origin first
     cvm::atom_pos const cog = fit_group->center_of_geometry();
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       ai->pos -= cog;
     }
   }
 
   if (b_rotate) {
     // rotate the group (around the center of geometry if b_center is
     // true, around the origin otherwise)
     rot.calc_optimal_rotation (fit_group->positions(), ref_pos);
 
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       ai->pos = rot.rotate (ai->pos);
     }
   }
 
   if (b_center) {
     // align with the center of geometry of ref_pos
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       ai->pos += ref_pos_cog;
     }
   }
 }
 
-void cvm::atom_group::apply_translation (cvm::rvector const &t) 
+void cvm::atom_group::apply_translation (cvm::rvector const &t)
 {
   if (b_dummy) return;
 
   for (cvm::atom_iter ai = this->begin();
        ai != this->end(); ai++) {
     ai->pos += t;
   }
 }
 
-void cvm::atom_group::apply_rotation (cvm::rotation const &rot) 
+void cvm::atom_group::apply_rotation (cvm::rotation const &rot)
 {
   if (b_dummy) return;
 
   for (cvm::atom_iter ai = this->begin();
        ai != this->end(); ai++) {
     ai->pos = rot.rotate (ai->pos);
   }
 }
 
 
 void cvm::atom_group::read_velocities()
 {
   if (b_dummy) return;
 
   if (b_rotate) {
 
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       ai->read_velocity();
       ai->vel = rot.rotate (ai->vel);
     }
 
   } else {
 
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       ai->read_velocity();
     }
   }
 }
 
 void cvm::atom_group::read_system_forces()
 {
   if (b_dummy) return;
 
   if (b_rotate) {
 
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       ai->read_system_force();
       ai->system_force = rot.rotate (ai->system_force);
     }
 
   } else {
 
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       ai->read_system_force();
     }
   }
 }
 
 cvm::atom_pos cvm::atom_group::center_of_geometry() const
 {
   if (b_dummy)
     return dummy_atom_pos;
 
   cvm::atom_pos cog (0.0, 0.0, 0.0);
   for (cvm::atom_const_iter ai = this->begin();
        ai != this->end(); ai++) {
     cog += ai->pos;
   }
   cog /= this->size();
   return cog;
 }
 
 cvm::atom_pos cvm::atom_group::center_of_mass() const
 {
   if (b_dummy)
     return dummy_atom_pos;
 
   cvm::atom_pos com (0.0, 0.0, 0.0);
   for (cvm::atom_const_iter ai = this->begin();
        ai != this->end(); ai++) {
     com += ai->mass * ai->pos;
   }
   com /= this->total_mass;
   return com;
 }
 
 
 void cvm::atom_group::set_weighted_gradient (cvm::rvector const &grad)
 {
   if (b_dummy) return;
 
   for (cvm::atom_iter ai = this->begin();
        ai != this->end(); ai++) {
     ai->grad = (ai->mass/this->total_mass) * grad;
   }
 }
 
 
 void cvm::atom_group::calc_fit_gradients()
 {
   if (b_dummy) return;
 
   if ((!b_center) && (!b_rotate)) return; // no fit
 
   if (cvm::debug())
     cvm::log ("Calculating fit gradients.\n");
 
   atom_group *group_for_fit = ref_pos_group ? ref_pos_group : this;
   group_for_fit->fit_gradients.assign (group_for_fit->size(), cvm::rvector (0.0, 0.0, 0.0));
 
   if (b_center) {
     // add the center of geometry contribution to the gradients
     for (size_t i = 0; i < this->size(); i++) {
       // need to bring the gradients in original frame first
       cvm::rvector const atom_grad = b_rotate ?
         (rot.inverse()).rotate ((*this)[i].grad) :
         (*this)[i].grad;
       for (size_t j = 0; j < group_for_fit->size(); j++) {
         group_for_fit->fit_gradients[j] +=
           (-1.0)/(cvm::real (group_for_fit->size())) *
           atom_grad;
       }
     }
   }
 
   if (b_rotate) {
-    
+
     // add the rotation matrix contribution to the gradients
     cvm::rotation const rot_inv = rot.inverse();
     cvm::atom_pos const cog = this->center_of_geometry();
-    
+
     for (size_t i = 0; i < this->size(); i++) {
 
       cvm::atom_pos const pos_orig = rot_inv.rotate ((b_center ? ((*this)[i].pos - cog) : ((*this)[i].pos)));
 
       for (size_t j = 0; j < group_for_fit->size(); j++) {
         // calculate \partial(R(q) \vec{x}_i)/\partial q) \cdot \partial\xi/\partial\vec{x}_i
         cvm::quaternion const dxdq =
           rot.q.position_derivative_inner (pos_orig, (*this)[i].grad);
         // multiply by \cdot {\partial q}/\partial\vec{x}_j and add it to the fit gradients
         for (size_t iq = 0; iq < 4; iq++) {
           group_for_fit->fit_gradients[j] += dxdq[iq] * rot.dQ0_1[j][iq];
         }
       }
     }
   }
   if (cvm::debug())
     cvm::log ("Done calculating fit gradients.\n");
 }
 
 
 std::vector<cvm::atom_pos> cvm::atom_group::positions() const
 {
   if (b_dummy)
     cvm::fatal_error ("Error: positions are not available "
                       "from a dummy atom group.\n");
 
   std::vector<cvm::atom_pos> x (this->size(), 0.0);
   cvm::atom_const_iter ai = this->begin();
   std::vector<cvm::atom_pos>::iterator xi = x.begin();
   for ( ; ai != this->end(); xi++, ai++) {
     *xi = ai->pos;
   }
   return x;
 }
 
 std::vector<cvm::atom_pos> cvm::atom_group::positions_shifted (cvm::rvector const &shift) const
 {
   if (b_dummy)
     cvm::fatal_error ("Error: positions are not available "
                       "from a dummy atom group.\n");
 
   std::vector<cvm::atom_pos> x (this->size(), 0.0);
   cvm::atom_const_iter ai = this->begin();
   std::vector<cvm::atom_pos>::iterator xi = x.begin();
   for ( ; ai != this->end(); xi++, ai++) {
     *xi = (ai->pos + shift);
   }
   return x;
 }
 
 std::vector<cvm::rvector> cvm::atom_group::velocities() const
 {
   if (b_dummy)
     cvm::fatal_error ("Error: velocities are not available "
                       "from a dummy atom group.\n");
 
   std::vector<cvm::rvector> v (this->size(), 0.0);
   cvm::atom_const_iter ai = this->begin();
   std::vector<cvm::atom_pos>::iterator vi = v.begin();
   for ( ; ai != this->end(); vi++, ai++) {
     *vi = ai->vel;
   }
   return v;
 }
 
 std::vector<cvm::rvector> cvm::atom_group::system_forces() const
 {
   if (b_dummy)
     cvm::fatal_error ("Error: system forces are not available "
                       "from a dummy atom group.\n");
 
   std::vector<cvm::rvector> f (this->size(), 0.0);
   cvm::atom_const_iter ai = this->begin();
   std::vector<cvm::atom_pos>::iterator fi = f.begin();
   for ( ; ai != this->end(); fi++, ai++) {
     *fi = ai->system_force;
   }
   return f;
 }
 
 cvm::rvector cvm::atom_group::system_force() const
 {
   if (b_dummy)
     cvm::fatal_error ("Error: system forces are not available "
                       "from a dummy atom group.\n");
 
   cvm::rvector f (0.0);
   for (cvm::atom_const_iter ai = this->begin(); ai != this->end(); ai++) {
     f += ai->system_force;
   }
   return f;
 }
 
 
 void cvm::atom_group::apply_colvar_force (cvm::real const &force)
 {
   if (b_dummy)
     return;
 
   if (noforce)
     cvm::fatal_error ("Error: sending a force to a group that has "
                       "\"enableForces\" set to off.\n");
 
   if (b_rotate) {
 
     // rotate forces back to the original frame
     cvm::rotation const rot_inv = rot.inverse();
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       ai->apply_force (rot_inv.rotate (force * ai->grad));
     }
 
   } else {
 
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       ai->apply_force (force * ai->grad);
     }
   }
 
   if ((b_center || b_rotate) && b_fit_gradients) {
 
     atom_group *group_for_fit = ref_pos_group ? ref_pos_group : this;
 
     // add the contribution from the roto-translational fit to the gradients
     if (b_rotate) {
       // rotate forces back to the original frame
       cvm::rotation const rot_inv = rot.inverse();
       for (size_t j = 0; j < group_for_fit->size(); j++) {
         (*group_for_fit)[j].apply_force (rot_inv.rotate (force * group_for_fit->fit_gradients[j]));
       }
     } else {
       for (size_t j = 0; j < group_for_fit->size(); j++) {
         (*group_for_fit)[j].apply_force (force * group_for_fit->fit_gradients[j]);
       }
     }
   }
 
 }
 
 
 void cvm::atom_group::apply_force (cvm::rvector const &force)
 {
   if (b_dummy)
     return;
 
   if (noforce)
     cvm::fatal_error ("Error: sending a force to a group that has "
                       "\"disableForces\" defined.\n");
 
   if (b_rotate) {
 
     cvm::rotation const rot_inv = rot.inverse();
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       ai->apply_force (rot_inv.rotate ((ai->mass/this->total_mass) * force));
     }
 
   } else {
 
     for (cvm::atom_iter ai = this->begin();
          ai != this->end(); ai++) {
       ai->apply_force ((ai->mass/this->total_mass) * force);
-    } 
+    }
   }
 }
 
 
 void cvm::atom_group::apply_forces (std::vector<cvm::rvector> const &forces)
 {
   if (b_dummy)
     return;
 
   if (noforce)
     cvm::fatal_error ("Error: sending a force to a group that has "
                       "\"disableForces\" defined.\n");
 
   if (forces.size() != this->size()) {
     cvm::fatal_error ("Error: trying to apply an array of forces to an atom "
                       "group which does not have the same length.\n");
   }
 
   if (b_rotate) {
 
     cvm::rotation const rot_inv = rot.inverse();
     cvm::atom_iter ai = this->begin();
     std::vector<cvm::rvector>::const_iterator fi = forces.begin();
     for ( ; ai != this->end(); fi++, ai++) {
       ai->apply_force (rot_inv.rotate (*fi));
     }
 
   } else {
 
     cvm::atom_iter ai = this->begin();
     std::vector<cvm::rvector>::const_iterator fi = forces.begin();
     for ( ; ai != this->end(); fi++, ai++) {
       ai->apply_force (*fi);
     }
   }
 }
 
diff --git a/lib/colvars/colvaratoms.h b/lib/colvars/colvaratoms.h
index 3cca61baa..96e383a91 100644
--- a/lib/colvars/colvaratoms.h
+++ b/lib/colvars/colvaratoms.h
@@ -1,327 +1,327 @@
 // -*- c++ -*-
 
 #ifndef COLVARATOMS_H
 #define COLVARATOMS_H
 
 #include "colvarmodule.h"
 #include "colvarparse.h"
 
 /// \brief Stores numeric id, mass and all mutable data for an atom,
 /// mostly used by a \link cvc \endlink
-/// 
+///
 /// This class may be used (although not necessarily) to keep atomic
 /// data (id, mass, position and collective variable derivatives)
 /// altogether.  There may be multiple instances with identical
 /// numeric id, all acting independently: forces communicated through
 /// these instances will be summed together.
 ///
 /// Read/write operations depend on the underlying code: hence, some
 /// member functions are defined in colvarproxy_xxx.h.
 class colvarmodule::atom {
 
 protected:
 
   /// \brief Index in the list of atoms involved by the colvars (\b
   /// NOT in the global topology!)
   int           index;
 
 public:
 
   /// Internal identifier (zero-based)
   int              id;
 
   /// Mass
   cvm::real      mass;
 
   /// \brief Current position (copied from the program, can be
   /// manipulated)
   cvm::atom_pos   pos;
 
   /// \brief Current velocity (copied from the program, can be
   /// manipulated)
   cvm::rvector    vel;
 
   /// \brief System force at the previous step (copied from the
   /// program, can be manipulated)
   cvm::rvector    system_force;
 
   /// \brief Gradient of a scalar collective variable with respect
   /// to this atom
-  /// 
+  ///
   /// This can only handle a scalar collective variable (i.e. when
   /// the \link colvarvalue::real_value \endlink member is used
   /// from the \link colvarvalue \endlink class), which is also the
   /// most frequent case. For more complex types of \link
   /// colvarvalue \endlink objects, atomic gradients should be
   /// defined within the specific \link cvc \endlink
   /// implementation
   cvm::rvector   grad;
 
   /// \brief Default constructor, setting id and index to invalid numbers
   atom() : id (-1), index (-1) { reset_data(); }
 
   /// \brief Initialize an atom for collective variable calculation
   /// and get its internal identifier \param atom_number Atom index in
   /// the system topology (starting from 1)
   atom (int const &atom_number);
 
   /// \brief Initialize an atom for collective variable calculation
   /// and get its internal identifier \param residue Residue number
   /// \param atom_name Name of the atom in the residue \param
   /// segment_id For PSF topologies, the segment identifier; for other
   /// type of topologies, may not be required
   atom (cvm::residue_id const &residue,
         std::string const     &atom_name,
         std::string const     &segment_id = std::string (""));
 
   /// Copy constructor
   atom (atom const &a);
 
   /// Destructor
   ~atom();
 
   /// Set non-constant data (everything except id and mass) to zero
   inline void reset_data() {
     pos = atom_pos (0.0);
     vel = grad = system_force = rvector (0.0);
   }
 
   /// Get the current position
   void read_position();
 
   /// Get the current velocity
   void read_velocity();
 
   /// Get the system force
   void read_system_force();
 
   /// \brief Apply a force to the atom
   ///
   /// The force will be used later by the MD integrator, the
   /// collective variables module does not integrate equations of
   /// motion.  Multiple calls to this function by either the same
   /// \link atom \endlink object or different objects with identical
   /// \link id \endlink, will all add to the existing MD force.
   void apply_force (cvm::rvector const &new_force);
 };
 
 
 
 
 /// \brief Group of \link atom \endlink objects, mostly used by a
 /// \link cvc \endlink
 ///
 /// This class inherits from \link colvarparse \endlink and from
 /// std::vector<colvarmodule::atom>, and hence all functions and
 /// operators (including the bracket operator, group[i]) can be used
 /// on an \link atom_group \endlink object.  It can be initialized as
 /// a vector, or by parsing a keyword in the configuration.
 class colvarmodule::atom_group
   : public std::vector<cvm::atom>,
     public colvarparse
 {
 public:
   // Note: all members here are kept public, to make possible to any
   // object accessing and manipulating them
 
 
   /// \brief If this option is on, this group merely acts as a wrapper
   /// for a fixed position; any calls to atoms within or to
   /// functions that return disaggregated data will fail
   bool b_dummy;
   /// \brief dummy atom position
   cvm::atom_pos dummy_atom_pos;
 
   /// Sorted list of zero-based (internal) atom ids
   /// (populated on-demand by create_sorted_ids)
   std::vector<int> sorted_ids;
 
   /// Allocates and populates the sorted list of atom ids
   void create_sorted_ids (void);
-  
+
 
   /// \brief When updating atomic coordinates, translate them to align with the
   /// center of mass of the reference coordinates
   bool b_center;
 
   /// \brief When updating atom coordinates (and after
   /// centering them if b_center is set), rotate the group to
   /// align with the reference coordinates.
   ///
   /// Note: gradients will be calculated in the rotated frame: when
   /// forces will be applied, they will rotated back to the original
   /// frame
   bool b_rotate;
   /// The rotation calculated automatically if b_rotate is defined
   cvm::rotation rot;
 
   /// \brief Indicates that the user has explicitly set centerReference or
   /// rotateReference, and the corresponding reference:
   /// cvc's (eg rmsd, eigenvector) will not override the user's choice
   bool b_user_defined_fit;
 
   /// \brief Whether or not the derivatives of the roto-translation
   /// should be included when calculating the colvar's gradients (default: no)
   bool b_fit_gradients;
 
   /// \brief use reference coordinates for b_center or b_rotate
   std::vector<cvm::atom_pos> ref_pos;
 
   /// \brief Center of geometry of the reference coordinates; regardless
   /// of whether b_center is true, ref_pos is centered to zero at
   /// initialization, and ref_pos_cog serves to center the positions
   cvm::atom_pos              ref_pos_cog;
 
   /// \brief If b_center or b_rotate is true, use this group to
   /// define the transformation (default: this group itself)
   atom_group                *ref_pos_group;
-  
+
   /// Total mass of the atom group
   cvm::real total_mass;
 
   /// \brief Don't apply any force on this group (use its coordinates
   /// only to calculate a colvar)
   bool        noforce;
 
 
   /// \brief Initialize the group by looking up its configuration
   /// string in conf and parsing it; this is actually done by parse(),
   /// which is a member function so that a group can be initialized
   /// also after construction
   atom_group (std::string const &conf,
               char const        *key);
 
   /// \brief Initialize the group by looking up its configuration
   /// string in conf and parsing it
   void parse (std::string const &conf,
               char const        *key);
 
   /// \brief Initialize the group after a temporary vector of atoms
   atom_group (std::vector<cvm::atom> const &atoms);
 
-  /// \brief Add an atom to this group  
+  /// \brief Add an atom to this group
   void add_atom (cvm::atom const &a);
 
   /// \brief Default constructor
   atom_group();
 
   /// \brief Destructor
   ~atom_group();
 
   /// \brief Get the current positions; if b_center or b_rotate are
   /// true, calc_apply_roto_translation() will be called too
   void read_positions();
 
   /// \brief (Re)calculate the optimal roto-translation
   void calc_apply_roto_translation();
 
   /// \brief Save center of geometry fo ref positions,
-  /// then subtract it 
+  /// then subtract it
   void center_ref_pos();
 
   /// \brief Move all positions
   void apply_translation (cvm::rvector const &t);
 
   /// \brief Rotate all positions
   void apply_rotation (cvm::rotation const &q);
 
 
   /// \brief Get the current velocities; this must be called always
   /// *after* read_positions(); if b_rotate is defined, the same
   /// rotation applied to the coordinates will be used
   void read_velocities();
 
   /// \brief Get the current system_forces; this must be called always
   /// *after* read_positions(); if b_rotate is defined, the same
   /// rotation applied to the coordinates will be used
   void read_system_forces();
 
   /// Call reset_data() for each atom
   inline void reset_atoms_data()
   {
     for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++)
       ai->reset_data();
     if (ref_pos_group)
       ref_pos_group->reset_atoms_data();
   }
 
   /// \brief Return a copy of the current atom positions
   std::vector<cvm::atom_pos> positions() const;
 
   /// \brief Return a copy of the current atom positions, shifted by a constant vector
   std::vector<cvm::atom_pos> positions_shifted (cvm::rvector const &shift) const;
 
   /// \brief Return the center of geometry of the positions, assuming
   /// that coordinates are already pbc-wrapped
   cvm::atom_pos center_of_geometry() const;
 
   /// \brief Return the center of mass of the positions, assuming that
   /// coordinates are already pbc-wrapped
   cvm::atom_pos center_of_mass() const;
 
   /// \brief Atom positions at the previous step
   std::vector<cvm::atom_pos> old_pos;
 
 
   /// \brief Return a copy of the current atom velocities
   std::vector<cvm::rvector> velocities() const;
 
 
   /// \brief Return a copy of the system forces
   std::vector<cvm::rvector> system_forces() const;
   /// \brief Return a copy of the aggregated total force on the group
   cvm::rvector system_force() const;
 
 
   /// \brief Shorthand: save the specified gradient on each atom,
   /// weighting with the atom mass (mostly used in combination with
   /// \link center_of_mass() \endlink)
   void set_weighted_gradient (cvm::rvector const &grad);
 
   /// \brief Calculate the derivatives of the fitting transformation
   void calc_fit_gradients();
 
   /// \brief Derivatives of the fitting transformation
   std::vector<cvm::atom_pos> fit_gradients;
 
   /// \brief Used by a (scalar) colvar to apply its force on its \link
   /// atom_group \endlink members
   ///
   /// The (scalar) force is multiplied by the colvar gradient for each
   /// atom; this should be used when a colvar with scalar \link
   /// colvarvalue \endlink type is used (this is the most frequent
   /// case: for colvars with a non-scalar type, the most convenient
   /// solution is to sum together the Cartesian forces from all the
   /// colvar components, and use apply_force() or apply_forces()).  If
   /// the group is being rotated to a reference frame (e.g. to express
   /// the colvar independently from the solute rotation), the
   /// gradients are temporarily rotated to the original frame.
   void apply_colvar_force (cvm::real const &force);
 
   /// \brief Apply a force "to the center of mass", i.e. the force is
   /// distributed on each atom according to its mass
   ///
   /// If the group is being rotated to a reference frame (e.g. to
   /// express the colvar independently from the solute rotation), the
   /// force is rotated back to the original frame.  Colvar gradients
   /// are not used, either because they were not defined (e.g because
   /// the colvar has not a scalar value) or the biases require to
   /// micromanage the force.
   void apply_force (cvm::rvector const &force);
 
   /// \brief Apply an array of forces directly on the individual
   /// atoms; the length of the specified vector must be the same of
   /// this \link atom_group \endlink.
   ///
   /// If the group is being rotated to a reference frame (e.g. to
   /// express the colvar independently from the solute rotation), the
   /// forces are rotated back to the original frame.  Colvar gradients
   /// are not used, either because they were not defined (e.g because
   /// the colvar has not a scalar value) or the biases require to
   /// micromanage the forces.
   void apply_forces (std::vector<cvm::rvector> const &forces);
 
 };
 
 
 #endif
diff --git a/lib/colvars/colvarbias.cpp b/lib/colvars/colvarbias.cpp
index 80877c97f..58ec049b3 100644
--- a/lib/colvars/colvarbias.cpp
+++ b/lib/colvars/colvarbias.cpp
@@ -1,590 +1,590 @@
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 #include "colvarbias.h"
 
 
 colvarbias::colvarbias (std::string const &conf, char const *key)
   : colvarparse(), has_data (false)
 {
   cvm::log ("Initializing a new \""+std::string (key)+"\" instance.\n");
 
   size_t rank = 1;
   std::string const key_str (key);
 
   if (to_lower_cppstr (key_str) == std::string ("abf")) {
     rank = cvm::n_abf_biases+1;
   }
   if (to_lower_cppstr (key_str) == std::string ("harmonic")) {
     rank = cvm::n_harm_biases+1;
   }
   if (to_lower_cppstr (key_str) == std::string ("histogram")) {
     rank = cvm::n_histo_biases+1;
   }
   if (to_lower_cppstr (key_str) == std::string ("metadynamics")) {
     rank = cvm::n_meta_biases+1;
   }
 
   get_keyval (conf, "name", name, key_str+cvm::to_str (rank));
 
   for (std::vector<colvarbias *>::iterator bi = cvm::biases.begin();
        bi != cvm::biases.end();
        bi++) {
     if ((*bi)->name == this->name)
       cvm::fatal_error ("Error: this bias cannot have the same name, \""+this->name+
                         "\", of another bias.\n");
   }
 
   // lookup the associated colvars
   std::vector<std::string> colvars_str;
   if (get_keyval (conf, "colvars", colvars_str)) {
     for (size_t i = 0; i < colvars_str.size(); i++) {
       add_colvar (colvars_str[i]);
     }
   }
   if (!colvars.size()) {
     cvm::fatal_error ("Error: no collective variables specified.\n");
   }
 
   get_keyval (conf, "outputEnergy", b_output_energy, false);
 }
 
 
 colvarbias::colvarbias()
   : colvarparse(), has_data (false)
 {}
 
 
 void colvarbias::add_colvar (std::string const &cv_name)
 {
   if (colvar *cvp = cvm::colvar_p (cv_name)) {
     cvp->enable (colvar::task_gradients);
     if (cvm::debug())
       cvm::log ("Applying this bias to collective variable \""+
-                cvp->name+"\".\n"); 
+                cvp->name+"\".\n");
     colvars.push_back (cvp);
     colvar_forces.push_back (colvarvalue (cvp->type()));
   } else {
     cvm::fatal_error ("Error: cannot find a colvar named \""+
                       cv_name+"\".\n");
   }
 }
 
 
 void colvarbias::communicate_forces()
 {
   for (size_t i = 0; i < colvars.size(); i++) {
     if (cvm::debug()) {
       cvm::log ("Communicating a force to colvar \""+
                 colvars[i]->name+"\", of type \""+
                 colvarvalue::type_desc[colvars[i]->type()]+"\".\n");
     }
     colvars[i]->add_bias_force (colvar_forces[i]);
   }
-}    
+}
 
 
 void colvarbias::change_configuration(std::string const &conf)
 {
   cvm::fatal_error ("Error: change_configuration() not implemented.\n");
 }
 
 
 cvm::real colvarbias::energy_difference(std::string const &conf)
 {
   cvm::fatal_error ("Error: energy_difference() not implemented.\n");
   return 0.;
 }
 
 
 std::ostream & colvarbias::write_traj_label (std::ostream &os)
 {
   os << " ";
-  if (b_output_energy) 
+  if (b_output_energy)
     os << " E_"
        << cvm::wrap_string (this->name, cvm::en_width-2);
   return os;
 }
 
 
 std::ostream & colvarbias::write_traj (std::ostream &os)
 {
   os << " ";
-  if (b_output_energy) 
+  if (b_output_energy)
     os << " "
        << bias_energy;
   return os;
 }
 
 
 
 
 colvarbias_harmonic::colvarbias_harmonic (std::string const &conf,
                                           char const *key)
-  : colvarbias (conf, key), 
+  : colvarbias (conf, key),
     target_nsteps (0),
     target_nstages (0)
 {
   get_keyval (conf, "forceConstant", force_k, 1.0);
   for (size_t i = 0; i < colvars.size(); i++) {
     if (colvars[i]->width != 1.0)
       cvm::log ("The force constant for colvar \""+colvars[i]->name+
                 "\" will be rescaled to "+
                 cvm::to_str (force_k/(colvars[i]->width*colvars[i]->width))+
                 " according to the specified width.\n");
   }
 
   // get the initial restraint centers
   colvar_centers.resize (colvars.size());
   colvar_centers_raw.resize (colvars.size());
   for (size_t i = 0; i < colvars.size(); i++) {
     colvar_centers[i].type (colvars[i]->type());
     colvar_centers_raw[i].type (colvars[i]->type());
   }
   if (get_keyval (conf, "centers", colvar_centers, colvar_centers)) {
     for (size_t i = 0; i < colvars.size(); i++) {
       colvar_centers[i].apply_constraints();
       colvar_centers_raw[i] = colvar_centers[i];
     }
   } else {
     colvar_centers.clear();
     cvm::fatal_error ("Error: must define the initial centers of the restraints.\n");
   }
 
   if (colvar_centers.size() != colvars.size())
     cvm::fatal_error ("Error: number of harmonic centers does not match "
                       "that of collective variables.\n");
 
   if (get_keyval (conf, "targetCenters", target_centers, colvar_centers)) {
     b_chg_centers = true;
     for (size_t i = 0; i < target_centers.size(); i++) {
       target_centers[i].apply_constraints();
     }
   } else {
     b_chg_centers = false;
     target_centers.clear();
   }
 
   if (get_keyval (conf, "targetForceConstant", target_force_k, 0.0)) {
     if (b_chg_centers)
       cvm::fatal_error ("Error: cannot specify both targetCenters and targetForceConstant.\n");
 
     starting_force_k = force_k;
     b_chg_force_k = true;
 
     get_keyval (conf, "targetEquilSteps", target_equil_steps, 0);
 
     get_keyval (conf, "lambdaSchedule", lambda_schedule, lambda_schedule);
     if (lambda_schedule.size()) {
       // There is one more lambda-point than stages
       target_nstages = lambda_schedule.size() - 1;
     }
   } else {
     b_chg_force_k = false;
   }
 
   if (b_chg_centers || b_chg_force_k) {
     get_keyval (conf, "targetNumSteps", target_nsteps, 0);
     if (!target_nsteps)
       cvm::fatal_error ("Error: targetNumSteps must be non-zero.\n");
 
     if (get_keyval (conf, "targetNumStages", target_nstages, target_nstages) &&
         lambda_schedule.size()) {
       cvm::fatal_error ("Error: targetNumStages and lambdaSchedule are incompatible.\n");
     }
 
     if (target_nstages) {
       // This means that either numStages of lambdaSchedule has been provided
       stage = 0;
       restraint_FE = 0.0;
     }
 
     if (get_keyval (conf, "targetForceExponent", force_k_exp, 1.0)) {
       if (! b_chg_force_k)
         cvm::log ("Warning: not changing force constant: targetForceExponent will be ignored\n");
       if (force_k_exp < 1.0)
         cvm::log ("Warning: for all practical purposes, targetForceExponent should be 1.0 or greater.\n");
     }
   }
 
   get_keyval (conf, "outputCenters", b_output_centers, false);
   get_keyval (conf, "outputAccumulatedWork", b_output_acc_work, false);
   acc_work = 0.0;
 
   if (cvm::debug())
     cvm::log ("Done initializing a new harmonic restraint bias.\n");
 }
 
 colvarbias_harmonic::~colvarbias_harmonic ()
 {
   if (cvm::n_harm_biases > 0)
     cvm::n_harm_biases -= 1;
 }
 
 
 void colvarbias_harmonic::change_configuration (std::string const &conf)
 {
   get_keyval (conf, "forceConstant", force_k, force_k);
   if (get_keyval (conf, "centers", colvar_centers, colvar_centers)) {
     for (size_t i = 0; i < colvars.size(); i++) {
       colvar_centers[i].apply_constraints();
       colvar_centers_raw[i] = colvar_centers[i];
     }
   }
 }
 
 
 cvm::real colvarbias_harmonic::energy_difference (std::string const &conf)
 {
   std::vector<colvarvalue> alt_colvar_centers;
   cvm::real alt_force_k;
   cvm::real alt_bias_energy = 0.0;
 
   get_keyval (conf, "forceConstant", alt_force_k, force_k);
 
   alt_colvar_centers.resize (colvars.size());
   for (size_t i = 0; i < colvars.size(); i++) {
     alt_colvar_centers[i].type (colvars[i]->type());
   }
   if (get_keyval (conf, "centers", alt_colvar_centers, colvar_centers)) {
     for (size_t i = 0; i < colvars.size(); i++) {
       colvar_centers[i].apply_constraints();
     }
   }
 
   for (size_t i = 0; i < colvars.size(); i++) {
     alt_bias_energy += 0.5 * alt_force_k / (colvars[i]->width * colvars[i]->width) *
       colvars[i]->dist2 (colvars[i]->value(), alt_colvar_centers[i]);
   }
 
   return alt_bias_energy - bias_energy;
 }
 
 
 cvm::real colvarbias_harmonic::update()
 {
   bias_energy = 0.0;
 
   if (cvm::debug())
     cvm::log ("Updating the harmonic bias \""+this->name+"\".\n");
 
   // Setup first stage of staged variable force constant calculation
   if (b_chg_force_k && target_nstages && cvm::step_absolute() == 0) {
     cvm::real lambda;
     if (lambda_schedule.size()) {
       lambda = lambda_schedule[0];
     } else {
       lambda = 0.0;
     }
     force_k = starting_force_k + (target_force_k - starting_force_k)
               * std::pow (lambda, force_k_exp);
     cvm::log ("Harmonic restraint " + this->name + ", stage " +
         cvm::to_str(stage) + " : lambda = " + cvm::to_str(lambda));
     cvm::log ("Setting force constant to " + cvm::to_str (force_k));
   }
 
   if (b_chg_centers) {
 
     if (!centers_incr.size()) {
       // if this is the first calculation, calculate the advancement
       // at each simulation step (or stage, if applicable)
       // (take current stage into account: it can be non-zero
       //  if we are restarting a staged calculation)
       centers_incr.resize (colvars.size());
       for (size_t i = 0; i < colvars.size(); i++) {
         centers_incr[i].type (colvars[i]->type());
         centers_incr[i] = (target_centers[i] - colvar_centers_raw[i]) /
           cvm::real ( target_nstages ? (target_nstages - stage) :
                                       (target_nsteps - cvm::step_absolute()));
       }
       if (cvm::debug())
         cvm::log ("Center increment for the harmonic bias \""+
                   this->name+"\": "+cvm::to_str (centers_incr)+" at stage "+cvm::to_str (stage)+ ".\n");
 
     }
 
     if (target_nstages) {
       if ((cvm::step_relative() > 0)
             && (cvm::step_absolute() % target_nsteps) == 0
             && stage < target_nstages) {
 
           for (size_t i = 0; i < colvars.size(); i++) {
             colvar_centers_raw[i] += centers_incr[i];
             colvar_centers[i] = colvar_centers_raw[i];
             colvars[i]->wrap(colvar_centers[i]);
             colvar_centers[i].apply_constraints();
           }
           stage++;
           cvm::log ("Moving restraint stage " + cvm::to_str(stage) +
               " : setting centers to " + cvm::to_str (colvar_centers) +
               " at step " +  cvm::to_str (cvm::step_absolute()));
       }
     } else if ((cvm::step_relative() > 0) && (cvm::step_absolute() <= target_nsteps)) {
       // move the restraint centers in the direction of the targets
       // (slow growth)
       for (size_t i = 0; i < colvars.size(); i++) {
         colvar_centers_raw[i] += centers_incr[i];
         colvar_centers[i] = colvar_centers_raw[i];
         colvars[i]->wrap(colvar_centers[i]);
         colvar_centers[i].apply_constraints();
       }
     }
 
     if (cvm::debug())
       cvm::log ("Current centers for the harmonic bias \""+
                 this->name+"\": "+cvm::to_str (colvar_centers)+".\n");
   }
 
   if (b_chg_force_k) {
     // Coupling parameter, between 0 and 1
     cvm::real lambda;
 
     if (target_nstages) {
       // TI calculation: estimate free energy derivative
       // need current lambda
       if (lambda_schedule.size()) {
         lambda = lambda_schedule[stage];
       } else {
         lambda = cvm::real(stage) / cvm::real(target_nstages);
       }
 
       if (target_equil_steps == 0 || cvm::step_absolute() % target_nsteps >= target_equil_steps) {
         // Start averaging after equilibration period, if requested
-        
+
         // Square distance normalized by square colvar width
         cvm::real dist_sq = 0.0;
         for (size_t i = 0; i < colvars.size(); i++) {
           dist_sq += colvars[i]->dist2 (colvars[i]->value(), colvar_centers[i])
             / (colvars[i]->width * colvars[i]->width);
         }
 
         restraint_FE += 0.5 * force_k_exp * std::pow(lambda, force_k_exp - 1.0)
           * (target_force_k - starting_force_k) * dist_sq;
       }
 
       // Finish current stage...
       if (cvm::step_absolute() % target_nsteps == 0 &&
           cvm::step_absolute() > 0) {
 
           cvm::log ("Lambda= " + cvm::to_str (lambda) + " dA/dLambda= "
               + cvm::to_str (restraint_FE / cvm::real(target_nsteps - target_equil_steps)));
-      
+
         //  ...and move on to the next one
         if (stage < target_nstages) {
 
           restraint_FE = 0.0;
           stage++;
           if (lambda_schedule.size()) {
             lambda = lambda_schedule[stage];
           } else {
             lambda = cvm::real(stage) / cvm::real(target_nstages);
           }
           force_k = starting_force_k + (target_force_k - starting_force_k)
                     * std::pow (lambda, force_k_exp);
           cvm::log ("Harmonic restraint " + this->name + ", stage " +
               cvm::to_str(stage) + " : lambda = " + cvm::to_str(lambda));
           cvm::log ("Setting force constant to " + cvm::to_str (force_k));
         }
       }
     } else if (cvm::step_absolute() <= target_nsteps) {
       // update force constant (slow growth)
       lambda = cvm::real(cvm::step_absolute()) / cvm::real(target_nsteps);
       force_k = starting_force_k + (target_force_k - starting_force_k)
           * std::pow (lambda, force_k_exp);
     }
   }
 
   if (cvm::debug())
     cvm::log ("Done updating the harmonic bias \""+this->name+"\".\n");
-  
+
   // Force and energy calculation
   for (size_t i = 0; i < colvars.size(); i++) {
     colvar_forces[i] =
       (-0.5) * force_k /
       (colvars[i]->width * colvars[i]->width) *
       colvars[i]->dist2_lgrad (colvars[i]->value(),
                                colvar_centers[i]);
     bias_energy += 0.5 * force_k / (colvars[i]->width * colvars[i]->width) *
               colvars[i]->dist2(colvars[i]->value(), colvar_centers[i]);
     if (cvm::debug())
       cvm::log ("dist_grad["+cvm::to_str (i)+
                 "] = "+cvm::to_str (colvars[i]->dist2_lgrad (colvars[i]->value(),
                                colvar_centers[i]))+"\n");
   }
 
   if (b_output_acc_work) {
     if ((cvm::step_relative() > 0) || (cvm::step_absolute() == 0)) {
       for (size_t i = 0; i < colvars.size(); i++) {
         // project forces on the calculated increments at this step
         acc_work += colvar_forces[i] * centers_incr[i];
       }
     }
   }
 
   if (cvm::debug())
     cvm::log ("Current forces for the harmonic bias \""+
               this->name+"\": "+cvm::to_str (colvar_forces)+".\n");
 
   return bias_energy;
 }
 
 
 std::istream & colvarbias_harmonic::read_restart (std::istream &is)
 {
   size_t const start_pos = is.tellg();
 
   cvm::log ("Restarting harmonic bias \""+
             this->name+"\".\n");
 
   std::string key, brace, conf;
   if ( !(is >> key)   || !(key == "harmonic") ||
        !(is >> brace) || !(brace == "{") ||
        !(is >> colvarparse::read_block ("configuration", conf)) ) {
 
     cvm::log ("Error: in reading restart configuration for harmonic bias \""+
               this->name+"\" at position "+
               cvm::to_str (is.tellg())+" in stream.\n");
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
     return is;
   }
 
-//   int id = -1; 
+//   int id = -1;
   std::string name = "";
 //   if ( ( (colvarparse::get_keyval (conf, "id", id, -1, colvarparse::parse_silent)) &&
 //          (id != this->id) ) ||
   if ( (colvarparse::get_keyval (conf, "name", name, std::string (""), colvarparse::parse_silent)) &&
        (name != this->name) )
     cvm::fatal_error ("Error: in the restart file, the "
                       "\"harmonic\" block has a wrong name\n");
 //   if ( (id == -1) && (name == "") ) {
   if (name.size() == 0) {
     cvm::fatal_error ("Error: \"harmonic\" block in the restart file "
                       "has no identifiers.\n");
   }
 
   if (b_chg_centers) {
 //    cvm::log ("Reading the updated restraint centers from the restart.\n");
     if (!get_keyval (conf, "centers", colvar_centers))
       cvm::fatal_error ("Error: restraint centers are missing from the restart.\n");
     if (!get_keyval (conf, "centers_raw", colvar_centers_raw))
       cvm::fatal_error ("Error: \"raw\" restraint centers are missing from the restart.\n");
   }
 
   if (b_chg_force_k) {
 //    cvm::log ("Reading the updated force constant from the restart.\n");
     if (!get_keyval (conf, "forceConstant", force_k))
       cvm::fatal_error ("Error: force constant is missing from the restart.\n");
   }
 
   if (target_nstages) {
 //    cvm::log ("Reading current stage from the restart.\n");
     if (!get_keyval (conf, "stage", stage))
       cvm::fatal_error ("Error: current stage is missing from the restart.\n");
   }
 
   if (b_output_acc_work) {
     if (!get_keyval (conf, "accumulatedWork", acc_work))
       cvm::fatal_error ("Error: accumulatedWork is missing from the restart.\n");
   }
 
   is >> brace;
   if (brace != "}") {
     cvm::fatal_error ("Error: corrupt restart information for harmonic bias \""+
                       this->name+"\": no matching brace at position "+
                       cvm::to_str (is.tellg())+" in the restart file.\n");
     is.setstate (std::ios::failbit);
   }
   return is;
 }
 
 
 std::ostream & colvarbias_harmonic::write_restart (std::ostream &os)
 {
   os << "harmonic {\n"
      << "  configuration {\n"
     //      << "    id " << this->id << "\n"
      << "    name " << this->name << "\n";
 
   if (b_chg_centers) {
     os << "    centers ";
     for (size_t i = 0; i < colvars.size(); i++) {
       os << " " << colvar_centers[i];
     }
     os << "\n";
     os << "    centers_raw ";
     for (size_t i = 0; i < colvars.size(); i++) {
       os << " " << colvar_centers_raw[i];
     }
     os << "\n";
   }
 
   if (b_chg_force_k) {
     os << "    forceConstant "
        << std::setprecision (cvm::en_prec)
        << std::setw (cvm::en_width) << force_k << "\n";
   }
 
   if (target_nstages) {
     os << "    stage " << std::setw (cvm::it_width)
        << stage << "\n";
   }
 
   if (b_output_acc_work) {
     os << "    accumulatedWork " << acc_work << "\n";
   }
 
   os << "  }\n"
      << "}\n\n";
 
   return os;
 }
 
 
 std::ostream & colvarbias_harmonic::write_traj_label (std::ostream &os)
 {
   os << " ";
 
-  if (b_output_energy) 
+  if (b_output_energy)
     os << " E_"
        << cvm::wrap_string (this->name, cvm::en_width-2);
 
-  if (b_output_centers) 
+  if (b_output_centers)
     for (size_t i = 0; i < colvars.size(); i++) {
       size_t const this_cv_width = (colvars[i]->value()).output_width (cvm::cv_width);
       os << " x0_"
          << cvm::wrap_string (colvars[i]->name, this_cv_width-3);
     }
 
-  if (b_output_acc_work) 
+  if (b_output_acc_work)
     os << " W_"
        << cvm::wrap_string (this->name, cvm::en_width-2);
 
   return os;
 }
 
 
 std::ostream & colvarbias_harmonic::write_traj (std::ostream &os)
 {
   os << " ";
 
-  if (b_output_energy) 
+  if (b_output_energy)
     os << " "
        << std::setprecision (cvm::en_prec) << std::setw (cvm::en_width)
        << bias_energy;
 
-  if (b_output_centers) 
+  if (b_output_centers)
     for (size_t i = 0; i < colvars.size(); i++) {
       os << " "
          << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
          << colvar_centers[i];
     }
 
-  if (b_output_acc_work) 
+  if (b_output_acc_work)
     os << " "
        << std::setprecision (cvm::en_prec) << std::setw (cvm::en_width)
        << acc_work;
 
   return os;
 }
 
diff --git a/lib/colvars/colvarbias.h b/lib/colvars/colvarbias.h
index c2063329b..5a2c2d8c5 100644
--- a/lib/colvars/colvarbias.h
+++ b/lib/colvars/colvarbias.h
@@ -1,193 +1,193 @@
 #ifndef COLVARBIAS_H
 #define COLVARBIAS_H
 
 #include "colvar.h"
 #include "colvarparse.h"
 
 
 /// \brief Collective variable bias, base class
 class colvarbias : public colvarparse {
 public:
 
   /// Numeric id of this bias
   int            id;
 
   /// Name of this bias
   std::string    name;
-  
+
   /// Add a new collective variable to this bias
   void add_colvar (std::string const &cv_name);
 
   /// Retrieve colvar values and calculate their biasing forces
   /// Return bias energy
   virtual cvm::real update() = 0;
 
   /// Load new configuration - force constant and/or centers only
   virtual void change_configuration(std::string const &conf);
 
   /// Calculate change in energy from using alternate configuration
   virtual cvm::real energy_difference(std::string const &conf);
 
   /// Perform analysis tasks
   virtual inline void analyse() {}
 
   /// Send forces to the collective variables
   void communicate_forces();
 
   /// \brief Constructor
-  /// 
+  ///
   /// The constructor of the colvarbias base class is protected, so
   /// that it can only be called from inherited classes
   colvarbias (std::string const &conf, char const *key);
 
   /// Default constructor
   colvarbias();
 
   /// Destructor
   virtual inline ~colvarbias() {}
 
   /// Read the bias configuration from a restart file
   virtual std::istream & read_restart (std::istream &is) = 0;
 
   /// Write the bias configuration to a restart file
   virtual std::ostream & write_restart (std::ostream &os) = 0;
 
   /// Write a label to the trajectory file (comment line)
   virtual std::ostream & write_traj_label (std::ostream &os);
 
   /// Output quantities such as the bias energy to the trajectory file
   virtual std::ostream & write_traj (std::ostream &os);
 
 
 protected:
 
   /// \brief Pointers to collective variables to which the bias is
   /// applied; current values and metric functions will be obtained
   /// through each colvar object
   std::vector<colvar *>    colvars;
 
   /// \brief Current forces from this bias to the colvars
   std::vector<colvarvalue> colvar_forces;
 
   /// \brief Current energy of this bias (colvar_forces should be obtained by deriving this)
   cvm::real                bias_energy;
 
   /// Whether to write the current bias energy from this bias to the trajectory file
   bool                     b_output_energy;
 
   /// \brief Whether this bias has already accumulated information
   /// (when relevant)
   bool                     has_data;
 
 };
 
 
 /// \brief Harmonic restraint, optionally moving towards a target
 /// (implementation of \link colvarbias \endlink)
 class colvarbias_harmonic : public colvarbias {
 
 public:
 
   /// Retrieve colvar values and calculate their biasing forces
   virtual cvm::real update();
 
   /// Load new configuration - force constant and/or centers only
   virtual void change_configuration(std::string const &conf);
 
   /// Calculate change in energy from using alternate configuration
   virtual cvm::real energy_difference(std::string const &conf);
 
   /// Read the bias configuration from a restart file
   virtual std::istream & read_restart (std::istream &is);
 
   /// Write the bias configuration to a restart file
   virtual std::ostream & write_restart (std::ostream &os);
 
   /// Write a label to the trajectory file (comment line)
   virtual std::ostream & write_traj_label (std::ostream &os);
 
   /// Output quantities such as the bias energy to the trajectory file
   virtual std::ostream & write_traj (std::ostream &os);
 
   /// \brief Constructor
   colvarbias_harmonic (std::string const &conf, char const *key);
 
   /// Destructor
   virtual ~colvarbias_harmonic();
 
 
 protected:
 
   /// \brief Restraint centers
   std::vector<colvarvalue> colvar_centers;
 
   /// \brief Restraint centers without wrapping or constraints applied
   std::vector<colvarvalue> colvar_centers_raw;
 
   /// \brief Moving target?
   bool b_chg_centers;
 
   /// \brief New restraint centers
   std::vector<colvarvalue> target_centers;
 
   /// \brief Amplitude of the restraint centers' increment at each step
   /// (or stage) towards the new values (calculated from target_nsteps)
   std::vector<colvarvalue> centers_incr;
 
   /// Whether to write the current restraint centers to the trajectory file
   bool b_output_centers;
 
   /// Whether to write the current accumulated work to the trajectory file
   bool b_output_acc_work;
 
   /// \brief Accumulated work
   cvm::real acc_work;
 
 
   /// \brief Restraint force constant
   cvm::real force_k;
 
   /// \brief Changing force constant?
   bool b_chg_force_k;
 
   /// \brief Restraint force constant (target value)
   cvm::real target_force_k;
 
   /// \brief Restraint force constant (starting value)
   cvm::real starting_force_k;
 
   /// \brief Lambda-schedule for custom varying force constant
   std::vector<cvm::real> lambda_schedule;
 
   /// \brief Exponent for varying the force constant
   cvm::real force_k_exp;
-  
+
   /// \brief Intermediate quantity to compute the restraint free energy
   /// (in TI, would be the accumulating FE derivative)
   cvm::real restraint_FE;
 
 
   /// \brief Equilibration steps for restraint FE calculation through TI
   cvm::real target_equil_steps;
 
   /// \brief Number of stages over which to perform the change
   /// If zero, perform a continuous change
   int target_nstages;
 
   /// \brief Number of current stage of the perturbation
   int stage;
 
   /// \brief Number of steps required to reach the target force constant
   /// or restraint centers
   size_t target_nsteps;
 };
 
 
 #endif
 
 
 
 // Emacs
 // Local Variables:
 // mode: C++
 // End:
diff --git a/lib/colvars/colvarbias_abf.cpp b/lib/colvars/colvarbias_abf.cpp
index b441f3bd6..5de562f29 100644
--- a/lib/colvars/colvarbias_abf.cpp
+++ b/lib/colvars/colvarbias_abf.cpp
@@ -1,498 +1,498 @@
 /********************************************************************************
  * Implementation of the ABF and histogram biases                               *
  ********************************************************************************/
 
 #include "colvarmodule.h"
 #include "colvar.h"
 #include "colvarbias_abf.h"
 
 /// ABF bias constructor; parses the config file
 
 colvarbias_abf::colvarbias_abf (std::string const &conf, char const *key)
   : colvarbias (conf, key),
     gradients (NULL),
     samples (NULL)
 {
   if (cvm::temperature() == 0.0)
     cvm::log ("WARNING: ABF should not be run without a thermostat or at 0 Kelvin!\n");
-  
+
   // ************* parsing general ABF options ***********************
 
   get_keyval (conf, "applyBias",  apply_bias, true);
   if (!apply_bias) cvm::log ("WARNING: ABF biases will *not* be applied!\n");
 
   get_keyval (conf, "updateBias",  update_bias, true);
   if (!update_bias) cvm::log ("WARNING: ABF biases will *not* be updated!\n");
 
   get_keyval (conf, "hideJacobian", hide_Jacobian, false);
   if (hide_Jacobian) {
     cvm::log ("Jacobian (geometric) forces will be handled internally.\n");
   } else {
     cvm::log ("Jacobian (geometric) forces will be included in reported free energy gradients.\n");
   }
 
   get_keyval (conf, "fullSamples", full_samples, 200);
-  if ( full_samples <= 1 ) full_samples = 1; 
+  if ( full_samples <= 1 ) full_samples = 1;
   min_samples = full_samples / 2;
   // full_samples - min_samples >= 1 is guaranteed
 
   get_keyval (conf, "inputPrefix",  input_prefix, std::vector<std::string> ());
   get_keyval (conf, "outputFreq", output_freq, cvm::restart_out_freq);
   get_keyval (conf, "historyFreq", history_freq, 0);
   b_history_files = (history_freq > 0);
 
   // ************* checking the associated colvars *******************
 
   if (colvars.size() == 0) {
     cvm::fatal_error ("Error: no collective variables specified for the ABF bias.\n");
   }
 
   for (size_t i = 0; i < colvars.size(); i++) {
 
     if (colvars[i]->type() != colvarvalue::type_scalar) {
       cvm::fatal_error ("Error: ABF bias can only use scalar-type variables.\n");
     }
 
     colvars[i]->enable (colvar::task_gradients);
 
     if (update_bias) {
       // Request calculation of system force (which also checks for availability)
       colvars[i]->enable (colvar::task_system_force);
 
       if (!colvars[i]->tasks[colvar::task_extended_lagrangian]) {
         // request computation of Jacobian force
         colvars[i]->enable (colvar::task_Jacobian_force);
 
         // request Jacobian force as part as system force
         // except if the user explicitly requires the "silent" Jacobian
         // correction AND the colvar has a single component
         if (hide_Jacobian) {
           if (colvars[i]->n_components() > 1) {
             cvm::log ("WARNING: colvar \"" + colvars[i]->name
             + "\" has multiple components; reporting its Jacobian forces\n");
             colvars[i]->enable (colvar::task_report_Jacobian_force);
           }
         } else {
           colvars[i]->enable (colvar::task_report_Jacobian_force);
         }
       }
     }
 
     // Here we could check for orthogonality of the Cartesian coordinates
-    // and make it just a warning if some parameter is set? 
+    // and make it just a warning if some parameter is set?
   }
 
   bin.assign (colvars.size(), 0);
   force_bin.assign (colvars.size(), 0);
   force = new cvm::real [colvars.size()];
 
   // Construct empty grids based on the colvars
   samples   = new colvar_grid_count    (colvars);
   gradients = new colvar_grid_gradient (colvars);
   gradients->samples = samples;
   samples->has_parent_data = true;
 
   // If custom grids are provided, read them
   if ( input_prefix.size() > 0 ) {
     read_gradients_samples ();
   }
-  
+
   cvm::log ("Finished ABF setup.\n");
 }
 
 /// Destructor
 colvarbias_abf::~colvarbias_abf()
 {
   if (samples) {
     delete samples;
     samples = NULL;
   }
 
   if (gradients) {
     delete gradients;
     gradients = NULL;
   }
 
   delete [] force;
 
   if (cvm::n_abf_biases > 0)
     cvm::n_abf_biases -= 1;
 }
 
 
 /// Update the FE gradient, compute and apply biasing force
 /// also output data to disk if needed
 
 cvm::real colvarbias_abf::update()
 {
   if (cvm::debug()) cvm::log ("Updating ABF bias " + this->name);
 
   if (cvm::step_relative() == 0) {
-	
+
     // At first timestep, do only:
     // initialization stuff (file operations relying on n_abf_biases
     // compute current value of colvars
 
     if ( cvm::n_abf_biases == 1 && cvm::n_meta_biases == 0 ) {
       // This is the only ABF bias
       output_prefix = cvm::output_prefix;
     } else {
       output_prefix = cvm::output_prefix + "." + this->name;
     }
 
     for (size_t i=0; i<colvars.size(); i++) {
       bin[i] = samples->current_bin_scalar(i);
     }
 
   } else {
 
     for (size_t i=0; i<colvars.size(); i++) {
       bin[i] = samples->current_bin_scalar(i);
     }
 
     if ( update_bias && samples->index_ok (force_bin) ) {
       // Only if requested and within bounds of the grid...
 
       for (size_t i=0; i<colvars.size(); i++) {	  // get forces (lagging by 1 timestep) from colvars
         force[i] = colvars[i]->system_force();
       }
       gradients->acc_force (force_bin, force);
     }
   }
 
   // save bin for next timestep
-  force_bin = bin;  
+  force_bin = bin;
 
   // Reset biasing forces from previous timestep
   for (size_t i=0; i<colvars.size(); i++) {
     colvar_forces[i].reset();
   }
 
   // Compute and apply the new bias, if applicable
   if ( apply_bias && samples->index_ok (bin) ) {
 
     size_t  count = samples->value (bin);
     cvm::real	fact = 1.0;
 
     // Factor that ensures smooth introduction of the force
     if ( count < full_samples ) {
       fact = ( count < min_samples) ? 0.0 :
         (cvm::real (count - min_samples)) / (cvm::real (full_samples - min_samples));
     }
-	
+
     const cvm::real * grad  = &(gradients->value (bin));
 
     if ( fact != 0.0 ) {
 
       if ( (colvars.size() == 1) && colvars[0]->periodic_boundaries() ) {
         // Enforce a zero-mean bias on periodic, 1D coordinates
         colvar_forces[0].real_value += fact * (grad[0] / cvm::real (count) - gradients->average ());
       } else {
         for (size_t i=0; i<colvars.size(); i++) {
           // subtracting the mean force (opposite of the FE gradient) means adding the gradient
           colvar_forces[i].real_value += fact * grad[i] / cvm::real (count);
           // without .real_value, the above would do (cheap) runtime type checking
         }
       }
     }
   }
 
   if (output_freq && (cvm::step_absolute() % output_freq) == 0) {
     if (cvm::debug()) cvm::log ("ABF bias trying to write gradients and samples to disk");
     write_gradients_samples (output_prefix);
   }
   if (b_history_files && (cvm::step_absolute() % history_freq) == 0) {
     // append to existing file only if cvm::step_absolute() > 0
     // otherwise, backup and replace
     write_gradients_samples (output_prefix + ".hist", (cvm::step_absolute() > 0));
   }
   return 0.0; // TODO compute bias energy whenever possible (i.e. 1D with updateBias off)
 }
 
 
 void colvarbias_abf::write_gradients_samples (const std::string &prefix, bool append)
 {
   std::string  samples_out_name = prefix + ".count";
   std::string  gradients_out_name = prefix + ".grad";
   std::ios::openmode mode = (append ? std::ios::app : std::ios::out);
 
   std::ofstream samples_os;
   std::ofstream gradients_os;
 
   if (!append) cvm::backup_file (samples_out_name.c_str());
   samples_os.open (samples_out_name.c_str(), mode);
   if (!samples_os.good()) cvm::fatal_error ("Error opening ABF samples file " + samples_out_name + " for writing");
   samples->write_multicol (samples_os);
   samples_os.close ();
 
   if (!append) cvm::backup_file (gradients_out_name.c_str());
   gradients_os.open (gradients_out_name.c_str(), mode);
   if (!gradients_os.good())	cvm::fatal_error ("Error opening ABF gradient file " + gradients_out_name + " for writing");
   gradients->write_multicol (gradients_os);
   gradients_os.close ();
 
   if (colvars.size () == 1) {
     std::string  pmf_out_name = prefix + ".pmf";
     if (!append) cvm::backup_file (pmf_out_name.c_str());
     std::ofstream pmf_os;
     // Do numerical integration and output a PMF
     pmf_os.open (pmf_out_name.c_str(), mode);
     if (!pmf_os.good())	cvm::fatal_error ("Error opening pmf file " + pmf_out_name + " for writing");
     gradients->write_1D_integral (pmf_os);
     pmf_os << std::endl;
     pmf_os.close ();
   }
   return;
 }
 
 void colvarbias_abf::read_gradients_samples ()
 {
   std::string samples_in_name, gradients_in_name;
 
   for ( size_t i = 0; i < input_prefix.size(); i++ ) {
     samples_in_name = input_prefix[i] + ".count";
     gradients_in_name = input_prefix[i] + ".grad";
     // For user-provided files, the per-bias naming scheme may not apply
-    
+
     std::ifstream is;
 
     cvm::log ("Reading sample count from " + samples_in_name + " and gradients from " + gradients_in_name);
     is.open (samples_in_name.c_str());
     if (!is.good()) cvm::fatal_error ("Error opening ABF samples file " + samples_in_name + " for reading");
     samples->read_multicol (is, true);
     is.close ();
     is.clear();
 
     is.open (gradients_in_name.c_str());
     if (!is.good())	cvm::fatal_error ("Error opening ABF gradient file " + gradients_in_name + " for reading");
     gradients->read_multicol (is, true);
     is.close ();
   }
   return;
 }
 
 
 std::ostream & colvarbias_abf::write_restart (std::ostream& os)
 {
 
-  std::ios::fmtflags flags (os.flags ()); 
+  std::ios::fmtflags flags (os.flags ());
   os.setf(std::ios::fmtflags (0), std::ios::floatfield); // default floating-point format
 
   os << "abf {\n"
      << "  configuration {\n"
      << "    name " << this->name << "\n";
   os << "  }\n";
 
   os << "samples\n";
   samples->write_raw (os, 8);
 
   os << "\ngradient\n";
   gradients->write_raw (os);
 
   os << "}\n\n";
 
   os.flags (flags);
   return os;
 }
 
 
 std::istream & colvarbias_abf::read_restart (std::istream& is)
 {
   if ( input_prefix.size() > 0 ) {
     cvm::fatal_error ("ERROR: cannot provide both inputPrefix and restart information (colvarsInput)");
   }
 
   size_t const start_pos = is.tellg();
 
   cvm::log ("Restarting ABF bias \""+
             this->name+"\".\n");
   std::string key, brace, conf;
 
   if ( !(is >> key)   || !(key == "abf") ||
        !(is >> brace) || !(brace == "{") ||
        !(is >> colvarparse::read_block ("configuration", conf)) ) {
     cvm::log ("Error: in reading restart configuration for ABF bias \""+
               this->name+"\" at position "+
               cvm::to_str (is.tellg())+" in stream.\n");
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
     return is;
   }
 
   std::string name = "";
   if ( (colvarparse::get_keyval (conf, "name", name, std::string (""), colvarparse::parse_silent)) &&
          (name != this->name) )
     cvm::fatal_error ("Error: in the restart file, the "
                       "\"abf\" block has wrong name (" + name + ")\n");
   if ( name == "" ) {
     cvm::fatal_error ("Error: \"abf\" block in the restart file has no name.\n");
   }
-  
+
   if ( !(is >> key)   || !(key == "samples")) {
     cvm::log ("Error: in reading restart configuration for ABF bias \""+
               this->name+"\" at position "+
               cvm::to_str (is.tellg())+" in stream.\n");
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
     return is;
   }
   if (! samples->read_raw (is)) {
     samples->read_raw_error();
   }
 
   if ( !(is >> key)   || !(key == "gradient")) {
     cvm::log ("Error: in reading restart configuration for ABF bias \""+
               this->name+"\" at position "+
               cvm::to_str (is.tellg())+" in stream.\n");
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
     return is;
   }
   if (! gradients->read_raw (is)) {
     gradients->read_raw_error();
   }
 
   is >> brace;
   if (brace != "}") {
     cvm::fatal_error ("Error: corrupt restart information for ABF bias \""+
                       this->name+"\": no matching brace at position "+
                       cvm::to_str (is.tellg())+" in the restart file.\n");
     is.setstate (std::ios::failbit);
   }
   return is;
 }
 
 
 
 
 /// Histogram "bias" constructor
 
 colvarbias_histogram::colvarbias_histogram (std::string const &conf, char const *key)
   : colvarbias (conf, key),
     grid (NULL)
 {
   get_keyval (conf, "outputfreq", output_freq, cvm::restart_out_freq);
 
   if ( output_freq == 0 ) {
     cvm::fatal_error ("User required histogram with zero output frequency");
   }
 
   grid   = new colvar_grid_count    (colvars);
   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 ("Histogram will be written to file " + out_name);
 
   cvm::log ("Finished histogram setup.\n");
 }
 
 /// Destructor
 colvarbias_histogram::~colvarbias_histogram()
 {
   if (grid_os.good())	grid_os.close();
 
   if (grid) {
     delete grid;
     grid = NULL;
   }
 
   if (cvm::n_histo_biases > 0)
     cvm::n_histo_biases -= 1;
 }
 
 /// Update the grid
 cvm::real colvarbias_histogram::update()
 {
   if (cvm::debug()) cvm::log ("Updating Grid bias " + this->name);
 
   for (size_t i=0; i<colvars.size(); i++) {
     bin[i] = grid->current_bin_scalar(i);
   }
 
   if ( grid->index_ok (bin) ) {	  // Only within bounds of the grid...
     grid->incr_count (bin);
   }
 
   if (output_freq && (cvm::step_absolute() % output_freq) == 0) {
     if (cvm::debug()) cvm::log ("Histogram bias trying to write grid to disk");
 
     grid_os.open (out_name.c_str());
     if (!grid_os.good()) cvm::fatal_error ("Error opening histogram file " + out_name + " for writing");
     grid->write_multicol (grid_os);
     grid_os.close ();
   }
   return 0.0; // no bias energy for histogram
 }
 
 
 std::istream & colvarbias_histogram::read_restart (std::istream& is)
 {
   size_t const start_pos = is.tellg();
 
   cvm::log ("Restarting collective variable histogram \""+
             this->name+"\".\n");
   std::string key, brace, conf;
 
   if ( !(is >> key)   || !(key == "histogram") ||
        !(is >> brace) || !(brace == "{") ||
        !(is >> colvarparse::read_block ("configuration", conf)) ) {
     cvm::log ("Error: in reading restart configuration for histogram \""+
               this->name+"\" at position "+
               cvm::to_str (is.tellg())+" in stream.\n");
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
     return is;
   }
 
   int id = -1;
   std::string name = "";
   if ( (colvarparse::get_keyval (conf, "name", name, std::string (""), colvarparse::parse_silent)) &&
          (name != this->name) )
     cvm::fatal_error ("Error: in the restart file, the "
                       "\"histogram\" block has a wrong name: different system?\n");
   if ( (id == -1) && (name == "") ) {
     cvm::fatal_error ("Error: \"histogram\" block in the restart file "
                       "has no name.\n");
   }
-  
+
   if ( !(is >> key)   || !(key == "grid")) {
     cvm::log ("Error: in reading restart configuration for histogram \""+
               this->name+"\" at position "+
               cvm::to_str (is.tellg())+" in stream.\n");
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
     return is;
   }
   if (! grid->read_raw (is)) {
     grid->read_raw_error();
   }
 
   is >> brace;
   if (brace != "}") {
     cvm::fatal_error ("Error: corrupt restart information for ABF bias \""+
                       this->name+"\": no matching brace at position "+
                       cvm::to_str (is.tellg())+" in the restart file.\n");
     is.setstate (std::ios::failbit);
   }
   return is;
 }
 
 std::ostream & colvarbias_histogram::write_restart (std::ostream& os)
 {
   os << "histogram {\n"
      << "  configuration {\n"
      << "    name " << this->name << "\n";
   os << "  }\n";
 
   os << "grid\n";
   grid->write_raw (os, 8);
 
   os << "}\n\n";
 
   return os;
 }
diff --git a/lib/colvars/colvarbias_abf.h b/lib/colvars/colvarbias_abf.h
index f107b7824..dfb6aec8d 100644
--- a/lib/colvars/colvarbias_abf.h
+++ b/lib/colvars/colvarbias_abf.h
@@ -1,95 +1,95 @@
 /************************************************************************
  * Headers for the ABF and histogram biases                             *
  ************************************************************************/
 
 #ifndef COLVARBIAS_ABF_H
 #define COLVARBIAS_ABF_H
 
 #include <vector>
 #include <list>
 #include <sstream>
 #include <iomanip>
 //#include <cmath>
 
 #include "colvarbias.h"
 #include "colvargrid.h"
 
 typedef cvm::real* gradient_t;
 
 
 /// ABF bias
 class colvarbias_abf : public colvarbias {
 
 public:
 
   colvarbias_abf (std::string const &conf, char const *key);
   ~colvarbias_abf ();
 
   cvm::real update ();
 
 private:
 
   /// Filename prefix for human-readable gradient/sample count output
   std::string	output_prefix;
 
   /// Base filename(s) for reading previous gradient data (replaces data from restart file)
   std::vector<std::string> input_prefix;
 
   bool		apply_bias;
   bool		update_bias;
   bool		hide_Jacobian;
   size_t	full_samples;
   size_t	min_samples;
   /// frequency for updating output files (default: same as restartFreq?)
   int		output_freq;
   /// Write combined files with a history of all output data?
   bool      b_history_files;
   size_t    history_freq;
 
   // Internal data and methods
 
   std::vector<int>  bin, force_bin;
   gradient_t	    force;
 
   /// n-dim grid of free energy gradients
   colvar_grid_gradient  *gradients;
   /// n-dim grid of number of samples
   colvar_grid_count     *samples;
 
   /// Write human-readable FE gradients and sample count
   void		  write_gradients_samples (const std::string &prefix, bool append = false);
 
   /// Read human-readable FE gradients and sample count (if not using restart)
   void		  read_gradients_samples ();
 
   std::istream& read_restart  (std::istream&);
   std::ostream& write_restart (std::ostream&);
 };
 
 
 /// Histogram "bias" (does as the name says)
 class colvarbias_histogram : public colvarbias {
 
 public:
 
   colvarbias_histogram (std::string const &conf, char const *key);
   ~colvarbias_histogram ();
 
   cvm::real update ();
 
 private:
 
   /// n-dim histogram
   colvar_grid_count    *grid;
   std::vector<int>  bin;
   std::string	  out_name;
 
-  int		  output_freq;  
+  int		  output_freq;
   void		  write_grid ();
   std::ofstream	  grid_os;  /// Stream for writing grid to disk
 
   std::istream& read_restart  (std::istream&);
   std::ostream& write_restart (std::ostream&);
 };
 
 #endif
diff --git a/lib/colvars/colvarbias_meta.cpp b/lib/colvars/colvarbias_meta.cpp
index 5ad6d8f24..3ddc6af6c 100644
--- a/lib/colvars/colvarbias_meta.cpp
+++ b/lib/colvars/colvarbias_meta.cpp
@@ -1,1717 +1,1717 @@
 #include <iostream>
 #include <sstream>
 #include <fstream>
 #include <iomanip>
 #include <cmath>
 #include <algorithm>
 
 // used to set the absolute path of a replica file
 #if defined (WIN32) && !defined(__CYGWIN__)
 #include <direct.h>
 #define CHDIR ::_chdir
 #define GETCWD ::_getcwd
 #define PATHSEP "\\"
 #else
 #include <unistd.h>
 #define CHDIR ::chdir
 #define GETCWD ::getcwd
 #define PATHSEP "/"
 #endif
 
 
 #include "colvar.h"
 #include "colvarbias_meta.h"
 
 
 colvarbias_meta::colvarbias_meta()
   : colvarbias(),
     state_file_step (0),
     new_hills_begin (hills.end())
 {
 }
 
 
 colvarbias_meta::colvarbias_meta (std::string const &conf, char const *key)
   : colvarbias (conf, key),
     state_file_step (0),
     new_hills_begin (hills.end())
 {
   if (cvm::n_abf_biases > 0)
     cvm::log ("Warning: ABF and metadynamics running at the "
               "same time can lead to inconsistent results.\n");
 
   get_keyval (conf, "hillWeight", hill_weight, 0.01);
   if (hill_weight == 0.0)
     cvm::log ("Warning: hillWeight has been set to zero, "
               "this bias will have no effect.\n");
 
   get_keyval (conf, "newHillFrequency", new_hill_freq, 1000);
 
   get_keyval (conf, "hillWidth", hill_width, std::sqrt (2.0 * PI) / 2.0);
 
   {
     bool b_replicas = false;
     get_keyval (conf, "multipleReplicas", b_replicas, false);
     if (b_replicas)
       comm = multiple_replicas;
-    else 
+    else
       comm = single_replica;
   }
 
   get_keyval (conf, "useGrids", use_grids, true);
 
   if (use_grids) {
     get_keyval (conf, "gridsUpdateFrequency", grids_freq, new_hill_freq);
     get_keyval (conf, "rebinGrids", rebin_grids, false);
 
     expand_grids = false;
     for (size_t i = 0; i < colvars.size(); i++) {
       if (colvars[i]->expand_boundaries) {
         expand_grids = true;
         cvm::log ("Metadynamics bias \""+this->name+"\""+
                   ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                   ": Will expand grids when the colvar \""+
                   colvars[i]->name+"\" approaches its boundaries.\n");
       }
     }
 
     get_keyval (conf, "keepHills", keep_hills, false);
     if (! get_keyval (conf, "writeFreeEnergyFile", dump_fes, true))
       get_keyval (conf, "dumpFreeEnergyFile", dump_fes, true, colvarparse::parse_silent);
     get_keyval (conf, "saveFreeEnergyFile", dump_fes_save, false);
 
     for (size_t i = 0; i < colvars.size(); i++) {
       colvars[i]->enable (colvar::task_grid);
     }
 
     hills_energy           = new colvar_grid_scalar   (colvars);
     hills_energy_gradients = new colvar_grid_gradient (colvars);
   } else {
     rebin_grids = false;
     keep_hills = false;
     dump_fes = false;
     dump_fes_save = false;
     dump_replica_fes = false;
   }
 
   if (comm != single_replica) {
 
     if (expand_grids)
       cvm::fatal_error ("Error: expandBoundaries is not supported when "
                         "using more than one replicas; please allocate "
                         "wide enough boundaries for each colvar"
                         "ahead of time.\n");
 
     if (get_keyval (conf, "dumpPartialFreeEnergyFile", dump_replica_fes, false)) {
       if (dump_replica_fes && (! dump_fes)) {
         cvm::log ("Enabling \"dumpFreeEnergyFile\".\n");
       }
     }
 
     get_keyval (conf, "replicaID", replica_id, std::string (""));
     if (!replica_id.size())
       cvm::fatal_error ("Error: replicaID must be defined "
                         "when using more than one replica.\n");
 
     get_keyval (conf, "replicasRegistry",
-                replicas_registry_file, 
+                replicas_registry_file,
                 (this->name+".replicas.registry.txt"));
 
     get_keyval (conf, "replicaUpdateFrequency",
                 replica_update_freq, new_hill_freq);
 
     if (keep_hills)
       cvm::log ("Warning: in metadynamics bias \""+this->name+"\""+
                 ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                 ": keepHills with more than one replica can lead to a very "
                 "large amount input/output and slow down your calculations.  "
                 "Please consider disabling it.\n");
 
 
     {
       // TODO: one may want to specify the path manually for intricated filesystems?
       char *pwd = new char[3001];
       if (GETCWD (pwd, 3000) == NULL)
         cvm::fatal_error ("Error: cannot get the path of the current working directory.\n");
       replica_list_file =
         (std::string (pwd)+std::string (PATHSEP)+
          this->name+"."+replica_id+".files.txt");
       // replica_hills_file and replica_state_file are those written
       // by the current replica; within the mirror biases, they are
       // those by another replica
       replica_hills_file =
         (std::string (pwd)+std::string (PATHSEP)+
          cvm::output_prefix+".colvars."+this->name+"."+replica_id+".hills");
       replica_state_file =
         (std::string (pwd)+std::string (PATHSEP)+
          cvm::output_prefix+".colvars."+this->name+"."+replica_id+".state");
       delete pwd;
     }
 
     // now register this replica
 
     // first check that it isn't already there
     bool registered_replica = false;
     std::ifstream reg_is (replicas_registry_file.c_str());
     if (reg_is.good()) {  // the file may not be there yet
       std::string existing_replica ("");
       std::string existing_replica_file ("");
       while ((reg_is >> existing_replica) && existing_replica.size() &&
              (reg_is >> existing_replica_file) && existing_replica_file.size()) {
         if (existing_replica == replica_id) {
           // this replica was already registered
           replica_list_file = existing_replica_file;
           reg_is.close();
           registered_replica = true;
           break;
         }
       }
       reg_is.close();
     }
 
     // if this replica was not included yet, we should generate a
     // new record for it: but first, we write this replica's files,
     // for the others to read
-      
+
     // open the "hills" buffer file
     replica_hills_os.open (replica_hills_file.c_str());
     if (!replica_hills_os.good())
       cvm::fatal_error ("Error: in opening file \""+
                         replica_hills_file+"\" for writing.\n");
     replica_hills_os.setf (std::ios::scientific, std::ios::floatfield);
 
     // write the state file (so that there is always one available)
     write_replica_state_file();
     // schedule to read the state files of the other replicas
     for (size_t ir = 0; ir < replicas.size(); ir++) {
       (replicas[ir])->replica_state_file_in_sync = false;
     }
 
     // if we're running without grids, use a growing list of "hills" files
     // otherwise, just one state file and one "hills" file as buffer
-    std::ofstream list_os (replica_list_file.c_str(), 
+    std::ofstream list_os (replica_list_file.c_str(),
                            (use_grids ? std::ios::trunc : std::ios::app));
     if (! list_os.good())
       cvm::fatal_error ("Error: in opening file \""+
                         replica_list_file+"\" for writing.\n");
     list_os << "stateFile " << replica_state_file << "\n";
     list_os << "hillsFile " << replica_hills_file << "\n";
     list_os.close();
 
     // finally, if add a new record for this replica to the registry
     if (! registered_replica) {
       std::ofstream reg_os (replicas_registry_file.c_str(), std::ios::app);
       if (! reg_os.good())
         cvm::fatal_error ("Error: in opening file \""+
                           replicas_registry_file+"\" for writing.\n");
       reg_os << replica_id << " " << replica_list_file << "\n";
       reg_os.close();
     }
   }
 
   get_keyval (conf, "writeHillsTrajectory", b_hills_traj, false);
   if (b_hills_traj) {
     std::string const traj_file_name (cvm::output_prefix+
                                       ".colvars."+this->name+
                                       ( (comm != single_replica) ?
                                         ("."+replica_id) :
                                         ("") )+
                                       ".hills.traj");
     hills_traj_os.open (traj_file_name.c_str());
     if (!hills_traj_os.good())
       cvm::fatal_error ("Error: in opening hills output file \"" +
                         traj_file_name + "\".\n");
   }
 
   // for well-tempered metadynamics
   get_keyval (conf, "wellTempered", well_tempered, false);
   get_keyval (conf, "biasTemperature", bias_temperature, -1.0);
   if ((bias_temperature == -1.0) && well_tempered) {
     cvm::fatal_error ("Error: biasTemperature is not set.\n");
   }
   if (well_tempered) {
     cvm::log("Well-tempered metadynamics is used.\n");
     cvm::log("The bias temperature is "+cvm::to_str(bias_temperature)+".\n");
   }
-  
+
   if (cvm::debug())
     cvm::log ("Done initializing the metadynamics bias \""+this->name+"\""+
               ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+".\n");
 
   save_delimiters = false;
 }
 
 
 colvarbias_meta::~colvarbias_meta()
 {
   if (hills_energy) {
     delete hills_energy;
     hills_energy = NULL;
   }
 
   if (hills_energy_gradients) {
     delete hills_energy_gradients;
     hills_energy_gradients = NULL;
   }
 
   if (replica_hills_os.good())
     replica_hills_os.close();
 
   if (hills_traj_os.good())
     hills_traj_os.close();
 
   if (cvm::n_meta_biases > 0)
     cvm::n_meta_biases -= 1;
 }
 
 
 
 // **********************************************************************
 // Hill management member functions
 // **********************************************************************
 
-std::list<colvarbias_meta::hill>::const_iterator 
+std::list<colvarbias_meta::hill>::const_iterator
 colvarbias_meta::create_hill (colvarbias_meta::hill const &h)
 {
   hill_iter const hills_end = hills.end();
   hills.push_back (h);
   if (new_hills_begin == hills_end) {
     // if new_hills_begin is unset, set it for the first time
     new_hills_begin = hills.end();
     new_hills_begin--;
   }
 
   if (use_grids) {
 
     // also add it to the list of hills that are off-grid, which may
     // need to be computed analytically when the colvar returns
     // off-grid
     cvm::real const min_dist = hills_energy->bin_distance_from_boundaries (h.centers, true);
     if (min_dist < (3.0 * std::floor (hill_width)) + 1.0) {
       hills_off_grid.push_back (h);
     }
   }
 
   // output to trajectory (if specified)
   if (hills_traj_os.good()) {
     hills_traj_os << (hills.back()).output_traj();
     if (cvm::debug()) {
       hills_traj_os.flush();
     }
   }
 
   has_data = true;
   return hills.end();
 }
 
 
 std::list<colvarbias_meta::hill>::const_iterator
 colvarbias_meta::delete_hill (hill_iter &h)
 {
   if (cvm::debug()) {
     cvm::log ("Deleting hill from the metadynamics bias \""+this->name+"\""+
               ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
               ", with step number "+
               cvm::to_str (h->it)+(h->replica.size() ?
                                    ", replica id \""+h->replica :
                                    "")+".\n");
   }
 
   if (use_grids && hills_off_grid.size()) {
     for (hill_iter hoff = hills_off_grid.begin();
          hoff != hills_off_grid.end(); hoff++) {
       if (*h == *hoff) {
         hills_off_grid.erase (hoff);
         break;
       }
     }
   }
 
   if (hills_traj_os.good()) {
-    // output to the trajectory 
+    // output to the trajectory
     hills_traj_os << "# DELETED this hill: "
                   << (hills.back()).output_traj()
                   << "\n";
     if (cvm::debug())
       hills_traj_os.flush();
   }
 
   return hills.erase (h);
 }
 
 
 cvm::real colvarbias_meta::update()
 {
   if (cvm::debug())
     cvm::log ("Updating the metadynamics bias \""+this->name+"\""+
               ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+".\n");
 
   if (use_grids) {
 
     std::vector<int> curr_bin = hills_energy->get_colvars_index();
 
     if (expand_grids) {
 
       // first of all, expand the grids, if specified
       if (cvm::debug())
         cvm::log ("Metadynamics bias \""+this->name+"\""+
                   ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                   ": current coordinates on the grid: "+
                   cvm::to_str (curr_bin)+".\n");
 
       bool changed_grids = false;
       int const min_buffer =
         (3 * (size_t) std::floor (hill_width)) + 1;
 
       std::vector<int>         new_sizes (hills_energy->sizes());
       std::vector<colvarvalue> new_lower_boundaries (hills_energy->lower_boundaries);
       std::vector<colvarvalue> new_upper_boundaries (hills_energy->upper_boundaries);
 
       for (size_t i = 0; i < colvars.size(); i++) {
 
         if (! colvars[i]->expand_boundaries)
           continue;
 
         cvm::real &new_lb   = new_lower_boundaries[i].real_value;
         cvm::real &new_ub   = new_upper_boundaries[i].real_value;
         int       &new_size = new_sizes[i];
         bool changed_lb = false, changed_ub = false;
 
         if (!colvars[i]->hard_lower_boundary)
           if (curr_bin[i] < min_buffer) {
             int const extra_points = (min_buffer - curr_bin[i]);
             new_lb -= extra_points * colvars[i]->width;
             new_size += extra_points;
             // changed offset in this direction => the pointer needs to
             // be changed, too
             curr_bin[i] += extra_points;
 
             changed_lb = true;
             cvm::log ("Metadynamics bias \""+this->name+"\""+
                       ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                       ": new lower boundary for colvar \""+
                       colvars[i]->name+"\", at "+
                       cvm::to_str (new_lower_boundaries[i])+".\n");
           }
 
         if (!colvars[i]->hard_upper_boundary)
           if (curr_bin[i] > new_size - min_buffer - 1) {
             int const extra_points = (curr_bin[i] - (new_size - 1) + min_buffer);
             new_ub += extra_points * colvars[i]->width;
             new_size += extra_points;
 
             changed_ub = true;
             cvm::log ("Metadynamics bias \""+this->name+"\""+
                       ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                       ": new upper boundary for colvar \""+
                       colvars[i]->name+"\", at "+
                       cvm::to_str (new_upper_boundaries[i])+".\n");
           }
 
         if (changed_lb || changed_ub)
           changed_grids = true;
       }
 
       if (changed_grids) {
 
         // map everything into new grids
 
         colvar_grid_scalar *new_hills_energy =
           new colvar_grid_scalar (*hills_energy);
         colvar_grid_gradient *new_hills_energy_gradients =
           new colvar_grid_gradient (*hills_energy_gradients);
 
         // supply new boundaries to the new grids
 
         new_hills_energy->lower_boundaries = new_lower_boundaries;
         new_hills_energy->upper_boundaries = new_upper_boundaries;
         new_hills_energy->create (new_sizes, 0.0, 1);
 
         new_hills_energy_gradients->lower_boundaries = new_lower_boundaries;
         new_hills_energy_gradients->upper_boundaries = new_upper_boundaries;
         new_hills_energy_gradients->create (new_sizes, 0.0, colvars.size());
 
         new_hills_energy->map_grid (*hills_energy);
         new_hills_energy_gradients->map_grid (*hills_energy_gradients);
 
         delete hills_energy;
         delete hills_energy_gradients;
         hills_energy = new_hills_energy;
         hills_energy_gradients = new_hills_energy_gradients;
 
         curr_bin = hills_energy->get_colvars_index();
         if (cvm::debug())
           cvm::log ("Coordinates on the new grid: "+
                     cvm::to_str (curr_bin)+".\n");
       }
     }
   }
 
   // add a new hill if the required time interval has passed
   if ((cvm::step_absolute() % new_hill_freq) == 0) {
 
     if (cvm::debug())
       cvm::log ("Metadynamics bias \""+this->name+"\""+
                 ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                 ": adding a new hill at step "+cvm::to_str (cvm::step_absolute())+".\n");
 
     switch (comm) {
 
     case single_replica:
       if (well_tempered) {
         std::vector<int> curr_bin = hills_energy->get_colvars_index();
         cvm::real const hills_energy_sum_here = hills_energy->value(curr_bin);
         cvm::real const exp_weight = std::exp(-hills_energy_sum_here/(bias_temperature*cvm::boltzmann()));
         create_hill (hill ((hill_weight*exp_weight), colvars, hill_width));
-      } else { 
+      } else {
         create_hill (hill (hill_weight, colvars, hill_width));
-      } 
+      }
       break;
 
     case multiple_replicas:
       if (well_tempered) {
         std::vector<int> curr_bin = hills_energy->get_colvars_index();
         cvm::real const hills_energy_sum_here = hills_energy->value(curr_bin);
         cvm::real const exp_weight = std::exp(-hills_energy_sum_here/(bias_temperature*cvm::boltzmann()));
         create_hill (hill ((hill_weight*exp_weight), colvars, hill_width, replica_id));
-      } else { 
+      } else {
         create_hill (hill (hill_weight, colvars, hill_width, replica_id));
-      } 
+      }
       if (replica_hills_os.good()) {
         replica_hills_os << hills.back();
       } else {
         cvm::fatal_error ("Error: in metadynamics bias \""+this->name+"\""+
                           ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                           " while writing hills for the other replicas.\n");
       }
       break;
     }
   }
 
   // sync with the other replicas (if needed)
   if (comm != single_replica) {
 
     // reread the replicas registry
     if ((cvm::step_absolute() % replica_update_freq) == 0) {
       update_replicas_registry();
       // empty the output buffer
       replica_hills_os.flush();
 
       read_replica_files();
     }
   }
 
   // calculate the biasing energy and forces
   bias_energy = 0.0;
   for (size_t ir = 0; ir < colvars.size(); ir++) {
     colvar_forces[ir].reset();
   }
   if (comm == multiple_replicas)
     for (size_t ir = 0; ir < replicas.size(); ir++) {
       replicas[ir]->bias_energy = 0.0;
       for (size_t ic = 0; ic < colvars.size(); ic++) {
         replicas[ir]->colvar_forces[ic].reset();
       }
     }
 
   if (use_grids) {
 
     // get the forces from the grid
 
     if ((cvm::step_absolute() % grids_freq) == 0) {
       // map the most recent gaussians to the grids
       project_hills (new_hills_begin, hills.end(),
                      hills_energy,    hills_energy_gradients);
       new_hills_begin = hills.end();
 
       // TODO: we may want to condense all into one replicas array,
       // including "this" as the first element
       if (comm == multiple_replicas) {
         for (size_t ir = 0; ir < replicas.size(); ir++) {
           replicas[ir]->project_hills (replicas[ir]->new_hills_begin,
                                        replicas[ir]->hills.end(),
                                        replicas[ir]->hills_energy,
                                        replicas[ir]->hills_energy_gradients);
           replicas[ir]->new_hills_begin = replicas[ir]->hills.end();
         }
       }
     }
 
     std::vector<int> curr_bin = hills_energy->get_colvars_index();
     if (cvm::debug())
       cvm::log ("Metadynamics bias \""+this->name+"\""+
                 ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                 ": current coordinates on the grid: "+
                 cvm::to_str (curr_bin)+".\n");
 
     if (hills_energy->index_ok (curr_bin)) {
 
       // within the grid: add the energy and the forces from there
 
       bias_energy += hills_energy->value (curr_bin);
       for (size_t ic = 0; ic < colvars.size(); ic++) {
         cvm::real const *f = &(hills_energy_gradients->value (curr_bin));
         colvar_forces[ic].real_value += -1.0 * f[ic];
         // the gradients are stored, not the forces
       }
       if (comm == multiple_replicas)
         for (size_t ir = 0; ir < replicas.size(); ir++) {
           bias_energy += replicas[ir]->hills_energy->value (curr_bin);
           cvm::real const *f = &(replicas[ir]->hills_energy_gradients->value (curr_bin));
           for (size_t ic = 0; ic < colvars.size(); ic++) {
             colvar_forces[ic].real_value += -1.0 * f[ic];
           }
         }
 
     } else {
 
       // off the grid: compute analytically only the hills at the grid's edges
 
       calc_hills (hills_off_grid.begin(), hills_off_grid.end(), bias_energy);
       for (size_t ic = 0; ic < colvars.size(); ic++) {
         calc_hills_force (ic, hills_off_grid.begin(), hills_off_grid.end(), colvar_forces);
       }
 
       if (comm == multiple_replicas)
         for (size_t ir = 0; ir < replicas.size(); ir++) {
           calc_hills (replicas[ir]->hills_off_grid.begin(),
                       replicas[ir]->hills_off_grid.end(),
                       bias_energy);
           for (size_t ic = 0; ic < colvars.size(); ic++) {
             calc_hills_force (ic,
                               replicas[ir]->hills_off_grid.begin(),
                               replicas[ir]->hills_off_grid.end(),
                               colvar_forces);
           }
         }
     }
   }
 
   // now include the hills that have not been binned yet (starting
   // from new_hills_begin)
 
   calc_hills (new_hills_begin, hills.end(), bias_energy);
   for (size_t ic = 0; ic < colvars.size(); ic++) {
     calc_hills_force (ic, new_hills_begin, hills.end(), colvar_forces);
   }
 
-  if (cvm::debug()) 
+  if (cvm::debug())
     cvm::log ("Hills energy = "+cvm::to_str (bias_energy)+
               ", hills forces = "+cvm::to_str (colvar_forces)+".\n");
 
-  if (cvm::debug()) 
+  if (cvm::debug())
     cvm::log ("Metadynamics bias \""+this->name+"\""+
               ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
               ": adding the forces from the other replicas.\n");
 
   if (comm == multiple_replicas)
     for (size_t ir = 0; ir < replicas.size(); ir++) {
       calc_hills (replicas[ir]->new_hills_begin,
                   replicas[ir]->hills.end(),
                   bias_energy);
       for (size_t ic = 0; ic < colvars.size(); ic++) {
         calc_hills_force (ic,
                           replicas[ir]->new_hills_begin,
                           replicas[ir]->hills.end(),
                           colvar_forces);
       }
-      if (cvm::debug()) 
+      if (cvm::debug())
         cvm::log ("Hills energy = "+cvm::to_str (bias_energy)+
                   ", hills forces = "+cvm::to_str (colvar_forces)+".\n");
     }
 
   return bias_energy;
 }
 
 
 void colvarbias_meta::calc_hills (colvarbias_meta::hill_iter      h_first,
                                   colvarbias_meta::hill_iter      h_last,
                                   cvm::real                      &energy,
                                   std::vector<colvarvalue> const &colvar_values)
 {
   std::vector<colvarvalue> curr_values (colvars.size());
   for (size_t i = 0; i < colvars.size(); i++) {
     curr_values[i].type (colvars[i]->type());
   }
 
   if (colvar_values.size()) {
     for (size_t i = 0; i < colvars.size(); i++) {
       curr_values[i] = colvar_values[i];
     }
   } else {
     for (size_t i = 0; i < colvars.size(); i++) {
       curr_values[i] = colvars[i]->value();
     }
   }
 
   for (hill_iter h = h_first; h != h_last; h++) {
-      
+
     // compute the gaussian exponent
     cvm::real cv_sqdev = 0.0;
     for (size_t i = 0; i < colvars.size(); i++) {
       colvarvalue const &x  = curr_values[i];
       colvarvalue const &center = h->centers[i];
       cvm::real const    half_width = 0.5 * h->widths[i];
       cv_sqdev += (colvars[i]->dist2 (x, center)) / (half_width*half_width);
     }
 
     // compute the gaussian
     if (cv_sqdev > 23.0) {
       // set it to zero if the exponent is more negative than log(1.0E-05)
       h->value (0.0);
     } else {
       h->value (std::exp (-0.5*cv_sqdev));
     }
     energy += h->energy();
   }
 }
 
 
 void colvarbias_meta::calc_hills_force (size_t const &i,
                                         colvarbias_meta::hill_iter      h_first,
                                         colvarbias_meta::hill_iter      h_last,
                                         std::vector<colvarvalue>       &forces,
                                         std::vector<colvarvalue> const &values)
 {
   // Retrieve the value of the colvar
   colvarvalue x (values.size() ? values[i].type() : colvars[i]->type());
   x = (values.size() ? values[i] : colvars[i]->value());
 
   // do the type check only once (all colvarvalues in the hills series
   // were already saved with their types matching those in the
   // colvars)
 
   switch (colvars[i]->type()) {
 
   case colvarvalue::type_scalar:
     for (hill_iter 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].real_value += 
-        ( h->weight() * h->value() * (0.5 / (half_width*half_width)) * 
+      forces[i].real_value +=
+        ( h->weight() * h->value() * (0.5 / (half_width*half_width)) *
           (colvars[i]->dist2_lgrad (x, center)).real_value );
     }
     break;
 
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
     for (hill_iter 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].rvector_value +=
         ( h->weight() * h->value() * (0.5 / (half_width*half_width)) *
           (colvars[i]->dist2_lgrad (x, center)).rvector_value );
     }
     break;
 
   case colvarvalue::type_quaternion:
     for (hill_iter 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].quaternion_value +=
         ( h->weight() * h->value() * (0.5 / (half_width*half_width)) *
           (colvars[i]->dist2_lgrad (x, center)).quaternion_value );
     }
     break;
 
   case colvarvalue::type_notset:
     break;
   }
 }
 
 
 // **********************************************************************
 // grid management functions
 // **********************************************************************
 
 void colvarbias_meta::project_hills (colvarbias_meta::hill_iter  h_first,
                                      colvarbias_meta::hill_iter  h_last,
                                      colvar_grid_scalar         *he,
                                      colvar_grid_gradient       *hg,
                                      bool print_progress)
 {
   if (cvm::debug())
     cvm::log ("Metadynamics bias \""+this->name+"\""+
               ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
               ": projecting hills.\n");
 
   // TODO: improve it by looping over a small subgrid instead of the whole grid
 
   std::vector<colvarvalue> colvar_values (colvars.size());
   std::vector<cvm::real> colvar_forces_scalar (colvars.size());
 
   std::vector<int> he_ix = he->new_index();
   std::vector<int> hg_ix = (hg != NULL) ? hg->new_index() : std::vector<int> (0);
   cvm::real hills_energy_here = 0.0;
   std::vector<colvarvalue> hills_forces_here (colvars.size(), 0.0);
 
   size_t count = 0;
   size_t const print_frequency = ((hills.size() >= 1000000) ? 1 : (1000000/(hills.size()+1)));
 
   if (hg != NULL) {
 
     // loop over the points of the grid
     for ( ;
           (he->index_ok (he_ix)) && (hg->index_ok (hg_ix));
           count++) {
 
       for (size_t i = 0; i < colvars.size(); i++) {
         colvar_values[i] = hills_energy->bin_to_value_scalar (he_ix[i], i);
       }
 
       // loop over the hills and increment the energy grid locally
       hills_energy_here = 0.0;
       calc_hills (h_first, h_last, hills_energy_here, colvar_values);
       he->acc_value (he_ix, hills_energy_here);
 
       for (size_t i = 0; i < colvars.size(); i++) {
         hills_forces_here[i].reset();
         calc_hills_force (i, h_first, h_last, hills_forces_here, colvar_values);
         colvar_forces_scalar[i] = hills_forces_here[i].real_value;
       }
       hg->acc_force (hg_ix, &(colvar_forces_scalar.front()));
 
       he->incr (he_ix);
       hg->incr (hg_ix);
 
       if ((count % print_frequency) == 0) {
         if (print_progress) {
           cvm::real const progress = cvm::real (count) / cvm::real (hg->number_of_points());
           std::ostringstream os;
           os.setf (std::ios::fixed, std::ios::floatfield);
           os << std::setw (6) << std::setprecision (2)
              << 100.0 * progress
              << "% done.";
           cvm::log (os.str());
         }
       }
     }
 
   } else {
 
     // simpler version, with just the energy
 
     for ( ; (he->index_ok (he_ix)); ) {
 
       for (size_t i = 0; i < colvars.size(); i++) {
         colvar_values[i] = hills_energy->bin_to_value_scalar (he_ix[i], i);
       }
 
       hills_energy_here = 0.0;
       calc_hills (h_first, h_last, hills_energy_here, colvar_values);
       he->acc_value (he_ix, hills_energy_here);
 
       he->incr (he_ix);
 
       count++;
       if ((count % print_frequency) == 0) {
         if (print_progress) {
           cvm::real const progress = cvm::real (count) / cvm::real (he->number_of_points());
           std::ostringstream os;
           os.setf (std::ios::fixed, std::ios::floatfield);
           os << std::setw (6) << std::setprecision (2)
              << 100.0 * progress
              << "% done.";
           cvm::log (os.str());
         }
       }
     }
   }
 
   if (print_progress) {
     cvm::log ("100.00% done.");
   }
 
   if (! keep_hills) {
     hills.erase (hills.begin(), hills.end());
   }
 }
 
 
 void colvarbias_meta::recount_hills_off_grid (colvarbias_meta::hill_iter  h_first,
                                               colvarbias_meta::hill_iter  h_last,
                                               colvar_grid_scalar         *he)
 {
   hills_off_grid.clear();
 
   for (hill_iter h = h_first; h != h_last; h++) {
     cvm::real const min_dist = hills_energy->bin_distance_from_boundaries (h->centers, true);
     if (min_dist < (3.0 * std::floor (hill_width)) + 1.0) {
       hills_off_grid.push_back (*h);
     }
   }
 }
 
 
 
 // **********************************************************************
 // multiple replicas functions
 // **********************************************************************
 
 
 void colvarbias_meta::update_replicas_registry()
 {
   if (cvm::debug())
     cvm::log ("Metadynamics bias \""+this->name+"\""+
               ": updating the list of replicas, currently containing "+
               cvm::to_str (replicas.size())+" elements.\n");
 
   {
     // copy the whole file into a string for convenience
     std::string line ("");
     std::ifstream reg_file (replicas_registry_file.c_str());
     if (reg_file.good()) {
       replicas_registry.clear();
       while (colvarparse::getline_nocomments (reg_file, line))
         replicas_registry.append (line+"\n");
     } else {
       cvm::fatal_error ("Error: failed to open file \""+replicas_registry_file+
                         "\" for reading.\n");
     }
   }
 
   // now parse it
   std::istringstream reg_is (replicas_registry);
   if (reg_is.good()) {
 
     std::string new_replica ("");
     std::string new_replica_file ("");
     while ((reg_is >> new_replica) && new_replica.size() &&
            (reg_is >> new_replica_file) && new_replica_file.size()) {
 
       if (new_replica == this->replica_id) {
         // this is the record for this same replica, skip it
         if (cvm::debug())
           cvm::log ("Metadynamics bias \""+this->name+"\""+
                     ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                     ": skipping this replica's own record: \""+
                     new_replica+"\", \""+new_replica_file+"\"\n");
         new_replica_file.clear();
         new_replica.clear();
         continue;
       }
 
       bool already_loaded = false;
       for (size_t ir = 0; ir < replicas.size(); ir++) {
         if (new_replica == (replicas[ir])->replica_id) {
           // this replica was already added
           if (cvm::debug())
             cvm::log ("Metadynamics bias \""+this->name+"\""+
                       ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                       ": skipping a replica already loaded, \""+
                       (replicas[ir])->replica_id+"\".\n");
           already_loaded = true;
           break;
         }
       }
 
       if (!already_loaded) {
         // add this replica to the registry
         cvm::log ("Metadynamics bias \""+this->name+"\""+
                   ": accessing replica \""+new_replica+"\".\n");
         replicas.push_back (new colvarbias_meta());
         (replicas.back())->replica_id = new_replica;
         (replicas.back())->replica_list_file = new_replica_file;
         (replicas.back())->replica_state_file = "";
         (replicas.back())->replica_state_file_in_sync = false;
 
         // Note: the following could become a copy constructor?
         (replicas.back())->name = this->name;
         (replicas.back())->colvars = colvars;
         (replicas.back())->use_grids = use_grids;
         (replicas.back())->dump_fes = false;
         (replicas.back())->expand_grids = false;
         (replicas.back())->rebin_grids = false;
         (replicas.back())->keep_hills = false;
         (replicas.back())->colvar_forces = colvar_forces;
 
         (replicas.back())->comm = multiple_replicas;
 
         if (use_grids) {
           (replicas.back())->hills_energy           = new colvar_grid_scalar   (colvars);
           (replicas.back())->hills_energy_gradients = new colvar_grid_gradient (colvars);
         }
       }
     }
 
     // continue the cycle
     new_replica_file = "";
     new_replica = "";
   } else {
     cvm::fatal_error ("Error: cannot read the replicas registry file \""+
                       replicas_registry+"\".\n");
   }
 
   // now (re)read the list file of each replica
   for (size_t ir = 0; ir < replicas.size(); ir++) {
     if (cvm::debug())
       cvm::log ("Metadynamics bias \""+this->name+"\""+
                 ": reading the list file for replica \""+
                 (replicas[ir])->replica_id+"\".\n");
 
     std::ifstream list_is ((replicas[ir])->replica_list_file.c_str());
     std::string key;
     std::string new_state_file, new_hills_file;
     if (!(list_is >> key) ||
         !(key == std::string ("stateFile")) ||
         !(list_is >> new_state_file) ||
         !(list_is >> key) ||
         !(key == std::string ("hillsFile")) ||
         !(list_is >> new_hills_file)) {
       cvm::log ("Metadynamics bias \""+this->name+"\""+
                 ": failed to read the file \""+
                 (replicas[ir])->replica_list_file+"\": will try again after "+
                 cvm::to_str (replica_update_freq)+" steps.\n");
       (replicas[ir])->update_status++;
     } else {
       (replicas[ir])->update_status = 0;
       if (new_state_file != (replicas[ir])->replica_state_file) {
         cvm::log ("Metadynamics bias \""+this->name+"\""+
                   ": replica \""+(replicas[ir])->replica_id+
                   "\" has supplied a new state file, \""+new_state_file+
                   "\".\n");
         (replicas[ir])->replica_state_file_in_sync = false;
         (replicas[ir])->replica_state_file = new_state_file;
         (replicas[ir])->replica_hills_file = new_hills_file;
       }
     }
   }
 
 
   if (cvm::debug())
     cvm::log ("Metadynamics bias \""+this->name+"\": the list of replicas contains "+
               cvm::to_str (replicas.size())+" elements.\n");
 }
 
 
 void colvarbias_meta::read_replica_files()
 {
   for (size_t ir = 0; ir < replicas.size(); ir++) {
 
     if (! (replicas[ir])->replica_state_file_in_sync) {
       // if a new state file is being read, the hills file is also new
       (replicas[ir])->replica_hills_file_pos = 0;
     }
 
     // (re)read the state file if necessary
-    if ( (! (replicas[ir])->has_data) || 
+    if ( (! (replicas[ir])->has_data) ||
          (! (replicas[ir])->replica_state_file_in_sync) ) {
 
       cvm::log ("Metadynamics bias \""+this->name+"\""+
                 ": reading the state of replica \""+
                 (replicas[ir])->replica_id+"\" from file \""+
                 (replicas[ir])->replica_state_file+"\".\n");
 
       std::ifstream is ((replicas[ir])->replica_state_file.c_str());
       if (! (replicas[ir])->read_restart (is)) {
         cvm::log ("Reading from file \""+(replicas[ir])->replica_state_file+
                   "\" failed or incomplete: will try again in "+
                   cvm::to_str (replica_update_freq)+" steps.\n");
       } else {
         // state file has been read successfully
         (replicas[ir])->replica_state_file_in_sync = true;
         (replicas[ir])->update_status = 0;
       }
       is.close();
     }
-    
+
     // now read the hills added after writing the state file
     if ((replicas[ir])->replica_hills_file.size()) {
 
-      if (cvm::debug()) 
+      if (cvm::debug())
         cvm::log ("Metadynamics bias \""+this->name+"\""+
                   ": checking for new hills from replica \""+
                   (replicas[ir])->replica_id+"\" in the file \""+
                   (replicas[ir])->replica_hills_file+"\".\n");
 
       // read hills from the other replicas' files; for each file, resume
       // the position recorded previously
 
       std::ifstream is ((replicas[ir])->replica_hills_file.c_str());
       if (is.good()) {
 
         // try to resume the previous position
         is.seekg ((replicas[ir])->replica_hills_file_pos, std::ios::beg);
         if (!is.good()){
           // if fail (the file may have been overwritten), reset this
           // position
           is.clear();
           is.seekg (0, std::ios::beg);
           // reset the counter
           (replicas[ir])->replica_hills_file_pos = 0;
           // schedule to reread the state file
           (replicas[ir])->replica_state_file_in_sync = false;
           // and record the failure
           (replicas[ir])->update_status++;
           cvm::log ("Failed to read the file \""+(replicas[ir])->replica_hills_file+
                     "\" at the previous position: will try again in "+
                     cvm::to_str (replica_update_freq)+" steps.\n");
         } else {
 
           while ((replicas[ir])->read_hill (is)) {
             //           if (cvm::debug())
               cvm::log ("Metadynamics bias \""+this->name+"\""+
                         ": received a hill from replica \""+
                         (replicas[ir])->replica_id+
                         "\" at step "+
                         cvm::to_str (((replicas[ir])->hills.back()).it)+".\n");
           }
           is.clear();
           // store the position for the next read
           (replicas[ir])->replica_hills_file_pos = is.tellg();
           if (cvm::debug())
             cvm::log ("Metadynamics bias \""+this->name+"\""+
                       ": stopped reading file \""+(replicas[ir])->replica_hills_file+
                       "\" at position "+
                       cvm::to_str ((replicas[ir])->replica_hills_file_pos)+".\n");
 
-          // test whether this is the end of the file 
+          // test whether this is the end of the file
           is.seekg (0, std::ios::end);
           if (is.tellg() > (replicas[ir])->replica_hills_file_pos+1) {
             (replicas[ir])->update_status++;
           } else {
             (replicas[ir])->update_status = 0;
           }
         }
 
       } else {
         cvm::log ("Failed to read the file \""+(replicas[ir])->replica_hills_file+
                   "\": will try again in "+
                   cvm::to_str (replica_update_freq)+" steps.\n");
         (replicas[ir])->update_status++;
         // cvm::fatal_error ("Error: cannot read from file \""+
         //                   (replicas[ir])->replica_hills_file+"\".\n");
       }
       is.close();
     }
 
     size_t const n_flush = (replica_update_freq/new_hill_freq + 1);
     if ((replicas[ir])->update_status > 3*n_flush) {
       // TODO: suspend the calculation?
       cvm::log ("WARNING: in metadynamics bias \""+this->name+"\""+
                 " failed to read completely the output of replica \""+
                 (replicas[ir])->replica_id+
                 "\" after more than "+
                 cvm::to_str ((replicas[ir])->update_status * replica_update_freq)+
                 " steps.  Ensure that it is still running.\n");
     }
   }
 }
 
 
 // **********************************************************************
 // input functions
 // **********************************************************************
 
 
 std::istream & colvarbias_meta::read_restart (std::istream& is)
 {
   size_t const start_pos = is.tellg();
 
   if (comm == single_replica) {
-    // if using a multiple replicas scheme, output messages 
+    // if using a multiple replicas scheme, output messages
     // are printed before and after calling this function
     cvm::log ("Restarting metadynamics bias \""+this->name+"\""+
               ".\n");
   }
   std::string key, brace, conf;
   if ( !(is >> key)   || !(key == "metadynamics") ||
        !(is >> brace) || !(brace == "{") ||
        !(is >> colvarparse::read_block ("configuration", conf)) ) {
 
-    if (comm == single_replica) 
+    if (comm == single_replica)
       cvm::log ("Error: in reading restart configuration for metadynamics bias \""+
                 this->name+"\""+
                 ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                 (replica_state_file_in_sync ? ("at position "+
                                                cvm::to_str (start_pos)+
                                                " in the state file") : "")+".\n");
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
     return is;
   }
 
   std::string name = "";
   if ( colvarparse::get_keyval (conf, "name", name,
                                 std::string (""), colvarparse::parse_silent) &&
        (name != this->name) )
     cvm::fatal_error ("Error: in the restart file, the "
                       "\"metadynamics\" block has a different name: different system?\n");
 
   if (name.size() == 0) {
     cvm::fatal_error ("Error: \"metadynamics\" block within the restart file "
                       "has no identifiers.\n");
   }
 
   if (comm != single_replica) {
     std::string replica = "";
     if (colvarparse::get_keyval (conf, "replicaID", replica,
                                  std::string (""), colvarparse::parse_silent) &&
         (replica != this->replica_id))
       cvm::fatal_error ("Error: in the restart file, the "
                         "\"metadynamics\" block has a different replicaID: different system?\n");
 
     colvarparse::get_keyval (conf, "step", state_file_step,
                              cvm::step_absolute(), colvarparse::parse_silent);
   }
 
   bool grids_from_restart_file = use_grids;
 
   if (use_grids) {
 
     if (expand_grids) {
       // the boundaries of the colvars may have been changed; TODO:
       // this reallocation is only for backward-compatibility, and may
       // be deleted when grid_parameters (i.e. colvargrid's own
       // internal reallocation) has kicked in
       delete hills_energy;
       delete hills_energy_gradients;
       hills_energy = new colvar_grid_scalar (colvars);
       hills_energy_gradients = new colvar_grid_gradient (colvars);
     }
 
     colvar_grid_scalar   *hills_energy_backup = NULL;
     colvar_grid_gradient *hills_energy_gradients_backup = NULL;
 
     if (has_data) {
       if (cvm::debug())
         cvm::log ("Backupping grids for metadynamics bias \""+
                   this->name+"\""+
                   ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+".\n");
       hills_energy_backup           = hills_energy;
       hills_energy_gradients_backup = hills_energy_gradients;
       hills_energy                  = new colvar_grid_scalar (colvars);
       hills_energy_gradients        = new colvar_grid_gradient (colvars);
     }
 
     size_t const hills_energy_pos = is.tellg();
     if (!(is >> key)) {
       if (hills_energy_backup != NULL) {
         delete hills_energy;
         delete hills_energy_gradients;
         hills_energy           = hills_energy_backup;
         hills_energy_gradients = hills_energy_gradients_backup;
       }
       is.clear();
       is.seekg (hills_energy_pos, std::ios::beg);
       is.setstate (std::ios::failbit);
       return is;
     } else if (!(key == std::string ("hills_energy")) ||
                !(hills_energy->read_restart (is))) {
       is.clear();
       is.seekg (hills_energy_pos, std::ios::beg);
       grids_from_restart_file = false;
       if (!rebin_grids) {
         if (hills_energy_backup == NULL)
           cvm::fatal_error ("Error: couldn't read the free energy grid for metadynamics bias \""+
                             this->name+"\""+
                             ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                             "; if useGrids was off when the state file was written, "
                             "enable rebinGrids now to regenerate the grids.\n");
         else {
           if (comm == single_replica)
             cvm::log ("Error: couldn't read the free energy grid for metadynamics bias \""+
                       this->name+"\".\n");
           delete hills_energy;
           delete hills_energy_gradients;
           hills_energy           = hills_energy_backup;
           hills_energy_gradients = hills_energy_gradients_backup;
           is.setstate (std::ios::failbit);
           return is;
         }
       }
     }
 
     size_t const hills_energy_gradients_pos = is.tellg();
     if (!(is >> key)) {
       if (hills_energy_backup != NULL)  {
         delete hills_energy;
         delete hills_energy_gradients;
         hills_energy           = hills_energy_backup;
         hills_energy_gradients = hills_energy_gradients_backup;
       }
       is.clear();
       is.seekg (hills_energy_gradients_pos, std::ios::beg);
       is.setstate (std::ios::failbit);
       return is;
     } else if (!(key == std::string ("hills_energy_gradients")) ||
                !(hills_energy_gradients->read_restart (is))) {
       is.clear();
       is.seekg (hills_energy_gradients_pos, std::ios::beg);
       grids_from_restart_file = false;
-      if (!rebin_grids) { 
+      if (!rebin_grids) {
         if (hills_energy_backup == NULL)
           cvm::fatal_error ("Error: couldn't read the free energy gradients grid for metadynamics bias \""+
                             this->name+"\""+
                             ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
                             "; if useGrids was off when the state file was written, "
                             "enable rebinGrids now to regenerate the grids.\n");
         else {
           if (comm == single_replica)
             cvm::log ("Error: couldn't read the free energy gradients grid for metadynamics bias \""+
                       this->name+"\".\n");
           delete hills_energy;
           delete hills_energy_gradients;
           hills_energy           = hills_energy_backup;
           hills_energy_gradients = hills_energy_gradients_backup;
           is.setstate (std::ios::failbit);
           return is;
         }
       }
     }
 
     if (cvm::debug())
       cvm::log ("Successfully read new grids for bias \""+
                 this->name+"\""+
                 ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+"\n");
 
     if (hills_energy_backup != NULL) {
       // now that we have successfully updated the grids, delete the
       // backup copies
       if (cvm::debug())
         cvm::log ("Deallocating the older grids.\n");
 
       delete hills_energy_backup;
       delete hills_energy_gradients_backup;
     }
   }
 
   bool const existing_hills = (hills.size() > 0);
   size_t const old_hills_size = hills.size();
   hill_iter old_hills_end = hills.end();
   hill_iter old_hills_off_grid_end = hills_off_grid.end();
 
   // read the hills explicitly written (if there are any)
   while (read_hill (is)) {
-    if (cvm::debug()) 
+    if (cvm::debug())
       cvm::log ("Read a previously saved hill under the "
                 "metadynamics bias \""+
                 this->name+"\", created at step "+
                 cvm::to_str ((hills.back()).it)+".\n");
   }
   is.clear();
   new_hills_begin = hills.end();
   if (grids_from_restart_file) {
     if (hills.size() > old_hills_size)
       cvm::log ("Read "+cvm::to_str (hills.size())+
                 " hills in addition to the grids.\n");
   } else {
     if (hills.size())
       cvm::log ("Read "+cvm::to_str (hills.size())+" hills.\n");
   }
 
   if (rebin_grids) {
 
     // allocate new grids (based on the new boundaries and widths just
     // read from the configuration file), and project onto them the
     // grids just read from the restart file
 
     colvar_grid_scalar   *new_hills_energy =
       new colvar_grid_scalar (colvars);
     colvar_grid_gradient *new_hills_energy_gradients =
       new colvar_grid_gradient (colvars);
 
     if (!grids_from_restart_file || (keep_hills && hills.size())) {
       // if there are hills, recompute the new grids from them
       cvm::log ("Rebinning the energy and forces grids from "+
                 cvm::to_str (hills.size())+" hills (this may take a while)...\n");
       project_hills (hills.begin(), hills.end(),
                      new_hills_energy, new_hills_energy_gradients, true);
       cvm::log ("rebinning done.\n");
 
     } else {
       // otherwise, use the grids in the restart file
       cvm::log ("Rebinning the energy and forces grids "
                 "from the grids in the restart file.\n");
       new_hills_energy->map_grid (*hills_energy);
       new_hills_energy_gradients->map_grid (*hills_energy_gradients);
     }
 
     delete hills_energy;
     delete hills_energy_gradients;
     hills_energy = new_hills_energy;
     hills_energy_gradients = new_hills_energy_gradients;
 
     // assuming that some boundaries have expanded, eliminate those
     // off-grid hills that aren't necessary any more
     if (hills.size())
       recount_hills_off_grid (hills.begin(), hills.end(), hills_energy);
   }
 
   if (use_grids) {
     if (hills_off_grid.size()) {
       cvm::log (cvm::to_str (hills_off_grid.size())+" hills are near the "
                 "grid boundaries: they will be computed analytically "
                 "and saved to the state files.\n");
     }
   }
 
   is >> brace;
   if (brace != "}") {
     cvm::log ("Incomplete restart information for metadynamics bias \""+
               this->name+"\""+
               ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
               ": no closing brace at position "+
               cvm::to_str (is.tellg())+" in the file.\n");
     is.setstate (std::ios::failbit);
     return is;
   }
 
   if (cvm::debug())
     cvm::log ("colvarbias_meta::read_restart() done\n");
 
   if (existing_hills) {
     hills.erase (hills.begin(), old_hills_end);
     hills_off_grid.erase (hills_off_grid.begin(), old_hills_off_grid_end);
   }
-  
+
   has_data = true;
 
   if (comm != single_replica) {
     read_replica_files();
   }
 
   return is;
-}  
+}
 
 
 std::istream & colvarbias_meta::read_hill (std::istream &is)
 {
   if (!is) return is; // do nothing if failbit is set
 
   size_t const start_pos = is.tellg();
 
   std::string data;
   if ( !(is >> read_block ("hill", data)) ) {
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
     return is;
   }
 
   size_t h_it;
   get_keyval (data, "step", h_it, 0, parse_silent);
   if (h_it <= state_file_step) {
     if (cvm::debug())
       cvm::log ("Skipping a hill older than the state file for metadynamics bias \""+
                 this->name+"\""+
                 ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+"\n");
     return is;
   }
 
   cvm::real h_weight;
   get_keyval (data, "weight", h_weight, hill_weight, parse_silent);
 
   std::vector<colvarvalue> h_centers (colvars.size());
   for (size_t i = 0; i < colvars.size(); i++) {
-    h_centers[i].type ((colvars[i]->value()).type()); 
+    h_centers[i].type ((colvars[i]->value()).type());
   }
   {
     // it is safer to read colvarvalue objects one at a time;
     // TODO: change this it later
     std::string centers_input;
     key_lookup (data, "centers", centers_input);
     std::istringstream centers_is (centers_input);
     for (size_t i = 0; i < colvars.size(); i++) {
       centers_is >> h_centers[i];
     }
   }
 
   std::vector<cvm::real> h_widths (colvars.size());
   get_keyval (data, "widths", h_widths,
               std::vector<cvm::real> (colvars.size(), (std::sqrt (2.0 * PI) / 2.0)),
               parse_silent);
-  
+
   std::string h_replica = "";
   if (comm != single_replica) {
     get_keyval (data, "replicaID", h_replica, replica_id, parse_silent);
     if (h_replica != replica_id)
       cvm::fatal_error ("Error: trying to read a hill created by replica \""+h_replica+
                         "\" for replica \""+replica_id+
                         "\"; did you swap output files?\n");
   }
 
   hill_iter const hills_end = hills.end();
   hills.push_back (hill (h_it, h_weight, h_centers, h_widths, h_replica));
   if (new_hills_begin == hills_end) {
     // if new_hills_begin is unset, set it for the first time
     new_hills_begin = hills.end();
     new_hills_begin--;
   }
 
   if (use_grids) {
     // add this also to the list of hills that are off-grid, which will
     // be computed analytically
     cvm::real const min_dist =
       hills_energy->bin_distance_from_boundaries ((hills.back()).centers, true);
     if (min_dist < (3.0 * std::floor (hill_width)) + 1.0) {
       hills_off_grid.push_back (hills.back());
     }
   }
 
   has_data = true;
   return is;
 }
 
 
 
 
 // **********************************************************************
 // output functions
 // **********************************************************************
 
 std::ostream & colvarbias_meta::write_restart (std::ostream& os)
 {
   os << "metadynamics {\n"
      << "  configuration {\n"
      << "    step " << cvm::step_absolute() << "\n"
      << "    name " << this->name << "\n";
   if (this->comm != single_replica)
     os << "    replicaID " << this->replica_id << "\n";
   os << "  }\n\n";
 
   if (use_grids) {
 
     // this is a very good time to project hills, if you haven't done
     // it already!
     project_hills (new_hills_begin, hills.end(),
                    hills_energy,    hills_energy_gradients);
     new_hills_begin = hills.end();
 
     // write down the grids to the restart file
     os << "  hills_energy\n";
     hills_energy->write_restart (os);
     os << "  hills_energy_gradients\n";
     hills_energy_gradients->write_restart (os);
   }
 
   if ( (!use_grids) || keep_hills ) {
     // write all hills currently in memory
     for (std::list<hill>::const_iterator h = this->hills.begin();
          h != this->hills.end();
          h++) {
       os << *h;
     }
   } else {
     // write just those that are near the grid boundaries
     for (std::list<hill>::const_iterator h = this->hills_off_grid.begin();
          h != this->hills_off_grid.end();
          h++) {
       os << *h;
     }
   }
 
   os << "}\n\n";
 
   if (comm != single_replica) {
     write_replica_state_file();
     // schedule to reread the state files of the other replicas (they
     // have also rewritten them)
     for (size_t ir = 0; ir < replicas.size(); ir++) {
       (replicas[ir])->replica_state_file_in_sync = false;
     }
   }
 
   if (dump_fes) {
     write_pmf();
   }
 
   return os;
-}  
+}
 
 
 void colvarbias_meta::write_pmf()
 {
   // allocate a new grid to store the pmf
   colvar_grid_scalar *pmf = new colvar_grid_scalar (*hills_energy);
   pmf->create();
 
   std::string fes_file_name_prefix (cvm::output_prefix);
-  
+
   if ((cvm::n_meta_biases > 1) || (cvm::n_abf_biases > 0)) {
     // if this is not the only free energy integrator, append
     // this bias's name, to distinguish it from the output of the other
     // biases producing a .pmf file
     // TODO: fix for ABF with updateBias == no
     fes_file_name_prefix += ("."+this->name);
   }
 
   if ((comm == single_replica) || (dump_replica_fes)) {
     // output the PMF from this instance or replica
     pmf->reset();
     pmf->add_grid (*hills_energy);
     cvm::real const max = pmf->maximum_value();
     pmf->add_constant (-1.0 * max);
     pmf->multiply_constant (-1.0);
     if (well_tempered) {
       cvm::real const well_temper_scale = (bias_temperature + cvm::temperature()) / bias_temperature;
       pmf->multiply_constant (well_temper_scale);
     }
     {
       std::string const fes_file_name (fes_file_name_prefix +
                                        ((comm != single_replica) ? ".partial" : "") +
                                        (dump_fes_save ?
                                         "."+cvm::to_str (cvm::step_absolute()) : "") +
                                        ".pmf");
       cvm::backup_file (fes_file_name.c_str());
       std::ofstream fes_os (fes_file_name.c_str());
       pmf->write_multicol (fes_os);
       fes_os.close();
     }
   }
   if (comm != single_replica) {
     // output the combined PMF from all replicas
     pmf->reset();
     pmf->add_grid (*hills_energy);
     for (size_t ir = 0; ir < replicas.size(); ir++) {
       pmf->add_grid (*(replicas[ir]->hills_energy));
     }
     cvm::real const max = pmf->maximum_value();
     pmf->add_constant (-1.0 * max);
     pmf->multiply_constant (-1.0);
     if (well_tempered) {
       cvm::real const well_temper_scale = (bias_temperature + cvm::temperature()) / bias_temperature;
       pmf->multiply_constant (well_temper_scale);
     }
     std::string const fes_file_name (fes_file_name_prefix +
                                      (dump_fes_save ?
                                       "."+cvm::to_str (cvm::step_absolute()) : "") +
                                      ".pmf");
     cvm::backup_file (fes_file_name.c_str());
     std::ofstream fes_os (fes_file_name.c_str());
     pmf->write_multicol (fes_os);
     fes_os.close();
   }
 
   delete pmf;
 }
 
 
 
 void colvarbias_meta::write_replica_state_file()
 {
   // write down also the restart for the other replicas: TODO: this
   // is duplicated code, that could be cleaned up later
   cvm::backup_file (replica_state_file.c_str());
   std::ofstream rep_state_os (replica_state_file.c_str());
   if (!rep_state_os.good())
     cvm::fatal_error ("Error: in opening file \""+
                       replica_state_file+"\" for writing.\n");
 
-  rep_state_os.setf (std::ios::scientific, std::ios::floatfield); 
+  rep_state_os.setf (std::ios::scientific, std::ios::floatfield);
   rep_state_os << "\n"
                << "metadynamics {\n"
                << "  configuration {\n"
                << "    name " << this->name << "\n"
                << "    step " << cvm::step_absolute() << "\n";
   if (this->comm != single_replica) {
     rep_state_os << "    replicaID " << this->replica_id << "\n";
   }
   rep_state_os << "  }\n\n";
   rep_state_os << "  hills_energy\n";
   rep_state_os << std::setprecision (cvm::cv_prec)
                << std::setw (cvm::cv_width);
   hills_energy->write_restart (rep_state_os);
   rep_state_os << "  hills_energy_gradients\n";
   rep_state_os << std::setprecision (cvm::cv_prec)
                << std::setw (cvm::cv_width);
   hills_energy_gradients->write_restart (rep_state_os);
 
   if ( (!use_grids) || keep_hills ) {
     // write all hills currently in memory
     for (std::list<hill>::const_iterator h = this->hills.begin();
          h != this->hills.end();
          h++) {
       rep_state_os << *h;
     }
   } else {
     // write just those that are near the grid boundaries
     for (std::list<hill>::const_iterator h = this->hills_off_grid.begin();
          h != this->hills_off_grid.end();
          h++) {
       rep_state_os << *h;
     }
   }
 
   rep_state_os << "}\n\n";
   rep_state_os.close();
 
   // reopen the hills file
   replica_hills_os.close();
   replica_hills_os.open (replica_hills_file.c_str());
   if (!replica_hills_os.good())
     cvm::fatal_error ("Error: in opening file \""+
                       replica_hills_file+"\" for writing.\n");
   replica_hills_os.setf (std::ios::scientific, std::ios::floatfield);
 }
 
 std::string colvarbias_meta::hill::output_traj()
 {
   std::ostringstream os;
   os.setf (std::ios::fixed, std::ios::floatfield);
   os << std::setw (cvm::it_width) << it << " ";
 
   os.setf (std::ios::scientific, std::ios::floatfield);
 
   os << "  ";
   for (size_t i = 0; i < centers.size(); i++) {
     os << " ";
     os << std::setprecision (cvm::cv_prec)
        << std::setw (cvm::cv_width)  << centers[i];
   }
 
   os << "  ";
   for (size_t i = 0; i < widths.size(); i++) {
     os << " ";
     os << std::setprecision (cvm::cv_prec)
        << std::setw (cvm::cv_width) << widths[i];
   }
 
   os << "  ";
   os << std::setprecision (cvm::en_prec)
      << std::setw (cvm::en_width) << W << "\n";
 
   return os.str();
-}  
+}
 
 
 std::ostream & operator << (std::ostream &os, colvarbias_meta::hill const &h)
 {
   os.setf (std::ios::scientific, std::ios::floatfield);
 
   os << "hill {\n";
   os << "  step " << std::setw (cvm::it_width) << h.it << "\n";
   os << "  weight   "
      << std::setprecision (cvm::en_prec)
      << std::setw (cvm::en_width)
      << h.W << "\n";
 
   if (h.replica.size())
     os << "  replicaID  " << h.replica << "\n";
 
   os << "  centers ";
   for (size_t i = 0; i < (h.centers).size(); i++) {
     os << " "
        << std::setprecision (cvm::cv_prec)
        << std::setw (cvm::cv_width)
        << h.centers[i];
   }
   os << "\n";
 
   os << "  widths  ";
   for (size_t i = 0; i < (h.widths).size(); i++) {
     os << " "
        << std::setprecision (cvm::cv_prec)
        << std::setw (cvm::cv_width)
        << h.widths[i];
   }
   os << "\n";
 
   os << "}\n";
 
   return os;
 }
diff --git a/lib/colvars/colvarbias_meta.h b/lib/colvars/colvarbias_meta.h
index 1f51e5469..8c3eb9100 100644
--- a/lib/colvars/colvarbias_meta.h
+++ b/lib/colvars/colvarbias_meta.h
@@ -1,425 +1,425 @@
 #ifndef COLVARBIAS_META_H
 #define COLVARBIAS_META_H
 
 #include <vector>
 #include <list>
 #include <sstream>
 #include <fstream>
 
 #include "colvarbias.h"
 #include "colvargrid.h"
 
 /// Metadynamics bias (implementation of \link colvarbias \endlink)
 class colvarbias_meta : public colvarbias {
 
 public:
 
   /// Communication between different replicas
   enum Communication {
     /// One replica (default)
     single_replica,
     /// Hills added concurrently by several replicas
     multiple_replicas
   };
 
   /// Communication between different replicas
   Communication comm;
 
   /// Constructor
   colvarbias_meta (std::string const &conf, char const *key);
 
   /// Default constructor
   colvarbias_meta();
 
   /// Destructor
   virtual ~colvarbias_meta();
-  
+
   virtual cvm::real update();
 
   virtual std::istream & read_restart (std::istream &is);
 
   virtual std::ostream & write_restart (std::ostream &os);
 
   virtual void write_pmf();
 
   class hill;
   typedef std::list<hill>::iterator hill_iter;
 
 protected:
 
   /// \brief width of a hill
   ///
   /// The local width of each collective variable, multiplied by this
   /// number, provides the hill width along that direction
   cvm::real  hill_width;
 
   /// \brief Number of simulation steps between two hills
   size_t     new_hill_freq;
 
   /// Write the hill logfile
   bool           b_hills_traj;
   /// Logfile of hill management (creation and deletion)
   std::ofstream  hills_traj_os;
 
   /// \brief List of hills used on this bias (total); if a grid is
   /// employed, these don't need to be updated at every time step
   std::list<hill> hills;
 
   /// \brief Iterator to the first of the "newest" hills (when using
   /// grids, those who haven't been mapped yet)
   hill_iter new_hills_begin;
 
   /// \brief List of hills used on this bias that are on the boundary
   /// edges; these are updated regardless of whether hills are used
   std::list<hill> hills_off_grid;
 
   /// \brief Same as new_hills_begin, but for the off-grid ones
   hill_iter new_hills_off_grid_begin;
 
   /// Regenerate the hills_off_grid list
   void recount_hills_off_grid (hill_iter h_first, hill_iter h_last,
                                colvar_grid_scalar *ge);
 
   /// Read a hill from a file
   std::istream & read_hill (std::istream &is);
 
   /// \brief step present in a state file
-  /// 
+  ///
   /// When using grids and reading state files containing them
   /// (multiple replicas), this is used to check whether a hill is
   /// newer or older than the grids
   size_t                   state_file_step;
 
   /// \brief Add a new hill; if a .hills trajectory is written,
   /// write it there; if there is more than one replica, communicate
   /// it to the others
   virtual std::list<hill>::const_iterator create_hill (hill const &h);
 
   /// \brief Remove a previously saved hill (returns an iterator for
   /// the next hill in the list)
   virtual std::list<hill>::const_iterator delete_hill (hill_iter &h);
 
   /// \brief Calculate the values of the hills, incrementing
   /// bias_energy
   virtual void calc_hills (hill_iter  h_first,
                            hill_iter  h_last,
                            cvm::real &energy,
                            std::vector<colvarvalue> const &values = std::vector<colvarvalue> (0));
 
   /// \brief Calculate the forces acting on the i-th colvar,
   /// incrementing colvar_forces[i]; must be called after calc_hills
   /// each time the values of the colvars are changed
   virtual void calc_hills_force (size_t const &i,
                                  hill_iter h_first,
                                  hill_iter h_last,
                                  std::vector<colvarvalue> &forces,
                                  std::vector<colvarvalue> const &values = std::vector<colvarvalue> (0));
 
 
   /// Height of new hills
   cvm::real  hill_weight;
 
   /// \brief Bin the hills on grids of energy and forces, and use them
   /// to force the colvars (as opposed to deriving the hills analytically)
   bool       use_grids;
 
   /// \brief Rebin the hills upon restarting
   bool       rebin_grids;
 
   /// \brief Should the grids be expanded if necessary?
   bool       expand_grids;
 
   /// \brief How often the hills should be projected onto the grids
   size_t     grids_freq;
 
   /// \brief Whether to keep the hills in the restart file (e.g. to do
   /// meaningful accurate rebinning afterwards)
   bool       keep_hills;
 
   /// \brief Dump the free energy surface (.pmf file) every restartFrequency
   bool       dump_fes;
 
   /// \brief Dump the free energy surface (.pmf file) every restartFrequency
   /// using only the hills from this replica (only applicable to more than one replica)
   bool       dump_replica_fes;
 
   /// \brief Dump the free energy surface files at different
   /// time steps, appending the step number to each file
   bool       dump_fes_save;
 
-  /// \brief Whether to use well-tempered metadynamics 
-  bool       well_tempered; 
+  /// \brief Whether to use well-tempered metadynamics
+  bool       well_tempered;
 
-  /// \brief Biasing temperature in well-tempered metadynamics 
+  /// \brief Biasing temperature in well-tempered metadynamics
   cvm::real  bias_temperature;
 
   /// \brief Try to read the restart information by allocating new
   /// grids before replacing the current ones (used e.g. in
   /// multiple_replicas)
   bool       safely_read_restart;
 
   /// Hill energy, cached on a grid
   colvar_grid_scalar    *hills_energy;
 
   /// Hill forces, cached on a grid
   colvar_grid_gradient  *hills_energy_gradients;
 
   /// \brief Project the selected hills onto grids
   void project_hills (hill_iter h_first, hill_iter h_last,
                       colvar_grid_scalar *ge, colvar_grid_gradient *gf,
                       bool print_progress = false);
 
 
   // Multiple Replicas variables and functions
 
   /// \brief Identifier for this replica
   std::string            replica_id;
 
   /// \brief File containing the paths to the output files from this replica
   std::string            replica_file_name;
 
   /// \brief Read the existing replicas on registry
   virtual void update_replicas_registry();
 
   /// \brief Read new data from replicas' files
   virtual void read_replica_files();
 
   /// \brief Write data to other replicas
   virtual void write_replica_state_file();
 
   /// \brief Additional, "mirror" metadynamics biases, to collect info
   /// from the other replicas
   ///
   /// These are supposed to be synchronized by reading data from the
   /// other replicas, and not be modified by the "local" replica
   std::vector<colvarbias_meta *> replicas;
 
   /// \brief Frequency at which data the "mirror" biases are updated
   size_t                 replica_update_freq;
 
   /// List of replicas (and their output list files): contents are
   /// copied into replicas_registry for convenience
   std::string            replicas_registry_file;
   /// List of replicas (and their output list files)
   std::string            replicas_registry;
   /// List of files written by this replica
   std::string            replica_list_file;
 
   /// Hills energy and gradients written specifically for other
   /// replica (in addition to its own restart file)
   std::string            replica_state_file;
   /// Whether a mirror bias has read the latest version of its state file
   bool                   replica_state_file_in_sync;
 
   /// If there was a failure reading one of the files (because they
   /// are not complete), this counter is incremented
   size_t                 update_status;
 
   /// Explicit hills communicated between replicas
   ///
   /// This file becomes empty after replica_state_file is rewritten
   std::string            replica_hills_file;
 
   /// \brief Output stream corresponding to replica_hills_file
   std::ofstream          replica_hills_os;
 
   /// Position within replica_hills_file (when reading it)
   size_t                 replica_hills_file_pos;
 
 };
 
 
 
 
 /// \brief A hill for the metadynamics bias
 class colvarbias_meta::hill {
 
 protected:
 
   /// Value of the hill function (ranges between 0 and 1)
   cvm::real hill_value;
 
   /// Scale factor, which could be modified at runtime (default: 1)
   cvm::real sW;
 
   /// Maximum height in energy of the hill
   cvm::real W;
 
   /// Center of the hill in the collective variable space
   std::vector<colvarvalue>  centers;
 
   /// Widths of the hill in the collective variable space
   std::vector<cvm::real>    widths;
 
 public:
 
   friend class colvarbias_meta;
 
   /// Time step at which this hill was added
   size_t      it;
 
   /// Identity of the replica who added this hill (only in multiple replica simulations)
   std::string replica;
 
   /// \brief Runtime constructor: data are read directly from
   /// collective variables \param weight Weight of the hill \param
   /// cv Pointer to the array of collective variables involved \param
   /// replica (optional) Identity of the replica which creates the
   /// hill
   inline hill (cvm::real             const &W_in,
                std::vector<colvar *>       &cv,
                cvm::real             const &hill_width,
                std::string           const &replica_in = "")
     : sW (1.0),
       W (W_in),
       centers (cv.size()),
       widths (cv.size()),
       it (cvm::it),
       replica (replica_in)
   {
     for (size_t i = 0; i < cv.size(); i++) {
       centers[i].type (cv[i]->type());
       centers[i] = cv[i]->value();
       widths[i] = cv[i]->width * hill_width;
     }
-    if (cvm::debug()) 
+    if (cvm::debug())
       cvm::log ("New hill, applied to "+cvm::to_str (cv.size())+
                 " collective variables, with centers "+
                 cvm::to_str (centers)+", widths "+
                 cvm::to_str (widths)+" and weight "+
                 cvm::to_str (W)+".\n");
   }
 
   /// \brief General constructor: all data are explicitly passed as
   /// arguments (used for instance when reading hills saved on a
   /// file) \param it Time step of creation of the hill \param
   /// weight Weight of the hill \param centers Center of the hill
   /// \param widths Width of the hill around centers \param replica
   /// (optional) Identity of the replica which creates the hill
   inline hill (size_t                    const &it_in,
                cvm::real                 const &W_in,
                std::vector<colvarvalue>  const &centers_in,
                std::vector<cvm::real>    const &widths_in,
                std::string               const &replica_in = "")
     : sW (1.0),
       W (W_in),
       centers (centers_in),
       widths (widths_in),
       it (it_in),
       replica (replica_in)
   {}
 
   /// Copy constructor
   inline hill (colvarbias_meta::hill const &h)
     : sW (1.0),
       W (h.W),
       centers (h.centers),
       widths (h.widths),
       it (h.it),
       replica (h.replica)
   {}
 
   /// Destructor
   inline ~hill()
   {}
-  
+
   /// Get the energy
   inline cvm::real energy()
   {
     return W * sW * hill_value;
   }
 
   /// Get the energy using another hill weight
   inline cvm::real energy (cvm::real const &new_weight)
   {
     return new_weight * sW * hill_value;
   }
 
   /// Get the current hill value
   inline cvm::real const &value()
   {
     return hill_value;
   }
 
   /// Set the hill value as specified
   inline void value (cvm::real const &new_value)
   {
     hill_value = new_value;
   }
 
   /// Get the weight
   inline cvm::real weight()
   {
     return W * sW;
   }
 
   /// Scale the weight with this factor (by default 1.0 is used)
   inline void scale (cvm::real const &new_scale_fac)
   {
     sW = new_scale_fac;
   }
 
   /// Get the center of the hill
   inline std::vector<colvarvalue> & center()
   {
     return centers;
   }
 
   /// Get the i-th component of the center
   inline colvarvalue & center (size_t const &i)
   {
     return centers[i];
   }
 
   /// Comparison operator
   inline friend bool operator < (hill const &h1, hill const &h2)
   {
     if (h1.it < h2.it) return true;
     else return false;
   }
 
   /// Comparison operator
   inline friend bool operator <= (hill const &h1, hill const &h2)
   {
     if (h1.it <= h2.it) return true;
     else return false;
   }
 
   /// Comparison operator
   inline friend bool operator > (hill const &h1, hill const &h2)
   {
     if (h1.it > h2.it) return true;
     else return false;
   }
 
   /// Comparison operator
   inline friend bool operator >= (hill const &h1, hill const &h2)
   {
     if (h1.it >= h2.it) return true;
     else return false;
   }
 
   /// Comparison operator
   inline friend bool operator == (hill const &h1, hill const &h2)
   {
     if ( (h1.it >= h2.it) && (h1.replica == h2.replica) ) return true;
     else return false;
   }
 
   /// Represent the hill ina string suitable for a trajectory file
   std::string output_traj();
 
   /// Write the hill to an output stream
   inline friend std::ostream & operator << (std::ostream &os,
                                             hill const &h);
 
 };
 
 
 #endif
 
 
 // Emacs
 // Local Variables:
 // mode: C++
 // End:
diff --git a/lib/colvars/colvarcomp.cpp b/lib/colvars/colvarcomp.cpp
index 25da537da..316454e8e 100644
--- a/lib/colvars/colvarcomp.cpp
+++ b/lib/colvars/colvarcomp.cpp
@@ -1,147 +1,147 @@
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 #include "colvar.h"
 #include "colvarcomp.h"
 
 
 
 colvar::cvc::cvc()
   : sup_coeff (1.0), sup_np (1),
     b_periodic (false),
     b_debug_gradients (false),
     b_inverse_gradients (false),
     b_Jacobian_derivative (false)
 {}
 
 
 colvar::cvc::cvc (std::string const &conf)
   : sup_coeff (1.0), sup_np (1),
     b_periodic (false),
     b_debug_gradients (false),
     b_inverse_gradients (false),
     b_Jacobian_derivative (false)
 {
   if (cvm::debug())
     cvm::log ("Initializing cvc base object.\n");
 
   get_keyval (conf, "name", this->name, std::string (""), parse_silent);
 
   get_keyval (conf, "componentCoeff", sup_coeff, 1.0);
   get_keyval (conf, "componentExp", sup_np, 1);
 
   get_keyval (conf, "period", period, 0.0);
   get_keyval (conf, "wrapAround", wrap_center, 0.0);
 
   get_keyval (conf, "debugGradients", b_debug_gradients, false, parse_silent);
 
   if (cvm::debug())
     cvm::log ("Done initializing cvc base object.\n");
 }
 
 
-void colvar::cvc::parse_group (std::string const &conf, 
+void colvar::cvc::parse_group (std::string const &conf,
                                char const *group_key,
                                cvm::atom_group &group,
                                bool optional)
 {
   if (key_lookup (conf, group_key)) {
     group.parse (conf, group_key);
   } else {
     if (! optional) {
       cvm::fatal_error ("Error: definition for atom group \""+
                       std::string (group_key)+"\" not found.\n");
     }
   }
 }
 
 
 colvar::cvc::~cvc()
 {}
 
 
 void colvar::cvc::calc_force_invgrads()
 {
   cvm::fatal_error ("Error: calculation of inverse gradients is not implemented "
                     "for colvar components of type \""+function_type+"\".\n");
 }
 
 
 void colvar::cvc::calc_Jacobian_derivative()
 {
   cvm::fatal_error ("Error: calculation of inverse gradients is not implemented "
                     "for colvar components of type \""+function_type+"\".\n");
 }
 
 
 void colvar::cvc::debug_gradients (cvm::atom_group &group)
 {
   // this function should work for any scalar variable:
   // the only difference will be the name of the atom group (here, "group")
 
   // collect into a vector for convenience
   std::vector<cvm::rvector> gradients (group.size());
   for (size_t i = 0; i < group.size(); i++) {
     gradients[i] = group[i].grad;
   }
 
   cvm::rotation const rot_0 = group.rot;
   cvm::rotation const rot_inv = group.rot.inverse();
 
   cvm::real const x_0 = x.real_value;
 
   cvm::log ("gradients     = "+cvm::to_str (gradients)+"\n");
 
   // it only makes sense to debug the fit gradients
   // when the fitting group is the same as this group
   if (group.b_rotate || group.b_center)
     if (group.b_fit_gradients && (group.ref_pos_group == NULL)) {
       group.calc_fit_gradients();
       if (group.b_rotate) {
         // fit_gradients are in the original frame, we should print them in the rotated frame
         for (size_t j = 0; j < group.fit_gradients.size(); j++) {
           group.fit_gradients[j] = rot_0.rotate (group.fit_gradients[j]);
         }
       }
       cvm::log ("fit_gradients = "+cvm::to_str (group.fit_gradients)+"\n");
       if (group.b_rotate) {
         for (size_t j = 0; j < group.fit_gradients.size(); j++) {
           group.fit_gradients[j] = rot_inv.rotate (group.fit_gradients[j]);
         }
       }
     }
 
   for (size_t ia = 0; ia < group.size(); ia++) {
 
     // tests are best conducted in the unrotated (simulation) frame
     cvm::rvector const atom_grad = group.b_rotate ?
       rot_inv.rotate (group[ia].grad) :
       group[ia].grad;
 
     for (size_t id = 0; id < 3; id++) {
       // (re)read original positions
       group.read_positions();
-      // change one coordinate 
+      // change one coordinate
       group[ia].pos[id] += cvm::debug_gradients_step_size;
       // (re)do the fit (if defined)
       if (group.b_center || group.b_rotate) {
         group.calc_apply_roto_translation();
       }
       calc_value();
       cvm::real const x_1 = x.real_value;
       cvm::log ("Atom "+cvm::to_str (ia)+", component "+cvm::to_str (id)+":\n");
       cvm::log ("dx(actual) = "+cvm::to_str (x_1 - x_0,
                              21, 14)+"\n");
       cvm::real const dx_pred = (group.fit_gradients.size() && (group.ref_pos_group == NULL)) ?
         (cvm::debug_gradients_step_size * (atom_grad[id] + group.fit_gradients[ia][id])) :
         (cvm::debug_gradients_step_size * atom_grad[id]);
       cvm::log ("dx(interp) = "+cvm::to_str (dx_pred,
                              21, 14)+"\n");
       cvm::log ("|dx(actual) - dx(interp)|/|dx(actual)| = "+
                 cvm::to_str (std::fabs (x_1 - x_0 - dx_pred) /
                              std::fabs (x_1 - x_0),
                              12, 5)+
                 ".\n");
 
     }
   }
 }
diff --git a/lib/colvars/colvarcomp.h b/lib/colvars/colvarcomp.h
index 3924ba24f..078c9b4cd 100644
--- a/lib/colvars/colvarcomp.h
+++ b/lib/colvars/colvarcomp.h
@@ -1,1445 +1,1445 @@
 #ifndef COLVARCOMP_H
 #define COLVARCOMP_H
 
 // Declaration of colvar::cvc base class and derived ones.
 //
 // Future cvc's could be declared on additional header files.
-// After the declaration of a new derived class, its metric 
+// After the declaration of a new derived class, its metric
 // functions must be reimplemented as well.
 // If the new cvc has no symmetry or periodicity,
 // this can be done straightforwardly by using the macro:
 // simple_scalar_dist_functions (derived_class)
 
 
 #include <fstream>
 #include <cmath>
 
 
 #include "colvarmodule.h"
 #include "colvar.h"
 #include "colvaratoms.h"
 
 
 /// \brief Colvar component (base class); most implementations of
 /// \link cvc \endlink utilize one or more \link
 /// colvarmodule::atom \endlink or \link colvarmodule::atom_group
 /// \endlink objects to access atoms.
 ///
 /// A \link cvc \endlink object (or an object of a
 /// cvc-derived class) specifies how to calculate a collective
 /// variable, its gradients and other related physical quantities
 /// which do not depend only on the numeric value (the \link colvar
 /// \endlink class already serves this purpose).
 ///
 /// No restriction is set to what kind of calculation a \link
 /// cvc \endlink object performs (usually calculate an
 /// analytical function of atomic coordinates).  The only constraint
 /// is that the value calculated is implemented as a \link colvarvalue
 /// \endlink object.  This serves to provide a unique way to calculate
 /// scalar and non-scalar collective variables, and specify if and how
 /// they can be combined together by the parent \link colvar \endlink
 /// object.
 ///
 /// <b> If you wish to implement a new collective variable component, you
 /// should write your own class by inheriting directly from \link
 /// cvc \endlink, or one of its derived classes (for instance,
 /// \link distance \endlink is frequently used, because it provides
 /// useful data and function members for any colvar based on two
 /// atom groups).  The steps are: \par
 /// 1. add the name of this class under colvar.h \par
 /// 2. add a call to the parser in colvar.C, within the function colvar::colvar() \par
 /// 3. declare the class in colvarcomp.h \par
 /// 4. implement the class in one of the files colvarcomp_*.C
-/// 
+///
 /// </b>
 /// The cvm::atom and cvm::atom_group classes are available to
 /// transparently communicate with the simulation program.  However,
 /// they are not strictly needed, as long as all the degrees of
 /// freedom associated to the cvc are properly evolved by a simple
 /// call to e.g. apply_force().
 
 class colvar::cvc
   : public colvarparse
 {
 public:
 
   /// \brief The name of the object (helps to identify this
   /// cvc instance when debugging)
   std::string name;
 
   /// \brief Description of the type of collective variable
-  /// 
+  ///
   /// Normally this string is set by the parent \link colvar \endlink
   /// object within its constructor, when all \link cvc \endlink
   /// objects are initialized; therefore the main "config string"
   /// constructor does not need to define it.  If a \link cvc
   /// \endlink is initialized and/or a different constructor is used,
   /// this variable definition should be set within the constructor.
   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)
   cvm::real sup_coeff;
   /// \brief Exponent in the polynomial combination (default: 1)
   int       sup_np;
 
   /// \brief Period of this cvc value, (default: 0.0, non periodic)
   cvm::real period;
 
   /// \brief If the component is periodic, wrap around this value (default: 0.0)
   cvm::real wrap_center;
 
   bool b_periodic;
 
   /// \brief Constructor
   ///
   /// At least one constructor which reads a string should be defined
   /// for every class inheriting from cvc \param conf Contents
   /// of the configuration file pertaining to this \link cvc
   /// \endlink
   cvc (std::string const &conf);
 
   /// \brief Within the constructor, make a group parse its own
   /// options from the provided configuration string
-  void parse_group (std::string const &conf, 
+  void parse_group (std::string const &conf,
                     char const *group_key,
                     cvm::atom_group &group,
                     bool optional = false);
 
   /// \brief Default constructor (used when \link cvc \endlink
   /// objects are declared within other ones)
   cvc();
 
   /// Destructor
   virtual ~cvc();
 
 
   /// \brief If this flag is false (default), inverse gradients
   /// (derivatives of atom coordinates with respect to x) are
   /// unavailable; it should be set to true by the constructor of each
   /// derived object capable of calculating them
   bool b_inverse_gradients;
 
   /// \brief If this flag is false (default), the Jacobian derivative
   /// (divergence of the inverse gradients) is unavailable; it should
   /// be set to true by the constructor of each derived object capable
   /// of calculating it
   bool b_Jacobian_derivative;
 
   /// \brief Calculate the variable
   virtual void calc_value() = 0;
 
   /// \brief Calculate the atomic gradients, to be reused later in
   /// order to apply forces
   virtual void calc_gradients() = 0;
 
   /// \brief If true, calc_gradients() will call debug_gradients() for every group needed
   bool b_debug_gradients;
 
   /// \brief Calculate finite-difference gradients alongside the analytical ones, for each Cartesian component
   virtual void debug_gradients (cvm::atom_group &group);
 
   /// \brief Calculate the total force from the system using the
   /// inverse atomic gradients
   virtual void calc_force_invgrads();
 
   /// \brief Calculate the divergence of the inverse atomic gradients
   virtual void calc_Jacobian_derivative();
 
 
   /// \brief Return the previously calculated value
   virtual colvarvalue value() const;
 
   /// \brief Return the previously calculated system force
   virtual colvarvalue system_force() const;
 
   /// \brief Return the previously calculated divergence of the
   /// inverse atomic gradients
   virtual colvarvalue Jacobian_derivative() const;
 
   /// \brief Apply the collective variable force, by communicating the
   /// atomic forces to the simulation program (\b Note: the \link ft
   /// \endlink member is not altered by this function)
   ///
   /// Note: multiple calls to this function within the same simulation
   /// step will add the forces altogether \param cvforce The
   /// collective variable force, usually coming from the biases and
   /// eventually manipulated by the parent \link colvar \endlink
   /// object
   virtual void apply_force (colvarvalue const &cvforce) = 0;
 
   /// \brief Square distance between x1 and x2 (can be redefined to
   /// transparently implement constraints, symmetries and
   /// periodicities)
-  /// 
+  ///
   /// colvar::cvc::dist2() and the related functions are
   /// declared as "const" functions, but not "static", because
   /// additional parameters defining the metrics (e.g. the
   /// periodicity) may be specific to each colvar::cvc object.
   ///
   /// If symmetries or periodicities are present, the
   /// colvar::cvc::dist2() should be redefined to return the
   /// "closest distance" value and colvar::cvc::dist2_lgrad(),
   /// colvar::cvc::dist2_rgrad() to return its gradients.
   ///
   /// If constraints are present (and not already implemented by any
   /// of the \link colvarvalue \endlink types), the
   /// colvar::cvc::dist2_lgrad() and
   /// colvar::cvc::dist2_rgrad() functions should be redefined
   /// to provide a gradient which is compatible with the constraint,
   /// i.e. already deprived of its component normal to the constraint
   /// hypersurface.
-  /// 
+  ///
   /// Finally, another useful application, if you are performing very
   /// many operations with these functions, could be to override the
   /// \link colvarvalue \endlink member functions and access directly
   /// its member data.  For instance: to define dist2(x1,x2) as
   /// (x2.real_value-x1.real_value)*(x2.real_value-x1.real_value) in
   /// case of a scalar \link colvarvalue \endlink type.
   virtual cvm::real dist2 (colvarvalue const &x1,
                            colvarvalue const &x2) const;
 
   /// \brief Gradient (with respect to x1) of the square distance (can
   /// be redefined to transparently implement constraints, symmetries
   /// and periodicities)
   virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
 
   /// \brief Gradient (with respect to x2) of the square distance (can
   /// be redefined to transparently implement constraints, symmetries
   /// and periodicities)
   virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
 
   /// \brief Return a positive number if x2>x1, zero if x2==x1,
   /// negative otherwise (can be redefined to transparently implement
   /// constraints, symmetries and periodicities) \b Note: \b it \b
   /// only \b works \b with \b scalar \b variables, otherwise raises
   /// an error
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 
   /// \brief Wrapp value (for periodic/symmetric cvcs)
   virtual void wrap (colvarvalue &x) const;
 
   /// \brief Pointers to all atom groups, to let colvars collect info
   /// e.g. atomic gradients
   std::vector<cvm::atom_group *> atom_groups;
 
 protected:
 
   /// \brief Cached value
   colvarvalue x;
 
   /// \brief Value at the previous step
   colvarvalue x_old;
 
   /// \brief Calculated system force (\b Note: this is calculated from
   /// the total atomic forces read from the program, subtracting fromt
   /// the "internal" forces of the system the "external" forces from
   /// the colvar biases)
   colvarvalue ft;
 
   /// \brief Calculated Jacobian derivative (divergence of the inverse
   /// gradients): serves to calculate the phase space correction
   colvarvalue jd;
 };
 
 
 
 
 inline colvarvalue::Type colvar::cvc::type() const
 {
   return x.type();
 }
 
 inline colvarvalue colvar::cvc::value() const
 {
   return x;
 }
 
 inline colvarvalue colvar::cvc::system_force() const
 {
   return ft;
 }
 
 inline colvarvalue colvar::cvc::Jacobian_derivative() const
 {
   return jd;
 }
 
 
 inline cvm::real colvar::cvc::dist2 (colvarvalue const &x1,
                                      colvarvalue const &x2) const
 {
   return x1.dist2 (x2);
 }
 
 inline colvarvalue colvar::cvc::dist2_lgrad (colvarvalue const &x1,
                                              colvarvalue const &x2) const
 {
   return x1.dist2_grad (x2);
 }
 
 inline colvarvalue colvar::cvc::dist2_rgrad (colvarvalue const &x1,
                                              colvarvalue const &x2) const
 {
   return x2.dist2_grad (x1);
 }
 
 inline cvm::real colvar::cvc::compare (colvarvalue const &x1,
                                        colvarvalue const &x2) const
 {
   if (this->type() == colvarvalue::type_scalar) {
     return cvm::real (x1 - x2);
   } else {
     cvm::fatal_error ("Error: you requested an operation which requires "
                       "comparison between two non-scalar values.\n");
     return 0.0;
   }
 }
 
 inline void colvar::cvc::wrap (colvarvalue &x) const
 {
   return;
 }
 
 
 /// \brief Colvar component: distance between the centers of mass of
 /// two groups (colvarvalue::type_scalar type, range [0:*))
 ///
 /// This class also serves as the template for many collective
 /// variables with two atom groups: in this case, the
 /// distance::distance() constructor should be called on the same
 /// configuration string, to make the same member data and functions
 /// available to the derived object
 class colvar::distance
   : public colvar::cvc
 {
 protected:
   /// First atom group
   cvm::atom_group  group1;
   /// Second atom group
   cvm::atom_group  group2;
   /// Vector distance, cached to be recycled
   cvm::rvector     dist_v;
   /// Use absolute positions, ignoring PBCs when present
   bool b_no_PBC;
   /// Compute system force on first site only to avoid unwanted
   /// coupling to other colvars (see e.g. Ciccotti et al., 2005)
   bool b_1site_force;
 public:
   distance (std::string const &conf, bool twogroups = true);
   distance();
   virtual inline ~distance() {}
   virtual void calc_value();
   virtual void calc_gradients();
   virtual void calc_force_invgrads();
   virtual void calc_Jacobian_derivative();
   virtual void apply_force (colvarvalue const &force);
   virtual cvm::real dist2 (colvarvalue const &x1,
                            colvarvalue const &x2) const;
   virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 // \brief Colvar component: distance vector between centers of mass
 // of two groups (\link colvarvalue::type_vector \endlink type,
 // range (-*:*)x(-*:*)x(-*:*))
 class colvar::distance_vec
   : public colvar::distance
 {
 public:
   distance_vec (std::string const &conf);
   distance_vec();
   virtual inline ~distance_vec() {}
   virtual void calc_value();
   virtual void calc_gradients();
   virtual void apply_force (colvarvalue const &force);
   /// Redefined to handle the box periodicity
   virtual cvm::real dist2 (colvarvalue const &x1,
                            colvarvalue const &x2) const;
   /// Redefined to handle the box periodicity
   virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   /// Redefined to handle the box periodicity
   virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   /// Redefined to handle the box periodicity
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 /// \brief Colvar component: distance unit vector (direction) between
 /// centers of mass of two groups (colvarvalue::type_unitvector type,
 /// range [-1:1]x[-1:1]x[-1:1])
 class colvar::distance_dir
   : public colvar::distance
 {
 public:
   distance_dir (std::string const &conf);
   distance_dir();
   virtual inline ~distance_dir() {}
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 /// \brief Colvar component: projection of the distance vector along
 /// an axis (colvarvalue::type_scalar type, range (-*:*))
 class colvar::distance_z
   : public colvar::cvc
 {
 protected:
   /// Main atom group
   cvm::atom_group  main;
   /// Reference atom group
   cvm::atom_group  ref1;
   /// Optional, second ref atom group
   cvm::atom_group  ref2;
   /// Use absolute positions, ignoring PBCs when present
   bool b_no_PBC;
   /// Compute system 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
   cvm::rvector axis;
   /// Norm of the axis
   cvm::real axis_norm;
   /// Vector distance, cached to be recycled
   cvm::rvector     dist_v;
   /// Flag: using a fixed axis vector?
   bool fixed_axis;
 public:
   distance_z (std::string const &conf);
   distance_z();
   virtual inline ~distance_z() {}
   virtual void calc_value();
   virtual void calc_gradients();
   virtual void calc_force_invgrads();
   virtual void calc_Jacobian_derivative();
   virtual void apply_force (colvarvalue const &force);
   virtual cvm::real dist2 (colvarvalue const &x1,
                            colvarvalue const &x2) const;
   virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
   /// \brief Redefined to make use of the user-provided period
   virtual void wrap (colvarvalue &x) const;
 };
 
 
 /// \brief Colvar component: projection of the distance vector on a
 /// plane (colvarvalue::type_scalar type, range [0:*))
 class colvar::distance_xy
   : public colvar::distance_z
 {
 protected:
   /// Components of the distance vector orthogonal to the axis
   cvm::rvector dist_v_ortho;
   /// Vector distances
   cvm::rvector v12, v13;
 public:
   distance_xy (std::string const &conf);
   distance_xy();
   virtual inline ~distance_xy() {}
   virtual void calc_value();
   virtual void calc_gradients();
   virtual void calc_force_invgrads();
   virtual void calc_Jacobian_derivative();
   virtual void apply_force (colvarvalue const &force);
   virtual cvm::real dist2 (colvarvalue const &x1,
                            colvarvalue const &x2) const;
   virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 /// \brief Colvar component: average distance between two groups of atoms, weighted as the sixth power,
 /// as in NMR refinements (colvarvalue::type_scalar type, range (0:*))
 class colvar::distance_inv
   : public colvar::distance
 {
 protected:
   /// Components of the distance vector orthogonal to the axis
   int exponent;
 public:
   distance_inv (std::string const &conf);
   distance_inv();
   virtual inline ~distance_inv() {}
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 
 /// \brief Colvar component: Radius of gyration of an atom group
 /// (colvarvalue::type_scalar type, range [0:*))
 class colvar::gyration
   : public colvar::cvc
 {
 protected:
   /// Atoms involved
   cvm::atom_group atoms;
 public:
   /// Constructor
   gyration (std::string const &conf);
   gyration();
   virtual inline ~gyration() {}
   virtual void calc_value();
   virtual void calc_gradients();
   virtual void calc_force_invgrads();
   virtual void calc_Jacobian_derivative();
   virtual void apply_force (colvarvalue const &force);
   virtual cvm::real dist2 (colvarvalue const &x1,
                            colvarvalue const &x2) const;
   virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 /// \brief Colvar component: moment of inertia of an atom group
 /// (colvarvalue::type_scalar type, range [0:*))
 class colvar::inertia
   : public colvar::gyration
 {
 public:
   /// Constructor
   inertia (std::string const &conf);
   inertia();
   virtual inline ~inertia() {}
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 /// \brief Colvar component: moment of inertia of an atom group
 /// around a user-defined axis (colvarvalue::type_scalar type, range [0:*))
 class colvar::inertia_z
   : public colvar::inertia
 {
 protected:
   /// Vector on which the inertia tensor is projected
   cvm::rvector axis;
 public:
   /// Constructor
   inertia_z (std::string const &conf);
   inertia_z();
   virtual inline ~inertia_z() {}
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 /// \brief Colvar component: projection of 3N coordinates onto an
 /// eigenvector (colvarvalue::type_scalar type, range (-*:*))
 class colvar::eigenvector
   : public colvar::cvc
 {
 protected:
 
   /// Atom group
   cvm::atom_group             atoms;
 
   /// Reference coordinates
   std::vector<cvm::atom_pos>  ref_pos;
 
   /// Geometric center of the reference coordinates
   cvm::rvector                ref_pos_center;
 
   /// Eigenvector (of a normal or essential mode): will always have zero center
   std::vector<cvm::rvector>   eigenvec;
 
   /// Inverse square norm of the eigenvector
   cvm::real                   eigenvec_invnorm2;
 
 public:
 
   /// Constructor
   eigenvector (std::string const &conf);
   virtual inline ~eigenvector() {}
   virtual void calc_value();
   virtual void calc_gradients();
   virtual void calc_force_invgrads();
   virtual void calc_Jacobian_derivative();
   virtual void apply_force (colvarvalue const &force);
   virtual cvm::real dist2 (colvarvalue const &x1,
                            colvarvalue const &x2) const;
   virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 
 /// \brief Colvar component: angle between the centers of mass of
 /// three groups (colvarvalue::type_scalar type, range [0:PI])
 class colvar::angle
   : public colvar::cvc
 {
 protected:
 
   /// Atom group
   cvm::atom_group group1;
   /// Atom group
   cvm::atom_group group2;
   /// Atom group
   cvm::atom_group group3;
 
   /// Inter site vectors
   cvm::rvector r21, r23;
   /// Inter site vector norms
   cvm::real r21l, r23l;
   /// Derivatives wrt group centers of mass
   cvm::rvector dxdr1, dxdr3;
 
   /// Compute system force on first site only to avoid unwanted
   /// coupling to other colvars (see e.g. Ciccotti et al., 2005)
   /// (or to allow dummy atoms)
   bool b_1site_force;
 public:
 
   /// Initialize by parsing the configuration
   angle (std::string const &conf);
   /// \brief Initialize the three groups after three atoms
   angle (cvm::atom const &a1, cvm::atom const &a2, cvm::atom const &a3);
   angle();
   virtual inline ~angle() {}
   virtual void calc_value();
   virtual void calc_gradients();
   virtual void calc_force_invgrads();
   virtual void calc_Jacobian_derivative();
   virtual void apply_force (colvarvalue const &force);
   virtual cvm::real dist2 (colvarvalue const &x1,
                            colvarvalue const &x2) const;
   virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 /// \brief Colvar component: dihedral between the centers of mass of
 /// four groups (colvarvalue::type_scalar type, range [-PI:PI])
 class colvar::dihedral
   : public colvar::cvc
 {
 protected:
 
   /// Atom group
   cvm::atom_group group1;
   /// Atom group
   cvm::atom_group group2;
   /// Atom group
   cvm::atom_group group3;
   /// Atom group
   cvm::atom_group group4;
   /// Inter site vectors
   cvm::rvector r12, r23, r34;
 
   /// \brief Compute system force on first site only to avoid unwanted
   /// coupling to other colvars (see e.g. Ciccotti et al., 2005)
   bool b_1site_force;
-  
+
 public:
 
   /// Initialize by parsing the configuration
   dihedral (std::string  const &conf);
   /// \brief Initialize the four groups after four atoms
   dihedral (cvm::atom const &a1, cvm::atom const &a2, cvm::atom const &a3, cvm::atom const &a4);
   dihedral();
   virtual inline ~dihedral() {}
   virtual void calc_value();
   virtual void calc_gradients();
   virtual void calc_force_invgrads();
   virtual void calc_Jacobian_derivative();
   virtual void apply_force (colvarvalue const &force);
 
   /// Redefined to handle the 2*PI periodicity
   virtual cvm::real dist2 (colvarvalue const &x1,
                            colvarvalue const &x2) const;
   /// Redefined to handle the 2*PI periodicity
   virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   /// Redefined to handle the 2*PI periodicity
   virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   /// Redefined to handle the 2*PI periodicity
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
   /// Redefined to handle the 2*PI periodicity
   virtual void wrap (colvarvalue &x) const;
 };
 
 
 /// \brief Colvar component: coordination number between two groups
 /// (colvarvalue::type_scalar type, range [0:N1*N2])
 class colvar::coordnum
   : 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;
   /// \brief If true, group2 will be treated as a single atom
   /// (default: loop over all pairs of atoms in group1 and group2)
   bool b_group2_center_only;
 public:
   /// Constructor
   coordnum (std::string const &conf);
   coordnum();
   virtual inline ~coordnum() {}
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 /// \brief Colvar component: self-coordination number within a group
 /// (colvarvalue::type_scalar type, range [0:N*(N-1)/2])
 class colvar::selfcoordnum
   : public colvar::distance
 {
 protected:
   /// \brief "Cutoff" for isotropic calculation (default)
   cvm::real     r0;
   /// Integer exponent of the function numerator
   int en;
   /// Integer exponent of the function denominator
   int ed;
 public:
   /// Constructor
   selfcoordnum (std::string const &conf);
   selfcoordnum();
   virtual inline ~selfcoordnum() {}
   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);
-  
+
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 /// \brief Colvar component: hydrogen bond, defined as the product of
 /// a colvar::coordnum and 1/2*(1-cos((180-ang)/ang_tol))
 /// (colvarvalue::type_scalar type, range [0:1])
-class colvar::h_bond 
+class colvar::h_bond
   : public colvar::cvc
 {
 protected:
   /// Atoms involved in the component
   cvm::atom     acceptor, donor;
   /// \brief "Cutoff" distance between acceptor and donor
   cvm::real     r0;
   /// Integer exponent of the function numerator
   int en;
   /// Integer exponent of the function denominator
   int ed;
 public:
   h_bond (std::string const &conf);
   /// Constructor for atoms already allocated
   h_bond (cvm::atom const &acceptor,
           cvm::atom const &donor,
           cvm::real r0, int en, int ed);
   h_bond();
   virtual ~h_bond();
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 /// \brief Colvar component: alpha helix content of a contiguous
 /// segment of 5 or more residues, implemented as a sum of phi/psi
 /// dihedral angles and hydrogen bonds (colvarvalue::type_scalar type,
 /// range [0:1])
 // class colvar::alpha_dihedrals
 //   : public colvar::cvc
 // {
 // protected:
 
 //   /// Alpha-helical reference phi value
 //   cvm::real phi_ref;
 
 //   /// Alpha-helical reference psi value
 //   cvm::real psi_ref;
 
 //   /// List of phi dihedral angles
 //   std::vector<dihedral *> phi;
 
 //   /// List of psi dihedral angles
 //   std::vector<dihedral *> psi;
 
 //   /// List of hydrogen bonds
 //   std::vector<h_bond *>   hb;
 
 // public:
 
 //   alpha_dihedrals (std::string const &conf);
 //   alpha_dihedrals();
 //   virtual inline ~alpha_dihedrals() {}
 //   virtual void calc_value();
-//   virtual void calc_gradients(); 
+//   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;
 //   virtual cvm::real compare (colvarvalue const &x1,
 //                              colvarvalue const &x2) const;
 // };
 
 
 /// \brief Colvar component: alpha helix content of a contiguous
 /// segment of 5 or more residues, implemented as a sum of Ca-Ca-Ca
 /// angles and hydrogen bonds (colvarvalue::type_scalar type, range
 /// [0:1])
 class colvar::alpha_angles
   : public colvar::cvc
 {
 protected:
 
   /// Reference Calpha-Calpha angle (default: 88 degrees)
   cvm::real theta_ref;
 
   /// Tolerance on the Calpha-Calpha angle
   cvm::real theta_tol;
 
   /// List of Calpha-Calpha angles
   std::vector<angle *> theta;
 
   /// List of hydrogen bonds
   std::vector<h_bond *>   hb;
 
-  /// Contribution of the hb terms 
+  /// Contribution of the hb terms
   cvm::real hb_coeff;
 
 public:
 
   alpha_angles (std::string const &conf);
   alpha_angles();
   virtual ~alpha_angles();
   void calc_value();
   void calc_gradients();
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 /// \brief Colvar component: dihedPC
 /// Projection of the config onto a dihedral principal component
 /// See e.g. Altis et al., J. Chem. Phys 126, 244111 (2007)
 /// Based on a set of 'dihedral' cvcs
 class colvar::dihedPC
   : public colvar::cvc
 {
 protected:
 
   std::vector<dihedral *> theta;
   std::vector<cvm::real> coeffs;
 
 public:
 
   dihedPC (std::string const &conf);
   dihedPC();
   virtual  ~dihedPC();
   void calc_value();
   void calc_gradients();
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 /// \brief Colvar component: orientation in space of an atom group,
 /// with respect to a set of reference coordinates
 /// (colvarvalue::type_quaternion type, range
 /// [-1:1]x[-1:1]x[-1:1]x[-1:1])
 class colvar::orientation
   : public colvar::cvc
 {
 protected:
 
   /// Atom group
   cvm::atom_group            atoms;
   /// Center of geometry of the group
   cvm::atom_pos              atoms_cog;
 
   /// Reference coordinates
   std::vector<cvm::atom_pos> ref_pos;
 
   /// Rotation object
   cvm::rotation              rot;
 
   /// \brief This is used to remove jumps in the sign of the
   /// quaternion, which may be annoying in the colvars trajectory
   cvm::quaternion            ref_quat;
 
 public:
 
   orientation (std::string const &conf);
   orientation();
   virtual inline ~orientation() {}
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 /// \brief Colvar component: angle of rotation with respect to a set
 /// of reference coordinates (colvarvalue::type_scalar type, range
 /// [0:PI))
 class colvar::orientation_angle
   : public colvar::orientation
 {
 public:
 
   orientation_angle (std::string const &conf);
   orientation_angle();
   virtual inline ~orientation_angle() {}
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 /// \brief Colvar component: projection of the orientation vector onto
 /// a predefined axis (colvarvalue::type_scalar type, range [-1:1])
 class colvar::tilt
   : public colvar::orientation
 {
 protected:
 
   cvm::rvector axis;
 
 public:
 
   tilt (std::string const &conf);
   tilt();
   virtual inline ~tilt() {}
   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;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 
 /// \brief Colvar component: angle of rotation around a predefined
 /// axis (colvarvalue::type_scalar type, range [-PI:PI])
 class colvar::spin_angle
   : public colvar::orientation
 {
 protected:
 
   cvm::rvector axis;
 
 public:
 
   spin_angle (std::string const &conf);
   spin_angle();
   virtual inline ~spin_angle() {}
   virtual void calc_value();
   virtual void calc_gradients();
   virtual void apply_force (colvarvalue const &force);
   /// Redefined to handle the 2*PI periodicity
   virtual cvm::real dist2 (colvarvalue const &x1,
                            colvarvalue const &x2) const;
   /// Redefined to handle the 2*PI periodicity
   virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   /// Redefined to handle the 2*PI periodicity
   virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   /// Redefined to handle the 2*PI periodicity
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
   /// Redefined to handle the 2*PI periodicity
   virtual void wrap (colvarvalue &x) const;
 };
 
 
 
 /// \brief Colvar component: root mean square deviation (RMSD) of a
 /// group with respect to a set of reference coordinates; uses \link
 /// colvar::orientation \endlink to calculate the rotation matrix
 /// (colvarvalue::type_scalar type, range [0:*))
 class colvar::rmsd
   : public colvar::cvc
 {
 protected:
 
   /// Atom group
   cvm::atom_group             atoms;
 
   /// Reference coordinates (for RMSD calculation only)
   std::vector<cvm::atom_pos>  ref_pos;
 
 public:
 
   /// Constructor
   rmsd (std::string const &conf);
   virtual inline ~rmsd() {}
   virtual void calc_value();
   virtual void calc_gradients();
   virtual void calc_force_invgrads();
   virtual void calc_Jacobian_derivative();
   virtual void apply_force (colvarvalue const &force);
   virtual cvm::real dist2 (colvarvalue const &x1,
                            colvarvalue const &x2) const;
   virtual colvarvalue dist2_lgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual colvarvalue dist2_rgrad (colvarvalue const &x1,
                                    colvarvalue const &x2) const;
   virtual cvm::real compare (colvarvalue const &x1,
                              colvarvalue const &x2) const;
 };
 
 
 
-// metrics functions for cvc implementations 
+// metrics functions for cvc implementations
 
 // simple definitions of the distance functions; these are useful only
 // for optimization (the type check performed in the default
 // colvarcomp functions is skipped)
 
 // definitions assuming the scalar type
 
 #define simple_scalar_dist_functions(TYPE)                              \
                                                                         \
   inline cvm::real colvar::TYPE::dist2 (colvarvalue const &x1,          \
                                         colvarvalue const &x2) const    \
   {                                                                     \
     return (x1.real_value - x2.real_value)*(x1.real_value - x2.real_value); \
   }                                                                     \
                                                                         \
   inline colvarvalue colvar::TYPE::dist2_lgrad (colvarvalue const &x1,  \
                                                 colvarvalue const &x2) const \
   {                                                                     \
     return 2.0 * (x1.real_value - x2.real_value);                       \
   }                                                                     \
                                                                         \
   inline colvarvalue colvar::TYPE::dist2_rgrad (colvarvalue const &x1,  \
                                                 colvarvalue const &x2) const \
   {                                                                     \
     return this->dist2_lgrad (x2, x1);                                  \
   }                                                                     \
                                                                         \
   inline cvm::real colvar::TYPE::compare (colvarvalue const &x1,        \
                                           colvarvalue const &x2) const  \
   {                                                                     \
     return this->dist2_lgrad (x1, x2);                                  \
   }                                                                     \
                                                                         \
 
   simple_scalar_dist_functions (distance)
-  // NOTE: distance_z has explicit functions, see below 
+  // NOTE: distance_z has explicit functions, see below
   simple_scalar_dist_functions (distance_xy)
   simple_scalar_dist_functions (distance_inv)
   simple_scalar_dist_functions (angle)
   simple_scalar_dist_functions (coordnum)
   simple_scalar_dist_functions (selfcoordnum)
   simple_scalar_dist_functions (h_bond)
   simple_scalar_dist_functions (gyration)
   simple_scalar_dist_functions (inertia)
   simple_scalar_dist_functions (inertia_z)
   simple_scalar_dist_functions (rmsd)
   simple_scalar_dist_functions (orientation_angle)
   simple_scalar_dist_functions (tilt)
   simple_scalar_dist_functions (eigenvector)
   //  simple_scalar_dist_functions (alpha_dihedrals)
   simple_scalar_dist_functions (alpha_angles)
   simple_scalar_dist_functions (dihedPC)
 
 
 // metrics functions for cvc implementations with a periodicity
 
 inline cvm::real colvar::dihedral::dist2 (colvarvalue const &x1,
                                           colvarvalue const &x2) const
 {
   cvm::real diff = x1.real_value - x2.real_value;
   diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
   return diff * diff;
 }
 
 inline colvarvalue colvar::dihedral::dist2_lgrad (colvarvalue const &x1,
                                                   colvarvalue const &x2) const
 {
   cvm::real diff = x1.real_value - x2.real_value;
   diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
   return 2.0 * diff;
 }
 
 inline colvarvalue colvar::dihedral::dist2_rgrad (colvarvalue const &x1,
                                                   colvarvalue const &x2) const
 {
   cvm::real diff = x1.real_value - x2.real_value;
   diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
   return (-2.0) * diff;
 }
 
 inline cvm::real colvar::dihedral::compare (colvarvalue const &x1,
                                             colvarvalue const &x2) const
 {
   return dist2_lgrad (x1, x2);
 }
 
 inline void colvar::dihedral::wrap (colvarvalue &x) const
 {
   if ((x.real_value - wrap_center) >= 180.0) {
     x.real_value -= 360.0;
     return;
-  } 
+  }
 
   if ((x.real_value - wrap_center) < -180.0) {
     x.real_value += 360.0;
     return;
-  } 
+  }
 
   return;
 }
 
 inline cvm::real colvar::spin_angle::dist2 (colvarvalue const &x1,
                                           colvarvalue const &x2) const
 {
   cvm::real diff = x1.real_value - x2.real_value;
   diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
   return diff * diff;
 }
 
 inline colvarvalue colvar::spin_angle::dist2_lgrad (colvarvalue const &x1,
                                                   colvarvalue const &x2) const
 {
   cvm::real diff = x1.real_value - x2.real_value;
   diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
   return 2.0 * diff;
 }
 
 inline colvarvalue colvar::spin_angle::dist2_rgrad (colvarvalue const &x1,
                                                   colvarvalue const &x2) const
 {
   cvm::real diff = x1.real_value - x2.real_value;
   diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
   return (-2.0) * diff;
 }
 
 inline cvm::real colvar::spin_angle::compare (colvarvalue const &x1,
                                             colvarvalue const &x2) const
 {
   return dist2_lgrad (x1, x2);
 }
 
 inline void colvar::spin_angle::wrap (colvarvalue &x) const
 {
   if ((x.real_value - wrap_center) >= 180.0) {
     x.real_value -= 360.0;
     return;
-  } 
+  }
 
   if ((x.real_value - wrap_center) < -180.0) {
     x.real_value += 360.0;
     return;
-  } 
+  }
 
   return;
 }
 
 
 // Projected distance
 // Differences should always be wrapped around 0 (ignoring wrap_center)
 inline cvm::real colvar::distance_z::dist2 (colvarvalue const &x1,
                                             colvarvalue const &x2) const
 {
   cvm::real diff = x1.real_value - x2.real_value;
   if (period != 0.0) {
     cvm::real shift = std::floor (diff/period + 0.5);
     diff -= shift * period;
   }
   return diff * diff;
 }
 
 inline colvarvalue colvar::distance_z::dist2_lgrad (colvarvalue const &x1,
                                                     colvarvalue const &x2) const
 {
   cvm::real diff = x1.real_value - x2.real_value;
   if (period != 0.0) {
     cvm::real shift = std::floor (diff/period + 0.5);
     diff -= shift * period;
   }
   return 2.0 * diff;
 }
 
 inline colvarvalue colvar::distance_z::dist2_rgrad (colvarvalue const &x1,
                                                     colvarvalue const &x2) const
 {
   cvm::real diff = x1.real_value - x2.real_value;
   if (period != 0.0) {
     cvm::real shift = std::floor (diff/period + 0.5);
     diff -= shift * period;
   }
   return (-2.0) * diff;
 }
 
 inline cvm::real colvar::distance_z::compare (colvarvalue const &x1,
                                               colvarvalue const &x2) const
 {
   return dist2_lgrad (x1, x2);
 }
 
 inline void colvar::distance_z::wrap (colvarvalue &x) const
 {
   if (! this->b_periodic) {
     // don't wrap if the period has not been set
     return;
   }
 
   cvm::real shift = std::floor ((x.real_value - wrap_center) / period + 0.5);
   x.real_value -= shift * period;
   return;
 }
 
 
 // distance between three dimensional vectors
 //
 // TODO apply PBC to distance_vec
 // Note: differences should be centered around (0, 0, 0)!
 
 inline cvm::real colvar::distance_vec::dist2 (colvarvalue const &x1,
                                               colvarvalue const &x2) const
 {
   return cvm::position_dist2 (x1.rvector_value, x2.rvector_value);
 }
 
 inline colvarvalue colvar::distance_vec::dist2_lgrad (colvarvalue const &x1,
                                                       colvarvalue const &x2) const
 {
   return 2.0 * cvm::position_distance(x2.rvector_value, x1.rvector_value);
 }
 
 inline colvarvalue colvar::distance_vec::dist2_rgrad (colvarvalue const &x1,
                                                       colvarvalue const &x2) const
 {
   return 2.0 * cvm::position_distance(x2.rvector_value, x1.rvector_value);
 }
 
 inline cvm::real colvar::distance_vec::compare (colvarvalue const &x1,
                                                 colvarvalue const &x2) const
 {
   cvm::fatal_error ("Error: cannot compare() two distance vectors.\n");
   return 0.0;
 }
 
 inline cvm::real colvar::distance_dir::dist2 (colvarvalue const &x1,
                                               colvarvalue const &x2) const
 {
   return (x1.rvector_value - x2.rvector_value).norm2();
 }
 
 inline colvarvalue colvar::distance_dir::dist2_lgrad (colvarvalue const &x1,
                                                       colvarvalue const &x2) const
 {
   return colvarvalue ((x1.rvector_value - x2.rvector_value), colvarvalue::type_unitvector);
 }
 
 inline colvarvalue colvar::distance_dir::dist2_rgrad (colvarvalue const &x1,
                                                       colvarvalue const &x2) const
 {
   return colvarvalue ((x2.rvector_value - x1.rvector_value), colvarvalue::type_unitvector);
 }
 
 inline cvm::real colvar::distance_dir::compare (colvarvalue const &x1,
                                                 colvarvalue const &x2) const
 {
   cvm::fatal_error ("Error: cannot compare() two distance directions.\n");
   return 0.0;
 }
 
 // distance between quaternions
 
 inline cvm::real colvar::orientation::dist2 (colvarvalue const &x1,
                                              colvarvalue const &x2) const
 {
   return x1.quaternion_value.dist2 (x2);
 }
 
 inline colvarvalue colvar::orientation::dist2_lgrad (colvarvalue const &x1,
                                                      colvarvalue const &x2) const
 {
   return x1.quaternion_value.dist2_grad (x2);
 }
 
 inline colvarvalue colvar::orientation::dist2_rgrad (colvarvalue const &x1,
                                                      colvarvalue const &x2) const
 {
   return x2.quaternion_value.dist2_grad (x1);
 }
 
 inline cvm::real colvar::orientation::compare (colvarvalue const &x1,
                                                colvarvalue const &x2) const
 {
   cvm::fatal_error ("Error: cannot compare() two quaternions.\n");
   return 0.0;
 }
 
 
 #endif
 
 
 // Emacs
 // Local Variables:
 // mode: C++
 // End:
diff --git a/lib/colvars/colvarcomp_angles.cpp b/lib/colvars/colvarcomp_angles.cpp
index 414c01df7..bc2aee059 100644
--- a/lib/colvars/colvarcomp_angles.cpp
+++ b/lib/colvars/colvarcomp_angles.cpp
@@ -1,377 +1,377 @@
 
 #include "colvarmodule.h"
 #include "colvar.h"
 #include "colvarcomp.h"
 
 #include <cmath>
 
 
 
 colvar::angle::angle (std::string const &conf)
   : cvc (conf)
 {
   function_type = "angle";
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   parse_group (conf, "group1", group1);
   parse_group (conf, "group2", group2);
   parse_group (conf, "group3", group3);
   atom_groups.push_back (&group1);
   atom_groups.push_back (&group2);
   atom_groups.push_back (&group3);
   if (get_keyval (conf, "oneSiteSystemForce", b_1site_force, false)) {
     cvm::log ("Computing system force on group 1 only");
   }
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::angle::angle (cvm::atom const &a1,
                       cvm::atom const &a2,
                       cvm::atom const &a3)
   : group1 (std::vector<cvm::atom> (1, a1)),
     group2 (std::vector<cvm::atom> (1, a2)),
     group3 (std::vector<cvm::atom> (1, a3))
 {
   function_type = "angle";
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   b_1site_force = false;
   atom_groups.push_back (&group1);
   atom_groups.push_back (&group2);
   atom_groups.push_back (&group3);
 
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::angle::angle()
 {
   function_type = "angle";
   x.type (colvarvalue::type_scalar);
 }
 
 
 void colvar::angle::calc_value()
 {
   group1.read_positions();
   group2.read_positions();
   group3.read_positions();
 
   cvm::atom_pos const g1_pos = group1.center_of_mass();
   cvm::atom_pos const g2_pos = group2.center_of_mass();
   cvm::atom_pos const g3_pos = group3.center_of_mass();
 
   r21  = cvm::position_distance (g2_pos, g1_pos);
   r21l = r21.norm();
   r23  = cvm::position_distance (g2_pos, g3_pos);
   r23l = r23.norm();
 
   cvm::real     const cos_theta = (r21*r23)/(r21l*r23l);
 
   x.real_value = (180.0/PI) * std::acos (cos_theta);
 }
 
 
 void colvar::angle::calc_gradients()
 {
   cvm::real const cos_theta = (r21*r23)/(r21l*r23l);
   cvm::real const dxdcos = -1.0 / std::sqrt (1.0 - cos_theta*cos_theta);
-    
+
   dxdr1 = (180.0/PI) * dxdcos *
     (1.0/r21l) * ( r23/r23l + (-1.0) * cos_theta * r21/r21l );
 
   dxdr3 = (180.0/PI) * dxdcos *
     (1.0/r23l) * ( r21/r21l + (-1.0) * cos_theta * r23/r23l );
 
   for (size_t i = 0; i < group1.size(); i++) {
     group1[i].grad = (group1[i].mass/group1.total_mass) *
       (dxdr1);
   }
 
   for (size_t i = 0; i < group2.size(); i++) {
     group2[i].grad = (group2[i].mass/group2.total_mass) *
       (dxdr1 + dxdr3) * (-1.0);
   }
 
   for (size_t i = 0; i < group3.size(); i++) {
     group3[i].grad = (group3[i].mass/group3.total_mass) *
       (dxdr3);
   }
 }
 
 void colvar::angle::calc_force_invgrads()
 {
   // This uses a force measurement on groups 1 and 3 only
   // to keep in line with the implicit variable change used to
   // evaluate the Jacobian term (essentially polar coordinates
   // centered on group2, which means group2 is kept fixed
   // when propagating changes in the angle)
 
   if (b_1site_force) {
     group1.read_system_forces();
     cvm::real norm_fact = 1.0 / dxdr1.norm2();
     ft.real_value = norm_fact * dxdr1 * group1.system_force();
   } else {
     group1.read_system_forces();
     group3.read_system_forces();
     cvm::real norm_fact = 1.0 / (dxdr1.norm2() + dxdr3.norm2());
     ft.real_value = norm_fact * ( dxdr1 * group1.system_force()
                                 + dxdr3 * group3.system_force());
   }
   return;
 }
 
 void colvar::angle::calc_Jacobian_derivative()
 {
   // det(J) = (2 pi) r^2 * sin(theta)
   // hence Jd = cot(theta)
   const cvm::real theta = x.real_value * PI / 180.0;
   jd = PI / 180.0 * (theta != 0.0 ? std::cos(theta) / std::sin(theta) : 0.0);
 }
 
 
 void colvar::angle::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);
 
   if (!group3.noforce)
     group3.apply_colvar_force (force.real_value);
 }
 
 
 
 
 colvar::dihedral::dihedral (std::string const &conf)
   : cvc (conf)
 {
   function_type = "dihedral";
   period = 360.0;
   b_periodic = true;
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   if (get_keyval (conf, "oneSiteSystemForce", b_1site_force, false)) {
     cvm::log ("Computing system force on group 1 only");
   }
   parse_group (conf, "group1", group1);
   parse_group (conf, "group2", group2);
   parse_group (conf, "group3", group3);
   parse_group (conf, "group4", group4);
   atom_groups.push_back (&group1);
   atom_groups.push_back (&group2);
   atom_groups.push_back (&group3);
   atom_groups.push_back (&group4);
 
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::dihedral::dihedral (cvm::atom const &a1,
                             cvm::atom const &a2,
                             cvm::atom const &a3,
                             cvm::atom const &a4)
   : group1 (std::vector<cvm::atom> (1, a1)),
     group2 (std::vector<cvm::atom> (1, a2)),
     group3 (std::vector<cvm::atom> (1, a3)),
     group4 (std::vector<cvm::atom> (1, a4))
 {
   if (cvm::debug())
     cvm::log ("Initializing dihedral object from atom groups.\n");
 
   function_type = "dihedral";
   period = 360.0;
   b_periodic = true;
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   b_1site_force = false;
 
   atom_groups.push_back (&group1);
   atom_groups.push_back (&group2);
   atom_groups.push_back (&group3);
   atom_groups.push_back (&group4);
 
   x.type (colvarvalue::type_scalar);
 
   if (cvm::debug())
     cvm::log ("Done initializing dihedral object from atom groups.\n");
 }
 
 
 colvar::dihedral::dihedral()
 {
   function_type = "dihedral";
   period = 360.0;
   b_periodic = true;
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   x.type (colvarvalue::type_scalar);
 }
 
 
 void colvar::dihedral::calc_value()
 {
   group1.read_positions();
   group2.read_positions();
   group3.read_positions();
   group4.read_positions();
 
   cvm::atom_pos const g1_pos = group1.center_of_mass();
   cvm::atom_pos const g2_pos = group2.center_of_mass();
   cvm::atom_pos const g3_pos = group3.center_of_mass();
   cvm::atom_pos const g4_pos = group4.center_of_mass();
 
   // Usual sign convention: r12 = r2 - r1
   r12 = cvm::position_distance (g1_pos, g2_pos);
   r23 = cvm::position_distance (g2_pos, g3_pos);
   r34 = cvm::position_distance (g3_pos, g4_pos);
 
   cvm::rvector const n1 = cvm::rvector::outer (r12, r23);
   cvm::rvector const n2 = cvm::rvector::outer (r23, r34);
 
   cvm::real const cos_phi = n1 * n2;
   cvm::real const sin_phi = n1 * r34 * r23.norm();
 
   x.real_value = (180.0/PI) * std::atan2 (sin_phi, cos_phi);
   this->wrap (x);
 }
 
 
 void colvar::dihedral::calc_gradients()
 {
   cvm::rvector A = cvm::rvector::outer (r12, r23);
   cvm::real   rA = A.norm();
   cvm::rvector B = cvm::rvector::outer (r23, r34);
   cvm::real   rB = B.norm();
-  cvm::rvector C = cvm::rvector::outer (r23, A); 
+  cvm::rvector C = cvm::rvector::outer (r23, A);
   cvm::real   rC = C.norm();
 
   cvm::real const cos_phi = (A*B)/(rA*rB);
   cvm::real const sin_phi = (C*B)/(rC*rB);
 
   cvm::rvector f1, f2, f3;
 
   rB = 1.0/rB;
   B *= rB;
 
   if (std::fabs (sin_phi) > 0.1) {
     rA = 1.0/rA;
     A *= rA;
     cvm::rvector const dcosdA = rA*(cos_phi*A-B);
     cvm::rvector const dcosdB = rB*(cos_phi*B-A);
     rA = 1.0;
 
     cvm::real const K = (1.0/sin_phi) * (180.0/PI);
 
 	f1 = K * cvm::rvector::outer (r23, dcosdA);
 	f3 = K * cvm::rvector::outer (dcosdB, r23);
 	f2 = K * (cvm::rvector::outer (dcosdA, r12)
 		   +  cvm::rvector::outer (r34, dcosdB));
   }
   else {
     rC = 1.0/rC;
     C *= rC;
     cvm::rvector const dsindC = rC*(sin_phi*C-B);
     cvm::rvector const dsindB = rB*(sin_phi*B-C);
     rC = 1.0;
 
     cvm::real    const K = (-1.0/cos_phi) * (180.0/PI);
 
     f1.x = K*((r23.y*r23.y + r23.z*r23.z)*dsindC.x
               - r23.x*r23.y*dsindC.y
               - r23.x*r23.z*dsindC.z);
     f1.y = K*((r23.z*r23.z + r23.x*r23.x)*dsindC.y
               - r23.y*r23.z*dsindC.z
               - r23.y*r23.x*dsindC.x);
     f1.z = K*((r23.x*r23.x + r23.y*r23.y)*dsindC.z
               - r23.z*r23.x*dsindC.x
               - r23.z*r23.y*dsindC.y);
 
     f3 = cvm::rvector::outer (dsindB, r23);
     f3 *= K;
 
     f2.x = K*(-(r23.y*r12.y + r23.z*r12.z)*dsindC.x
               +(2.0*r23.x*r12.y - r12.x*r23.y)*dsindC.y
               +(2.0*r23.x*r12.z - r12.x*r23.z)*dsindC.z
               +dsindB.z*r34.y - dsindB.y*r34.z);
     f2.y = K*(-(r23.z*r12.z + r23.x*r12.x)*dsindC.y
               +(2.0*r23.y*r12.z - r12.y*r23.z)*dsindC.z
               +(2.0*r23.y*r12.x - r12.y*r23.x)*dsindC.x
               +dsindB.x*r34.z - dsindB.z*r34.x);
     f2.z = K*(-(r23.x*r12.x + r23.y*r12.y)*dsindC.z
               +(2.0*r23.z*r12.x - r12.z*r23.x)*dsindC.x
               +(2.0*r23.z*r12.y - r12.z*r23.y)*dsindC.y
               +dsindB.y*r34.x - dsindB.x*r34.y);
   }
 
   for (size_t i = 0; i < group1.size(); i++)
     group1[i].grad = (group1[i].mass/group1.total_mass) * (-f1);
 
   for (size_t i = 0; i < group2.size(); i++)
     group2[i].grad = (group2[i].mass/group2.total_mass) * (-f2 + f1);
 
   for (size_t i = 0; i < group3.size(); i++)
 	group3[i].grad = (group3[i].mass/group3.total_mass) * (-f3 + f2);
 
   for (size_t i = 0; i < group4.size(); i++)
     group4[i].grad = (group4[i].mass/group4.total_mass) * (f3);
 }
 
 
 void colvar::dihedral::calc_force_invgrads()
 {
   cvm::rvector const u12 = r12.unit();
   cvm::rvector const u23 = r23.unit();
   cvm::rvector const u34 = r34.unit();
 
   cvm::real const d12 = r12.norm();
   cvm::real const d34 = r34.norm();
 
   cvm::rvector const cross1 = (cvm::rvector::outer (u23, u12)).unit();
   cvm::rvector const cross4 = (cvm::rvector::outer (u23, u34)).unit();
 
   cvm::real const dot1 = u23 * u12;
   cvm::real const dot4 = u23 * u34;
 
   cvm::real const fact1 = d12 * std::sqrt (1.0 - dot1 * dot1);
   cvm::real const fact4 = d34 * std::sqrt (1.0 - dot4 * dot4);
 
   group1.read_system_forces();
   if ( b_1site_force ) {
     // This is only measuring the force on group 1
     ft.real_value = PI/180.0 * fact1 * (cross1 * group1.system_force());
   } else {
     // Default case: use groups 1 and 4
     group4.read_system_forces();
     ft.real_value = PI/180.0 * 0.5 * (fact1 * (cross1 * group1.system_force())
 				      + fact4 * (cross4 * group4.system_force()));
   }
 }
 
 
 void colvar::dihedral::calc_Jacobian_derivative()
 {
   // With this choice of inverse gradient ("internal coordinates"), Jacobian correction is 0
   jd = 0.0;
 }
 
 
 void colvar::dihedral::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);
 
   if (!group3.noforce)
     group3.apply_colvar_force (force.real_value);
 
   if (!group4.noforce)
     group4.apply_colvar_force (force.real_value);
 }
 
 
diff --git a/lib/colvars/colvarcomp_coordnums.cpp b/lib/colvars/colvarcomp_coordnums.cpp
index 6afb118c0..d08a5e505 100644
--- a/lib/colvars/colvarcomp_coordnums.cpp
+++ b/lib/colvars/colvarcomp_coordnums.cpp
@@ -1,359 +1,359 @@
 #include <cmath>
 
 #include "colvarmodule.h"
 #include "colvarparse.h"
 #include "colvaratoms.h"
 #include "colvarvalue.h"
 #include "colvar.h"
 #include "colvarcomp.h"
 
 
 
 template<bool calculate_gradients>
 cvm::real colvar::coordnum::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;
 }
 
 
 template<bool calculate_gradients>
 cvm::real colvar::coordnum::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;
 }
 
 
 
 colvar::coordnum::coordnum (std::string const &conf)
   : distance (conf), b_anisotropic (false), b_group2_center_only (false)
-{ 
+{
   function_type = "coordnum";
   x.type (colvarvalue::type_scalar);
 
   // group1 and group2 are already initialized by distance()
   if (group1.b_dummy)
     cvm::fatal_error ("Error: only group2 is allowed to be a dummy atom\n");
 
-  
+
   // need to specify this explicitly because the distance() constructor
   // has set it to true
   b_inverse_gradients = false;
 
   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");
   }
 
   get_keyval (conf, "group2CenterOnly", b_group2_center_only, group2.b_dummy);
 }
 
 
 colvar::coordnum::coordnum()
   : b_anisotropic (false), b_group2_center_only (false)
 {
   function_type = "coordnum";
   x.type (colvarvalue::type_scalar);
 }
 
 
 void colvar::coordnum::calc_value()
 {
   x.real_value = 0.0;
 
   if (b_group2_center_only) {
 
     // create a fake atom to hold the group2 com coordinates
     cvm::atom group2_com_atom;
     group2_com_atom.pos = group2.center_of_mass();
 
     if (b_anisotropic) {
       for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
         x.real_value += switching_function<false> (r0_vec, en, ed, *ai1, group2_com_atom);
     } else {
       for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
         x.real_value += switching_function<false> (r0, en, ed, *ai1, group2_com_atom);
     }
 
   } else {
 
     if (b_anisotropic) {
       for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
         for (cvm::atom_iter ai2 = group2.begin(); ai2 != group2.end(); ai2++) {
           x.real_value += switching_function<false> (r0_vec, en, ed, *ai1, *ai2);
         }
     } else {
       for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
         for (cvm::atom_iter ai2 = group2.begin(); ai2 != group2.end(); ai2++) {
           x.real_value += switching_function<false> (r0, en, ed, *ai1, *ai2);
         }
     }
   }
 }
 
 
 void colvar::coordnum::calc_gradients()
 {
   if (b_group2_center_only) {
 
     // create a fake atom to hold the group2 com coordinates
     cvm::atom group2_com_atom;
     group2_com_atom.pos = group2.center_of_mass();
 
 
     if (b_anisotropic) {
       for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
         switching_function<true> (r0_vec, en, ed, *ai1, group2_com_atom);
     } else {
       for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
         switching_function<true> (r0, en, ed, *ai1, group2_com_atom);
     }
 
     group2.set_weighted_gradient (group2_com_atom.grad);
 
   } else {
 
     if (b_anisotropic) {
       for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
         for (cvm::atom_iter ai2 = group2.begin(); ai2 != group2.end(); ai2++) {
           switching_function<true> (r0_vec, en, ed, *ai1, *ai2);
         }
     } else {
       for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
         for (cvm::atom_iter ai2 = group2.begin(); ai2 != group2.end(); ai2++) {
           switching_function<true> (r0, en, ed, *ai1, *ai2);
         }
     }
   }
 
   //   if (cvm::debug()) {
   //     for (size_t i = 0; i < group1.size(); i++) {
   //       cvm::log ("atom["+cvm::to_str (group1[i].id+1)+"] gradient: "+
   //                 cvm::to_str (group1[i].grad)+"\n");
   //     }
 
   //     for (size_t i = 0; i < group2.size(); i++) {
   //       cvm::log ("atom["+cvm::to_str (group2[i].id+1)+"] gradient: "+
   //                 cvm::to_str (group2[i].grad)+"\n");
   //     }
   //   }
 }
 
 void colvar::coordnum::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);
 }
 
 
 
 // h_bond member functions
 
 colvar::h_bond::h_bond (std::string const &conf)
   : cvc (conf)
 {
   if (cvm::debug())
     cvm::log ("Initializing h_bond object.\n");
 
   function_type = "h_bond";
   x.type (colvarvalue::type_scalar);
 
   int a_num, d_num;
   get_keyval (conf, "acceptor", a_num, -1);
   get_keyval (conf, "donor",    d_num, -1);
 
   if ( (a_num == -1) || (d_num == -1) ) {
     cvm::fatal_error ("Error: either acceptor or donor undefined.\n");
   }
 
   acceptor = cvm::atom (a_num);
   donor    = cvm::atom (d_num);
   atom_groups.push_back (new cvm::atom_group);
   atom_groups[0]->add_atom (acceptor);
   atom_groups[0]->add_atom (donor);
 
   get_keyval (conf, "cutoff",   r0, (3.3 * cvm::unit_angstrom()));
   get_keyval (conf, "expNumer", en, 6);
   get_keyval (conf, "expDenom", ed, 8);
 
   if ( (en%2) || (ed%2) ) {
     cvm::fatal_error ("Error: odd exponents provided, can only use even ones.\n");
   }
 
   if (cvm::debug())
     cvm::log ("Done initializing h_bond object.\n");
 }
 
 
 colvar::h_bond::h_bond (cvm::atom const &acceptor_i,
                         cvm::atom const &donor_i,
                         cvm::real r0_i, int en_i, int ed_i)
   : acceptor (acceptor_i),
     donor (donor_i),
     r0 (r0_i), en (en_i), ed (ed_i)
 {
   function_type = "h_bond";
   x.type (colvarvalue::type_scalar);
 
   atom_groups.push_back (new cvm::atom_group);
   atom_groups[0]->add_atom (acceptor);
   atom_groups[0]->add_atom (donor);
 }
 
 colvar::h_bond::h_bond()
   : cvc ()
 {
   function_type = "h_bond";
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::h_bond::~h_bond()
 {
   for (int i=0; i<atom_groups.size(); i++) {
     delete atom_groups[i];
   }
 }
 
 
 void colvar::h_bond::calc_value()
 {
   x.real_value = colvar::coordnum::switching_function<false> (r0, en, ed, acceptor, donor);
 }
 
 
 void colvar::h_bond::calc_gradients()
 {
   colvar::coordnum::switching_function<true> (r0, en, ed, acceptor, donor);
   (*atom_groups[0])[0].grad = acceptor.grad;
   (*atom_groups[0])[1].grad = donor.grad;
 }
 
 
 void colvar::h_bond::apply_force (colvarvalue const &force)
 {
   acceptor.apply_force (force.real_value * acceptor.grad);
   donor.apply_force    (force.real_value * donor.grad);
 }
 
 
 
 
 colvar::selfcoordnum::selfcoordnum (std::string const &conf)
  : distance (conf, false)
-{ 
+{
   function_type = "selfcoordnum";
   x.type (colvarvalue::type_scalar);
 
   // group1 is already initialized by distance()
 
   // need to specify this explicitly because the distance() constructor
   // has set it to true
   b_inverse_gradients = false;
 
   get_keyval (conf, "cutoff", r0, cvm::real (4.0 * cvm::unit_angstrom()));
   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::selfcoordnum::selfcoordnum()
 {
   function_type = "selfcoordnum";
   x.type (colvarvalue::type_scalar);
 }
 
 
 void colvar::selfcoordnum::calc_value()
 {
   x.real_value = 0.0;
 
   for (size_t i = 0; i < group1.size() - 1; i++)
     for (size_t j = i + 1; j < group1.size(); j++)
       x.real_value += colvar::coordnum::switching_function<false> (r0, en, ed, group1[i], group1[j]);
 }
 
 
 void colvar::selfcoordnum::calc_gradients()
 {
   for (size_t i = 0; i < group1.size() - 1; i++)
     for (size_t j = i + 1; j < group1.size(); j++)
       colvar::coordnum::switching_function<true> (r0, en, ed, group1[i], group1[j]);
 }
 
 void colvar::selfcoordnum::apply_force (colvarvalue const &force)
 {
   if (!group1.noforce)
     group1.apply_colvar_force (force.real_value);
 }
 
diff --git a/lib/colvars/colvarcomp_distances.cpp b/lib/colvars/colvarcomp_distances.cpp
index a371cff60..f59bab8a9 100644
--- a/lib/colvars/colvarcomp_distances.cpp
+++ b/lib/colvars/colvarcomp_distances.cpp
@@ -1,1151 +1,1151 @@
 #include <cmath>
 
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 #include "colvarparse.h"
 #include "colvar.h"
 #include "colvarcomp.h"
 
 
 
 // "twogroup" flag defaults to true; set to false by selfCoordNum
 // (only distance-derived component based on only one group)
 
 colvar::distance::distance (std::string const &conf, bool twogroups)
   : cvc (conf)
 {
   function_type = "distance";
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   if (get_keyval (conf, "forceNoPBC", b_no_PBC, false)) {
     cvm::log ("Computing distance using absolute positions (not minimal-image)");
   }
   if (twogroups && get_keyval (conf, "oneSiteSystemForce", b_1site_force, false)) {
     cvm::log ("Computing system force on group 1 only");
   }
   parse_group (conf, "group1", group1);
   atom_groups.push_back (&group1);
   if (twogroups) {
     parse_group (conf, "group2", group2);
     atom_groups.push_back (&group2);
   }
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::distance::distance()
   : cvc ()
 {
   function_type = "distance";
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   b_1site_force = false;
   x.type (colvarvalue::type_scalar);
 }
 
 void colvar::distance::calc_value()
 {
   if (b_no_PBC) {
     dist_v = group2.center_of_mass() - group1.center_of_mass();
   } else {
     dist_v = cvm::position_distance (group1.center_of_mass(),
                                      group2.center_of_mass());
   }
   x.real_value = dist_v.norm();
 }
 
 void colvar::distance::calc_gradients()
 {
   cvm::rvector const u = dist_v.unit();
   group1.set_weighted_gradient (-1.0 * u);
   group2.set_weighted_gradient (       u);
 }
 
 void colvar::distance::calc_force_invgrads()
 {
   group1.read_system_forces();
   if ( b_1site_force ) {
     ft.real_value = -1.0 * (group1.system_force() * dist_v.unit());
   } else {
     group2.read_system_forces();
     ft.real_value = 0.5 * ((group2.system_force() - group1.system_force()) * dist_v.unit());
   }
 }
 
 void colvar::distance::calc_Jacobian_derivative()
 {
   jd.real_value = x.real_value ? (2.0 / x.real_value) : 0.0;
 }
 
 void colvar::distance::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);
 }
 
 
 
 colvar::distance_vec::distance_vec (std::string const &conf)
   : distance (conf)
 {
   function_type = "distance_vec";
   x.type (colvarvalue::type_vector);
 }
 
 colvar::distance_vec::distance_vec()
   : distance()
 {
   function_type = "distance_vec";
   x.type (colvarvalue::type_vector);
 }
 
 void colvar::distance_vec::calc_value()
 {
   if (b_no_PBC) {
     x.rvector_value = group2.center_of_mass() - group1.center_of_mass();
   } else {
     x.rvector_value = cvm::position_distance (group1.center_of_mass(),
                                               group2.center_of_mass());
   }
 }
 
 void colvar::distance_vec::calc_gradients()
-{ 
+{
   // gradients are not stored: a 3x3 matrix for each atom would be
   // needed to store just the identity matrix
 }
 
 void colvar::distance_vec::apply_force (colvarvalue const &force)
 {
   if (!group1.noforce)
     group1.apply_force (-1.0 * force.rvector_value);
 
   if (!group2.noforce)
     group2.apply_force (       force.rvector_value);
 }
 
 
 
 colvar::distance_z::distance_z (std::string const &conf)
   : cvc (conf)
 {
   function_type = "distance_z";
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   x.type (colvarvalue::type_scalar);
 
   // TODO detect PBC from MD engine (in simple cases)
   // and then update period in real time
   if (period != 0.0)
-    b_periodic = true;    
+    b_periodic = true;
 
   if ((wrap_center != 0.0) && (period == 0.0)) {
     cvm::fatal_error ("Error: wrapAround was defined in a distanceZ component,"
                       " but its period has not been set.\n");
   }
 
   parse_group (conf, "main", main);
   parse_group (conf, "ref", ref1);
   atom_groups.push_back (&main);
   atom_groups.push_back (&ref1);
   // this group is optional
   parse_group (conf, "ref2", ref2, true);
- 
+
   if (ref2.size()) {
     atom_groups.push_back (&ref2);
     cvm::log ("Using axis joining the centers of mass of groups \"ref\" and \"ref2\"");
     fixed_axis = false;
     if (key_lookup (conf, "axis"))
       cvm::log ("Warning: explicit axis definition will be ignored!");
   } else {
     if (get_keyval (conf, "axis", axis, cvm::rvector (0.0, 0.0, 1.0))) {
       if (axis.norm2() == 0.0)
         cvm::fatal_error ("Axis vector is zero!");
       if (axis.norm2() != 1.0) {
         axis = axis.unit();
         cvm::log ("The normalized axis is: "+cvm::to_str (axis)+".\n");
       }
     }
     fixed_axis = true;
   }
 
   if (get_keyval (conf, "forceNoPBC", b_no_PBC, false)) {
     cvm::log ("Computing distance using absolute positions (not minimal-image)");
   }
   if (get_keyval (conf, "oneSiteSystemForce", b_1site_force, false)) {
     cvm::log ("Computing system force on group \"main\" only");
   }
 }
 
 colvar::distance_z::distance_z()
 {
   function_type = "distance_z";
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   x.type (colvarvalue::type_scalar);
 }
 
 void colvar::distance_z::calc_value()
 {
   if (fixed_axis) {
     if (b_no_PBC) {
       dist_v = main.center_of_mass() - ref1.center_of_mass();
     } else {
       dist_v = cvm::position_distance (ref1.center_of_mass(),
                                        main.center_of_mass());
     }
   } else {
 
     if (b_no_PBC) {
       dist_v = main.center_of_mass() -
                (0.5 * (ref1.center_of_mass() + ref2.center_of_mass()));
       axis = ref2.center_of_mass() - ref1.center_of_mass();
     } else {
       dist_v = cvm::position_distance (0.5 * (ref1.center_of_mass() +
                ref2.center_of_mass()), main.center_of_mass());
       axis = cvm::position_distance (ref1.center_of_mass(), ref2.center_of_mass());
     }
     axis_norm = axis.norm();
     axis = axis.unit();
   }
   x.real_value = axis * dist_v;
   this->wrap (x);
 }
 
 void colvar::distance_z::calc_gradients()
 {
   main.set_weighted_gradient ( axis );
 
   if (fixed_axis) {
     ref1.set_weighted_gradient (-1.0 * axis);
   } else {
     if (b_no_PBC) {
       ref1.set_weighted_gradient ( 1.0 / axis_norm * (main.center_of_mass() - ref2.center_of_mass() -
                                    x.real_value * axis ));
       ref2.set_weighted_gradient ( 1.0 / axis_norm * (ref1.center_of_mass() - main.center_of_mass() +
                                    x.real_value * axis ));
     } else {
       ref1.set_weighted_gradient ( 1.0 / axis_norm * (
         cvm::position_distance (ref2.center_of_mass(), main.center_of_mass()) - x.real_value * axis ));
       ref2.set_weighted_gradient ( 1.0 / axis_norm * (
         cvm::position_distance (main.center_of_mass(), ref1.center_of_mass()) + x.real_value * axis ));
     }
   }
 }
 
 void colvar::distance_z::calc_force_invgrads()
 {
   main.read_system_forces();
 
   if (fixed_axis && !b_1site_force) {
     ref1.read_system_forces();
     ft.real_value = 0.5 * ((main.system_force() - ref1.system_force()) * axis);
   } else {
     ft.real_value = main.system_force() * axis;
   }
 }
 
 void colvar::distance_z::calc_Jacobian_derivative()
 {
   jd.real_value = 0.0;
 }
 
 void colvar::distance_z::apply_force (colvarvalue const &force)
 {
   if (!ref1.noforce)
     ref1.apply_colvar_force (force.real_value);
 
   if (ref2.size() && !ref2.noforce)
     ref2.apply_colvar_force (force.real_value);
 
   if (!main.noforce)
     main.apply_colvar_force (force.real_value);
 }
 
 
 
 colvar::distance_xy::distance_xy (std::string const &conf)
   : distance_z (conf)
 {
   function_type = "distance_xy";
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   x.type (colvarvalue::type_scalar);
 }
 
 colvar::distance_xy::distance_xy()
   : distance_z()
 {
   function_type = "distance_xy";
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   x.type (colvarvalue::type_scalar);
 }
 
 void colvar::distance_xy::calc_value()
 {
   if (b_no_PBC) {
     dist_v = main.center_of_mass() - ref1.center_of_mass();
   } else {
     dist_v = cvm::position_distance (ref1.center_of_mass(),
                                      main.center_of_mass());
   }
   if (!fixed_axis) {
     if (b_no_PBC) {
       v12 = ref2.center_of_mass() - ref1.center_of_mass();
     } else {
       v12 = cvm::position_distance (ref1.center_of_mass(), ref2.center_of_mass());
     }
     axis_norm = v12.norm();
     axis = v12.unit();
   }
 
   dist_v_ortho = dist_v - (dist_v * axis) * axis;
   x.real_value = dist_v_ortho.norm();
 }
 
 void colvar::distance_xy::calc_gradients()
 {
   // Intermediate quantity (r_P3 / r_12 where P is the projection
   // of 3 (main) on the plane orthogonal to 12, containing 1 (ref1))
   cvm::real A;
   cvm::real x_inv;
 
   if (x.real_value == 0.0) return;
   x_inv = 1.0 / x.real_value;
 
   if (fixed_axis) {
     ref1.set_weighted_gradient (-1.0 * x_inv * dist_v_ortho);
     main.set_weighted_gradient (       x_inv * dist_v_ortho);
   } else {
     if (b_no_PBC) {
       v13 = main.center_of_mass() - ref1.center_of_mass();
     } else {
       v13 = cvm::position_distance (ref1.center_of_mass(), main.center_of_mass());
     }
     A = (dist_v * axis) / axis_norm;
 
     ref1.set_weighted_gradient ( (A - 1.0) * x_inv * dist_v_ortho);
     ref2.set_weighted_gradient ( -A        * x_inv * dist_v_ortho);
     main.set_weighted_gradient (      1.0  * x_inv * dist_v_ortho);
   }
 }
 
 void colvar::distance_xy::calc_force_invgrads()
 {
   main.read_system_forces();
 
   if (fixed_axis && !b_1site_force) {
     ref1.read_system_forces();
     ft.real_value = 0.5 / x.real_value * ((main.system_force() - ref1.system_force()) * dist_v_ortho);
   } else {
     ft.real_value = 1.0 / x.real_value * main.system_force() * dist_v_ortho;
   }
 }
 
 void colvar::distance_xy::calc_Jacobian_derivative()
 {
   jd.real_value = x.real_value ? (1.0 / x.real_value) : 0.0;
 }
 
 void colvar::distance_xy::apply_force (colvarvalue const &force)
 {
   if (!ref1.noforce)
     ref1.apply_colvar_force (force.real_value);
 
   if (ref2.size() && !ref2.noforce)
     ref2.apply_colvar_force (force.real_value);
 
   if (!main.noforce)
     main.apply_colvar_force (force.real_value);
 }
 
 
 
 colvar::distance_dir::distance_dir (std::string const &conf)
   : distance (conf)
 {
   function_type = "distance_dir";
   x.type (colvarvalue::type_unitvector);
 }
 
 
 colvar::distance_dir::distance_dir()
   : distance()
 {
   function_type = "distance_dir";
   x.type (colvarvalue::type_unitvector);
 }
 
 
 void colvar::distance_dir::calc_value()
 {
   if (b_no_PBC) {
     dist_v = group2.center_of_mass() - group1.center_of_mass();
   } else {
     dist_v = cvm::position_distance (group1.center_of_mass(),
                                      group2.center_of_mass());
   }
   x.rvector_value = dist_v.unit();
 }
 
 
 void colvar::distance_dir::calc_gradients()
 {
   // gradients are computed on the fly within apply_force()
   // Note: could be a problem if a future bias relies on gradient
   // calculations...
 }
 
 
 void colvar::distance_dir::apply_force (colvarvalue const &force)
 {
   // remove the radial force component
   cvm::real const iprod = force.rvector_value * x.rvector_value;
   cvm::rvector const force_tang = force.rvector_value - iprod * x.rvector_value;
 
   if (!group1.noforce)
     group1.apply_force (-1.0 * force_tang);
 
   if (!group2.noforce)
     group2.apply_force (       force_tang);
 }
 
 
 
 colvar::distance_inv::distance_inv (std::string const &conf)
   : distance (conf)
 {
   function_type = "distance_inv";
   get_keyval (conf, "exponent", exponent, 6);
   if (exponent%2) {
     cvm::fatal_error ("Error: odd exponent provided, can only use even ones.\n");
   }
   if (exponent <= 0) {
     cvm::fatal_error ("Error: negative or zero exponent provided.\n");
   }
 
   for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++) {
     for (cvm::atom_iter ai2 = group2.begin(); ai2 != group2.end(); ai2++) {
       if (ai1->id == ai2->id)
         cvm::fatal_error ("Error: group1 and group1 have some atoms in common: this is not allowed for distanceInv.\n");
     }
   }
 
   b_inverse_gradients = false;
   b_Jacobian_derivative = false;
   x.type (colvarvalue::type_scalar);
 }
 
 colvar::distance_inv::distance_inv()
 {
   function_type = "distance_inv";
   exponent = 6;
   b_inverse_gradients = false;
   b_Jacobian_derivative = false;
   b_1site_force = false;
   x.type (colvarvalue::type_scalar);
 }
 
 void colvar::distance_inv::calc_value()
 {
   x.real_value = 0.0;
   if (b_no_PBC) {
     for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++) {
       for (cvm::atom_iter ai2 = group2.begin(); ai2 != group2.end(); ai2++) {
         cvm::rvector const dv = ai2->pos - ai1->pos;
         cvm::real const d2 = dv.norm2();
         cvm::real dinv = 1.0;
         for (int ne = 0; ne < exponent/2; ne++)
           dinv *= 1.0/d2;
         x.real_value += dinv;
         cvm::rvector const dsumddv = -(cvm::real (exponent)) * dinv/d2 * dv;
         ai1->grad += -1.0 * dsumddv;
         ai2->grad +=        dsumddv;
       }
     }
   } else {
     for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++) {
       for (cvm::atom_iter ai2 = group2.begin(); ai2 != group2.end(); ai2++) {
         cvm::rvector const dv = cvm::position_distance (ai1->pos, ai2->pos);
         cvm::real const d2 = dv.norm2();
         cvm::real dinv = 1.0;
         for (int ne = 0; ne < exponent/2; ne++)
           dinv *= 1.0/d2;
         x.real_value += dinv;
         cvm::rvector const dsumddv = -(cvm::real (exponent)) * dinv/d2 * dv;
         ai1->grad += -1.0 * dsumddv;
         ai2->grad +=        dsumddv;
       }
     }
   }
 
   x.real_value *= 1.0 / cvm::real (group1.size() * group2.size());
   x.real_value = std::pow (x.real_value, -1.0/(cvm::real (exponent)));
 }
 
 void colvar::distance_inv::calc_gradients()
 {
   cvm::real const dxdsum = (-1.0/(cvm::real (exponent))) * std::pow (x.real_value, exponent+1) / cvm::real (group1.size() * group2.size());
   for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++) {
     ai1->grad *= dxdsum;
   }
   for (cvm::atom_iter ai2 = group2.begin(); ai2 != group2.end(); ai2++) {
     ai2->grad *= dxdsum;
   }
 }
 
 void colvar::distance_inv::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);
 }
 
 
 
 colvar::gyration::gyration (std::string const &conf)
   : cvc (conf)
 {
   function_type = "gyration";
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   parse_group (conf, "atoms", atoms);
   atom_groups.push_back (&atoms);
 
   if (atoms.b_user_defined_fit) {
     cvm::log ("WARNING: explicit fitting parameters were provided for atom group \"atoms\".");
   } else {
     atoms.b_center = true;
     atoms.ref_pos.assign (1, cvm::rvector (0.0, 0.0, 0.0));
   }
 
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::gyration::gyration()
 {
   function_type = "gyration";
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   x.type (colvarvalue::type_scalar);
 }
 
 
 void colvar::gyration::calc_value()
 {
   x.real_value = 0.0;
   for (cvm::atom_iter ai = atoms.begin(); ai != atoms.end(); ai++) {
     x.real_value += (ai->pos).norm2();
   }
   x.real_value = std::sqrt (x.real_value / cvm::real (atoms.size()));
 }
 
 
 void colvar::gyration::calc_gradients()
 {
   cvm::real const drdx = 1.0/(cvm::real (atoms.size()) * x.real_value);
   for (cvm::atom_iter ai = atoms.begin(); ai != atoms.end(); ai++) {
     ai->grad = drdx * ai->pos;
   }
 
   if (b_debug_gradients) {
     cvm::log ("Debugging gradients:\n");
     debug_gradients (atoms);
   }
 }
 
 
 void colvar::gyration::calc_force_invgrads()
 {
   atoms.read_system_forces();
 
   cvm::real const dxdr = 1.0/x.real_value;
   ft.real_value = 0.0;
 
   for (cvm::atom_iter ai = atoms.begin(); ai != atoms.end(); ai++) {
     ft.real_value += dxdr * ai->pos * ai->system_force;
   }
 }
 
 
 void colvar::gyration::calc_Jacobian_derivative()
 {
   jd = x.real_value ? (3.0 * cvm::real (atoms.size()) - 4.0) / x.real_value : 0.0;
 }
 
 
 void colvar::gyration::apply_force (colvarvalue const &force)
 {
   if (!atoms.noforce)
     atoms.apply_colvar_force (force.real_value);
 }
 
 
 
 colvar::inertia::inertia (std::string const &conf)
   : gyration (conf)
 {
   function_type = "inertia";
   b_inverse_gradients = false;
   b_Jacobian_derivative = false;
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::inertia::inertia()
 {
   function_type = "inertia";
   x.type (colvarvalue::type_scalar);
 }
 
 
 void colvar::inertia::calc_value()
 {
   x.real_value = 0.0;
   for (cvm::atom_iter ai = atoms.begin(); ai != atoms.end(); ai++) {
     x.real_value += (ai->pos).norm2();
   }
 }
 
 
 void colvar::inertia::calc_gradients()
 {
   for (cvm::atom_iter ai = atoms.begin(); ai != atoms.end(); ai++) {
     ai->grad = 2.0 * ai->pos;
   }
 
   if (b_debug_gradients) {
     cvm::log ("Debugging gradients:\n");
     debug_gradients (atoms);
   }
 }
 
 
 void colvar::inertia::apply_force (colvarvalue const &force)
 {
   if (!atoms.noforce)
     atoms.apply_colvar_force (force.real_value);
 }
 
 
 colvar::inertia_z::inertia_z (std::string const &conf)
   : inertia (conf)
 {
   function_type = "inertia_z";
   if (get_keyval (conf, "axis", axis, cvm::rvector (0.0, 0.0, 1.0))) {
     if (axis.norm2() == 0.0)
       cvm::fatal_error ("Axis vector is zero!");
     if (axis.norm2() != 1.0) {
       axis = axis.unit();
       cvm::log ("The normalized axis is: "+cvm::to_str (axis)+".\n");
     }
   }
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::inertia_z::inertia_z()
 {
   function_type = "inertia_z";
   x.type (colvarvalue::type_scalar);
 }
 
 
 void colvar::inertia_z::calc_value()
 {
   x.real_value = 0.0;
   for (cvm::atom_iter ai = atoms.begin(); ai != atoms.end(); ai++) {
     cvm::real const iprod = ai->pos * axis;
     x.real_value += iprod * iprod;
   }
 }
 
 
 void colvar::inertia_z::calc_gradients()
 {
   for (cvm::atom_iter ai = atoms.begin(); ai != atoms.end(); ai++) {
     ai->grad = 2.0 * (ai->pos * axis) * axis;
   }
 
   if (b_debug_gradients) {
     cvm::log ("Debugging gradients:\n");
     debug_gradients (atoms);
   }
 }
 
 
 void colvar::inertia_z::apply_force (colvarvalue const &force)
 {
   if (!atoms.noforce)
     atoms.apply_colvar_force (force.real_value);
 }
 
 
 
 colvar::rmsd::rmsd (std::string const &conf)
   : cvc (conf)
 {
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   function_type = "rmsd";
   x.type (colvarvalue::type_scalar);
 
   parse_group (conf, "atoms", atoms);
   atom_groups.push_back (&atoms);
 
-  if (atoms.b_dummy) 
+  if (atoms.b_dummy)
     cvm::fatal_error ("Error: \"atoms\" cannot be a dummy atom.");
 
   if (atoms.ref_pos_group != NULL) {
     cvm::log ("The option \"refPositionsGroup\" (alternative group for fitting) was enabled: "
               "Jacobian derivatives of the RMSD will not be calculated.\n");
     b_Jacobian_derivative = false;
   }
 
   // the following is a simplified version of the corresponding atom group options;
   // we need this because the reference coordinates defined inside the atom group
   // may be used only for fitting, and even more so if ref_pos_group is used
   if (get_keyval (conf, "refPositions", ref_pos, ref_pos)) {
     cvm::log ("Using reference positions from configuration file to calculate the variable.\n");
     if (ref_pos.size() != atoms.size()) {
       cvm::fatal_error ("Error: the number of reference positions provided ("+
                         cvm::to_str (ref_pos.size())+
                         ") does not match the number of atoms of group \"atoms\" ("+
                         cvm::to_str (atoms.size())+").\n");
     }
   }
   {
     std::string ref_pos_file;
     if (get_keyval (conf, "refPositionsFile", ref_pos_file, std::string (""))) {
 
       if (ref_pos.size()) {
         cvm::fatal_error ("Error: cannot specify \"refPositionsFile\" and "
                           "\"refPositions\" at the same time.\n");
       }
 
       std::string ref_pos_col;
       double ref_pos_col_value;
-      
+
       if (get_keyval (conf, "refPositionsCol", ref_pos_col, std::string (""))) {
         // if provided, use PDB column to select coordinates
         bool found = get_keyval (conf, "refPositionsColValue", ref_pos_col_value, 0.0);
         if (found && !ref_pos_col_value)
           cvm::fatal_error ("Error: refPositionsColValue, "
                             "if provided, must be non-zero.\n");
       } else {
         // if not, rely on existing atom indices for the group
         atoms.create_sorted_ids();
       }
 
       ref_pos.resize (atoms.size());
       cvm::load_coords (ref_pos_file.c_str(), ref_pos, atoms.sorted_ids,
                         ref_pos_col, ref_pos_col_value);
     }
   }
 
   if (atoms.b_user_defined_fit) {
     cvm::log ("WARNING: explicit fitting parameters were provided for atom group \"atoms\".");
   } else {
     // Default: fit everything
     cvm::log ("Enabling \"centerReference\" and \"rotateReference\", to minimize RMSD before calculating it as a variable: "
               "if this is not the desired behavior, disable them explicitly within the \"atoms\" block.\n");
     atoms.b_center = true;
     atoms.b_rotate = true;
     // default case: reference positions for calculating the rmsd are also those used
     // for fitting
     atoms.ref_pos = ref_pos;
     atoms.center_ref_pos();
 
     // request the calculation of the derivatives of the rotation defined by the atom group
     atoms.rot.request_group1_gradients (atoms.size());
     // request derivatives of optimal rotation wrt reference coordinates for Jacobian:
     // this is only required for ABF, but we do both groups here for better caching
     atoms.rot.request_group2_gradients (atoms.size());
   }
 }
 
-  
+
 void colvar::rmsd::calc_value()
 {
   // rotational-translational fit is handled by the atom group
 
   x.real_value = 0.0;
   for (size_t ia = 0; ia < atoms.size(); ia++) {
     x.real_value += (atoms[ia].pos - ref_pos[ia]).norm2();
   }
   x.real_value /= cvm::real (atoms.size()); // MSD
   x.real_value = std::sqrt (x.real_value);
 }
 
 
 void colvar::rmsd::calc_gradients()
 {
   cvm::real const drmsddx2 = (x.real_value > 0.0) ?
     0.5 / (x.real_value * cvm::real (atoms.size())) :
     0.0;
 
   for (size_t ia = 0; ia < atoms.size(); ia++) {
     atoms[ia].grad = (drmsddx2 * 2.0 * (atoms[ia].pos - ref_pos[ia]));
   }
 
   if (b_debug_gradients) {
     cvm::log ("Debugging gradients:\n");
     debug_gradients (atoms);
   }
 }
 
 
 void colvar::rmsd::apply_force (colvarvalue const &force)
 {
   if (!atoms.noforce)
     atoms.apply_colvar_force (force.real_value);
 }
 
 
 void colvar::rmsd::calc_force_invgrads()
 {
   atoms.read_system_forces();
   ft.real_value = 0.0;
-    
+
   // Note: gradient square norm is 1/N_atoms
-          
+
   for (size_t ia = 0; ia < atoms.size(); ia++) {
     ft.real_value += atoms[ia].grad * atoms[ia].system_force;
   }
   ft.real_value *= atoms.size();
 }
 
 
 void colvar::rmsd::calc_Jacobian_derivative()
 {
   // divergence of the rotated coordinates (including only derivatives of the rotation matrix)
   cvm::real divergence = 0.0;
 
   if (atoms.b_rotate) {
 
     // gradient of the rotation matrix
     cvm::matrix2d <cvm::rvector, 3, 3> grad_rot_mat;
-    // 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;
     for (size_t ia = 0; ia < atoms.size(); ia++) {
 
       // Gradient of optimal quaternion wrt current Cartesian position
       cvm::vector1d< cvm::rvector, 4 >      &dq = atoms.rot.dQ0_1[ia];
 
       g11 = 2.0 * (atoms.rot.q)[1]*dq[1];
       g22 = 2.0 * (atoms.rot.q)[2]*dq[2];
       g33 = 2.0 * (atoms.rot.q)[3]*dq[3];
       g01 = (atoms.rot.q)[0]*dq[1] + (atoms.rot.q)[1]*dq[0];
       g02 = (atoms.rot.q)[0]*dq[2] + (atoms.rot.q)[2]*dq[0];
       g03 = (atoms.rot.q)[0]*dq[3] + (atoms.rot.q)[3]*dq[0];
       g12 = (atoms.rot.q)[1]*dq[2] + (atoms.rot.q)[2]*dq[1];
       g13 = (atoms.rot.q)[1]*dq[3] + (atoms.rot.q)[3]*dq[1];
       g23 = (atoms.rot.q)[2]*dq[3] + (atoms.rot.q)[3]*dq[2];
 
       // Gradient of the rotation matrix wrt current Cartesian position
-      grad_rot_mat[0][0] = -2.0 * (g22 + g33); 
-      grad_rot_mat[1][0] =  2.0 * (g12 + g03); 
-      grad_rot_mat[2][0] =  2.0 * (g13 - g02); 
-      grad_rot_mat[0][1] =  2.0 * (g12 - g03); 
-      grad_rot_mat[1][1] = -2.0 * (g11 + g33); 
-      grad_rot_mat[2][1] =  2.0 * (g01 + g23); 
-      grad_rot_mat[0][2] =  2.0 * (g02 + g13); 
-      grad_rot_mat[1][2] =  2.0 * (g23 - g01); 
-      grad_rot_mat[2][2] = -2.0 * (g11 + g22); 
+      grad_rot_mat[0][0] = -2.0 * (g22 + g33);
+      grad_rot_mat[1][0] =  2.0 * (g12 + g03);
+      grad_rot_mat[2][0] =  2.0 * (g13 - g02);
+      grad_rot_mat[0][1] =  2.0 * (g12 - g03);
+      grad_rot_mat[1][1] = -2.0 * (g11 + g33);
+      grad_rot_mat[2][1] =  2.0 * (g01 + g23);
+      grad_rot_mat[0][2] =  2.0 * (g02 + g13);
+      grad_rot_mat[1][2] =  2.0 * (g23 - g01);
+      grad_rot_mat[2][2] = -2.0 * (g11 + g22);
 
       cvm::atom_pos &y = ref_pos[ia];
 
       for (size_t alpha = 0; alpha < 3; alpha++) {
         for (size_t beta = 0; beta < 3; beta++) {
           divergence += grad_rot_mat[beta][alpha][alpha] * y[beta];
         // Note: equation was derived for inverse rotation (see colvars paper)
         // so here the matrix is transposed
         // (eq would give   divergence += grad_rot_mat[alpha][beta][alpha] * y[beta];)
         }
       }
     }
   }
 
   jd.real_value = x.real_value > 0.0 ? (3.0 * atoms.size() - 4.0 - divergence) / x.real_value : 0.0;
 }
 
 
 
 
 colvar::eigenvector::eigenvector (std::string const &conf)
   : cvc (conf)
 {
   b_inverse_gradients = true;
   b_Jacobian_derivative = true;
   function_type = "eigenvector";
   x.type (colvarvalue::type_scalar);
 
   parse_group (conf, "atoms", atoms);
   atom_groups.push_back (&atoms);
 
 
   {
     bool const b_inline = get_keyval (conf, "refPositions", ref_pos, ref_pos);
 
     if (b_inline) {
       cvm::log ("Using reference positions from input file.\n");
       if (ref_pos.size() != atoms.size()) {
         cvm::fatal_error ("Error: reference positions do not "
                           "match the number of requested atoms.\n");
       }
     }
 
     std::string file_name;
     if (get_keyval (conf, "refPositionsFile", file_name)) {
 
       if (b_inline)
         cvm::fatal_error ("Error: refPositions and refPositionsFile cannot be specified at the same time.\n");
 
       std::string file_col;
       double file_col_value;
       if (get_keyval (conf, "refPositionsCol", file_col, std::string (""))) {
         // use PDB flags if column is provided
         bool found = get_keyval (conf, "refPositionsColValue", file_col_value, 0.0);
         if (found && !file_col_value)
           cvm::fatal_error ("Error: refPositionsColValue, "
                             "if provided, must be non-zero.\n");
       } else {
         // if not, use atom indices
         atoms.create_sorted_ids();
       }
 
       ref_pos.resize (atoms.size());
       cvm::load_coords (file_name.c_str(), ref_pos, atoms.sorted_ids, file_col, file_col_value);
     }
   }
 
   // save for later the geometric center of the provided positions (may not be the origin)
   cvm::rvector ref_pos_center (0.0, 0.0, 0.0);
   for (size_t i = 0; i < atoms.size(); i++) {
     ref_pos_center += ref_pos[i];
   }
   ref_pos_center *= 1.0 / atoms.size();
 
   if (atoms.b_user_defined_fit) {
     cvm::log ("WARNING: explicit fitting parameters were provided for atom group \"atoms\".\n");
   } else {
     // default: fit everything
     cvm::log ("Enabling \"centerReference\" and \"rotateReference\", to minimize RMSD before calculating the vector projection: "
               "if this is not the desired behavior, disable them explicitly within the \"atoms\" block.\n");
     atoms.b_center = true;
     atoms.b_rotate = true;
     atoms.ref_pos = ref_pos;
     atoms.center_ref_pos();
 
     // request the calculation of the derivatives of the rotation defined by the atom group
     atoms.rot.request_group1_gradients (atoms.size());
     // request derivatives of optimal rotation wrt reference coordinates for Jacobian:
     // this is only required for ABF, but we do both groups here for better caching
     atoms.rot.request_group2_gradients (atoms.size());
   }
 
   {
     bool const b_inline = get_keyval (conf, "vector", eigenvec, eigenvec);
     // now load the eigenvector
     if (b_inline) {
       cvm::log ("Using vector components from input file.\n");
       if (eigenvec.size() != atoms.size()) {
         cvm::fatal_error ("Error: vector components do not "
                           "match the number of requested atoms.\n");
       }
     }
 
     std::string file_name;
     if (get_keyval (conf, "vectorFile", file_name)) {
 
       if (b_inline)
         cvm::fatal_error ("Error: vector and vectorFile cannot be specified at the same time.\n");
 
       std::string file_col;
       double file_col_value;
       if (get_keyval (conf, "vectorCol", file_col, std::string (""))) {
         // use PDB flags if column is provided
         bool found = get_keyval (conf, "vectorColValue", file_col_value, 0.0);
         if (found && !file_col_value)
           cvm::fatal_error ("Error: vectorColValue, "
                             "if provided, must be non-zero.\n");
       } else {
         // if not, use atom indices
         atoms.create_sorted_ids();
       }
 
       eigenvec.resize (atoms.size());
       cvm::load_coords (file_name.c_str(), eigenvec, atoms.sorted_ids, file_col, file_col_value);
     }
   }
 
   if (!ref_pos.size() || !eigenvec.size()) {
     cvm::fatal_error ("Error: both reference coordinates"
                       "and eigenvector must be defined.\n");
   }
 
   cvm::rvector eig_center (0.0, 0.0, 0.0);
   for (size_t i = 0; i < atoms.size(); i++) {
     eig_center += eigenvec[i];
   }
   eig_center *= 1.0 / atoms.size();
   cvm::log ("Geometric center of the provided vector: "+cvm::to_str (eig_center)+"\n");
 
   bool b_difference_vector = false;
   get_keyval (conf, "differenceVector", b_difference_vector, false);
 
   if (b_difference_vector) {
 
     if (atoms.b_center) {
       // both sets should be centered on the origin for fitting
       for (size_t i = 0; i < atoms.size(); i++) {
         eigenvec[i] -= eig_center;
         ref_pos[i]  -= ref_pos_center;
       }
     }
     if (atoms.b_rotate) {
       atoms.rot.calc_optimal_rotation (eigenvec, ref_pos);
       for (size_t i = 0; i < atoms.size(); i++) {
         eigenvec[i] = atoms.rot.rotate (eigenvec[i]);
       }
     }
     cvm::log ("\"differenceVector\" is on: subtracting the reference positions from the provided vector: v = v - x0.\n");
     for (size_t i = 0; i < atoms.size(); i++) {
       eigenvec[i] -= ref_pos[i];
     }
     if (atoms.b_center) {
       // bring back the ref positions to where they were
       for (size_t i = 0; i < atoms.size(); i++) {
         ref_pos[i] += ref_pos_center;
       }
     }
 
   } else {
     cvm::log ("Centering the provided vector to zero.\n");
     for (size_t i = 0; i < atoms.size(); i++) {
       eigenvec[i] -= eig_center;
     }
   }
 
   // cvm::log ("The first three components (v1x, v1y, v1z) of the resulting vector are: "+cvm::to_str (eigenvec[0])+".\n");
 
   // for inverse gradients
   eigenvec_invnorm2 = 0.0;
   for (size_t i = 0; i < atoms.size(); i++) {
     eigenvec_invnorm2 += eigenvec[i].norm2();
   }
   eigenvec_invnorm2 = 1.0 / eigenvec_invnorm2;
 
   if (b_difference_vector) {
     cvm::log ("\"differenceVector\" is on: normalizing the vector.\n");
     for (size_t i = 0; i < atoms.size(); i++) {
       eigenvec[i] *= eigenvec_invnorm2;
     }
   } else {
     cvm::log ("The norm of the vector is |v| = "+cvm::to_str (eigenvec_invnorm2)+".\n");
   }
 }
 
-  
+
 void colvar::eigenvector::calc_value()
 {
   x.real_value = 0.0;
   for (size_t i = 0; i < atoms.size(); i++) {
     x.real_value += (atoms[i].pos - ref_pos[i]) * eigenvec[i];
   }
 }
 
 
 void colvar::eigenvector::calc_gradients()
 {
   for (size_t ia = 0; ia < atoms.size(); ia++) {
     atoms[ia].grad = eigenvec[ia];
   }
 
   if (b_debug_gradients) {
     cvm::log ("Debugging gradients:\n");
     debug_gradients (atoms);
   }
 }
 
 
 void colvar::eigenvector::apply_force (colvarvalue const &force)
 {
   if (!atoms.noforce)
     atoms.apply_colvar_force (force.real_value);
 }
 
 
 void colvar::eigenvector::calc_force_invgrads()
 {
   atoms.read_system_forces();
   ft.real_value = 0.0;
-    
+
   for (size_t ia = 0; ia < atoms.size(); ia++) {
     ft.real_value += eigenvec_invnorm2 * atoms[ia].grad *
       atoms[ia].system_force;
   }
 }
 
 
 void colvar::eigenvector::calc_Jacobian_derivative()
 {
   // gradient of the rotation matrix
   cvm::matrix2d <cvm::rvector, 3, 3> grad_rot_mat;
   cvm::quaternion &quat0 = atoms.rot.q;
 
-  // 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::atom_pos x_relative; 
+  cvm::atom_pos x_relative;
   cvm::real sum = 0.0;
 
   for (size_t ia = 0; ia < atoms.size(); ia++) {
 
     // Gradient of optimal quaternion wrt current Cartesian position
     // trick: d(R^-1)/dx = d(R^t)/dx = (dR/dx)^t
     // we can just transpose the derivatives of the direct matrix
     cvm::vector1d< cvm::rvector, 4 >      &dq_1 = atoms.rot.dQ0_1[ia];
 
     g11 = 2.0 * quat0[1]*dq_1[1];
     g22 = 2.0 * quat0[2]*dq_1[2];
     g33 = 2.0 * quat0[3]*dq_1[3];
     g01 = quat0[0]*dq_1[1] + quat0[1]*dq_1[0];
     g02 = quat0[0]*dq_1[2] + quat0[2]*dq_1[0];
     g03 = quat0[0]*dq_1[3] + quat0[3]*dq_1[0];
     g12 = quat0[1]*dq_1[2] + quat0[2]*dq_1[1];
     g13 = quat0[1]*dq_1[3] + quat0[3]*dq_1[1];
     g23 = quat0[2]*dq_1[3] + quat0[3]*dq_1[2];
 
     // Gradient of the inverse rotation matrix wrt current Cartesian position
     // (transpose of the gradient of the direct rotation)
-    grad_rot_mat[0][0] = -2.0 * (g22 + g33); 
-    grad_rot_mat[0][1] =  2.0 * (g12 + g03); 
-    grad_rot_mat[0][2] =  2.0 * (g13 - g02); 
-    grad_rot_mat[1][0] =  2.0 * (g12 - g03); 
-    grad_rot_mat[1][1] = -2.0 * (g11 + g33); 
-    grad_rot_mat[1][2] =  2.0 * (g01 + g23); 
-    grad_rot_mat[2][0] =  2.0 * (g02 + g13); 
-    grad_rot_mat[2][1] =  2.0 * (g23 - g01); 
-    grad_rot_mat[2][2] = -2.0 * (g11 + g22); 
+    grad_rot_mat[0][0] = -2.0 * (g22 + g33);
+    grad_rot_mat[0][1] =  2.0 * (g12 + g03);
+    grad_rot_mat[0][2] =  2.0 * (g13 - g02);
+    grad_rot_mat[1][0] =  2.0 * (g12 - g03);
+    grad_rot_mat[1][1] = -2.0 * (g11 + g33);
+    grad_rot_mat[1][2] =  2.0 * (g01 + g23);
+    grad_rot_mat[2][0] =  2.0 * (g02 + g13);
+    grad_rot_mat[2][1] =  2.0 * (g23 - g01);
+    grad_rot_mat[2][2] = -2.0 * (g11 + g22);
 
     for (size_t i = 0; i < 3; i++) {
       for (size_t j = 0; j < 3; j++) {
         sum += grad_rot_mat[i][j][i] * eigenvec[ia][j];
       }
     }
   }
 
-  jd.real_value = sum * std::sqrt (eigenvec_invnorm2); 
+  jd.real_value = sum * std::sqrt (eigenvec_invnorm2);
 }
 
 
 
 
diff --git a/lib/colvars/colvarcomp_protein.cpp b/lib/colvars/colvarcomp_protein.cpp
index b30d50e1c..1750782b7 100644
--- a/lib/colvars/colvarcomp_protein.cpp
+++ b/lib/colvars/colvarcomp_protein.cpp
@@ -1,385 +1,385 @@
 #include <cmath>
 
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 #include "colvarparse.h"
 #include "colvar.h"
 #include "colvarcomp.h"
 
 
 //////////////////////////////////////////////////////////////////////
 // alpha component
 //////////////////////////////////////////////////////////////////////
 
 colvar::alpha_angles::alpha_angles (std::string const &conf)
   : cvc (conf)
 {
   if (cvm::debug())
     cvm::log ("Initializing alpha_angles object.\n");
 
   function_type = "alpha_angles";
   x.type (colvarvalue::type_scalar);
 
   std::string segment_id;
   get_keyval (conf, "psfSegID", segment_id, std::string ("MAIN"));
 
   std::vector<int> residues;
   {
     std::string residues_conf = "";
     key_lookup (conf, "residueRange", residues_conf);
     if (residues_conf.size()) {
       std::istringstream is (residues_conf);
       int initial, final;
       char dash;
       if ( (is >> initial) && (initial > 0) &&
            (is >> dash) && (dash == '-') &&
            (is >> final) && (final > 0) ) {
         for (int rnum = initial; rnum <= final; rnum++) {
           residues.push_back (rnum);
         }
       }
     } else {
       cvm::fatal_error ("Error: no residues defined in \"residueRange\".\n");
     }
   }
 
   if (residues.size() < 5) {
     cvm::fatal_error ("Error: not enough residues defined in \"residueRange\".\n");
   }
 
   std::string const &sid    = segment_id;
   std::vector<int> const &r = residues;
 
 
   get_keyval (conf, "hBondCoeff", hb_coeff, 0.5);
   if ( (hb_coeff < 0.0) || (hb_coeff > 1.0) ) {
     cvm::fatal_error ("Error: hBondCoeff must be defined between 0 and 1.\n");
   }
 
 
   get_keyval (conf, "angleRef", theta_ref, 88.0);
   get_keyval (conf, "angleTol", theta_tol, 15.0);
 
   if (hb_coeff < 1.0) {
 
     for (size_t i = 0; i < residues.size()-2; i++) {
       theta.push_back (new colvar::angle (cvm::atom (r[i  ], "CA", sid),
                                           cvm::atom (r[i+1], "CA", sid),
                                           cvm::atom (r[i+2], "CA", sid)));
     }
 
   } else {
     cvm::log ("The hBondCoeff specified will disable the Calpha-Calpha-Calpha angle terms.\n");
   }
 
   {
     cvm::real r0;
     size_t en, ed;
     get_keyval (conf, "hBondCutoff",   r0, (3.3 * cvm::unit_angstrom()));
     get_keyval (conf, "hBondExpNumer", en, 6);
     get_keyval (conf, "hBondExpDenom", ed, 8);
 
     if (hb_coeff > 0.0) {
 
       for (size_t i = 0; i < residues.size()-4; i++) {
         hb.push_back (new colvar::h_bond (cvm::atom (r[i  ], "O",  sid),
                                           cvm::atom (r[i+4], "N",  sid),
                                           r0, en, ed));
       }
 
     } else {
       cvm::log ("The hBondCoeff specified will disable the hydrogen bond terms.\n");
     }
   }
 
   if (cvm::debug())
     cvm::log ("Done initializing alpha_angles object.\n");
 }
 
 
 colvar::alpha_angles::alpha_angles()
   : cvc ()
 {
   function_type = "alpha_angles";
   x.type (colvarvalue::type_scalar);
 }
 
 colvar::alpha_angles::~alpha_angles()
 {
   while (theta.size() != 0) {
     delete theta.back();
     theta.pop_back();
   }
   while (hb.size() != 0) {
     delete hb.back();
     hb.pop_back();
   }
 }
 
 void colvar::alpha_angles::calc_value()
 {
   x.real_value = 0.0;
 
   if (theta.size()) {
 
-    cvm::real const theta_norm = 
+    cvm::real const theta_norm =
       (1.0-hb_coeff) / cvm::real (theta.size());
 
     for (size_t i = 0; i < theta.size(); i++) {
 
       (theta[i])->calc_value();
 
       cvm::real const t = ((theta[i])->value().real_value-theta_ref)/theta_tol;
       cvm::real const f = ( (1.0 - std::pow (t, (int) 2)) /
                             (1.0 - std::pow (t, (int) 4)) );
 
       x.real_value += theta_norm * f;
 
       if (cvm::debug())
         cvm::log ("Calpha-Calpha angle no. "+cvm::to_str (i+1)+" in \""+
                   this->name+"\" has a value of "+
                   (cvm::to_str ((theta[i])->value().real_value))+
                   " degrees, f = "+cvm::to_str (f)+".\n");
     }
   }
 
   if (hb.size()) {
 
     cvm::real const hb_norm =
       hb_coeff / cvm::real (hb.size());
 
     for (size_t i = 0; i < hb.size(); i++) {
       (hb[i])->calc_value();
       x.real_value += hb_norm * (hb[i])->value().real_value;
       if (cvm::debug())
         cvm::log ("Hydrogen bond no. "+cvm::to_str (i+1)+" in \""+
                   this->name+"\" has a value of "+
                   (cvm::to_str ((hb[i])->value().real_value))+".\n");
     }
   }
 }
 
 
 void colvar::alpha_angles::calc_gradients()
 {
-  for (size_t i = 0; i < theta.size(); i++) 
+  for (size_t i = 0; i < theta.size(); i++)
     (theta[i])->calc_gradients();
 
   for (size_t i = 0; i < hb.size(); i++)
     (hb[i])->calc_gradients();
 }
 
 
 void colvar::alpha_angles::apply_force (colvarvalue const &force)
 {
 
   if (theta.size()) {
 
-    cvm::real const theta_norm = 
+    cvm::real const theta_norm =
       (1.0-hb_coeff) / cvm::real (theta.size());
-    
+
     for (size_t i = 0; i < theta.size(); i++) {
 
       cvm::real const t = ((theta[i])->value().real_value-theta_ref)/theta_tol;
       cvm::real const f = ( (1.0 - std::pow (t, (int) 2)) /
                             (1.0 - std::pow (t, (int) 4)) );
 
       cvm::real const dfdt =
-        1.0/(1.0 - std::pow (t, (int) 4)) * 
+        1.0/(1.0 - std::pow (t, (int) 4)) *
         ( (-2.0 * t) + (-1.0*f)*(-4.0 * std::pow (t, (int) 3)) );
 
-      (theta[i])->apply_force (theta_norm * 
+      (theta[i])->apply_force (theta_norm *
                                dfdt * (1.0/theta_tol) *
                                force.real_value );
     }
   }
 
   if (hb.size()) {
 
     cvm::real const hb_norm =
       hb_coeff / cvm::real (hb.size());
 
     for (size_t i = 0; i < hb.size(); i++) {
       (hb[i])->apply_force (0.5 * hb_norm * force.real_value);
     }
   }
 }
 
 
 //////////////////////////////////////////////////////////////////////
 // dihedral principal component
 //////////////////////////////////////////////////////////////////////
 
     // FIXME: this will not make collect_gradients work
     // because gradients in individual atom groups
     // are those of the sub-cvcs (angle, hb), not those
     // of this cvc (alpha)
     // This is true of all cvcs with sub-cvcs, and those
     // that do not calculate explicit gradients
-    // SO: we need a flag giving the availability of 
+    // SO: we need a flag giving the availability of
     // atomic gradients
 colvar::dihedPC::dihedPC (std::string const &conf)
   : cvc (conf)
 {
   if (cvm::debug())
     cvm::log ("Initializing dihedral PC object.\n");
 
   function_type = "dihedPC";
   x.type (colvarvalue::type_scalar);
 
   std::string segment_id;
   get_keyval (conf, "psfSegID", segment_id, std::string ("MAIN"));
 
   std::vector<int> residues;
   {
     std::string residues_conf = "";
     key_lookup (conf, "residueRange", residues_conf);
     if (residues_conf.size()) {
       std::istringstream is (residues_conf);
       int initial, final;
       char dash;
       if ( (is >> initial) && (initial > 0) &&
            (is >> dash) && (dash == '-') &&
            (is >> final) && (final > 0) ) {
         for (int rnum = initial; rnum <= final; rnum++) {
           residues.push_back (rnum);
         }
       }
     } else {
       cvm::fatal_error ("Error: no residues defined in \"residueRange\".\n");
     }
   }
 
   if (residues.size() < 2) {
     cvm::fatal_error ("Error: dihedralPC requires at least two residues.\n");
   }
 
   std::string const &sid    = segment_id;
   std::vector<int> const &r = residues;
 
   std::string vecFileName;
   int         vecNumber;
   if (get_keyval (conf, "vectorFile", vecFileName, vecFileName)) {
-    get_keyval (conf, "vectorNumber", vecNumber, 0); 
+    get_keyval (conf, "vectorNumber", vecNumber, 0);
     if (vecNumber < 1)
       cvm::fatal_error ("A positive value of vectorNumber is required.");
 
     std::ifstream vecFile;
     vecFile.open (vecFileName.c_str());
     if (!vecFile.good())
       cvm::fatal_error ("Error opening dihedral PCA vector file " + vecFileName + " for reading");
 
     // TODO: adapt to different formats by setting this flag
     bool eigenvectors_as_columns = true;
 
     if (eigenvectors_as_columns) {
       // Carma-style dPCA file
       std::string line;
       cvm::real c;
       while (vecFile.good()) {
         getline(vecFile, line);
         if (line.length() < 2) break;
         std::istringstream ls (line);
         for (int i=0; i<vecNumber; i++) ls >> c;
         coeffs.push_back(c);
       }
     }
 /*  TODO Uncomment this when different formats are recognized
     else {
       // Eigenvectors as lines
       // Skip to the right line
       for (int i = 1; i<vecNumber; i++)
         vecFile.ignore(999999, '\n');
 
       if (!vecFile.good())
         cvm::fatal_error ("Error reading dihedral PCA vector file " + vecFileName);
 
       std::string line;
       getline(vecFile, line);
       std::istringstream ls (line);
       cvm::real c;
       while (ls.good()) {
         ls >> c;
         coeffs.push_back(c);
       }
     }
  */
     vecFile.close();
 
   } else {
     get_keyval (conf, "vector", coeffs, coeffs);
   }
 
   if ( coeffs.size() != 4 * (residues.size() - 1)) {
     cvm::fatal_error ("Error: wrong number of coefficients: " +
         cvm::to_str(coeffs.size()) + ". Expected " +
         cvm::to_str(4 * (residues.size() - 1)) +
         " (4 coeffs per residue, minus one residue).\n");
   }
 
   for (size_t i = 0; i < residues.size()-1; i++) {
     // Psi
     theta.push_back (new colvar::dihedral (cvm::atom (r[i  ], "N", sid),
                                            cvm::atom (r[i  ], "CA", sid),
                                            cvm::atom (r[i  ], "C", sid),
                                            cvm::atom (r[i+1], "N", sid)));
     // Phi (next res)
     theta.push_back (new colvar::dihedral (cvm::atom (r[i  ], "C", sid),
                                            cvm::atom (r[i+1], "N", sid),
                                            cvm::atom (r[i+1], "CA", sid),
                                            cvm::atom (r[i+1], "C", sid)));
   }
 
   if (cvm::debug())
     cvm::log ("Done initializing dihedPC object.\n");
 }
 
 
 colvar::dihedPC::dihedPC()
   : cvc ()
 {
   function_type = "dihedPC";
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::dihedPC::~dihedPC()
 {
   while (theta.size() != 0) {
     delete theta.back();
     theta.pop_back();
   }
 }
 
 
 void colvar::dihedPC::calc_value()
 {
   x.real_value = 0.0;
   for (size_t i = 0; i < theta.size(); i++) {
     theta[i]->calc_value();
     cvm::real const t = (PI / 180.) * theta[i]->value().real_value;
     x.real_value += coeffs[2*i  ] * std::cos(t)
                   + coeffs[2*i+1] * std::sin(t);
   }
 }
 
 
 void colvar::dihedPC::calc_gradients()
 {
   for (size_t i = 0; i < theta.size(); i++) {
     theta[i]->calc_gradients();
   }
 }
 
 
 void colvar::dihedPC::apply_force (colvarvalue const &force)
 {
   for (size_t i = 0; i < theta.size(); i++) {
     cvm::real const t = (PI / 180.) * theta[i]->value().real_value;
     cvm::real const dcosdt = - (PI / 180.) * std::sin(t);
     cvm::real const dsindt =   (PI / 180.) * std::cos(t);
 
     theta[i]->apply_force((coeffs[2*i  ] * dcosdt +
                            coeffs[2*i+1] * dsindt) * force);
   }
 }
diff --git a/lib/colvars/colvarcomp_rotations.cpp b/lib/colvars/colvarcomp_rotations.cpp
index 50c9e0da2..b77c56387 100644
--- a/lib/colvars/colvarcomp_rotations.cpp
+++ b/lib/colvars/colvarcomp_rotations.cpp
@@ -1,311 +1,311 @@
 #include <cmath>
 
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 #include "colvarparse.h"
 #include "colvar.h"
 #include "colvarcomp.h"
 
 
 
 colvar::orientation::orientation (std::string const &conf)
   : cvc (conf)
 {
   function_type = "orientation";
   parse_group (conf, "atoms", atoms);
   atom_groups.push_back (&atoms);
   x.type (colvarvalue::type_quaternion);
 
   ref_pos.reserve (atoms.size());
 
   if (get_keyval (conf, "refPositions", ref_pos, ref_pos)) {
     cvm::log ("Using reference positions from input file.\n");
     if (ref_pos.size() != atoms.size()) {
       cvm::fatal_error ("Error: reference positions do not "
                         "match the number of requested atoms.\n");
     }
   }
 
   {
     std::string file_name;
     if (get_keyval (conf, "refPositionsFile", file_name)) {
 
       std::string file_col;
         double file_col_value;
       if (get_keyval (conf, "refPositionsCol", file_col, std::string (""))) {
         // use PDB flags if column is provided
         bool found = get_keyval (conf, "refPositionsColValue", file_col_value, 0.0);
         if (found && !file_col_value)
           cvm::fatal_error ("Error: refPositionsColValue, "
                             "if provided, must be non-zero.\n");
       } else {
         // if not, use atom indices
         atoms.create_sorted_ids();
       }
       ref_pos.resize (atoms.size());
       cvm::load_coords (file_name.c_str(), ref_pos, atoms.sorted_ids, file_col, file_col_value);
     }
   }
 
   if (!ref_pos.size()) {
     cvm::fatal_error ("Error: must define a set of "
                       "reference coordinates.\n");
   }
 
 
   cvm::log ("Centering the reference coordinates: it is "
             "assumed that each atom is the closest "
             "periodic image to the center of geometry.\n");
   cvm::rvector cog (0.0, 0.0, 0.0);
   for (size_t i = 0; i < ref_pos.size(); i++) {
     cog += ref_pos[i];
   }
   cog /= cvm::real (ref_pos.size());
   for (size_t i = 0; i < ref_pos.size(); i++) {
     ref_pos[i] -= cog;
   }
 
   get_keyval (conf, "closestToQuaternion", ref_quat, cvm::quaternion (1.0, 0.0, 0.0, 0.0));
 
   // initialize rot member data
   if (!atoms.noforce) {
     rot.request_group2_gradients (atoms.size());
   }
 
 }
 
-  
+
 colvar::orientation::orientation()
   : cvc ()
 {
   function_type = "orientation";
   x.type (colvarvalue::type_quaternion);
 }
 
 
 void colvar::orientation::calc_value()
 {
   // atoms.reset_atoms_data();
   // atoms.read_positions();
 
   atoms_cog = atoms.center_of_geometry();
 
   rot.calc_optimal_rotation (ref_pos, atoms.positions_shifted (-1.0 * atoms_cog));
 
   if ((rot.q).inner (ref_quat) >= 0.0) {
     x.quaternion_value = rot.q;
   } else {
     x.quaternion_value = -1.0 * rot.q;
   }
 }
 
 
 void colvar::orientation::calc_gradients()
 {
   // gradients have already been calculated and stored within the
   // member object "rot"; we're not using the "grad" member of each
   // atom object, because it only can represent the gradient of a
   // scalar colvar
 }
 
 
 void colvar::orientation::apply_force (colvarvalue const &force)
 {
   cvm::quaternion const &FQ = force.quaternion_value;
 
   if (!atoms.noforce) {
     for (size_t ia = 0; ia < atoms.size(); ia++) {
       for (size_t i = 0; i < 4; i++) {
         atoms[ia].apply_force (FQ[i] * rot.dQ0_2[ia][i]);
       }
     }
   }
 }
 
 
 
 colvar::orientation_angle::orientation_angle (std::string const &conf)
   : orientation (conf)
 {
   function_type = "orientation_angle";
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::orientation_angle::orientation_angle()
   : orientation()
 {
   function_type = "orientation_angle";
   x.type (colvarvalue::type_scalar);
 }
 
 
 void colvar::orientation_angle::calc_value()
 {
   // atoms.reset_atoms_data();
   // atoms.read_positions();
 
   atoms_cog = atoms.center_of_geometry();
 
   rot.calc_optimal_rotation (ref_pos, atoms.positions_shifted (-1.0 * atoms_cog));
 
   if ((rot.q).q0 >= 0.0) {
     x.real_value = (180.0/PI) * 2.0 * std::acos ((rot.q).q0);
   } else {
     x.real_value = (180.0/PI) * 2.0 * std::acos (-1.0 * (rot.q).q0);
   }
 }
 
 
 void colvar::orientation_angle::calc_gradients()
 {
   cvm::real const dxdq0 =
-    ( ((rot.q).q0 * (rot.q).q0 < 1.0) ? 
+    ( ((rot.q).q0 * (rot.q).q0 < 1.0) ?
       ((180.0 / PI) * (-2.0) / std::sqrt (1.0 - ((rot.q).q0 * (rot.q).q0))) :
       0.0 );
 
   for (size_t ia = 0; ia < atoms.size(); ia++) {
     atoms[ia].grad = (dxdq0 * (rot.dQ0_2[ia])[0]);
   }
 }
 
 
 void colvar::orientation_angle::apply_force (colvarvalue const &force)
 {
   cvm::real const &fw = force.real_value;
 
   if (!atoms.noforce) {
     atoms.apply_colvar_force (fw);
   }
 }
 
 
 colvar::tilt::tilt (std::string const &conf)
   : orientation (conf)
 {
   function_type = "tilt";
 
   get_keyval (conf, "axis", axis, cvm::rvector (0.0, 0.0, 1.0));
 
   if (axis.norm2() != 1.0) {
     axis /= axis.norm();
     cvm::log ("Normalizing rotation axis to "+cvm::to_str (axis)+".\n");
   }
 
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::tilt::tilt()
   : orientation()
 {
   function_type = "tilt";
   x.type (colvarvalue::type_scalar);
 }
 
 
 void colvar::tilt::calc_value()
 {
   // atoms.reset_atoms_data();
   // atoms.read_positions();
 
   atoms_cog = atoms.center_of_geometry();
 
   rot.calc_optimal_rotation (ref_pos, atoms.positions_shifted (-1.0 * atoms_cog));
 
   x.real_value = rot.cos_theta (axis);
 }
 
 
 void colvar::tilt::calc_gradients()
 {
   cvm::quaternion const dxdq = rot.dcos_theta_dq (axis);
 
   for (size_t ia = 0; ia < atoms.size(); ia++) {
     atoms[ia].grad = cvm::rvector (0.0, 0.0, 0.0);
     for (size_t iq = 0; iq < 4; iq++) {
       atoms[ia].grad += (dxdq[iq] * (rot.dQ0_2[ia])[iq]);
     }
   }
 
   if (b_debug_gradients) {
     cvm::log ("Debugging tilt component gradients:\n");
     debug_gradients (atoms);
   }
 }
 
 
 void colvar::tilt::apply_force (colvarvalue const &force)
 {
   cvm::real const &fw = force.real_value;
 
   if (!atoms.noforce) {
     atoms.apply_colvar_force (fw);
   }
 }
 
 
 
 colvar::spin_angle::spin_angle (std::string const &conf)
   : orientation (conf)
 {
   function_type = "spin_angle";
 
   get_keyval (conf, "axis", axis, cvm::rvector (0.0, 0.0, 1.0));
 
   if (axis.norm2() != 1.0) {
     axis /= axis.norm();
     cvm::log ("Normalizing rotation axis to "+cvm::to_str (axis)+".\n");
   }
 
   period = 360.0;
   b_periodic = true;
   x.type (colvarvalue::type_scalar);
 }
 
 
 colvar::spin_angle::spin_angle()
   : orientation()
 {
   function_type = "spin_angle";
   period = 360.0;
   b_periodic = true;
   x.type (colvarvalue::type_scalar);
 }
 
 
 void colvar::spin_angle::calc_value()
 {
   // atoms.reset_atoms_data();
   // atoms.read_positions();
 
   atoms_cog = atoms.center_of_geometry();
 
   rot.calc_optimal_rotation (ref_pos, atoms.positions_shifted (-1.0 * atoms_cog));
 
   x.real_value = rot.spin_angle (axis);
   this->wrap (x);
 }
 
 
 void colvar::spin_angle::calc_gradients()
 {
   cvm::quaternion const dxdq = rot.dspin_angle_dq (axis);
 
   for (size_t ia = 0; ia < atoms.size(); ia++) {
     atoms[ia].grad = cvm::rvector (0.0, 0.0, 0.0);
     for (size_t iq = 0; iq < 4; iq++) {
       atoms[ia].grad += (dxdq[iq] * (rot.dQ0_2[ia])[iq]);
     }
   }
 }
 
 
 void colvar::spin_angle::apply_force (colvarvalue const &force)
 {
   cvm::real const &fw = force.real_value;
 
   if (!atoms.noforce) {
     atoms.apply_colvar_force (fw);
   }
 }
diff --git a/lib/colvars/colvargrid.cpp b/lib/colvars/colvargrid.cpp
index c6099bcb8..a300b9134 100644
--- a/lib/colvars/colvargrid.cpp
+++ b/lib/colvars/colvargrid.cpp
@@ -1,217 +1,217 @@
 // -*- c++ -*-
 
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 #include "colvarparse.h"
 #include "colvar.h"
 #include "colvarcomp.h"
 #include "colvargrid.h"
 
 
 colvar_grid_count::colvar_grid_count()
   : colvar_grid<size_t>()
 {}
 
 colvar_grid_count::colvar_grid_count (std::vector<int> const &nx_i,
                                       size_t const           &def_count)
   : colvar_grid<size_t> (nx_i, def_count)
 {}
 
 colvar_grid_count::colvar_grid_count (std::vector<colvar *>  &colvars,
                                       size_t const           &def_count)
   : colvar_grid<size_t> (colvars, def_count)
 {}
 
 std::istream & colvar_grid_count::read_restart (std::istream &is)
 {
   size_t const start_pos = is.tellg();
   std::string key, conf;
   if ((is >> key) && (key == std::string ("grid_parameters"))) {
     is.seekg (start_pos, std::ios::beg);
     is >> colvarparse::read_block ("grid_parameters", conf);
     parse_params (conf);
   } else {
     cvm::log ("Grid parameters are missing in the restart file, using those from the configuration.\n");
     is.seekg (start_pos, std::ios::beg);
   }
   read_raw (is);
   return is;
 }
 
 std::ostream & colvar_grid_count::write_restart (std::ostream &os)
 {
   write_params (os);
   write_raw (os);
   return os;
 }
 
 
 
 colvar_grid_scalar::colvar_grid_scalar()
   : colvar_grid<cvm::real>(), samples (NULL), grad (NULL)
 {}
 
 colvar_grid_scalar::colvar_grid_scalar (colvar_grid_scalar const &g)
   : colvar_grid<cvm::real> (g), samples (NULL), grad (NULL)
 {
   grad = new cvm::real[nd];
 }
 
 colvar_grid_scalar::colvar_grid_scalar (std::vector<int> const &nx_i)
   : colvar_grid<cvm::real> (nx_i, 0.0, 1), samples (NULL)
 {
   grad = new cvm::real[nd];
 }
 
 colvar_grid_scalar::colvar_grid_scalar (std::vector<colvar *> &colvars, bool margin)
   : colvar_grid<cvm::real> (colvars, 0.0, 1, margin), samples (NULL)
 {
   grad = new cvm::real[nd];
 }
 
 colvar_grid_scalar::~colvar_grid_scalar()
 {
   if (grad) {
     delete [] grad;
     grad = NULL;
   }
 }
 
 std::istream & colvar_grid_scalar::read_restart (std::istream &is)
 {
   size_t const start_pos = is.tellg();
   std::string key, conf;
   if ((is >> key) && (key == std::string ("grid_parameters"))) {
     is.seekg (start_pos, std::ios::beg);
     is >> colvarparse::read_block ("grid_parameters", conf);
     parse_params (conf);
   } else {
     cvm::log ("Grid parameters are missing in the restart file, using those from the configuration.\n");
     is.seekg (start_pos, std::ios::beg);
   }
   read_raw (is);
   return is;
 }
 
 std::ostream & colvar_grid_scalar::write_restart (std::ostream &os)
 {
   write_params (os);
   write_raw (os);
   return os;
 }
 
 
 
 colvar_grid_gradient::colvar_grid_gradient()
   : colvar_grid<cvm::real>(), samples (NULL)
 {}
 
 colvar_grid_gradient::colvar_grid_gradient (std::vector<int> const &nx_i)
   : colvar_grid<cvm::real> (nx_i, 0.0, nx_i.size()), samples (NULL)
 {}
 
 colvar_grid_gradient::colvar_grid_gradient (std::vector<colvar *> &colvars)
   : colvar_grid<cvm::real> (colvars, 0.0, colvars.size()), samples (NULL)
 {}
 
 std::istream & colvar_grid_gradient::read_restart (std::istream &is)
 {
   size_t const start_pos = is.tellg();
   std::string key, conf;
   if ((is >> key) && (key == std::string ("grid_parameters"))) {
     is.seekg (start_pos, std::ios::beg);
     is >> colvarparse::read_block ("grid_parameters", conf);
     parse_params (conf);
   } else {
     cvm::log ("Grid parameters are missing in the restart file, using those from the configuration.\n");
     is.seekg (start_pos, std::ios::beg);
   }
   read_raw (is);
   return is;
 }
 
 std::ostream & colvar_grid_gradient::write_restart (std::ostream &os)
 {
   write_params (os);
   write_raw (os);
   return os;
 }
 
 void colvar_grid_gradient::write_1D_integral (std::ostream &os)
 {
   cvm::real bin, min, integral;
   std::vector<cvm::real> int_vals;
-  
+
   os << "#       xi            A(xi)\n";
 
   if ( cv.size() != 1 ) {
     cvm::fatal_error ("Cannot write integral for multi-dimensional gradient grids.");
   }
 
   integral = 0.0;
   int_vals.push_back ( 0.0 );
   bin = 0.0;
   min = 0.0;
 
   // correction for periodic colvars, so that the PMF is periodic
   cvm::real corr;
   if ( periodic[0] ) {
     corr = average();
   } else {
     corr = 0.0;
   }
 
   for (std::vector<int> ix = new_index(); index_ok (ix); incr (ix), bin += 1.0 ) {
-	  
+
     if (samples) {
       size_t const samples_here = samples->value (ix);
       if (samples_here)
         integral += (value (ix) / cvm::real (samples_here) - corr) * cv[0]->width;
     } else {
       integral += (value (ix) - corr) * cv[0]->width;
     }
 
     if ( integral < min ) min = integral;
     int_vals.push_back ( integral );
   }
 
   bin = 0.0;
   for ( int i = 0; i < nx[0]; i++, bin += 1.0 ) {
     os << std::setw (10) << cv[0]->lower_boundary.real_value + cv[0]->width * bin << " "
        << std::setw (cvm::cv_width)
        << std::setprecision (cvm::cv_prec)
        << int_vals[i] - min << "\n";
   }
 
   os << std::setw (10) << cv[0]->lower_boundary.real_value + cv[0]->width * bin << " "
      << std::setw (cvm::cv_width)
      << std::setprecision (cvm::cv_prec)
      << int_vals[nx[0]] - min << "\n";
 
   return;
 }
 
 
 
 
 // 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());
 // }
 
diff --git a/lib/colvars/colvargrid.h b/lib/colvars/colvargrid.h
index 80a7b70b1..ccaf04603 100644
--- a/lib/colvars/colvargrid.h
+++ b/lib/colvars/colvargrid.h
@@ -1,1188 +1,1188 @@
 // -*- c++ -*-
 
 #ifndef COLVARGRID_H
 #define COLVARGRID_H
 
 #include <iostream>
 #include <iomanip>
 #include <cmath>
 
 #include "colvar.h"
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 #include "colvarparse.h"
 
 /// \brief Grid of values of a function of several collective
 /// variables \param T The data type
 ///
 /// Only scalar colvars supported so far
 template <class T> class colvar_grid : public colvarparse {
 
 protected:
 
   /// Number of dimensions
   size_t nd;
 
   /// Number of points along each dimension
   std::vector<int> nx;
 
   /// Cumulative number of points along each dimension
   std::vector<int> nxc;
 
   /// \brief Multiplicity of each datum (allow the binning of
   /// non-scalar types)
   size_t mult;
 
   /// Total number of grid points
   size_t nt;
 
   /// Low-level array of values
   std::vector<T> data;
 
   /// Newly read data (used for count grids, when adding several grids read from disk)
   std::vector<size_t> new_data;
 
   /// Colvars collected in this grid
   std::vector<colvar *> cv;
 
   /// Do we request actual value (for extended-system colvars)?
   std::vector<bool> actual_value;
 
   /// Get the low-level index corresponding to an index
   inline size_t address (std::vector<int> const &ix) const
   {
     size_t addr = 0;
     for (size_t i = 0; i < nd; i++) {
       addr += ix[i]*nxc[i];
       if (cvm::debug()) {
         if (ix[i] >= nx[i])
           cvm::fatal_error ("Error: exceeding bounds in colvar_grid.\n");
       }
     }
     return addr;
   }
 
 public:
 
   /// Lower boundaries of the colvars in this grid
   std::vector<colvarvalue> lower_boundaries;
 
   /// Upper boundaries of the colvars in this grid
   std::vector<colvarvalue> upper_boundaries;
 
   /// Whether some colvars are periodic
   std::vector<bool>        periodic;
 
   /// Whether some colvars have hard lower boundaries
   std::vector<bool>        hard_lower_boundaries;
 
   /// Whether some colvars have hard upper boundaries
   std::vector<bool>        hard_upper_boundaries;
 
   /// Widths of the colvars in this grid
   std::vector<cvm::real>   widths;
 
   /// True if this is a count grid related to another grid of data
   bool has_parent_data;
 
   /// Whether this grid has been filled with data or is still empty
   bool has_data;
 
   /// Return the number of colvars
   inline size_t number_of_colvars() const
   {
     return nd;
   }
 
   /// Return the number of points in the i-th direction, if provided, or
   /// the total number
   inline size_t number_of_points (int const icv = -1) const
   {
     if (icv < 0) {
       return nt;
     } else {
       return nx[icv];
     }
   }
 
   /// Get the sizes in each direction
   inline std::vector<int> const & sizes() const
   {
     return nx;
   }
 
   /// Set the sizes in each direction
   inline void set_sizes (std::vector<int> const &new_sizes)
   {
     nx = new_sizes;
   }
 
   /// Return the multiplicity of the type used
   inline size_t multiplicity() const
   {
     return mult;
   }
 
   /// \brief Allocate data (allow initialization also after construction)
   void create (std::vector<int> const &nx_i,
                T const &t = T(),
                size_t const &mult_i = 1)
   {
     mult = mult_i;
     nd = nx_i.size();
     nxc.resize (nd);
     nx = nx_i;
 
     nt = mult;
     for (int i = nd-1; i >= 0; i--) {
       if (nx_i[i] <= 0)
         cvm::fatal_error ("Error: providing an invalid number of points, "+
                           cvm::to_str (nx_i[i])+".\n");
       nxc[i] = nt;
       nt *= nx[i];
     }
 
     data.reserve (nt);
     data.assign (nt, t);
   }
 
   /// \brief Allocate data (allow initialization also after construction)
   void create()
   {
     create (this->nx, T(), this->mult);
   }
 
   /// \brief Reset data (in case the grid is being reused)
   void reset (T const &t = T())
   {
     data.assign (nt, t);
   }
 
 
   /// Default constructor
   colvar_grid() : has_data (false)
   {
     save_delimiters = false;
     nd = nt = 0;
   }
 
   /// Destructor
   virtual ~colvar_grid()
   {}
 
   /// \brief "Almost copy-constructor": only copies configuration
   /// parameters from another grid, but doesn't reallocate stuff;
   /// create() must be called after that;
   colvar_grid (colvar_grid<T> const &g) : has_data (false),
                                           nd (g.nd),
                                           nx (g.nx),
                                           mult (g.mult),
                                           cv (g.cv),
                                           lower_boundaries (g.lower_boundaries),
                                           upper_boundaries (g.upper_boundaries),
                                           hard_lower_boundaries (g.hard_lower_boundaries),
                                           hard_upper_boundaries (g.hard_upper_boundaries),
                                           periodic (g.periodic),
                                           widths (g.widths),
                                           actual_value (g.actual_value),
                                           data()
   {
     save_delimiters = false;
   }
 
   /// \brief Constructor from explicit grid sizes \param nx_i Number
   /// of grid points along each dimension \param t Initial value for
   /// the function at each point (optional) \param mult_i Multiplicity
   /// of each value
   colvar_grid (std::vector<int> const &nx_i,
                T const &t = T(),
                size_t const &mult_i = 1) : has_data (false)
   {
     save_delimiters = false;
     this->create (nx_i, t, mult_i);
   }
 
   /// \brief Constructor from a vector of colvars
   colvar_grid (std::vector<colvar *> const &colvars,
                T const &t = T(),
                size_t const &mult_i = 1,
                bool margin = false)
     : cv (colvars), has_data (false)
   {
     save_delimiters = false;
 
     std::vector<int> nx_i;
 
     if (cvm::debug())
       cvm::log ("Allocating a grid for "+cvm::to_str (colvars.size())+
                 " collective variables.\n");
 
     for (size_t i =  0; i < cv.size(); i++) {
 
       if (cv[i]->type() != colvarvalue::type_scalar) {
         cvm::fatal_error ("Colvar grids can only be automatically "
                           "constructed for scalar variables.  "
                           "ABF and histogram can not be used; metadynamics "
                           "can be used with useGrids disabled.\n");
       }
 
       if (cv[i]->width <= 0.0) {
         cvm::fatal_error ("Tried to initialize a grid on a "
                           "variable with negative or zero width.\n");
       }
 
       if (!cv[i]->tasks[colvar::task_lower_boundary] || !cv[i]->tasks[colvar::task_upper_boundary]) {
         cvm::fatal_error ("Tried to initialize a grid on a "
                           "variable with undefined boundaries.\n");
       }
 
       widths.push_back (cv[i]->width);
       hard_lower_boundaries.push_back (cv[i]->hard_lower_boundary);
       hard_upper_boundaries.push_back (cv[i]->hard_upper_boundary);
       periodic.push_back (cv[i]->periodic_boundaries());
 
       // By default, get reported colvar value (for extended Lagrangian colvars)
       actual_value.push_back (false);
 
       // except if a colvar is specified twice in a row
       // then the first instance is the actual value
       if (i > 0 && cv[i-1] == cv[i]) {
         actual_value[i-1] = true;
       }
 
       if (margin) {
         if (periodic[i]) {
           // Shift the grid by half the bin width (values at edges instead of center of bins)
           lower_boundaries.push_back (cv[i]->lower_boundary.real_value - 0.5 * widths[i]);
           upper_boundaries.push_back (cv[i]->upper_boundary.real_value - 0.5 * widths[i]);
         } else {
           // Make this grid larger by one bin width
           lower_boundaries.push_back (cv[i]->lower_boundary.real_value - 0.5 * widths[i]);
           upper_boundaries.push_back (cv[i]->upper_boundary.real_value + 0.5 * widths[i]);
         }
       } else {
         lower_boundaries.push_back (cv[i]->lower_boundary);
         upper_boundaries.push_back (cv[i]->upper_boundary);
       }
 
 
-      { 
+      {
         cvm::real nbins = ( upper_boundaries[i].real_value -
                             lower_boundaries[i].real_value ) / widths[i];
         int nbins_round = (int)(nbins+0.5);
-        
+
         if (std::fabs (nbins - cvm::real (nbins_round)) > 1.0E-10) {
           cvm::log ("Warning: grid interval ("+
                     cvm::to_str (lower_boundaries[i], cvm::cv_width, cvm::cv_prec)+" - "+
                     cvm::to_str (upper_boundaries[i], cvm::cv_width, cvm::cv_prec)+
                     ") is not commensurate to its bin width ("+
                     cvm::to_str (widths[i], cvm::cv_width, cvm::cv_prec)+").\n");
           upper_boundaries[i].real_value = lower_boundaries[i].real_value +
             (nbins_round * widths[i]);
         }
 
         if (cvm::debug())
           cvm::log ("Number of points is "+cvm::to_str ((int) nbins_round)+
                     " for the colvar no. "+cvm::to_str (i+1)+".\n");
-        
+
         nx_i.push_back (nbins_round);
       }
 
     }
 
     create (nx_i, t, mult_i);
   }
 
 
   /// Wrap an index vector around periodic boundary conditions
   /// also checks validity of non-periodic indices
   inline void wrap (std::vector<int> & ix) const
   {
     for (size_t i = 0; i < nd; i++) {
       if (periodic[i]) {
         ix[i] = (ix[i] + nx[i]) % nx[i]; //to ensure non-negative result
       } else {
         if (ix[i] < 0 || ix[i] >= nx[i])
           cvm::fatal_error ("Trying to wrap illegal index vector (non-PBC): "
                             + cvm::to_str (ix));
       }
     }
   }
 
   /// \brief Report the bin corresponding to the current value of variable i
   inline int current_bin_scalar(int const i) const
   {
     return value_to_bin_scalar (actual_value[i] ? cv[i]->actual_value() : cv[i]->value(), i);
   }
 
   /// \brief Use the lower boundary and the width to report which bin
   /// the provided value is in
   inline int value_to_bin_scalar (colvarvalue const &value, const int i) const
   {
     return (int) std::floor ( (value.real_value - lower_boundaries[i].real_value) / widths[i] );
   }
 
   /// \brief Same as the standard version, but uses another grid definition
   inline int value_to_bin_scalar (colvarvalue const &value,
                                   colvarvalue const &new_offset,
                                   cvm::real   const &new_width) const
   {
     return (int) std::floor ( (value.real_value - new_offset.real_value) / new_width );
   }
 
   /// \brief Use the two boundaries and the width to report the
   /// central value corresponding to a bin index
   inline colvarvalue bin_to_value_scalar (int const &i_bin, int const i) const
   {
     return lower_boundaries[i].real_value + widths[i] * (0.5 + i_bin);
   }
-  
+
   /// \brief Same as the standard version, but uses different parameters
   inline colvarvalue bin_to_value_scalar (int const &i_bin,
                                           colvarvalue const &new_offset,
                                           cvm::real const &new_width) const
   {
     return new_offset.real_value + new_width * (0.5 + i_bin);
   }
 
   /// Set the value at the point with index ix
   inline void set_value (std::vector<int> const &ix,
                          T const &t,
                          size_t const &imult = 0)
-  { 
+  {
     data[this->address (ix)+imult] = t;
     has_data = true;
   }
 
 
   /// \brief Get the binned value indexed by ix, or the first of them
   /// if the multiplicity is larger than 1
   inline T const & value (std::vector<int> const &ix,
                           size_t const &imult = 0) const
   {
     return data[this->address (ix) + imult];
   }
 
 
   /// \brief Add a constant to all elements (fast loop)
   inline void add_constant (T const &t)
   {
-    for (size_t i = 0; i < nt; i++) 
+    for (size_t i = 0; i < nt; i++)
       data[i] += t;
     has_data = true;
   }
 
   /// \brief Multiply all elements by a scalar constant (fast loop)
   inline void multiply_constant (cvm::real const &a)
   {
-    for (size_t i = 0; i < nt; i++) 
+    for (size_t i = 0; i < nt; i++)
       data[i] *= a;
   }
 
- 
+
   /// \brief Get the bin indices corresponding to the provided values of
   /// the colvars
   inline std::vector<int> const get_colvars_index (std::vector<colvarvalue> const &values) const
   {
     std::vector<int> index = new_index();
     for (size_t i = 0; i < nd; i++) {
       index[i] = value_to_bin_scalar (values[i], i);
     }
     return index;
   }
 
   /// \brief Get the bin indices corresponding to the current values
   /// of the colvars
   inline std::vector<int> const get_colvars_index() const
   {
     std::vector<int> index = new_index();
     for (size_t i = 0; i < nd; i++) {
       index[i] = current_bin_scalar (i);
     }
     return index;
   }
 
   /// \brief Get the minimal distance (in number of bins) from the
   /// boundaries; a negative number is returned if the given point is
   /// off-grid
   inline cvm::real bin_distance_from_boundaries (std::vector<colvarvalue> const &values,
                                                  bool skip_hard_boundaries = false)
   {
     cvm::real minimum = 1.0E+16;
     for (size_t i = 0; i < nd; i++) {
 
       if (periodic[i]) continue;
 
       cvm::real dl = std::sqrt (cv[i]->dist2 (values[i], lower_boundaries[i])) / widths[i];
       cvm::real du = std::sqrt (cv[i]->dist2 (values[i], upper_boundaries[i])) / widths[i];
 
       if (values[i].real_value < lower_boundaries[i])
         dl *= -1.0;
       if (values[i].real_value > upper_boundaries[i])
         du *= -1.0;
 
       if ( ((!skip_hard_boundaries) || (!hard_lower_boundaries[i])) && (dl < minimum))
         minimum = dl;
       if ( ((!skip_hard_boundaries) || (!hard_upper_boundaries[i])) && (du < minimum))
         minimum = du;
     }
 
     return minimum;
   }
 
 
   /// \brief Add data from another grid of the same type
-  /// 
+  ///
   /// Note: this function maps other_grid inside this one regardless
   /// of whether it fits or not.
   void map_grid (colvar_grid<T> const &other_grid)
   {
     if (other_grid.multiplicity() != this->multiplicity())
       cvm::fatal_error ("Error: trying to merge two grids with values of "
                         "different multiplicity.\n");
 
     std::vector<colvarvalue> const &gb  = this->lower_boundaries;
     std::vector<cvm::real> const &gw    = this->widths;
     std::vector<colvarvalue> const &ogb = other_grid.lower_boundaries;
     std::vector<cvm::real> const &ogw   = other_grid.widths;
 
     std::vector<int> ix = this->new_index();
     std::vector<int> oix = other_grid.new_index();
 
     if (cvm::debug())
       cvm::log ("Remapping grid...\n");
     for ( ; this->index_ok (ix); this->incr (ix)) {
 
       for (size_t i = 0; i < nd; i++) {
         oix[i] =
           value_to_bin_scalar (bin_to_value_scalar (ix[i], gb[i], gw[i]),
                                ogb[i],
                                ogw[i]);
       }
 
       if (! other_grid.index_ok (oix)) {
         continue;
       }
 
       for (size_t im = 0; im < mult; im++) {
         this->set_value (ix, other_grid.value (oix, im), im);
       }
     }
 
     has_data = true;
     if (cvm::debug())
       cvm::log ("Remapping done.\n");
   }
 
   /// \brief Add data from another grid of the same type, AND
   /// identical definition (boundaries, widths)
   void add_grid (colvar_grid<T> const &other_grid,
                  cvm::real scale_factor = 1.0)
   {
     if (other_grid.multiplicity() != this->multiplicity())
       cvm::fatal_error ("Error: trying to sum togetehr two grids with values of "
                         "different multiplicity.\n");
-    if (scale_factor != 1.0) 
+    if (scale_factor != 1.0)
       for (size_t i = 0; i < data.size(); i++) {
         data[i] += scale_factor * other_grid.data[i];
       }
-    else 
+    else
       // skip multiplication if possible
       for (size_t i = 0; i < data.size(); i++) {
         data[i] += other_grid.data[i];
       }
     has_data = true;
   }
 
   /// \brief Return the value suitable for output purposes (so that it
   /// may be rescaled or manipulated without changing it permanently)
   virtual inline T value_output (std::vector<int> const &ix,
                                  size_t const &imult = 0)
   {
     return value (ix, imult);
   }
 
   /// \brief Get the value from a formatted output and transform it
   /// into the internal representation (the two may be different,
   /// e.g. when using colvar_grid_count)
   virtual inline void value_input (std::vector<int> const &ix,
                                    T const &t,
                                    size_t const &imult = 0,
                                    bool add = false)
   {
     if ( add )
       data[address (ix) + imult] += t;
     else
       data[address (ix) + imult] = t;
     has_data = true;
   }
 
   //   /// Get the pointer to the binned value indexed by ix
   //   inline T const *value_p (std::vector<int> const &ix)
   //   {
   //     return &(data[address (ix)]);
   //   }
 
   /// \brief Get the index corresponding to the "first" bin, to be
   /// used as the initial value for an index in looping
   inline std::vector<int> const new_index() const
   {
     return std::vector<int> (nd, 0);
   }
 
   /// \brief Check that the index is within range in each of the
   /// dimensions
   inline bool index_ok (std::vector<int> const &ix) const
   {
     for (size_t i = 0; i < nd; i++) {
       if ( (ix[i] < 0) || (ix[i] >= int (nx[i])) )
         return false;
     }
     return true;
   }
 
   /// \brief Increment the index, in a way that will make it loop over
   /// the whole nd-dimensional array
   inline void incr (std::vector<int> &ix) const
   {
     for (int i = ix.size()-1; i >= 0; i--) {
 
       ix[i]++;
 
       if (ix[i] >= nx[i]) {
 
         if (i > 0) {
           ix[i] = 0;
           continue;
         } else {
           // this is the last iteration, a non-valid index is being
           // set for the outer index, which will be caught by
           // index_ok()
           ix[0] = nx[0];
           return;
         }
       } else {
         return;
       }
     }
   }
 
   /// \brief Write the grid parameters (number of colvars, boundaries, width and number of points)
   std::ostream & write_params (std::ostream &os)
   {
     os << "grid_parameters {\n  n_colvars " << nd << "\n";
-      
+
     os << "  lower_boundaries ";
-    for (size_t i = 0; i < nd; i++) 
+    for (size_t i = 0; i < nd; i++)
       os << " " << lower_boundaries[i];
     os << "\n";
 
     os << "  upper_boundaries ";
-    for (size_t i = 0; i < nd; i++) 
+    for (size_t i = 0; i < nd; i++)
       os << " " << upper_boundaries[i];
     os << "\n";
 
     os << "  widths ";
-    for (size_t i = 0; i < nd; i++) 
+    for (size_t i = 0; i < nd; i++)
       os << " " << widths[i];
     os << "\n";
 
     os << "  sizes ";
-    for (size_t i = 0; i < nd; i++) 
+    for (size_t i = 0; i < nd; i++)
       os << " " << nx[i];
     os << "\n";
 
     os << "}\n";
     return os;
-  } 
+  }
 
 
   bool parse_params (std::string const &conf)
   {
     std::vector<int> old_nx = nx;
     std::vector<colvarvalue> old_lb = lower_boundaries;
 
     {
       size_t nd_in = 0;
       colvarparse::get_keyval (conf, "n_colvars", nd_in, nd, colvarparse::parse_silent);
       if (nd_in != nd)
         cvm::fatal_error ("Error: trying to read data for a grid "
                           "that contains a different number of colvars ("+
                           cvm::to_str (nd_in)+") than the grid defined "
                           "in the configuration file ("+cvm::to_str (nd)+
                           ").\n");
     }
 
     colvarparse::get_keyval (conf, "lower_boundaries",
                              lower_boundaries, lower_boundaries, colvarparse::parse_silent);
 
     colvarparse::get_keyval (conf, "upper_boundaries",
                              upper_boundaries, upper_boundaries, colvarparse::parse_silent);
 
     colvarparse::get_keyval (conf, "widths", widths, widths, colvarparse::parse_silent);
 
     colvarparse::get_keyval (conf, "sizes", nx, nx, colvarparse::parse_silent);
 
     bool new_params = false;
     for (size_t i = 0; i < nd; i++) {
       if ( (old_nx[i] != nx[i]) ||
            (std::sqrt (cv[i]->dist2 (old_lb[i],
                                      lower_boundaries[i])) > 1.0E-10) ) {
         new_params = true;
       }
     }
 
     // reallocate the array in case the grid params have just changed
     if (new_params) {
       data.resize (0);
       this->create (nx, T(), mult);
     }
 
     return true;
   }
 
   /// \brief Check that the grid information inside (boundaries,
   /// widths, ...) is consistent with the current setting of the
   /// colvars
   void check_consistency()
   {
     for (size_t i = 0; i < nd; i++) {
       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,
-                                     upper_boundaries[i])) > 1.0E-10) || 
+                                     upper_boundaries[i])) > 1.0E-10) ||
            (std::sqrt (cv[i]->dist2 (cv[i]->width,
                                      widths[i])) > 1.0E-10) ) {
         cvm::fatal_error ("Error: restart information for a grid is "
                           "inconsistent with that of its colvars.\n");
       }
     }
   }
 
 
   /// \brief Check that the grid information inside (boundaries,
   /// widths, ...) is consistent with the one of another grid
   void check_consistency (colvar_grid<T> const &other_grid)
   {
     for (size_t i = 0; i < nd; i++) {
       // we skip dist2(), because periodicities and the like should
       // matter: boundaries should be EXACTLY the same (otherwise,
       // map_grid() should be used)
       if ( (std::fabs (other_grid.lower_boundaries[i] -
-                       lower_boundaries[i]) > 1.0E-10) || 
+                       lower_boundaries[i]) > 1.0E-10) ||
            (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] -
-                       widths[i]) > 1.0E-10) || 
+                       widths[i]) > 1.0E-10) ||
            (data.size() != other_grid.data.size()) ) {
       cvm::fatal_error ("Error: inconsistency between "
                         "two grids that are supposed to be equal, "
                         "aside from the data stored.\n");
     }
   }
 }
-  
+
 
 /// \brief Write the grid data without labels, as they are
 /// represented in memory
 /// \param buf_size Number of values per line
   std::ostream & write_raw (std::ostream &os,
                             size_t const buf_size = 3)
   {
     std::streamsize const w = os.width();
     std::streamsize const p = os.precision();
 
     std::vector<int> ix = new_index();
     size_t count = 0;
     for ( ; index_ok (ix); incr (ix)) {
       for (size_t imult = 0; imult < mult; imult++) {
         os << " "
            << std::setw (w) << std::setprecision (p)
            << value_output (ix, imult);
         if (((++count) % buf_size) == 0)
           os << "\n";
       }
     }
     // write a final newline only if buffer is not empty
     if ((count % buf_size) != 0)
       os << "\n";
 
     return os;
   }
 
 /// \brief Read data written by colvar_grid::write_raw()
 std::istream & read_raw (std::istream &is)
 {
   size_t const start_pos = is.tellg();
-    
+
   for (std::vector<int> ix = new_index(); index_ok (ix); incr (ix)) {
     for (size_t imult = 0; imult < mult; imult++) {
       T new_value;
       if (is >> new_value) {
         value_input (ix, new_value, imult);
       } else {
         is.clear();
         is.seekg (start_pos, std::ios::beg);
         is.setstate (std::ios::failbit);
         return is;
       }
     }
   }
 
   has_data = true;
   return is;
 }
 
 /// \brief To be called after colvar_grid::read_raw() returns an error
 void read_raw_error()
 {
   cvm::fatal_error ("Error: failed to read all of the grid points from file.  Possible explanations: grid parameters in the configuration (lowerBoundary, upperBoundary, width) are different from those in the file, or the file is corrupt/incomplete.\n");
 }
 
 /// \brief Write the grid in a format which is both human readable
 /// and suitable for visualization e.g. with gnuplot
 void write_multicol (std::ostream &os)
 {
   std::streamsize const w = os.width();
   std::streamsize const p = os.precision();
 
   // Data in the header: nColvars, then for each
   // xiMin, dXi, nPoints, periodic
 
   os << std::setw (2) << "# " << nd << "\n";
   for (size_t i = 0; i < nd; i++) {
     os << "# "
        << std::setw (10) << lower_boundaries[i]
        << std::setw (10) << widths[i]
        << std::setw (10) << nx[i] << "  "
        << periodic[i] << "\n";
   }
 
   for (std::vector<int> ix = new_index(); index_ok (ix); incr (ix) ) {
 
     if (ix.back() == 0) {
       // if the last index is 0, add a new line to mark the new record
       os << "\n";
     }
 
     for (size_t i = 0; i < nd; i++) {
       os << " "
          << std::setw (w) << std::setprecision (p)
          << bin_to_value_scalar (ix[i], i);
     }
     os << " ";
     for (size_t imult = 0; imult < mult; imult++) {
       os << " "
          << std::setw (w) << std::setprecision (p)
          << value_output (ix, imult);
     }
     os << "\n";
   }
 }
 
 /// \brief Read a grid written by colvar_grid::write_multicol()
 /// Adding data if add is true, replacing if false
 std::istream & read_multicol (std::istream &is, bool add = false)
 {
   // Data in the header: nColvars, then for each
   // xiMin, dXi, nPoints, periodic
 
   std::string   hash;
   cvm::real     lower, width, x;
   size_t        n, periodic;
   bool          remap;
   std::vector<T>        new_value;
   std::vector<int>      nx_read;
   std::vector<int>      bin;
 
   if ( cv.size() != nd ) {
     cvm::fatal_error ("Cannot read grid file: missing reference to colvars.");
   }
 
   if ( !(is >> hash) || (hash != "#") ) {
     cvm::fatal_error ("Error reading grid at position "+
                       cvm::to_str (is.tellg())+" in stream (read \"" + hash + "\")\n");
   }
 
   is >> n;
   if ( n != nd ) {
     cvm::fatal_error ("Error reading grid: wrong number of collective variables.\n");
   }
 
   nx_read.resize (n);
   bin.resize (n);
   new_value.resize (mult);
 
   if (this->has_parent_data && add) {
     new_data.resize (data.size());
   }
 
   remap = false;
   for (size_t i = 0; i < nd; i++ ) {
     if ( !(is >> hash) || (hash != "#") ) {
       cvm::fatal_error ("Error reading grid at position "+
                         cvm::to_str (is.tellg())+" in stream (read \"" + hash + "\")\n");
     }
 
     is >> lower >> width >> nx_read[i] >> periodic;
 
 
     if ( (std::fabs (lower - lower_boundaries[i].real_value) > 1.0e-10) ||
          (std::fabs (width - widths[i] ) > 1.0e-10) ||
          (nx_read[i] != nx[i]) ) {
       cvm::log ("Warning: reading from different grid definition (colvar "
                 + cvm::to_str (i+1) + "); remapping data on new grid.\n");
       remap = true;
     }
   }
 
   if ( remap ) {
     // re-grid data
     while (is.good()) {
       bool end_of_file = false;
 
       for (size_t i = 0; i < nd; i++ ) {
         if ( !(is >> x) ) end_of_file = true;
         bin[i] = value_to_bin_scalar (x, i);
       }
-      if (end_of_file) break;	
+      if (end_of_file) break;
 
       for (size_t imult = 0; imult < mult; imult++) {
         is >> new_value[imult];
       }
 
       if ( index_ok(bin) ) {
         for (size_t imult = 0; imult < mult; imult++) {
           value_input (bin, new_value[imult], imult, add);
         }
       }
     }
   } else {
     // do not re-grid the data but assume the same grid is used
     for (std::vector<int> ix = new_index(); index_ok (ix); incr (ix) ) {
       for (size_t i = 0; i < nd; i++ ) {
         is >> x;
       }
       for (size_t imult = 0; imult < mult; imult++) {
         is >> new_value[imult];
         value_input (ix, new_value[imult], imult, add);
       }
     }
   }
   has_data = true;
   return is;
 }
 
 };
 
 
 
 /// \brief Colvar_grid derived class to hold counters in discrete
 /// n-dim colvar space
 class colvar_grid_count : public colvar_grid<size_t>
 {
 public:
 
   /// Default constructor
   colvar_grid_count();
 
   /// Destructor
   virtual inline ~colvar_grid_count()
   {}
 
   /// Constructor
   colvar_grid_count (std::vector<int> const &nx_i,
                      size_t const           &def_count = 0);
 
   /// Constructor from a vector of colvars
   colvar_grid_count (std::vector<colvar *>  &colvars,
                      size_t const           &def_count = 0);
 
   /// Increment the counter at given position
   inline void incr_count (std::vector<int> const &ix)
   {
     ++(data[this->address (ix)]);
   }
 
-  /// \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,
                                    size_t const &imult = 0)
   {
     return new_data[address (ix) + imult];
   }
 
   /// \brief Read the grid from a restart
   std::istream & read_restart (std::istream &is);
 
   /// \brief Write the grid to a restart
   std::ostream & write_restart (std::ostream &os);
 
   /// \brief Get the value from a formatted output and transform it
   /// into the internal representation (it may have been rescaled or
   /// manipulated)
   virtual inline void value_input (std::vector<int> const &ix,
                                    size_t const &t,
                                    size_t const &imult = 0,
                                    bool add = false)
   {
     if (add) {
       data[address (ix)] += t;
       if (this->has_parent_data) {
         // save newly read data for inputting parent grid
         new_data[address (ix)] = t;
       }
     } else {
       data[address (ix)] = t;
     }
     has_data = true;
   }
 };
 
 
 /// Class for accumulating a scalar function on a grid
 class colvar_grid_scalar : public colvar_grid<cvm::real>
 {
 public:
 
   /// \brief Provide the associated sample count by which each binned value
   /// should be divided
   colvar_grid_count *samples;
 
   /// Default constructor
   colvar_grid_scalar();
 
   /// Copy constructor (needed because of the grad pointer)
   colvar_grid_scalar (colvar_grid_scalar const &g);
 
   /// Destructor
   ~colvar_grid_scalar();
 
   /// Constructor from specific sizes arrays
   colvar_grid_scalar (std::vector<int> const &nx_i);
 
   /// Constructor from a vector of colvars
   colvar_grid_scalar (std::vector<colvar *> &colvars,
                       bool margin = 0);
 
   /// Accumulate the value
   inline void acc_value (std::vector<int> const &ix,
                          cvm::real const &new_value,
                          size_t const &imult = 0)
   {
     // only legal value of imult here is 0
     data[address (ix)] += new_value;
     if (samples)
       samples->incr_count (ix);
     has_data = true;
   }
 
   /// Return the gradient of the scalar field from finite differences
   inline const cvm::real * gradient_finite_diff ( const std::vector<int> &ix0 )
   {
     cvm::real A0, A1;
     std::vector<int> ix;
     if (nd != 2) cvm::fatal_error ("Finite differences available in dimension 2 only.");
     for (int n = 0; n < nd; n++) {
       ix = ix0;
       A0 = data[address (ix)];
       ix[n]++; wrap (ix);
       A1 = data[address (ix)];
       ix[1-n]++; wrap (ix);
       A1 += data[address (ix)];
       ix[n]--; wrap (ix);
       A0 += data[address (ix)];
       grad[n] = 0.5 * (A1 - A0) / widths[n];
     }
-    return grad; 
+    return grad;
   }
 
   /// \brief Return the value of the function at ix divided by its
   /// number of samples (if the count grid is defined)
   virtual cvm::real value_output (std::vector<int> const &ix,
                                   size_t const &imult = 0)
   {
     if (imult > 0)
       cvm::fatal_error ("Error: trying to access a component "
                         "larger than 1 in a scalar data grid.\n");
     if (samples)
       return (samples->value (ix) > 0) ?
         (data[address (ix)] / cvm::real (samples->value (ix))) :
         0.0;
     else
       return data[address (ix)];
   }
 
   /// \brief Get the value from a formatted output and transform it
   /// into the internal representation (it may have been rescaled or
   /// manipulated)
   virtual void value_input (std::vector<int> const &ix,
                             cvm::real const &new_value,
                             size_t const &imult = 0,
                             bool add = false)
   {
     if (imult > 0)
       cvm::fatal_error ("Error: trying to access a component "
                         "larger than 1 in a scalar data grid.\n");
     if (add) {
       if (samples)
         data[address (ix)] += new_value * samples->new_count (ix);
       else
         data[address (ix)] += new_value;
     } else {
       if (samples)
         data[address (ix)] = new_value * samples->value (ix);
       else
         data[address (ix)] = new_value;
     }
     has_data = true;
   }
 
   /// \brief Read the grid from a restart
   std::istream & read_restart (std::istream &is);
 
   /// \brief Write the grid to a restart
   std::ostream & write_restart (std::ostream &os);
 
   /// \brief Return the highest value
   inline cvm::real maximum_value()
   {
     cvm::real max = data[0];
     for (size_t i = 0; i < nt; i++) {
       if (data[i] > max) max = data[i];
     }
     return max;
   }
 
   /// \brief Return the lowest value
   inline cvm::real minimum_value()
   {
     cvm::real min = data[0];
     for (size_t i = 0; i < nt; i++) {
       if (data[i] < min) min = data[i];
     }
     return min;
   }
 
 private:
   // gradient
   cvm::real * grad;
 };
 
 
 
 /// Class for accumulating the gradient of a scalar function on a grid
 class colvar_grid_gradient : public colvar_grid<cvm::real>
 {
 public:
 
   /// \brief Provide the sample count by which each binned value
   /// should be divided
   colvar_grid_count *samples;
 
   /// Default constructor
   colvar_grid_gradient();
 
   /// Destructor
   virtual inline ~colvar_grid_gradient()
   {}
 
   /// Constructor from specific sizes arrays
   colvar_grid_gradient (std::vector<int> const &nx_i);
 
   /// Constructor from a vector of colvars
   colvar_grid_gradient (std::vector<colvar *>  &colvars);
 
   /// \brief Accumulate the gradient
   inline void acc_grad (std::vector<int> const &ix, cvm::real const *grads) {
     for (size_t imult = 0; imult < mult; imult++) {
       data[address (ix) + imult] += grads[imult];
     }
     if (samples)
       samples->incr_count (ix);
   }
 
   /// \brief Accumulate the gradient based on the force (i.e. sums the
   /// opposite of the force)
   inline void acc_force (std::vector<int> const &ix, cvm::real const *forces) {
     for (size_t imult = 0; imult < mult; imult++) {
       data[address (ix) + imult] -= forces[imult];
     }
     if (samples)
       samples->incr_count (ix);
   }
 
   /// \brief Return the value of the function at ix divided by its
   /// number of samples (if the count grid is defined)
   virtual inline cvm::real value_output (std::vector<int> const &ix,
                                          size_t const &imult = 0)
   {
     if (samples)
       return (samples->value (ix) > 0) ?
         (data[address (ix) + imult] / cvm::real (samples->value (ix))) :
         0.0;
     else
       return data[address (ix) + imult];
   }
 
   /// \brief Get the value from a formatted output and transform it
   /// into the internal representation (it may have been rescaled or
   /// manipulated)
   virtual inline void value_input (std::vector<int> const &ix,
                                    cvm::real const &new_value,
                                    size_t const &imult = 0,
                                    bool add = false)
   {
     if (add) {
       if (samples)
         data[address (ix) + imult] += new_value * samples->new_count (ix);
       else
         data[address (ix) + imult] += new_value;
     } else {
       if (samples)
         data[address (ix) + imult] = new_value * samples->value (ix);
       else
         data[address (ix) + imult] = new_value;
     }
     has_data = true;
   }
 
 
   /// \brief Read the grid from a restart
   std::istream & read_restart (std::istream &is);
 
   /// \brief Write the grid to a restart
   std::ostream & write_restart (std::ostream &os);
 
   /// Compute and return average value for a 1D gradient grid
   inline cvm::real average()
   {
     size_t n = 0;
 
     if (nd != 1 || nx[0] == 0) {
       return 0.0;
     }
 
     cvm::real sum = 0.0;
     std::vector<int> ix = new_index();
     if (samples) {
       for ( ; index_ok (ix); incr (ix)) {
         if ( (n = samples->value (ix)) )
           sum += value (ix) / n;
       }
     } else {
       for ( ; index_ok (ix); incr (ix)) {
         sum += value (ix);
       }
     }
     return (sum / cvm::real (nx[0]));
   }
 
   /// \brief If the grid is 1-dimensional, integrate it and write the
   /// integral to a file
   void write_1D_integral (std::ostream &os);
 
 };
 
 
 #endif
 
diff --git a/lib/colvars/colvarmodule.cpp b/lib/colvars/colvarmodule.cpp
index c8a434706..948ddc1f2 100644
--- a/lib/colvars/colvarmodule.cpp
+++ b/lib/colvars/colvarmodule.cpp
@@ -1,1434 +1,1434 @@
 #include "colvarmodule.h"
 #include "colvarparse.h"
 #include "colvarproxy.h"
 #include "colvar.h"
 #include "colvarbias.h"
 #include "colvarbias_meta.h"
 #include "colvarbias_abf.h"
 
 
 colvarmodule::colvarmodule (char const  *config_filename,
                             colvarproxy *proxy_in)
-{ 
+{
   // pointer to the proxy object
   if (proxy == NULL) {
     proxy = proxy_in;
     parse = new colvarparse();
   } else {
     cvm::fatal_error ("Error: trying to allocate the collective "
                       "variable module twice.\n");
   }
 
   cvm::log (cvm::line_marker);
   cvm::log ("Initializing the collective variables module, version "+
             cvm::to_str(COLVARS_VERSION)+".\n");
 
   // "it_restart" will be set by the input state file, if any;
   // "it" should be updated by the proxy
   it = it_restart = 0;
   it_restart_from_state_file = true;
 
   // open the configfile
   config_s.open (config_filename);
   if (!config_s)
     cvm::fatal_error ("Error: in opening configuration file \""+
                       std::string (config_filename)+"\".\n");
 
   // read the config file into a string
   std::string conf = "";
   {
     std::string line;
     while (colvarparse::getline_nocomments (config_s, line))
       conf.append (line+"\n");
     // don't need the stream any more
     config_s.close();
   }
 
   std::string index_file_name;
   if (parse->get_keyval (conf, "indexFile", index_file_name)) {
     read_index_file (index_file_name.c_str());
   }
 
   parse->get_keyval (conf, "analysis", b_analysis, false);
 
   parse->get_keyval (conf, "debugGradientsStepSize", debug_gradients_step_size, 1.0e-07,
                      colvarparse::parse_silent);
 
   parse->get_keyval (conf, "eigenvalueCrossingThreshold",
                      colvarmodule::rotation::crossing_threshold, 1.0e-02,
                      colvarparse::parse_silent);
 
   parse->get_keyval (conf, "colvarsTrajFrequency", cv_traj_freq, 100);
   parse->get_keyval (conf, "colvarsRestartFrequency", restart_out_freq,
                      proxy->restart_frequency());
 
   // by default overwrite the existing trajectory file
   parse->get_keyval (conf, "colvarsTrajAppend", cv_traj_append, false);
 
   // input restart file
   restart_in_name = proxy->input_prefix().size() ?
     std::string (proxy->input_prefix()+".colvars.state") :
     std::string ("") ;
 
   // output restart file
   restart_out_name = proxy->restart_output_prefix().size() ?
     std::string (proxy->restart_output_prefix()+".colvars.state") :
     std::string ("");
 
   if (restart_out_name.size())
     cvm::log ("The restart output state file will be \""+restart_out_name+"\".\n");
 
   output_prefix = proxy->output_prefix();
 
   cvm::log ("The final output state file will be \""+
             (output_prefix.size() ?
              std::string (output_prefix+".colvars.state") :
              std::string ("colvars.state"))+"\".\n");
 
-  cv_traj_name = 
+  cv_traj_name =
     (output_prefix.size() ?
      std::string (output_prefix+".colvars.traj") :
      std::string ("colvars.traj"));
   cvm::log ("The trajectory file will be \""+
             cv_traj_name+"\".\n");
 
   if (cv_traj_freq) {
     // open trajectory file
     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 {
       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);
   }
 
   // parse the options for collective variables
   init_colvars (conf);
 
   // parse the options for biases
   init_biases (conf);
 
   // done with the parsing, check that all keywords are valid
   parse->check_keywords (conf, "colvarmodule");
   cvm::log (cvm::line_marker);
 
   // read the restart configuration, if available
   if (restart_in_name.size()) {
     // read the restart file
     std::ifstream input_is (restart_in_name.c_str());
     if (!input_is.good())
       fatal_error ("Error: in opening restart file \""+
                    std::string (restart_in_name)+"\".\n");
     else {
       cvm::log ("Restarting from file \""+restart_in_name+"\".\n");
       read_restart (input_is);
       cvm::log (cvm::line_marker);
     }
   }
 
   // check if it is possible to save output configuration
   if ((!output_prefix.size()) && (!restart_out_name.size())) {
     cvm::fatal_error ("Error: neither the final output state file or "
                       "the output restart file could be defined, exiting.\n");
   }
 
   cvm::log ("Collective variables module initialized.\n");
   cvm::log (cvm::line_marker);
 }
 
 
-std::istream & colvarmodule::read_restart (std::istream &is) 
+std::istream & colvarmodule::read_restart (std::istream &is)
 {
   {
     // read global restart information
     std::string restart_conf;
     if (is >> colvarparse::read_block ("configuration", restart_conf)) {
       if (it_restart_from_state_file) {
         parse->get_keyval (restart_conf, "step",
                            it_restart, (size_t) 0,
                            colvarparse::parse_silent);
         it = it_restart;
       }
     }
     is.clear();
   }
 
   // colvars restart
   cvm::increase_depth();
   for (std::vector<colvar *>::iterator cvi = colvars.begin();
        cvi != colvars.end();
        cvi++) {
     if ( !((*cvi)->read_restart (is)) )
       cvm::fatal_error ("Error: in reading restart configuration for collective variable \""+
                         (*cvi)->name+"\".\n");
   }
 
   // biases restart
   for (std::vector<colvarbias *>::iterator bi = biases.begin();
        bi != biases.end();
        bi++) {
     if (!((*bi)->read_restart (is)))
       fatal_error ("Error: in reading restart configuration for bias \""+
                    (*bi)->name+"\".\n");
   }
   cvm::decrease_depth();
 
   return is;
 }
 
 
 
 void colvarmodule::init_colvars (std::string const &conf)
 {
   if (cvm::debug())
     cvm::log ("Initializing the collective variables.\n");
 
   std::string colvar_conf = "";
   size_t pos = 0;
   while (parse->key_lookup (conf, "colvar", colvar_conf, pos)) {
 
     if (colvar_conf.size()) {
       cvm::log (cvm::line_marker);
       cvm::increase_depth();
       colvars.push_back (new colvar (colvar_conf));
       (colvars.back())->check_keywords (colvar_conf, "colvar");
       cvm::decrease_depth();
     } else {
-      cvm::log ("Warning: \"colvar\" keyword found without any configuration.\n"); 
+      cvm::log ("Warning: \"colvar\" keyword found without any configuration.\n");
     }
     colvar_conf = "";
   }
 
 
   if (!colvars.size())
     cvm::fatal_error ("Error: no collective variables defined.\n");
 
   if (colvars.size())
     cvm::log (cvm::line_marker);
   cvm::log ("Collective variables initialized, "+
             cvm::to_str (colvars.size())+
             " in total.\n");
 }
 
 
 void colvarmodule::init_biases (std::string const &conf)
 {
   if (cvm::debug())
     cvm::log ("Initializing the collective variables biases.\n");
 
   {
     /// initialize ABF instances
     std::string abf_conf = "";
     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"));
         (biases.back())->check_keywords (abf_conf, "abf");
         cvm::decrease_depth();
         n_abf_biases++;
       } else {
         cvm::log ("Warning: \"abf\" keyword found without configuration.\n");
       }
       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_harmonic (harm_conf, "harmonic"));
         (biases.back())->check_keywords (harm_conf, "harmonic");
         cvm::decrease_depth();
         n_harm_biases++;
       } else {
         cvm::log ("Warning: \"harmonic\" keyword found without configuration.\n");
       }
       harm_conf = "";
     }
   }
 
   {
     /// initialize histograms
     std::string histo_conf = "";
     size_t histo_pos = 0;
     while (parse->key_lookup (conf, "histogram", histo_conf, histo_pos)) {
       if (histo_conf.size()) {
         cvm::log (cvm::line_marker);
         cvm::increase_depth();
         biases.push_back (new colvarbias_histogram (histo_conf, "histogram"));
         (biases.back())->check_keywords (histo_conf, "histogram");
         cvm::decrease_depth();
         n_histo_biases++;
       } else {
         cvm::log ("Warning: \"histogram\" keyword found without configuration.\n");
       }
       histo_conf = "";
     }
   }
 
   {
     /// initialize metadynamics instances
     std::string meta_conf = "";
     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"));
         (biases.back())->check_keywords (meta_conf, "metadynamics");
         cvm::decrease_depth();
         n_meta_biases++;
       } else {
         cvm::log ("Warning: \"metadynamics\" keyword found without configuration.\n");
       }
       meta_conf = "";
     }
   }
 
   if (biases.size())
     cvm::log (cvm::line_marker);
   cvm::log ("Collective variables biases initialized, "+
             cvm::to_str (biases.size())+" in total.\n");
 }
 
 
 void colvarmodule::change_configuration (std::string const &bias_name,
                                          std::string const &conf)
 {
   cvm::increase_depth();
   int found = 0;
   for (std::vector<colvarbias *>::iterator bi = biases.begin();
        bi != biases.end();
        bi++) {
     if ( (*bi)->name == bias_name ) {
       ++found;
       (*bi)->change_configuration (conf);
     }
   }
   if (found < 1) cvm::fatal_error ("Error: bias not found.\n");
   if (found > 1) cvm::fatal_error ("Error: duplicate bias name.\n");
   cvm::decrease_depth();
 }
 
 cvm::real colvarmodule::energy_difference (std::string const &bias_name,
                                            std::string const &conf)
 {
   cvm::increase_depth();
   cvm::real energy_diff = 0.;
   int found = 0;
   for (std::vector<colvarbias *>::iterator bi = biases.begin();
        bi != biases.end();
        bi++) {
     if ( (*bi)->name == bias_name ) {
       ++found;
       energy_diff = (*bi)->energy_difference (conf);
     }
   }
   if (found < 1) cvm::fatal_error ("Error: bias not found.\n");
   if (found > 1) cvm::fatal_error ("Error: duplicate bias name.\n");
   cvm::decrease_depth();
   return energy_diff;
 }
 
 
 void colvarmodule::calc() {
   cvm::real total_bias_energy = 0.0;
   cvm::real total_colvar_energy = 0.0;
 
   if (cvm::debug()) {
     cvm::log (cvm::line_marker);
     cvm::log ("Collective variables module, step no. "+
               cvm::to_str (cvm::step_absolute())+"\n");
   }
 
   // calculate collective variables and their gradients
-  if (cvm::debug()) 
+  if (cvm::debug())
     cvm::log ("Calculating collective variables.\n");
   cvm::increase_depth();
   for (std::vector<colvar *>::iterator cvi = colvars.begin();
        cvi != colvars.end();
        cvi++) {
-    (*cvi)->calc(); 
+    (*cvi)->calc();
   }
   cvm::decrease_depth();
 
   // update the biases and communicate their forces to the collective
   // variables
   if (cvm::debug() && biases.size())
     cvm::log ("Updating collective variable biases.\n");
   cvm::increase_depth();
   for (std::vector<colvarbias *>::iterator bi = biases.begin();
        bi != biases.end();
        bi++) {
-    total_bias_energy += (*bi)->update(); 
+    total_bias_energy += (*bi)->update();
   }
   cvm::decrease_depth();
 
   // sum the forces from all biases for each collective variable
   if (cvm::debug() && biases.size())
     cvm::log ("Collecting forces from all biases.\n");
   cvm::increase_depth();
   for (std::vector<colvar *>::iterator cvi = colvars.begin();
        cvi != colvars.end();
        cvi++) {
-    (*cvi)->reset_bias_force(); 
+    (*cvi)->reset_bias_force();
   }
   for (std::vector<colvarbias *>::iterator bi = biases.begin();
        bi != biases.end();
        bi++) {
-    (*bi)->communicate_forces(); 
+    (*bi)->communicate_forces();
   }
   cvm::decrease_depth();
 
   if (cvm::b_analysis) {
     // perform runtime analysis of colvars and biases
     if (cvm::debug() && biases.size())
       cvm::log ("Perform runtime analyses.\n");
     cvm::increase_depth();
     for (std::vector<colvar *>::iterator cvi = colvars.begin();
          cvi != colvars.end();
          cvi++) {
-      (*cvi)->analyse(); 
+      (*cvi)->analyse();
     }
     for (std::vector<colvarbias *>::iterator bi = biases.begin();
          bi != biases.end();
          bi++) {
-      (*bi)->analyse(); 
+      (*bi)->analyse();
     }
     cvm::decrease_depth();
   }
 
   // sum up the forces for each colvar and integrate any internal
   // equation of motion
   if (cvm::debug())
     cvm::log ("Updating the internal degrees of freedom "
               "of colvars (if they have any).\n");
   cvm::increase_depth();
   for (std::vector<colvar *>::iterator cvi = colvars.begin();
        cvi != colvars.end();
        cvi++) {
     total_colvar_energy += (*cvi)->update();
   }
   cvm::decrease_depth();
   proxy->add_energy (total_bias_energy + total_colvar_energy);
 
   // make collective variables communicate their forces to their
   // coupled degrees of freedom (i.e. atoms)
   if (cvm::debug())
     cvm::log ("Communicating forces from the colvars to the atoms.\n");
   cvm::increase_depth();
   for (std::vector<colvar *>::iterator cvi = colvars.begin();
        cvi != colvars.end();
        cvi++) {
     if ((*cvi)->tasks[colvar::task_gradients])
-      (*cvi)->communicate_forces(); 
+      (*cvi)->communicate_forces();
   }
   cvm::decrease_depth();
 
   // write restart file, if needed
   if (restart_out_freq && restart_out_name.size() && !cvm::b_analysis) {
     if ( (cvm::step_relative() > 0) &&
          ((cvm::step_absolute() % restart_out_freq) == 0) ) {
       cvm::log ("Writing the state file \""+
                 restart_out_name+"\".\n");
       proxy->backup_file (restart_out_name.c_str());
       restart_out_os.open (restart_out_name.c_str());
       restart_out_os.setf (std::ios::scientific, std::ios::floatfield);
       if (!write_restart (restart_out_os))
         cvm::fatal_error ("Error: in writing restart file.\n");
       restart_out_os.close();
-    }    
+    }
   }
 
   // write trajectory file, if needed
   if (cv_traj_freq) {
 
     if (cvm::debug())
       cvm::log ("Writing trajectory file.\n");
 
     // (re)open trajectory file
     if (!cv_traj_os.good()) {
       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 ("Overwriting 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);
     }
 
     // write labels in the traj file every 1000 lines and at first ts
     cvm::increase_depth();
     if ((cvm::step_absolute() % (cv_traj_freq * 1000)) == 0 || cvm::step_relative() == 0) {
       cv_traj_os << "# " << cvm::wrap_string ("step", cvm::it_width-2)
                  << " ";
-      if (cvm::debug()) 
+      if (cvm::debug())
         cv_traj_os.flush();
       for (std::vector<colvar *>::iterator cvi = colvars.begin();
 	   cvi != colvars.end();
 	   cvi++) {
 	(*cvi)->write_traj_label (cv_traj_os);
       }
       for (std::vector<colvarbias *>::iterator bi = biases.begin();
 	   bi != biases.end();
 	   bi++) {
 	(*bi)->write_traj_label (cv_traj_os);
       }
       cv_traj_os << "\n";
-      if (cvm::debug()) 
+      if (cvm::debug())
         cv_traj_os.flush();
     }
     cvm::decrease_depth();
 
     // write collective variable values to the traj file
     cvm::increase_depth();
     if ((cvm::step_absolute() % cv_traj_freq) == 0) {
       cv_traj_os << std::setw (cvm::it_width) << it
                  << " ";
       for (std::vector<colvar *>::iterator cvi = colvars.begin();
 	   cvi != colvars.end();
 	   cvi++) {
         (*cvi)->write_traj (cv_traj_os);
       }
       for (std::vector<colvarbias *>::iterator bi = biases.begin();
 	   bi != biases.end();
 	   bi++) {
 	(*bi)->write_traj (cv_traj_os);
       }
       cv_traj_os << "\n";
       if (cvm::debug())
         cv_traj_os.flush();
     }
     cvm::decrease_depth();
 
-    if (restart_out_freq) { 
+    if (restart_out_freq) {
       // flush the trajectory file if we are at the restart frequency
       if ( (cvm::step_relative() > 0) &&
            ((cvm::step_absolute() % restart_out_freq) == 0) ) {
         cvm::log ("Synchronizing (emptying the buffer of) trajectory file \""+
                   cv_traj_name+"\".\n");
         cv_traj_os.flush();
       }
     }
   } // end if (cv_traj_freq)
 }
 
 
 void colvarmodule::analyze()
 {
   if (cvm::debug()) {
     cvm::log ("colvarmodule::analyze(), step = "+cvm::to_str (it)+".\n");
   }
 
   if (cvm::step_relative() == 0)
     cvm::log ("Performing analysis.\n");
 
   // perform colvar-specific analysis
   for (std::vector<colvar *>::iterator cvi = colvars.begin();
        cvi != colvars.end();
        cvi++) {
     cvm::increase_depth();
-    (*cvi)->analyse(); 
+    (*cvi)->analyse();
     cvm::decrease_depth();
   }
 
   // perform bias-specific analysis
   for (std::vector<colvarbias *>::iterator bi = biases.begin();
        bi != biases.end();
        bi++) {
     cvm::increase_depth();
-    (*bi)->analyse(); 
+    (*bi)->analyse();
     cvm::decrease_depth();
   }
 
 }
 
 
 colvarmodule::~colvarmodule()
 {
   for (std::vector<colvar *>::iterator cvi = colvars.begin();
        cvi != colvars.end();
        cvi++) {
     delete *cvi;
   }
   colvars.clear();
 
   for (std::vector<colvarbias *>::iterator bi = biases.begin();
        bi != biases.end();
        bi++) {
     delete *bi;
   }
   biases.clear();
 
   if (cv_traj_os.good()) {
     cv_traj_os.close();
   }
 
   delete parse;
   proxy = NULL;
-}  
+}
 
 
 void colvarmodule::write_output_files()
 {
   // if this is a simulation run (i.e. not a postprocessing), output data
   // must be written to be able to restart the simulation
   std::string const out_name =
     (output_prefix.size() ?
      std::string (output_prefix+".colvars.state") :
      std::string ("colvars.state"));
   cvm::log ("Saving collective variables state to \""+out_name+"\".\n");
   proxy->backup_file (out_name.c_str());
   std::ofstream out (out_name.c_str());
   out.setf (std::ios::scientific, std::ios::floatfield);
   this->write_restart (out);
   out.close();
 
   cvm::increase_depth();
   for (std::vector<colvar *>::iterator cvi = colvars.begin();
        cvi != colvars.end();
        cvi++) {
     (*cvi)->write_output_files();
   }
   cvm::decrease_depth();
-  
+
   // do not close to avoid problems with multiple NAMD runs
   cv_traj_os.flush();
 }
 
 
 
 bool colvarmodule::read_traj (char const *traj_filename,
                               size_t      traj_read_begin,
                               size_t      traj_read_end)
 {
   cvm::log ("Opening trajectory file \""+
             std::string (traj_filename)+"\".\n");
   std::ifstream traj_is (traj_filename);
 
   while (true) {
     while (true) {
 
       std::string line ("");
 
       do {
         if (!colvarparse::getline_nocomments (traj_is, line)) {
           cvm::log ("End of file \""+std::string (traj_filename)+
                     "\" reached, or corrupted file.\n");
           traj_is.close();
           return false;
         }
       } while (line.find_first_not_of (colvarparse::white_space) == std::string::npos);
 
       std::istringstream is (line);
 
       if (!(is >> it)) return false;
 
       if ( (it < traj_read_begin) ) {
 
         if ((it % 1000) == 0)
           std::cerr << "Skipping trajectory step " << it
                     << "                    \r";
 
         continue;
 
-      } else { 
+      } else {
 
         if ((it % 1000) == 0)
           std::cerr << "Reading from trajectory, step = " << it
                     << "                    \r";
 
         if ( (traj_read_end > traj_read_begin) &&
              (it > traj_read_end) ) {
           std::cerr << "\n";
           cvm::log ("Reached the end of the trajectory, "
                     "read_end = "+cvm::to_str (traj_read_end)+"\n");
           return false;
         }
 
         for (std::vector<colvar *>::iterator cvi = colvars.begin();
              cvi != colvars.end();
              cvi++) {
           if (!(*cvi)->read_traj (is)) {
             cvm::log ("Error: in reading colvar \""+(*cvi)->name+
                       "\" from trajectory file \""+
                       std::string (traj_filename)+"\".\n");
             return false;
           }
         }
 
         break;
       }
     }
   }
 
   return true;
 }
 
 
 std::ostream & colvarmodule::write_restart (std::ostream &os)
 {
   os << "configuration {\n"
      << "  step " << std::setw (it_width)
      << it << "\n"
      << "  dt " << dt() << "\n"
      << "}\n\n";
 
   cvm::increase_depth();
   for (std::vector<colvar *>::iterator cvi = colvars.begin();
        cvi != colvars.end();
        cvi++) {
     (*cvi)->write_restart (os);
   }
 
   for (std::vector<colvarbias *>::iterator bi = biases.begin();
        bi != biases.end();
        bi++) {
     (*bi)->write_restart (os);
   }
   cvm::decrease_depth();
 
   return os;
 }
 
 
 
 void cvm::log (std::string const &message)
 {
   if (depth > 0)
     proxy->log ((std::string (2*depth, ' '))+message);
   else
     proxy->log (message);
 }
 
 void cvm::increase_depth()
 {
   depth++;
 }
 
 void cvm::decrease_depth()
 {
   if (depth) depth--;
 }
 
 void cvm::fatal_error (std::string const &message)
 {
   proxy->fatal_error (message);
 }
 
 void cvm::exit (std::string const &message)
 {
   proxy->exit (message);
 }
 
 
 void cvm::read_index_file (char const *filename)
 {
   std::ifstream is (filename);
   if (!is.good())
     fatal_error ("Error: in opening index file \""+
                  std::string (filename)+"\".\n");
   // std::list<std::string>::iterator names_i = cvm::index_group_names.begin();
   // std::list<std::vector<int> >::iterator lists_i = cvm::index_groups.begin();
   while (is.good()) {
     char open, close;
     std::string group_name;
-    if ( (is >> open) && (open == '[') && 
+    if ( (is >> open) && (open == '[') &&
          (is >> group_name) &&
          (is >> close) && (close == ']') ) {
       cvm::index_group_names.push_back (group_name);
       cvm::index_groups.push_back (std::vector<int> ());
     } else {
       cvm::fatal_error ("Error: in parsing index file \""+
                  std::string (filename)+"\".\n");
     }
 
     int atom_number = 1;
     size_t pos = is.tellg();
     while ( (is >> atom_number) && (atom_number > 0) ) {
       (cvm::index_groups.back()).push_back (atom_number);
       pos = is.tellg();
     }
     is.clear();
     is.seekg (pos, std::ios::beg);
     std::string delim;
     if ( (is >> delim) && (delim == "[") ) {
       // new group
       is.clear();
       is.seekg (pos, std::ios::beg);
     } else {
       break;
     }
   }
 
   cvm::log ("The following index groups were read from the index file \""+
             std::string (filename)+"\":\n");
   std::list<std::string>::iterator names_i = cvm::index_group_names.begin();
   std::list<std::vector<int> >::iterator lists_i = cvm::index_groups.begin();
   for ( ; names_i != cvm::index_group_names.end() ; names_i++, lists_i++) {
     cvm::log ("  "+(*names_i)+" ("+cvm::to_str (lists_i->size())+" atoms).\n");
   }
 
 }
 
 
 // static pointers
 std::vector<colvar *>     colvarmodule::colvars;
 std::vector<colvarbias *> colvarmodule::biases;
 size_t                    colvarmodule::n_abf_biases = 0;
 size_t                    colvarmodule::n_harm_biases = 0;
 size_t                    colvarmodule::n_histo_biases = 0;
 size_t                    colvarmodule::n_meta_biases = 0;
 colvarproxy              *colvarmodule::proxy = NULL;
 
 
 // static runtime data
 cvm::real colvarmodule::debug_gradients_step_size = 1.0e-03;
 size_t    colvarmodule::it = 0;
 size_t    colvarmodule::it_restart = 0;
 size_t    colvarmodule::restart_out_freq = 0;
 size_t    colvarmodule::cv_traj_freq = 0;
 size_t    colvarmodule::depth = 0;
 bool      colvarmodule::b_analysis = false;
 cvm::real colvarmodule::rotation::crossing_threshold = 1.0E-04;
 std::list<std::string> colvarmodule::index_group_names;
 std::list<std::vector<int> > colvarmodule::index_groups;
 
 
 // file name prefixes
 std::string colvarmodule::output_prefix = "";
 std::string colvarmodule::input_prefix = "";
 std::string colvarmodule::restart_in_name = "";
 
 
 // i/o constants
 size_t const colvarmodule::it_width = 12;
 size_t const colvarmodule::cv_prec  = 14;
 size_t const colvarmodule::cv_width = 21;
 size_t const colvarmodule::en_prec  = 14;
 size_t const colvarmodule::en_width = 21;
 std::string const colvarmodule::line_marker =
   "----------------------------------------------------------------------\n";
 
 
 
 
 
 
 std::ostream & operator << (std::ostream &os, colvarmodule::rvector const &v)
 {
   std::streamsize const w = os.width();
   std::streamsize const p = os.precision();
 
   os.width (2);
   os << "( ";
   os.width (w); os.precision (p);
   os << v.x << " , ";
   os.width (w); os.precision (p);
   os << v.y << " , ";
   os.width (w); os.precision (p);
   os << v.z << " )";
   return os;
 }
 
 
 std::istream & operator >> (std::istream &is, colvarmodule::rvector &v)
 {
   size_t const start_pos = is.tellg();
   char sep;
   if ( !(is >> sep) || !(sep == '(') ||
        !(is >> v.x) || !(is >> sep)  || !(sep == ',') ||
        !(is >> v.y) || !(is >> sep)  || !(sep == ',') ||
        !(is >> v.z) || !(is >> sep)  || !(sep == ')') ) {
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
     return is;
   }
   return is;
 }
 
 
 
 std::ostream & operator << (std::ostream &os, colvarmodule::quaternion const &q)
 {
   std::streamsize const w = os.width();
   std::streamsize const p = os.precision();
 
   os.width (2);
   os << "( ";
   os.width (w); os.precision (p);
   os << q.q0 << " , ";
   os.width (w); os.precision (p);
   os << q.q1 << " , ";
   os.width (w); os.precision (p);
   os << q.q2 << " , ";
   os.width (w); os.precision (p);
   os << q.q3 << " )";
   return os;
 }
 
 
 std::istream & operator >> (std::istream &is, colvarmodule::quaternion &q)
 {
   size_t const start_pos = is.tellg();
 
   std::string euler ("");
 
   if ( (is >> euler) && (colvarparse::to_lower_cppstr (euler) ==
                          std::string ("euler")) ) {
 
     // parse the Euler angles
-    
+
     char sep;
     cvm::real phi, theta, psi;
     if ( !(is >> sep)   || !(sep == '(') ||
          !(is >> phi)   || !(is >> sep)  || !(sep == ',') ||
          !(is >> theta) || !(is >> sep)  || !(sep == ',') ||
          !(is >> psi)   || !(is >> sep)  || !(sep == ')') ) {
       is.clear();
       is.seekg (start_pos, std::ios::beg);
       is.setstate (std::ios::failbit);
       return is;
     }
 
     q = colvarmodule::quaternion (phi, theta, psi);
 
   } else {
 
     // parse the quaternion components
 
-    is.seekg (start_pos, std::ios::beg);      
+    is.seekg (start_pos, std::ios::beg);
     char sep;
     if ( !(is >> sep)  || !(sep == '(') ||
          !(is >> q.q0) || !(is >> sep)  || !(sep == ',') ||
          !(is >> q.q1) || !(is >> sep)  || !(sep == ',') ||
          !(is >> q.q2) || !(is >> sep)  || !(sep == ',') ||
          !(is >> q.q3) || !(is >> sep)  || !(sep == ')') ) {
       is.clear();
       is.seekg (start_pos, std::ios::beg);
       is.setstate (std::ios::failbit);
       return is;
     }
   }
 
   return is;
 }
 
 
 cvm::quaternion
 cvm::quaternion::position_derivative_inner (cvm::rvector const &pos,
                                             cvm::rvector const &vec) const
 {
   cvm::quaternion result (0.0, 0.0, 0.0, 0.0);
 
 
   result.q0 =   2.0 * pos.x * q0 * vec.x
                +2.0 * pos.y * q0 * vec.y
                +2.0 * pos.z * q0 * vec.z
 
                -2.0 * pos.y * q3 * vec.x
                +2.0 * pos.z * q2 * vec.x
 
                +2.0 * pos.x * q3 * vec.y
                -2.0 * pos.z * q1 * vec.y
 
                -2.0 * pos.x * q2 * vec.z
                +2.0 * pos.y * q1 * vec.z;
 
 
   result.q1 =  +2.0 * pos.x * q1 * vec.x
                -2.0 * pos.y * q1 * vec.y
                -2.0 * pos.z * q1 * vec.z
 
                +2.0 * pos.y * q2 * vec.x
                +2.0 * pos.z * q3 * vec.x
 
                +2.0 * pos.x * q2 * vec.y
                -2.0 * pos.z * q0 * vec.y
 
                +2.0 * pos.x * q3 * vec.z
                +2.0 * pos.y * q0 * vec.z;
 
 
   result.q2 =  -2.0 * pos.x * q2 * vec.x
                +2.0 * pos.y * q2 * vec.y
                -2.0 * pos.z * q2 * vec.z
 
                +2.0 * pos.y * q1 * vec.x
                +2.0 * pos.z * q0 * vec.x
 
                +2.0 * pos.x * q1 * vec.y
                +2.0 * pos.z * q3 * vec.y
 
                -2.0 * pos.x * q0 * vec.z
                +2.0 * pos.y * q3 * vec.z;
 
 
   result.q3 =  -2.0 * pos.x * q3 * vec.x
                -2.0 * pos.y * q3 * vec.y
                +2.0 * pos.z * q3 * vec.z
 
                -2.0 * pos.y * q0 * vec.x
                +2.0 * pos.z * q1 * vec.x
 
                +2.0 * pos.x * q0 * vec.y
                +2.0 * pos.z * q2 * vec.y
 
                +2.0 * pos.x * q1 * vec.z
                +2.0 * pos.y * q2 * vec.z;
 
   return result;
 }
 
 
 
 
 
 
 // Calculate the optimal rotation between two groups, and implement it
 // as a quaternion.  The method is the one documented in: Coutsias EA,
 // Seok C, Dill KA.  Using quaternions to calculate RMSD.  J Comput
 // Chem. 25(15):1849-57 (2004) DOI: 10.1002/jcc.20110 PubMed: 15376254
 
 void colvarmodule::rotation::build_matrix (std::vector<cvm::atom_pos> const &pos1,
                                            std::vector<cvm::atom_pos> const &pos2,
                                            matrix2d<cvm::real, 4, 4>        &S)
 {
   cvm::rmatrix C;
 
   // build the correlation matrix
   C.reset();
   for (size_t i = 0; i < pos1.size(); i++) {
     C.xx() += pos1[i].x * pos2[i].x;
     C.xy() += pos1[i].x * pos2[i].y;
     C.xz() += pos1[i].x * pos2[i].z;
     C.yx() += pos1[i].y * pos2[i].x;
     C.yy() += pos1[i].y * pos2[i].y;
     C.yz() += pos1[i].y * pos2[i].z;
     C.zx() += pos1[i].z * pos2[i].x;
     C.zy() += pos1[i].z * pos2[i].y;
     C.zz() += pos1[i].z * pos2[i].z;
-  } 
+  }
 
   // build the "overlap" matrix, whose eigenvectors are stationary
   // points of the RMSD in the space of rotations
   S[0][0] =    C.xx() + C.yy() + C.zz();
   S[1][0] =    C.yz() - C.zy();
   S[0][1] = S[1][0];
   S[2][0] =  - C.xz() + C.zx() ;
   S[0][2] = S[2][0];
   S[3][0] =    C.xy() - C.yx();
   S[0][3] = S[3][0];
   S[1][1] =    C.xx() - C.yy() - C.zz();
   S[2][1] =    C.xy() + C.yx();
   S[1][2] = S[2][1];
   S[3][1] =    C.xz() + C.zx();
   S[1][3] = S[3][1];
   S[2][2] = - C.xx() + C.yy() - C.zz();
   S[3][2] =   C.yz() + C.zy();
   S[2][3] = S[3][2];
   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,
                                                  cvm::real                  S_eigval[4],
                                                  matrix2d<cvm::real, 4, 4> &S_eigvec)
 {
   // diagonalize
   int jac_nrot = 0;
   jacobi (S, 4, S_eigval, S_eigvec, &jac_nrot);
   eigsrt (S_eigval, S_eigvec, 4);
   // jacobi saves eigenvectors by columns
   transpose (S_eigvec, 4);
 
   // normalize eigenvectors
   for (size_t ie = 0; ie < 4; ie++) {
     cvm::real norm2 = 0.0;
     for (size_t i = 0; i < 4; i++) norm2 += std::pow (S_eigvec[ie][i], int (2));
     cvm::real const norm = std::sqrt (norm2);
     for (size_t i = 0; i < 4; i++) S_eigvec[ie][i] /= norm;
   }
 }
 
 
 // Calculate the rotation, plus its derivatives
 
 void colvarmodule::rotation::calc_optimal_rotation
 (std::vector<cvm::atom_pos> const &pos1,
  std::vector<cvm::atom_pos> const &pos2)
 {
   matrix2d<cvm::real, 4, 4> S;
   matrix2d<cvm::real, 4, 4> S_backup;
   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);
   S_backup = S;
 
   if (cvm::debug()) {
     if (b_debug_gradients) {
       cvm::log ("S     = "+cvm::to_str (cvm::to_str (S_backup), cvm::cv_width, cvm::cv_prec)+"\n");
     }
   }
 
   diagonalize_matrix (S, S_eigval, S_eigvec);
 
   // eigenvalues and eigenvectors
   cvm::real const &L0 = S_eigval[0];
   cvm::real const &L1 = S_eigval[1];
   cvm::real const &L2 = S_eigval[2];
   cvm::real const &L3 = S_eigval[3];
   cvm::real const *Q0 = S_eigvec[0];
   cvm::real const *Q1 = S_eigvec[1];
   cvm::real const *Q2 = S_eigvec[2];
   cvm::real const *Q3 = S_eigvec[3];
 
   lambda = L0;
   q = cvm::quaternion (Q0);
 
   if (q_old.norm2() > 0.0) {
     q.match (q_old);
     if (q_old.inner (q) < (1.0 - crossing_threshold)) {
       cvm::log ("Warning: one molecular orientation has changed by more than "+
                 cvm::to_str (crossing_threshold)+": discontinuous rotation ?\n");
     }
   }
   q_old = q;
-                     
+
   if (cvm::debug()) {
     if (b_debug_gradients) {
       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*Q0 = "+cvm::to_str (cvm::quaternion (Q0).inner (cvm::quaternion (Q0)), cvm::cv_width, cvm::cv_prec)+
                 "\n");
       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)+
                 ", Q0*Q1 = "+cvm::to_str (cvm::quaternion (Q0).inner (cvm::quaternion (Q1)), cvm::cv_width, cvm::cv_prec)+
                 "\n");
       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)+
                 ", Q0*Q2 = "+cvm::to_str (cvm::quaternion (Q0).inner (cvm::quaternion (Q2)), cvm::cv_width, cvm::cv_prec)+
                 "\n");
       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)+
                 ", Q0*Q3 = "+cvm::to_str (cvm::quaternion (Q0).inner (cvm::quaternion (Q3)), cvm::cv_width, cvm::cv_prec)+
                 "\n");
     }
   }
 
   // calculate derivatives of L0 and Q0 with respect to each atom in
   // either group; note: if dS_1 is a null vector, nothing will be
   // calculated
   for (size_t ia = 0; ia < dS_1.size(); ia++) {
 
     cvm::real const &a2x = pos2[ia].x;
     cvm::real const &a2y = pos2[ia].y;
     cvm::real const &a2z = pos2[ia].z;
 
     matrix2d<cvm::rvector, 4, 4>    &ds_1 =  dS_1[ia];
 
     // derivative of the S matrix
     ds_1.reset();
     ds_1[0][0] = cvm::rvector ( a2x,  a2y,  a2z);
     ds_1[1][0] = cvm::rvector ( 0.0,  a2z, -a2y);
     ds_1[0][1] = ds_1[1][0];
     ds_1[2][0] = cvm::rvector (-a2z,  0.0,  a2x);
     ds_1[0][2] = ds_1[2][0];
     ds_1[3][0] = cvm::rvector ( a2y, -a2x,  0.0);
     ds_1[0][3] = ds_1[3][0];
     ds_1[1][1] = cvm::rvector ( a2x, -a2y, -a2z);
     ds_1[2][1] = cvm::rvector ( a2y,  a2x,  0.0);
     ds_1[1][2] = ds_1[2][1];
     ds_1[3][1] = cvm::rvector ( a2z,  0.0,  a2x);
     ds_1[1][3] = ds_1[3][1];
     ds_1[2][2] = cvm::rvector (-a2x,  a2y, -a2z);
     ds_1[3][2] = cvm::rvector ( 0.0,  a2z,  a2y);
     ds_1[2][3] = ds_1[3][2];
     ds_1[3][3] = cvm::rvector (-a2x, -a2y,  a2z);
 
     cvm::rvector              &dl0_1 = dL0_1[ia];
     vector1d<cvm::rvector, 4> &dq0_1 = dQ0_1[ia];
 
     // matrix multiplications; derivatives of L_0 and Q_0 are
     // calculated using Hellmann-Feynman theorem (i.e. exploiting the
     // fact that the eigenvectors Q_i form an orthonormal basis)
 
     dl0_1.reset();
     for (size_t i = 0; i < 4; i++) {
       for (size_t j = 0; j < 4; j++) {
         dl0_1 += Q0[i] * ds_1[i][j] * Q0[j];
       }
     }
 
     dq0_1.reset();
     for (size_t p = 0; p < 4; p++) {
       for (size_t i = 0; i < 4; i++) {
         for (size_t j = 0; j < 4; j++) {
           dq0_1[p] +=
-            (Q1[i] * ds_1[i][j] * Q0[j]) / (L0-L1) * Q1[p] + 
-            (Q2[i] * ds_1[i][j] * Q0[j]) / (L0-L2) * Q2[p] + 
+            (Q1[i] * ds_1[i][j] * Q0[j]) / (L0-L1) * Q1[p] +
+            (Q2[i] * ds_1[i][j] * Q0[j]) / (L0-L2) * Q2[p] +
             (Q3[i] * ds_1[i][j] * Q0[j]) / (L0-L3) * Q3[p];
         }
       }
     }
   }
 
   // do the same for the second group
   for (size_t ia = 0; ia < dS_2.size(); ia++) {
 
     cvm::real const &a1x = pos1[ia].x;
     cvm::real const &a1y = pos1[ia].y;
     cvm::real const &a1z = pos1[ia].z;
 
     matrix2d<cvm::rvector, 4, 4> &ds_2 =  dS_2[ia];
 
     ds_2.reset();
     ds_2[0][0] = cvm::rvector ( a1x,  a1y,  a1z);
     ds_2[1][0] = cvm::rvector ( 0.0, -a1z,  a1y);
     ds_2[0][1] = ds_2[1][0];
     ds_2[2][0] = cvm::rvector ( a1z,  0.0, -a1x);
     ds_2[0][2] = ds_2[2][0];
     ds_2[3][0] = cvm::rvector (-a1y,  a1x,  0.0);
     ds_2[0][3] = ds_2[3][0];
     ds_2[1][1] = cvm::rvector ( a1x, -a1y, -a1z);
     ds_2[2][1] = cvm::rvector ( a1y,  a1x,  0.0);
     ds_2[1][2] = ds_2[2][1];
     ds_2[3][1] = cvm::rvector ( a1z,  0.0,  a1x);
     ds_2[1][3] = ds_2[3][1];
     ds_2[2][2] = cvm::rvector (-a1x,  a1y, -a1z);
     ds_2[3][2] = cvm::rvector ( 0.0,  a1z,  a1y);
     ds_2[2][3] = ds_2[3][2];
     ds_2[3][3] = cvm::rvector (-a1x, -a1y,  a1z);
 
     cvm::rvector              &dl0_2 = dL0_2[ia];
     vector1d<cvm::rvector, 4> &dq0_2 = dQ0_2[ia];
 
     dl0_2.reset();
     for (size_t i = 0; i < 4; i++) {
       for (size_t j = 0; j < 4; j++) {
         dl0_2 += Q0[i] * ds_2[i][j] * Q0[j];
       }
     }
 
     dq0_2.reset();
     for (size_t p = 0; p < 4; p++) {
       for (size_t i = 0; i < 4; i++) {
         for (size_t j = 0; j < 4; j++) {
           dq0_2[p] +=
-            (Q1[i] * ds_2[i][j] * Q0[j]) / (L0-L1) * Q1[p] + 
-            (Q2[i] * ds_2[i][j] * Q0[j]) / (L0-L2) * Q2[p] + 
+            (Q1[i] * ds_2[i][j] * Q0[j]) / (L0-L1) * Q1[p] +
+            (Q2[i] * ds_2[i][j] * Q0[j]) / (L0-L2) * Q2[p] +
             (Q3[i] * ds_2[i][j] * Q0[j]) / (L0-L3) * Q3[p];
         }
       }
     }
 
     if (cvm::debug()) {
-      
+
       if (b_debug_gradients) {
 
       matrix2d<cvm::real, 4, 4> S_new;
       cvm::real                 S_new_eigval[4];
       matrix2d<cvm::real, 4, 4> S_new_eigvec;
 
         // make an infitesimal move along each cartesian coordinate of
         // this atom, and solve again the eigenvector problem
         for (size_t comp = 0; comp < 3; comp++) {
 
           S_new = S_backup;
           // diagonalize the new overlap matrix
           for (size_t i = 0; i < 4; i++) {
             for (size_t j = 0; j < 4; j++) {
-              S_new[i][j] += 
+              S_new[i][j] +=
                 colvarmodule::debug_gradients_step_size * ds_2[i][j][comp];
             }
           }
 
 //           cvm::log ("S_new = "+cvm::to_str (cvm::to_str (S_new), cvm::cv_width, cvm::cv_prec)+"\n");
 
           diagonalize_matrix (S_new, S_new_eigval, S_new_eigvec);
 
           cvm::real const &L0_new = S_new_eigval[0];
           cvm::real const *Q0_new = S_new_eigvec[0];
 
           cvm::real const DL0 = (dl0_2[comp]) * colvarmodule::debug_gradients_step_size;
           cvm::quaternion const q0 (Q0);
           cvm::quaternion const DQ0 (dq0_2[0][comp] * colvarmodule::debug_gradients_step_size,
                                      dq0_2[1][comp] * colvarmodule::debug_gradients_step_size,
                                      dq0_2[2][comp] * colvarmodule::debug_gradients_step_size,
                                      dq0_2[3][comp] * colvarmodule::debug_gradients_step_size);
 
           cvm::log (  "|(l_0+dl_0) - l_0^new|/l_0 = "+
                       cvm::to_str (std::fabs (L0+DL0 - L0_new)/L0, cvm::cv_width, cvm::cv_prec)+
                       ", |(q_0+dq_0) - q_0^new| = "+
                       cvm::to_str ((Q0+DQ0 - Q0_new).norm(), cvm::cv_width, cvm::cv_prec)+
                       "\n");
         }
       }
     }
   }
 }
 
 
 
 // Numerical Recipes routine for diagonalization
 
 #define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);    \
   a[k][l]=h+s*(g-h*tau);
 void jacobi(cvm::real **a, int n, cvm::real d[], cvm::real **v, int *nrot)
 {
   int j,iq,ip,i;
   cvm::real tresh,theta,tau,t,sm,s,h,g,c;
 
   std::vector<cvm::real> b (n, 0.0);
   std::vector<cvm::real> z (n, 0.0);
 
   for (ip=0;ip<n;ip++) {
     for (iq=0;iq<n;iq++) v[ip][iq]=0.0;
     v[ip][ip]=1.0;
   }
   for (ip=0;ip<n;ip++) {
     b[ip]=d[ip]=a[ip][ip];
     z[ip]=0.0;
   }
   *nrot=0;
   for (i=0;i<=50;i++) {
     sm=0.0;
     for (ip=0;ip<n-1;ip++) {
       for (iq=ip+1;iq<n;iq++)
         sm += std::fabs(a[ip][iq]);
     }
     if (sm == 0.0) {
       return;
     }
     if (i < 4)
       tresh=0.2*sm/(n*n);
     else
       tresh=0.0;
     for (ip=0;ip<n-1;ip++) {
       for (iq=ip+1;iq<n;iq++) {
         g=100.0*std::fabs(a[ip][iq]);
         if (i > 4 && (cvm::real)(std::fabs(d[ip])+g) == (cvm::real)std::fabs(d[ip])
             && (cvm::real)(std::fabs(d[iq])+g) == (cvm::real)std::fabs(d[iq]))
           a[ip][iq]=0.0;
         else if (std::fabs(a[ip][iq]) > tresh) {
           h=d[iq]-d[ip];
           if ((cvm::real)(std::fabs(h)+g) == (cvm::real)std::fabs(h))
             t=(a[ip][iq])/h;
           else {
             theta=0.5*h/(a[ip][iq]);
             t=1.0/(std::fabs(theta)+std::sqrt(1.0+theta*theta));
             if (theta < 0.0) t = -t;
           }
           c=1.0/std::sqrt(1+t*t);
           s=t*c;
           tau=s/(1.0+c);
           h=t*a[ip][iq];
           z[ip] -= h;
           z[iq] += h;
           d[ip] -= h;
           d[iq] += h;
           a[ip][iq]=0.0;
           for (j=0;j<=ip-1;j++) {
             ROTATE(a,j,ip,j,iq)
               }
           for (j=ip+1;j<=iq-1;j++) {
             ROTATE(a,ip,j,j,iq)
               }
           for (j=iq+1;j<n;j++) {
             ROTATE(a,ip,j,iq,j)
               }
           for (j=0;j<n;j++) {
             ROTATE(v,j,ip,j,iq)
               }
           ++(*nrot);
         }
       }
     }
     for (ip=0;ip<n;ip++) {
       b[ip] += z[ip];
       d[ip]=b[ip];
       z[ip]=0.0;
     }
   }
   cvm::fatal_error ("Too many iterations in routine jacobi.\n");
 }
 #undef ROTATE
 
 
 void eigsrt(cvm::real d[], cvm::real **v, int n)
 {
   int k,j,i;
   cvm::real p;
 
   for (i=0;i<n;i++) {
     p=d[k=i];
     for (j=i+1;j<n;j++)
       if (d[j] >= p) p=d[k=j];
     if (k != i) {
       d[k]=d[i];
       d[i]=p;
       for (j=0;j<n;j++) {
         p=v[j][i];
         v[j][i]=v[j][k];
         v[j][k]=p;
       }
     }
   }
 }
 
 
 void transpose(cvm::real **v, int n)
 {
   cvm::real p;
   for (int i=0;i<n;i++) {
     for (int j=i+1;j<n;j++) {
       p=v[i][j];
       v[i][j]=v[j][i];
       v[j][i]=p;
     }
   }
 }
 
diff --git a/lib/colvars/colvarmodule.h b/lib/colvars/colvarmodule.h
index c506f2cb5..997b0ea1b 100644
--- a/lib/colvars/colvarmodule.h
+++ b/lib/colvars/colvarmodule.h
@@ -1,505 +1,505 @@
 #ifndef COLVARMODULE_H
 #define COLVARMODULE_H
 
 #ifndef COLVARS_VERSION
-#define COLVARS_VERSION "2013-06-05"
+#define COLVARS_VERSION "2013-06-07"
 #endif
 
 #ifndef COLVARS_DEBUG
 #define COLVARS_DEBUG false
 #endif
 
-/// \file colvarmodule.h 
+/// \file colvarmodule.h
 /// \brief Collective variables main module
-/// 
+///
 /// This file declares the main class for defining and manipulating
 /// collective variables: there should be only one instance of this
 /// class, because several variables are made static (i.e. they are
 /// shared between all object instances) to be accessed from other
 /// objects.
 
 
 #include <iostream>
 #include <iomanip>
 #include <string>
 #include <sstream>
 #include <fstream>
 #include <cmath>
 #include <vector>
 #include <list>
 
 
 class colvarparse;
 class colvar;
 class colvarbias;
 class colvarproxy;
 
 
 /// \brief Collective variables module (main class)
 ///
 /// Class to control the collective variables calculation.  An object
 /// (usually one) of this class is spawned from the MD program,
 /// containing all i/o routines and general interface.
-/// 
+///
 /// At initialization, the colvarmodule object creates a proxy object
 /// to provide a transparent interface between the MD program and the
 /// child objects
 class colvarmodule {
 
 private:
 
   /// Impossible to initialize the main object without arguments
   colvarmodule();
 
 public:
 
   friend class colvarproxy;
-  
+
   /// Defining an abstract real number allows to switch precision
   typedef  double    real;
   /// Residue identifier
   typedef  int       residue_id;
 
   class rvector;
   template <class T,
             size_t const length> class vector1d;
   template <class T,
             size_t const outer_length,
             size_t const inner_length> class matrix2d;
   class quaternion;
   class rotation;
 
   /// \brief Atom position (different type name from rvector, to make
   /// possible future PBC-transparent implementations)
   typedef rvector atom_pos;
 
   /// \brief 3x3 matrix of real numbers
   class rmatrix;
 
   // allow these classes to access protected data
   class atom;
   class atom_group;
   friend class atom;
   friend class atom_group;
   typedef std::vector<atom>::iterator       atom_iter;
   typedef std::vector<atom>::const_iterator atom_const_iter;
 
   /// Current step number
   static size_t it;
   /// Starting step number for this run
   static size_t it_restart;
 
   /// Return the current step number from the beginning of this run
   static inline size_t step_relative()
   {
     return it - it_restart;
   }
 
   /// Return the current step number from the beginning of the whole
   /// calculation
   static inline size_t step_absolute()
   {
     return it;
   }
 
   /// If true, get it_restart from the state file; if set to false,
   /// the MD program is providing it
   bool it_restart_from_state_file;
 
   /// \brief Finite difference step size (if there is no dynamics, or
   /// if gradients need to be tested independently from the size of
   /// dt)
   static real debug_gradients_step_size;
 
   /// Prefix for all output files for this run
   static std::string output_prefix;
 
   /// Prefix for files from a previous run (including restart/output)
   static std::string input_prefix;
 
   /// input restart file name (determined from input_prefix)
   static std::string restart_in_name;
 
 
   /// Array of collective variables
   static std::vector<colvar *>     colvars;
 
   /* TODO: implement named CVCs
   /// Array of named (reusable) collective variable components
   static std::vector<cvc *>     cvcs;
   /// Named cvcs register themselves at initialization time
   inline void register_cvc (cvc *p) {
     cvcs.push_back(p);
   }
   */
 
   /// Array of collective variable biases
   static std::vector<colvarbias *> biases;
   /// \brief Number of ABF biases initialized (in normal conditions
   /// should be 1)
   static size_t n_abf_biases;
   /// \brief Number of metadynamics biases initialized (in normal
   /// conditions should be 1)
   static size_t n_meta_biases;
   /// \brief Number of harmonic biases initialized (no limit on the
   /// number)
   static size_t n_harm_biases;
   /// \brief Number of histograms initialized (no limit on the
   /// number)
   static size_t n_histo_biases;
-   
+
   /// \brief Whether debug output should be enabled (compile-time option)
   static inline bool debug()
   {
     return COLVARS_DEBUG;
   }
 
 
   /// \brief Constructor \param config_name Configuration file name
   /// \param restart_name (optional) Restart file name
-  colvarmodule (char const *config_name, 
+  colvarmodule (char const *config_name,
                 colvarproxy *proxy_in);
   /// Destructor
   ~colvarmodule();
 
   /// Initialize collective variables
   void init_colvars (std::string const &conf);
 
   /// Initialize collective variable biases
   void init_biases (std::string const &conf);
 
   /// Load new configuration for the given bias -
   /// currently works for harmonic (force constant and/or centers)
   void change_configuration (std::string const &bias_name, std::string const &conf);
 
   /// Calculate change in energy from using alt. config. for the given bias -
   /// currently works for harmonic (force constant and/or centers)
   real energy_difference (std::string const &bias_name, std::string const &conf);
 
   /// Calculate collective variables and biases
   void calc();
   /// Read the input restart file
   std::istream & read_restart (std::istream &is);
   /// Write the output restart file
   std::ostream & write_restart (std::ostream &os);
   /// Write all output files (called by the proxy)
   void write_output_files();
   /// \brief Call colvarproxy::backup_file()
   static void backup_file (char const *filename);
 
   /// Perform analysis
   void analyze();
   /// \brief Read a collective variable trajectory (post-processing
   /// only, not called at runtime)
   bool read_traj (char const *traj_filename,
                   size_t      traj_read_begin,
                   size_t      traj_read_end);
- 
+
   /// Get the pointer of a colvar from its name (returns NULL if not found)
   static colvar * colvar_p (std::string const &name);
 
   /// Quick conversion of an object to a string
-  template<typename T> static std::string to_str (T const &x, 
+  template<typename T> static std::string to_str (T const &x,
                                                   size_t const &width = 0,
                                                   size_t const &prec = 0);
   /// Quick conversion of a vector of objects to a string
-  template<typename T> static std::string to_str (std::vector<T> const &x, 
+  template<typename T> static std::string to_str (std::vector<T> const &x,
                                                   size_t const &width = 0,
                                                   size_t const &prec = 0);
 
   /// Reduce the number of characters in a string
   static inline std::string wrap_string (std::string const &s,
                                          size_t const &nchars)
   {
     if (!s.size())
       return std::string (nchars, ' ');
     else
       return ( (s.size() <= size_t (nchars)) ?
                (s+std::string (nchars-s.size(), ' ')) :
                (std::string (s, 0, nchars)) );
   }
 
   /// Number of characters to represent a time step
   static size_t const it_width;
   /// Number of digits to represent a collective variables value(s)
   static size_t const cv_prec;
   /// Number of characters to represent a collective variables value(s)
   static size_t const cv_width;
   /// Number of digits to represent the collective variables energy
   static size_t const en_prec;
   /// Number of characters to represent the collective variables energy
   static size_t const en_width;
   /// Line separator in the log output
   static std::string const line_marker;
 
 
   // proxy functions
 
   /// \brief Value of the unit for atomic coordinates with respect to
   /// angstroms (used by some variables for hard-coded default values)
   static real unit_angstrom();
 
   /// \brief Boltmann constant
   static real boltzmann();
 
   /// \brief Temperature of the simulation (K)
   static real temperature();
 
   /// \brief Time step of MD integrator (fs)
   static real dt();
-  
+
   /// Request calculation of system force from MD engine
   static void request_system_force();
-  
+
   /// Print a message to the main log
   static void log (std::string const &message);
 
   /// Print a message to the main log and exit with error code
   static void fatal_error (std::string const &message);
 
   /// Print a message to the main log and exit normally
   static void exit (std::string const &message);
 
 
   /// \brief Get the distance between two atomic positions with pbcs handled
   /// correctly
   static rvector position_distance (atom_pos const &pos1,
                                     atom_pos const &pos2);
 
 
   /// \brief Get the square distance between two positions (with
   /// periodic boundary conditions handled transparently)
   ///
   /// Note: in the case of periodic boundary conditions, this provides
   /// an analytical square distance (while taking the square of
   /// position_distance() would produce leads to a cusp)
   static real position_dist2 (atom_pos const &pos1,
                               atom_pos const &pos2);
 
   /// \brief Get the closest periodic image to a reference position
   /// \param pos The position to look for the closest periodic image
-  /// \param ref_pos (optional) The reference position 
+  /// \param ref_pos (optional) The reference position
   static void select_closest_image (atom_pos &pos,
                                     atom_pos const &ref_pos);
 
   /// \brief Perform select_closest_image() on a set of atomic positions
   ///
   /// After that, distance vectors can then be calculated directly,
   /// without using position_distance()
   static void select_closest_images (std::vector<atom_pos> &pos,
                                      atom_pos const &ref_pos);
 
 
   /// \brief Names of groups from a Gromacs .ndx file to be read at startup
   static std::list<std::string> index_group_names;
 
   /// \brief Groups from a Gromacs .ndx file read at startup
   static std::list<std::vector<int> > index_groups;
 
   /// \brief Read a Gromacs .ndx file
   static void read_index_file (char const *filename);
 
 
   /// \brief Create atoms from a file \param filename name of the file
   /// (usually a PDB) \param atoms array of the atoms to be allocated
   /// \param pdb_field (optiona) if "filename" is a PDB file, use this
   /// field to determine which are the atoms to be set
   static void load_atoms (char const *filename,
                           std::vector<atom> &atoms,
                           std::string const &pdb_field,
                           double const pdb_field_value = 0.0);
 
   /// \brief Load the coordinates for a group of atoms from a file
   /// (usually a PDB); the number of atoms in "filename" must match
   /// the number of elements in "pos"
   static void load_coords (char const *filename,
                            std::vector<atom_pos> &pos,
                            const std::vector<int> &indices,
                            std::string const &pdb_field,
                            double const pdb_field_value = 0.0);
 
 
   /// Frequency for collective variables trajectory output
   static size_t cv_traj_freq;
 
   /// \brief True if only analysis is performed and not a run
   static bool   b_analysis;
 
   /// Frequency for saving output restarts
   static size_t restart_out_freq;
   /// Output restart file name
   std::string   restart_out_name;
 
   /// Pseudo-random number with Gaussian distribution
   static real rand_gaussian (void);
 protected:
 
   /// Configuration file
   std::ifstream config_s;
 
   /// Configuration file parser object
   colvarparse *parse;
 
   /// Name of the trajectory file
   std::string   cv_traj_name;
 
   /// Collective variables output trajectory file
   std::ofstream cv_traj_os;
 
   /// Appending to the existing trajectory file?
   bool          cv_traj_append;
 
   /// Output restart file
   std::ofstream restart_out_os;
 
   /// \brief Pointer to the proxy object, used to retrieve atomic data
   /// from the hosting program; it is static in order to be accessible
   /// from static functions in the colvarmodule class
   static colvarproxy *proxy;
 
   /// \brief Counter for the current depth in the object hierarchy (useg e.g. in outpu
   static size_t depth;
 
 public:
 
   /// Increase the depth (number of indentations in the output)
   static void increase_depth();
 
   /// Decrease the depth (number of indentations in the output)
   static void decrease_depth();
 };
 
 
 /// Shorthand for the frequently used type prefix
 typedef colvarmodule cvm;
 
 
 #include "colvartypes.h"
 
 
 std::ostream & operator << (std::ostream &os, cvm::rvector const &v);
 std::istream & operator >> (std::istream &is, cvm::rvector &v);
 
 
-template<typename T> std::string cvm::to_str (T const &x, 
+template<typename T> std::string cvm::to_str (T const &x,
                                               size_t const &width,
                                               size_t const &prec) {
   std::ostringstream os;
   if (width) os.width (width);
   if (prec) {
     os.setf (std::ios::scientific, std::ios::floatfield);
     os.precision (prec);
   }
   os << x;
   return os.str();
 }
 
-template<typename T> std::string cvm::to_str (std::vector<T> const &x, 
+template<typename T> std::string cvm::to_str (std::vector<T> const &x,
                                               size_t const &width,
                                               size_t const &prec) {
   if (!x.size()) return std::string ("");
   std::ostringstream os;
   if (prec) {
     os.setf (std::ios::scientific, std::ios::floatfield);
   }
   os << "{ ";
   if (width) os.width (width);
   if (prec) os.precision (prec);
   os << x[0];
   for (size_t i = 1; i < x.size(); i++) {
     os << ", ";
     if (width) os.width (width);
     if (prec) os.precision (prec);
     os << x[i];
   }
   os << " }";
   return os.str();
 }
 
 
 #include "colvarproxy.h"
 
 
 inline cvm::real cvm::unit_angstrom()
 {
   return proxy->unit_angstrom();
 }
 
 inline cvm::real cvm::boltzmann()
 {
   return proxy->boltzmann();
 }
 
 inline cvm::real cvm::temperature()
 {
   return proxy->temperature();
 }
 
 inline cvm::real cvm::dt()
 {
   return proxy->dt();
 }
 
 inline void cvm::request_system_force()
 {
   proxy->request_system_force (true);
 }
-  
+
 inline void cvm::select_closest_image (atom_pos &pos,
                                        atom_pos const &ref_pos)
 {
   proxy->select_closest_image (pos, ref_pos);
 }
 
 inline void cvm::select_closest_images (std::vector<atom_pos> &pos,
                                         atom_pos const &ref_pos)
 {
   proxy->select_closest_images (pos, ref_pos);
 }
 
 inline cvm::rvector cvm::position_distance (atom_pos const &pos1,
                                             atom_pos const &pos2)
 {
   return proxy->position_distance (pos1, pos2);
 }
 
 inline cvm::real cvm::position_dist2 (cvm::atom_pos const &pos1,
                                       cvm::atom_pos const &pos2)
 {
   return proxy->position_dist2 (pos1, pos2);
 }
 
 inline void cvm::load_atoms (char const *file_name,
                              std::vector<cvm::atom> &atoms,
                              std::string const &pdb_field,
                              double const pdb_field_value)
 {
   proxy->load_atoms (file_name, atoms, pdb_field, pdb_field_value);
 }
 
 inline void cvm::load_coords (char const *file_name,
                               std::vector<cvm::atom_pos> &pos,
                               const std::vector<int> &indices,
                               std::string const &pdb_field,
                               double const pdb_field_value)
 {
   proxy->load_coords (file_name, pos, indices, pdb_field, pdb_field_value);
 }
 
 inline void cvm::backup_file (char const *filename)
 {
   proxy->backup_file (filename);
 }
 
 inline cvm::real cvm::rand_gaussian (void)
 {
   return proxy->rand_gaussian();
 }
 
 #endif
 
 
 // Emacs
 // Local Variables:
 // mode: C++
 // End:
diff --git a/lib/colvars/colvarparse.cpp b/lib/colvars/colvarparse.cpp
index 0a40de2d2..2e62072f3 100644
--- a/lib/colvars/colvarparse.cpp
+++ b/lib/colvars/colvarparse.cpp
@@ -1,643 +1,643 @@
 #include <sstream>
 #include <iostream>
 
 
 
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 #include "colvarparse.h"
 
 
 
 // space & tab
 std::string const colvarparse::white_space = " \t";
 
 std::string colvarparse::dummy_string = "";
 size_t      colvarparse::dummy_pos = 0;
 
 
 // definition of single-value keyword parsers
 
 #define _get_keyval_scalar_string_(TYPE)                                \
                                                                         \
   bool colvarparse::get_keyval (std::string const &conf,                \
                                 char const *key,                        \
                                 TYPE &value,                            \
                                 TYPE const &def_value,                  \
                                 Parse_Mode const parse_mode)            \
   {                                                                     \
     std::string data;                                                   \
     bool b_found = false, b_found_any = false;                          \
     size_t save_pos = 0, found_count = 0;                               \
                                                                         \
     do {                                                                \
       std::string data_this = "";                                       \
       b_found = key_lookup (conf, key, data_this, save_pos);            \
       if (b_found) {                                                    \
         if (!b_found_any)                                               \
           b_found_any = true;                                           \
         found_count++;                                                  \
         data = data_this;                                               \
       }                                                                 \
     } while (b_found);                                                  \
                                                                         \
     if (found_count > 1)                                                \
       cvm::log ("Warning: found more than one instance of \""+          \
                 std::string (key)+"\".\n");                             \
                                                                         \
     if (data.size()) {                                                  \
       std::istringstream is (data);                                     \
       TYPE x (def_value);                                               \
       if (is >> x)                                                      \
         value = x;                                                      \
       else                                                              \
         cvm::fatal_error ("Error: in parsing \""+                       \
                           std::string (key)+"\".\n");                   \
       if (parse_mode != parse_silent) {                                 \
         cvm::log ("# "+std::string (key)+" = "+                         \
                   cvm::to_str (value)+"\n");                            \
       }                                                                 \
     } else {                                                            \
                                                                         \
       if (b_found_any)                                                  \
         cvm::fatal_error ("Error: improper or missing value "           \
                           "for \""+std::string (key)+"\".\n");          \
       value = def_value;                                                \
       if (parse_mode != parse_silent) {                                 \
         cvm::log ("# "+std::string (key)+" = \""+                       \
                   cvm::to_str (def_value)+"\" [default]\n");            \
       }                                                                 \
     }                                                                   \
                                                                         \
     return b_found_any;                                                 \
   }
 
 
 #define _get_keyval_scalar_(TYPE)                                       \
                                                                         \
   bool colvarparse::get_keyval (std::string const &conf,                \
                                 char const *key,                        \
                                 TYPE &value,                            \
                                 TYPE const &def_value,                  \
                                 Parse_Mode const parse_mode)            \
   {                                                                     \
     std::string data;                                                   \
     bool b_found = false, b_found_any = false;                          \
     size_t save_pos = 0, found_count = 0;                               \
                                                                         \
     do {                                                                \
       std::string data_this = "";                                       \
       b_found = key_lookup (conf, key, data_this, save_pos);            \
       if (b_found) {                                                    \
         if (!b_found_any)                                               \
           b_found_any = true;                                           \
         found_count++;                                                  \
         data = data_this;                                               \
       }                                                                 \
     } while (b_found);                                                  \
                                                                         \
     if (found_count > 1)                                                \
       cvm::log ("Warning: found more than one instance of \""+          \
                 std::string (key)+"\".\n");                             \
                                                                         \
     if (data.size()) {                                                  \
       std::istringstream is (data);                                     \
       size_t data_count = 0;                                            \
       TYPE x (def_value);                                               \
       while (is >> x) {                                                 \
         value = x;                                                      \
         data_count++;                                                   \
       }                                                                 \
       if (data_count == 0)                                              \
         cvm::fatal_error ("Error: in parsing \""+                       \
                           std::string (key)+"\".\n");                   \
       if (data_count > 1)                                               \
         cvm::fatal_error ("Error: multiple values "                     \
                           "are not allowed for keyword \""+             \
                           std::string (key)+"\".\n");                   \
       if (parse_mode != parse_silent) {                                 \
         cvm::log ("# "+std::string (key)+" = "+                         \
                   cvm::to_str (value)+"\n");                            \
       }                                                                 \
     } else {                                                            \
                                                                         \
       if (b_found_any)                                                  \
         cvm::fatal_error ("Error: improper or missing value "           \
                           "for \""+std::string (key)+"\".\n");          \
       value = def_value;                                                \
       if (parse_mode != parse_silent) {                                 \
         cvm::log ("# "+std::string (key)+" = "+                         \
                   cvm::to_str (def_value)+" [default]\n");              \
       }                                                                 \
     }                                                                   \
                                                                         \
     return b_found_any;                                                 \
   }
 
 
 // definition of multiple-value keyword parsers
 
 #define _get_keyval_vector_(TYPE)                                       \
                                                                         \
   bool colvarparse::get_keyval (std::string const &conf,                \
                                 char const *key,                        \
                                 std::vector<TYPE> &values,              \
                                 std::vector<TYPE> const &def_values,    \
                                 Parse_Mode const parse_mode)            \
   {                                                                     \
     std::string data;                                                   \
     bool b_found = false, b_found_any = false;                          \
     size_t save_pos = 0, found_count = 0;                               \
                                                                         \
     do {                                                                \
       std::string data_this = "";                                       \
       b_found = key_lookup (conf, key, data_this, save_pos);            \
       if (b_found) {                                                    \
         if (!b_found_any)                                               \
           b_found_any = true;                                           \
         found_count++;                                                  \
         data = data_this;                                               \
       }                                                                 \
     } while (b_found);                                                  \
                                                                         \
     if (found_count > 1)                                                \
       cvm::log ("Warning: found more than one instance of \""+          \
                 std::string (key)+"\".\n");                             \
                                                                         \
     if (data.size()) {                                                  \
       std::istringstream is (data);                                     \
                                                                         \
       if (values.size() == 0) {                                         \
                                                                         \
         std::vector<TYPE> x;                                            \
         if (def_values.size())                                          \
           x = def_values;                                               \
         else                                                            \
           x.assign (1, TYPE());                                         \
                                                                         \
         for (size_t i = 0;                                              \
              ( is >> x[ ((i<x.size()) ? i : x.size()-1) ] );            \
              i++) {                                                     \
           values.push_back (x[ ((i<x.size()) ? i : x.size()-1) ]);      \
         }                                                               \
                                                                         \
       } else {                                                          \
                                                                         \
         size_t i = 0;                                                   \
         for ( ; i < values.size(); i++) {                               \
           TYPE x (values[i]);                                           \
           if (is >> x)                                                  \
             values[i] = x;                                              \
           else                                                          \
             cvm::fatal_error ("Error: in parsing \""+                   \
                               std::string (key)+"\".\n");               \
         }                                                               \
       }                                                                 \
                                                                         \
       if (parse_mode != parse_silent) {                                 \
         cvm::log ("# "+std::string (key)+" = "+                         \
                   cvm::to_str (values)+"\n");                           \
       }                                                                 \
                                                                         \
     } else {                                                            \
                                                                         \
       if (b_found_any)                                                  \
         cvm::fatal_error ("Error: improper or missing values for \""+   \
                           std::string (key)+"\".\n");                   \
                                                                         \
       for (size_t i = 0; i < values.size(); i++)                        \
         values[i] = def_values[ (i > def_values.size()) ? 0 : i ];      \
                                                                         \
       if (parse_mode != parse_silent) {                                 \
         cvm::log ("# "+std::string (key)+" = "+                         \
                   cvm::to_str (def_values)+" [default]\n");             \
       }                                                                 \
     }                                                                   \
                                                                         \
     return b_found_any;                                                 \
   }
 
 
 // single-value keyword parsers
 
 _get_keyval_scalar_ (int);
 _get_keyval_scalar_ (size_t);
 _get_keyval_scalar_string_ (std::string);
 _get_keyval_scalar_ (cvm::real);
 _get_keyval_scalar_ (cvm::rvector);
 _get_keyval_scalar_ (cvm::quaternion);
 _get_keyval_scalar_ (colvarvalue);
 
 
 // multiple-value keyword parsers
 
 _get_keyval_vector_ (int);
 _get_keyval_vector_ (size_t);
 _get_keyval_vector_ (std::string);
 _get_keyval_vector_ (cvm::real);
 _get_keyval_vector_ (cvm::rvector);
 _get_keyval_vector_ (cvm::quaternion);
 _get_keyval_vector_ (colvarvalue);
 
 
 
-bool colvarparse::get_keyval (std::string const &conf,        
-                              char const *key,                
-                              bool &value,                    
-                              bool const &def_value,          
-                              Parse_Mode const parse_mode)    
+bool colvarparse::get_keyval (std::string const &conf,
+                              char const *key,
+                              bool &value,
+                              bool const &def_value,
+                              Parse_Mode const parse_mode)
 {
   std::string data;
   bool b_found = false, b_found_any = false;
   size_t save_pos = 0, found_count = 0;
 
   do {
     std::string data_this = "";
     b_found = key_lookup (conf, key, data_this, save_pos);
     if (b_found) {
       if (!b_found_any)
         b_found_any = true;
       found_count++;
       data = data_this;
     }
   } while (b_found);
 
   if (found_count > 1)
     cvm::log ("Warning: found more than one instance of \""+
               std::string (key)+"\".\n");
 
   if (data.size()) {
     std::istringstream is (data);
     if ( (data == std::string ("on")) ||
          (data == std::string ("yes")) ||
          (data == std::string ("true")) ) {
       value = true;
     } else if ( (data == std::string ("off")) ||
               (data == std::string ("no")) ||
               (data == std::string ("false")) ) {
       value = false;
     } else
-      cvm::fatal_error ("Error: boolean values only are allowed "  
+      cvm::fatal_error ("Error: boolean values only are allowed "
                         "for \""+std::string (key)+"\".\n");
     if (parse_mode != parse_silent) {
       cvm::log ("# "+std::string (key)+" = "+
                 (value ? "on" : "off")+"\n");
     }
   } else {
 
     if (b_found_any) {
       if (parse_mode != parse_silent) {
         cvm::log ("# "+std::string (key)+" = on\n");
       }
       value = true;
     } else {
       value = def_value;
       if (parse_mode != parse_silent) {
         cvm::log ("# "+std::string (key)+" = "+
                   (def_value ? "on" : "off")+" [default]\n");
       }
     }
   }
 
   return b_found_any;
 }
 
 
 void colvarparse::add_keyword (char const *key)
 {
   for (std::list<std::string>::iterator ki = allowed_keywords.begin();
        ki != allowed_keywords.end(); ki++) {
     if (to_lower_cppstr (std::string (key)) == *ki)
       return;
   }
   // not found in the list
   //   if (cvm::debug())
   //     cvm::log ("Registering a new keyword, \""+std::string (key)+"\".\n");
   allowed_keywords.push_back (to_lower_cppstr (std::string (key)));
 }
 
 
 void colvarparse::strip_values (std::string &conf)
 {
   size_t offset = 0;
   data_begin_pos.sort();
   data_end_pos.sort();
 
   std::list<size_t>::iterator data_begin = data_begin_pos.begin();
   std::list<size_t>::iterator data_end   = data_end_pos.begin();
 
   for ( ; (data_begin != data_begin_pos.end()) &&
           (data_end   != data_end_pos.end()) ;
         data_begin++, data_end++) {
 
     //     std::cerr << "data_begin, data_end "
     //               << *data_begin << ", " << *data_end
     //               << "\n";
 
     size_t const nchars = *data_end-*data_begin;
 
     //     std::cerr << "conf[data_begin:data_end] = \""
     //               << std::string (conf, *data_begin - offset, nchars)
     //               << "\"\n";
 
     conf.erase (*data_begin - offset, nchars);
     offset += nchars;
 
     //     std::cerr << ("Stripped config = \"\n"+conf+"\"\n");
 
   }
 }
 
 
 void colvarparse::check_keywords (std::string &conf, char const *key)
 {
   if (cvm::debug())
     cvm::log ("Configuration string for \""+std::string (key)+
               "\": \"\n"+conf+"\".\n");
 
   strip_values (conf);
   // after stripping, the config string has either empty lines, or
   // lines beginning with a keyword
 
   std::string line;
   std::istringstream is (conf);
   while (std::getline (is, line)) {
     if (line.size() == 0)
       continue;
     if (line.find_first_not_of (white_space) ==
         std::string::npos)
       continue;
 
     std::string uk;
     std::istringstream line_is (line);
     line_is >> uk;
     // if (cvm::debug())
     //   cvm::log ("Checking the validity of \""+uk+"\" from line:\n" + line);
     uk = to_lower_cppstr (uk);
 
     bool found_keyword = false;
     for (std::list<std::string>::iterator ki = allowed_keywords.begin();
          ki != allowed_keywords.end(); ki++) {
       if (uk == *ki) {
         found_keyword = true;
         break;
       }
     }
     if (!found_keyword)
       cvm::fatal_error ("Error: keyword \""+uk+"\" is not supported, "
                         "or not recognized in this context.\n");
   }
 }
 
 
 std::istream & colvarparse::getline_nocomments (std::istream &is,
                                                 std::string &line,
                                                 char const delim)
 {
   std::getline (is, line, delim);
   size_t const comment = line.find ('#');
   if (comment != std::string::npos) {
     line.erase (comment);
   }
   return is;
 }
 
 
 bool colvarparse::key_lookup (std::string const &conf,
                               char const *key_in,
                               std::string &data,
                               size_t &save_pos)
 {
   // add this keyword to the register (in its camelCase version)
   add_keyword (key_in);
 
   // use the lowercase version from now on
   std::string const key (to_lower_cppstr (key_in));
 
   // "conf_lower" is only used to lookup the keyword, but its value
   // will be read from "conf", in order not to mess up file names
   std::string const conf_lower (to_lower_cppstr (conf));
 
   // by default, there is no value, unless we found one
   data = "";
 
   // when the function is invoked without save_pos, ensure that we
   // start from zero
   colvarparse::dummy_pos = 0;
 
   // start from the first occurrence of key
-  size_t pos = conf_lower.find (key, save_pos); 
-  
+  size_t pos = conf_lower.find (key, save_pos);
+
   // iterate over all instances until it finds the isolated keyword
   while (true) {
 
     if (pos == std::string::npos) {
       // no valid instance of the keyword has been found
       return false;
     }
 
     bool b_isolated_left = true, b_isolated_right = true;
 
     if (pos > 0) {
       if ( std::string ("\n"+white_space+
                         "}").find (conf[pos-1]) ==
            std::string::npos ) {
-        // none of the valid delimiting characters is on the left of key 
+        // none of the valid delimiting characters is on the left of key
         b_isolated_left = false;
       }
     }
 
     if (pos < conf.size()-key.size()-1) {
       if ( std::string ("\n"+white_space+
                         "{").find (conf[pos+key.size()]) ==
            std::string::npos ) {
-        // none of the valid delimiting characters is on the right of key 
+        // none of the valid delimiting characters is on the right of key
         b_isolated_right = false;
       }
     }
 
     // check that there are matching braces between here and the end of conf
     bool const b_not_within_block = brace_check (conf, pos);
 
     bool const b_isolated = (b_isolated_left && b_isolated_right &&
                              b_not_within_block);
-    
+
     if (b_isolated) {
       // found it
       break;
     } else {
       // try the next occurrence of key
       pos = conf_lower.find (key, pos+key.size());
     }
   }
 
   // check it is not between quotes
   //   if ( (conf.find_last_of  ("\"",
   //                             conf.find_last_of  (white_space, pos)) !=
   //         std::string::npos) &&
   //        (conf.find_first_of ("\"",
   //                             conf.find_first_of (white_space, pos)) !=
   //         std::string::npos) )
   //     return false;
 
 
   // save the pointer for a future call (when iterating over multiple
   // valid instances of the same keyword)
   save_pos = pos + key.size();
 
   // get the remainder of the line
   size_t pl = conf.rfind ("\n", pos);
   size_t line_begin = (pl == std::string::npos) ? 0 : pos;
   size_t nl = conf.find  ("\n", pos);
   size_t line_end = (nl == std::string::npos) ? conf.size() : nl;
-  std::string line (conf, line_begin, (line_end-line_begin)); 
+  std::string line (conf, line_begin, (line_end-line_begin));
 
   size_t data_begin = (to_lower_cppstr (line)).find (key) + key.size();
   data_begin = line.find_first_not_of (white_space, data_begin+1);
 
   //   size_t data_begin_absolute = data_begin + line_begin;
   //   size_t data_end_absolute   = data_begin;
 
   if (data_begin != std::string::npos) {
 
     size_t data_end = line.find_last_not_of (white_space) + 1;
     data_end = (data_end == std::string::npos) ? line.size() : data_end;
     //     data_end_absolute = data_end + line_begin;
 
     if (line.find ('{', data_begin) != std::string::npos) {
 
       size_t brace_count = 1;
       size_t brace = line.find ('{', data_begin);  // start from the first opening brace
 
       while (brace_count > 0) {
 
         // find the matching closing brace
         brace = line.find_first_of ("{}", brace+1);
         while (brace == std::string::npos) {
           // add a new line
           if (line_end >= conf.size()) {
             cvm::fatal_error ("Parse error: reached the end while "
                               "looking for closing brace; until now "
                               "the following was parsed: \"\n"+
                               line+"\".\n");
             return false;
           }
           size_t const old_end = line.size();
           //           data_end_absolute += old_end+1;
 
           line_begin = line_end;
           nl = conf.find ('\n', line_begin+1);
-          if (nl == std::string::npos) 
+          if (nl == std::string::npos)
             line_end = conf.size();
-          else 
+          else
             line_end = nl;
           line.append (conf, line_begin, (line_end-line_begin));
 
           brace = line.find_first_of ("{}", old_end);
         }
 
         if (line[brace] == '{') brace_count++;
         if (line[brace] == '}') brace_count--;
       }
 
       // set data_begin after the opening brace
       data_begin = line.find_first_of ('{', data_begin) + 1;
       data_begin = line.find_first_not_of (white_space,
                                            data_begin);
       // set data_end before the closing brace
       data_end = brace;
       data_end = line.find_last_not_of (white_space+"}",
                                         data_end) + 1;
       //       data_end_absolute = line_end;
 
       if (data_end > line.size())
         data_end = line.size();
     }
 
     data.append (line, data_begin, (data_end-data_begin));
 
     if (data.size() && save_delimiters) {
       data_begin_pos.push_back (conf.find (data, pos+key.size()));
       data_end_pos.push_back   (data_begin_pos.back()+data.size());
       //       std::cerr << "key = " << key << ", data = \""
       //                 << data << "\", data_begin, data_end = "
       //                 << data_begin_pos.back() << ", " << data_end_pos.back()
       //                 << "\n";
     }
   }
-  
+
   save_pos = line_end;
 
   return true;
 }
 
 
 std::istream & operator>> (std::istream &is, colvarparse::read_block const &rb)
 {
   size_t start_pos = is.tellg();
   std::string read_key, next;
 
   if ( !(is >> read_key) || !(read_key == rb.key) ||
        !(is >> next) ) {
     // the requested keyword has not been found, or it is not possible
     // to read data after it
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
     return is;
   }
 
   if (next != "{") {
     (*rb.data) = next;
     return is;
   }
 
   size_t brace_count = 1;
   std::string line;
   while (colvarparse::getline_nocomments (is, line)) {
     size_t br = 0, br_old;
     while ( (br = line.find_first_of ("{}", br)) != std::string::npos) {
       if (line[br] == '{') brace_count++;
       if (line[br] == '}') brace_count--;
       br_old = br;
       br++;
     }
     if (brace_count) (*rb.data).append (line + "\n");
     else {
       (*rb.data).append (line, 0, br_old);
       break;
     }
   }
   if (brace_count)  {
     // end-of-file reached
     // restore initial position
     is.clear();
     is.seekg (start_pos, std::ios::beg);
     is.setstate (std::ios::failbit);
   }
   return is;
 }
 
 
 bool colvarparse::brace_check (std::string const &conf,
                                size_t const start_pos)
 {
   size_t brace_count = 0;
   size_t brace = start_pos;
   while ( (brace = conf.find_first_of ("{}", brace)) != std::string::npos) {
     if (conf[brace] == '{') brace_count++;
     if (conf[brace] == '}') brace_count--;
     brace++;
   }
 
   if (brace_count != 0)
     return false;
   else
     return true;
 }
 
 
 // Emacs
 // Local Variables:
 // mode: C++
 // End:
diff --git a/lib/colvars/colvarparse.h b/lib/colvars/colvarparse.h
index e7e1d9627..d3b3968a7 100644
--- a/lib/colvars/colvarparse.h
+++ b/lib/colvars/colvarparse.h
@@ -1,201 +1,201 @@
 #ifndef COLVARPARSE_H
 #define COLVARPARSE_H
 
 #include <cstring>
 #include <string>
 
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 
 
 /// \file colvarparse.h Parsing functions for collective variables
 
 
 /// \brief Base class containing parsing functions; all objects which
 /// need to parse input inherit from this
 class colvarparse {
 
 protected:
 
   /// \brief List of legal keywords for this object: this is updated
   /// by each call to colvarparse::get_keyval() or
   /// colvarparse::key_lookup()
   std::list<std::string> allowed_keywords;
 
   /// \brief List of delimiters for the values of each keyword in the
   /// configuration string; all keywords will be stripped of their
   /// values before the keyword check is performed
   std::list<size_t>      data_begin_pos;
 
   /// \brief List of delimiters for the values of each keyword in the
   /// configuration string; all keywords will be stripped of their
   /// values before the keyword check is performed
   std::list<size_t>      data_end_pos;
 
   /// \brief Whether or not to accumulate data_begin_pos and
   /// data_end_pos in key_lookup(); it may be useful to disable
   /// this after the constructor is called, because other files may be
   /// read (e.g. restart) that would mess up with the registry; in any
   /// case, nothing serious happens until check_keywords() is invoked
   /// (which should happen only right after construction)
   bool save_delimiters;
 
   /// \brief Add a new valid keyword to the list
   void add_keyword (char const *key);
 
   /// \brief Remove all the values from the config string
   void strip_values (std::string &conf);
 
 public:
 
   inline colvarparse()
     : save_delimiters (true)
   {}
 
   /// How a keyword is parsed in a string
-  enum Parse_Mode { 
+  enum Parse_Mode {
     /// \brief (default) Read the first instance of a keyword (if
     /// any), report its value, and print a warning when there is more
     /// than one
-    parse_normal, 
+    parse_normal,
     /// \brief Like parse_normal, but don't send any message to the log
     /// (useful e.g. in restart files when such messages are very
     /// numerous and redundant)
-    parse_silent 
+    parse_silent
   };
 
   /// \fn get_keyval bool const get_keyval (std::string const &conf,
   /// char const *key, _type_ &value, _type_ const &def_value,
   /// Parse_Mode const parse_mode) \brief Helper function to parse
   /// keywords in the configuration and get their values
   ///
   /// In normal circumstances, you should use either version the
   /// get_keyval function.  Both of them look for the C string "key"
   /// in the C++ string "conf", and assign the corresponding value (if
   /// available) to the variable "value" (first version), or assign as
   /// many values as found to the vector "values" (second version).
   ///
   /// If "key" is found but no value is associated to it, the default
   /// value is provided (either one copy or as many copies as the
   /// current length of the vector "values" specifies).  A message
   /// will print, unless parse_mode is equal to parse_silent.  The
   /// return value of both forms of get_keyval is true if "key" is
   /// found (with or without value), and false when "key" is absent in
   /// the string "conf".  If there is more than one instance of the
   /// keyword, a warning will be raised; instead, to loop over
   /// multiple instances key_lookup() should be invoked directly.
   ///
   /// If you introduce a new data type, add two new instances of this
   /// functions, or insert this type in the \link colvarvalue \endlink
   /// wrapper class (colvarvalue.h).
 
 #define _get_keyval_scalar_proto_(_type_,_def_value_)           \
   bool get_keyval (std::string const &conf,                     \
                    char const *key,                             \
                    _type_ &value,                               \
                    _type_ const &def_value = _def_value_,       \
                    Parse_Mode const parse_mode = parse_normal)
 
     _get_keyval_scalar_proto_ (int, (int)0);
     _get_keyval_scalar_proto_ (size_t, (size_t)0);
     _get_keyval_scalar_proto_ (std::string, std::string (""));
     _get_keyval_scalar_proto_ (cvm::real, (cvm::real)0.0);
     _get_keyval_scalar_proto_ (cvm::rvector, cvm::rvector());
     _get_keyval_scalar_proto_ (cvm::quaternion, cvm::quaternion());
     _get_keyval_scalar_proto_ (colvarvalue, colvarvalue (colvarvalue::type_notset));
     _get_keyval_scalar_proto_ (bool, false);
 
 #define _get_keyval_vector_proto_(_type_,_def_value_)                   \
   bool get_keyval (std::string const &conf,                             \
                    char const *key,                                     \
                    std::vector<_type_> &values,                         \
                    std::vector<_type_> const &def_values =              \
                    std::vector<_type_> (0, static_cast<_type_>(_def_value_)),                \
                    Parse_Mode const parse_mode = parse_normal)
-  
+
     _get_keyval_vector_proto_ (int, 0);
     _get_keyval_vector_proto_ (size_t, 0);
     _get_keyval_vector_proto_ (std::string, std::string (""));
     _get_keyval_vector_proto_ (cvm::real, 0.0);
     _get_keyval_vector_proto_ (cvm::rvector, cvm::rvector());
     _get_keyval_vector_proto_ (cvm::quaternion, cvm::quaternion());
     _get_keyval_vector_proto_ (colvarvalue, colvarvalue (colvarvalue::type_notset));
 
 
   /// \brief Check that all the keywords within "conf" are in the list
   /// of allowed keywords; this will invoke strip_values() first and
   /// then loop over all words
   void check_keywords (std::string &conf, char const *key);
 
 
   /// \brief Return a lowercased copy of the string
   static inline std::string to_lower_cppstr (std::string const &in)
   {
     std::string out = "";
     for (size_t i = 0; i < in.size(); i++) {
       out.append (1, (char) ::tolower (in[i]) );
     }
     return out;
   }
 
   /// \brief Helper class to read a block of the type "key { ... }"
   /// from a stream and store it in a string
   ///
   /// Useful on restarts, where the file is too big to be loaded in a
   /// string by key_lookup; it can only check that the keyword is
   /// correct and the block is properly delimited by braces, not
   /// skipping other blocks
   class read_block {
 
     std::string const   key;
     std::string * const data;
 
   public:
     inline read_block (std::string const &key_in, std::string &data_in)
       : key (key_in), data (&data_in)
     {}
     inline ~read_block() {}
     friend std::istream & operator >> (std::istream &is, read_block const &rb);
   };
 
 
   /// Accepted white space delimiters, used in key_lookup()
   static std::string const white_space;
 
   /// \brief Low-level function for parsing configuration strings;
   /// automatically adds the requested keywords to the list of valid
   /// ones.  \param conf the content of the configuration file or one
   /// of its blocks \param key the keyword to search in "conf" \param
   /// data (optional) holds the string provided after "key", if any
   /// \param save_pos (optional) stores the position of the keyword
   /// within "conf", useful when doing multiple calls \param
-  /// save_delimiters (optional) 
+  /// save_delimiters (optional)
   bool key_lookup (std::string const &conf,
                    char const *key,
                    std::string &data = dummy_string,
                    size_t &save_pos = dummy_pos);
 
   /// Used as a default argument by key_lookup
   static std::string dummy_string;
   /// Used as a default argument by key_lookup
   static size_t dummy_pos;
 
   /// \brief Works as std::getline() but also removes everything
   /// between a comment character and the following newline
   static std::istream & getline_nocomments (std::istream &is,
                                             std::string &s,
                                             char const delim = '\n');
 
   /// Check if the content of the file has matching braces
   bool brace_check (std::string const &conf,
                     size_t const start_pos = 0);
 
 };
 
 
 #endif
 
 // Emacs
 // Local Variables:
 // mode: C++
 // End:
diff --git a/lib/colvars/colvarproxy.h b/lib/colvars/colvarproxy.h
index 43f3233de..c1416f13b 100644
--- a/lib/colvars/colvarproxy.h
+++ b/lib/colvars/colvarproxy.h
@@ -1,153 +1,153 @@
 #ifndef COLVARPROXY_H
 #define COLVARPROXY_H
 
 
 
 #include "colvarmodule.h"
 
 
 /// \brief Interface class between the collective variables module and
 /// the simulation program
 
 class colvarproxy {
 
 public:
 
   /// Pointer to the instance of colvarmodule
   colvarmodule *colvars;
 
   /// Default destructor
   virtual inline ~colvarproxy() {}
 
 
   // **************** SYSTEM-WIDE PHYSICAL QUANTITIES ****************
 
   /// \brief Value of the unit for atomic coordinates with respect to
   /// angstroms (used by some variables for hard-coded default values)
   virtual cvm::real unit_angstrom() = 0;
 
   /// \brief Boltzmann constant
   virtual cvm::real boltzmann() = 0;
 
   /// \brief Temperature of the simulation (K)
   virtual cvm::real temperature() = 0;
 
   /// \brief Time step of the simulation (fs)
   virtual cvm::real dt() = 0;
 
   /// \brief Pseudo-random number with Gaussian distribution
   virtual cvm::real rand_gaussian (void) = 0;
 
 
   // **************** SIMULATION PARAMETERS ****************
 
   /// \brief Prefix to be used for input files (restarts, not
   /// configuration)
   virtual std::string input_prefix() = 0;
 
   /// \brief Prefix to be used for output restart files
   virtual std::string restart_output_prefix() = 0;
 
   /// \brief Prefix to be used for output files (final system
   /// configuration)
   virtual std::string output_prefix() = 0;
 
   /// \brief Restarts will be fritten each time this number of steps has passed
   virtual size_t restart_frequency() = 0;
 
 
 
   // **************** ACCESS ATOMIC DATA ****************
 
   /// Pass restraint energy value for current timestep to MD engine
   virtual void add_energy (cvm::real energy) = 0;
 
   /// Tell the proxy whether system forces are needed (may not always be available)
   virtual void request_system_force (bool yesno) = 0;
 
 
 
   // **************** PERIODIC BOUNDARY CONDITIONS ****************
 
   /// \brief Get the PBC-aware distance vector between two positions
   virtual cvm::rvector position_distance (cvm::atom_pos const &pos1,
                                           cvm::atom_pos const &pos2) = 0;
 
   /// \brief Get the PBC-aware square distance between two positions;
   /// may be implemented independently from position_distance() for optimization purposes
   virtual cvm::real position_dist2 (cvm::atom_pos const &pos1,
                                     cvm::atom_pos const &pos2);
 
   /// \brief Get the closest periodic image to a reference position
   /// \param pos The position to look for the closest periodic image
-  /// \param ref_pos The reference position 
+  /// \param ref_pos The reference position
   virtual void select_closest_image (cvm::atom_pos &pos,
                                      cvm::atom_pos const &ref_pos) = 0;
 
   /// \brief Perform select_closest_image() on a set of atomic positions
   ///
   /// After that, distance vectors can then be calculated directly,
   /// without using position_distance()
   void select_closest_images (std::vector<cvm::atom_pos> &pos,
                               cvm::atom_pos const &ref_pos);
 
 
 
   // **************** INPUT/OUTPUT ****************
 
   /// Print a message to the main log
   virtual void log (std::string const &message) = 0;
 
   /// Print a message to the main log and exit with error code
   virtual void fatal_error (std::string const &message) = 0;
 
   /// Print a message to the main log and exit normally
   virtual void exit (std::string const &message) = 0;
 
   /// \brief Read atom identifiers from a file \param filename name of
   /// the file (usually a PDB) \param atoms array to which atoms read
   /// from "filename" will be appended \param pdb_field (optiona) if
   /// "filename" is a PDB file, use this field to determine which are
   /// the atoms to be set
   virtual void load_atoms (char const *filename,
                            std::vector<cvm::atom> &atoms,
                            std::string const pdb_field,
                            double const pdb_field_value = 0.0) {}
 
   /// \brief Load the coordinates for a group of atoms from a file
   /// (usually a PDB); if "pos" is already allocated, the number of its
   /// elements must match the number of atoms in "filename"
   virtual void load_coords (char const *filename,
                             std::vector<cvm::atom_pos> &pos,
                             const std::vector<int> &indices,
                             std::string const pdb_field,
                             double const pdb_field_value = 0.0) = 0;
 
   /// \brief Rename the given file, before overwriting it
   virtual void backup_file (char const *filename) {}
 
 };
 
 
 inline void colvarproxy::select_closest_images (std::vector<cvm::atom_pos> &pos,
                                                 cvm::atom_pos const &ref_pos)
 {
   for (std::vector<cvm::atom_pos>::iterator pi = pos.begin();
        pi != pos.end(); pi++) {
     select_closest_image (*pi, ref_pos);
   }
 }
 
 inline cvm::real colvarproxy::position_dist2 (cvm::atom_pos const &pos1,
                                               cvm::atom_pos const &pos2)
 {
   return (position_distance (pos1, pos2)).norm2();
 }
 
 #endif
 
 
 // Emacs
 // Local Variables:
 // mode: C++
 // End:
diff --git a/lib/colvars/colvartypes.h b/lib/colvars/colvartypes.h
index fa18310ac..4c285631a 100644
--- a/lib/colvars/colvartypes.h
+++ b/lib/colvars/colvartypes.h
@@ -1,1098 +1,1098 @@
 #ifndef COLVARTYPES_H
 #define COLVARTYPES_H
 
 #include <cmath>
 
 #ifndef PI
 #define PI 3.14159265358979323846
 #endif
 
 // ----------------------------------------------------------------------
 /// Linear algebra functions and data types used in the collective
 /// variables implemented so far
 // ----------------------------------------------------------------------
 
 
 /// 1-dimensional vector of real numbers with three components
 class colvarmodule::rvector {
 
 public:
 
   cvm::real x, y, z;
-     
+
   inline rvector()
     : x (0.0), y (0.0), z (0.0)
   {}
 
   inline rvector (cvm::real const &x_i,
                   cvm::real const &y_i,
                   cvm::real const &z_i)
     : x (x_i), y (y_i), z (z_i)
   {}
 
   inline rvector (cvm::real v)
     : x (v), y (v), z (v)
   {}
 
   /// \brief Set all components to a scalar value
   inline void set (cvm::real const value = 0.0) {
     x = y = z = value;
   }
 
   /// \brief Set all components to zero
   inline void reset() {
     x = y = z = 0.0;
   }
 
   /// \brief Access cartesian components by index
   inline cvm::real & operator [] (int const &i) {
     return (i == 0) ? x : (i == 1) ? y : (i == 2) ? z : x;
   }
 
   /// \brief Access cartesian components by index
   inline cvm::real const & operator [] (int const &i) const {
     return (i == 0) ? x : (i == 1) ? y : (i == 2) ? z : x;
   }
 
 
-  inline cvm::rvector & operator = (cvm::real const &v) 
+  inline cvm::rvector & operator = (cvm::real const &v)
   {
     x = v;
     y = v;
     z = v;
     return *this;
   }
 
-  inline void operator += (cvm::rvector const &v) 
+  inline void operator += (cvm::rvector const &v)
   {
     x += v.x;
     y += v.y;
     z += v.z;
   }
 
-  inline void operator -= (cvm::rvector const &v) 
+  inline void operator -= (cvm::rvector const &v)
   {
     x -= v.x;
     y -= v.y;
     z -= v.z;
   }
 
-  inline void operator *= (cvm::real const &v) 
+  inline void operator *= (cvm::real const &v)
   {
     x *= v;
     y *= v;
     z *= v;
   }
 
-  inline void operator /= (cvm::real const& v) 
+  inline void operator /= (cvm::real const& v)
   {
     x /= v;
     y /= v;
     z /= v;
   }
 
   inline cvm::real norm2() const
   {
     return (x*x + y*y + z*z);
   }
 
   inline cvm::real norm() const
   {
     return std::sqrt (this->norm2());
   }
 
   inline cvm::rvector unit() const
   {
     const cvm::real n = this->norm();
     return (n > 0. ? cvm::rvector (x, y, z)/n : cvm::rvector (1., 0., 0.));
   }
 
   static inline size_t output_width (size_t const &real_width)
   {
     return 3*real_width + 10;
   }
 
 
-  static inline cvm::rvector outer (cvm::rvector const &v1, cvm::rvector const &v2) 
+  static inline cvm::rvector outer (cvm::rvector const &v1, cvm::rvector const &v2)
   {
     return cvm::rvector ( v1.y*v2.z - v2.y*v1.z,
                          -v1.x*v2.z + v2.x*v1.z,
                           v1.x*v2.y - v2.x*v1.y);
   }
 
-  friend inline cvm::rvector operator - (cvm::rvector const &v) 
+  friend inline cvm::rvector operator - (cvm::rvector const &v)
   {
     return cvm::rvector (-v.x, -v.y, -v.z);
   }
 
-  friend inline int operator == (cvm::rvector const &v1, cvm::rvector const &v2) 
+  friend inline int operator == (cvm::rvector const &v1, cvm::rvector const &v2)
   {
     return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z);
   }
 
-  friend inline int operator != (cvm::rvector const &v1, cvm::rvector const &v2) 
+  friend inline int operator != (cvm::rvector const &v1, cvm::rvector const &v2)
   {
     return (v1.x != v2.x) || (v1.y != v2.y) || (v1.z != v2.z);
   }
 
-  friend inline cvm::rvector operator + (cvm::rvector const &v1, cvm::rvector const &v2) 
+  friend inline cvm::rvector operator + (cvm::rvector const &v1, cvm::rvector const &v2)
   {
     return cvm::rvector (v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
   }
-  friend inline cvm::rvector operator - (cvm::rvector const &v1, cvm::rvector const &v2) 
+  friend inline cvm::rvector operator - (cvm::rvector const &v1, cvm::rvector const &v2)
   {
     return cvm::rvector (v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
   }
 
-  friend inline cvm::real operator * (cvm::rvector const &v1, cvm::rvector const &v2) 
+  friend inline cvm::real operator * (cvm::rvector const &v1, cvm::rvector const &v2)
   {
     return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
   }
 
-  friend inline cvm::rvector operator * (cvm::real const &a, cvm::rvector const &v) 
+  friend inline cvm::rvector operator * (cvm::real const &a, cvm::rvector const &v)
   {
     return cvm::rvector (a*v.x, a*v.y, a*v.z);
   }
 
-  friend inline cvm::rvector operator * (cvm::rvector const &v, cvm::real const &a) 
+  friend inline cvm::rvector operator * (cvm::rvector const &v, cvm::real const &a)
   {
     return cvm::rvector (a*v.x, a*v.y, a*v.z);
   }
 
-  friend inline cvm::rvector operator / (cvm::rvector const &v, cvm::real const &a) 
+  friend inline cvm::rvector operator / (cvm::rvector const &v, cvm::real const &a)
   {
     return cvm::rvector (v.x/a, v.y/a, v.z/a);
   }
-     
+
 
 };
 
 
 
 /// \brief Arbitrary size array (one dimensions) suitable for linear
 /// algebra operations (i.e. for floating point numbers it can be used
 /// with library functions)
 template <class T, size_t const length> class colvarmodule::vector1d
 {
 protected:
 
   /// Underlying C-array
   T *array;
 
 public:
 
   /// Length of the array
   inline size_t size()
   {
     return length;
   }
- 
+
   /// Default constructor
   inline vector1d (T const &t = T())
   {
     array = new T[length];
     reset();
   }
 
   /// Set all elements to zero
   inline void reset()
   {
     for (size_t i = 0; i < length; i++) {
       array[i] = T (0.0);
     }
   }
 
   /// Constructor from a 1-d C array
   inline vector1d (T const *v)
   {
     array = new T[length];
     for (size_t i = 0; i < length; i++) {
       array[i] = v[i];
     }
   }
 
   /// Copy constructor
   inline vector1d (vector1d<T, length> const &v)
   {
     array = new T[length];
     for (size_t i = 0; i < length; i++) {
       array[i] = v.array[i];
     }
   }
 
   /// Assignment
   inline vector1d<T, length> & operator = (vector1d<T, length> const &v)
   {
     for (size_t i = 0; i < length; i++) {
       this->array[i] = v.array[i];
     }
     return *this;
   }
 
   /// Destructor
   inline ~vector1d() {
     delete [] array;
   }
 
   /// Return the 1-d C array
   inline T *c_array() { return array; }
 
   /// Return the 1-d C array
   inline operator T *() { return array; }
 
   /// Inner product
   inline friend T operator * (vector1d<T, length> const &v1,
                               vector1d<T, length> const &v2)
   {
     T prod (0.0);
     for (size_t i = 0; i < length; i++) {
       prod += v1.array[i] * v2.array[i];
     }
     return prod;
   }
 
-  /// Formatted output 
+  /// Formatted output
   friend std::ostream & operator << (std::ostream &os,
                                      vector1d<T, length> const &v)
   {
     std::streamsize const w = os.width();
     std::streamsize const p = os.precision();
 
     os << "( ";
     for (size_t i = 0; i < length-1; i++) {
       os.width (w); os.precision (p);
       os << v.array[i] << " , ";
     }
     os.width (w); os.precision (p);
     os << v.array[length-1] << " )";
     return os;
   }
 
 };
 
 
 
 /// \brief Arbitrary size array (two dimensions) suitable for linear
 /// algebra operations (i.e. for floating point numbers it can be used
 /// with library functions)
 template <class T,
           size_t const outer_length,
           size_t const inner_length> class colvarmodule::matrix2d
 {
 protected:
 
   /// Underlying C array
   T **array;
 
 public:
 
   /// Allocation routine, used by all constructors
   inline void alloc() {
     array = new T * [outer_length];
     for (size_t i = 0; i < outer_length; i++) {
       array[i] = new T [inner_length];
     }
   }
 
   /// Set all elements to zero
   inline void reset()
   {
     for (size_t i = 0; i < outer_length; i++) {
       for (size_t j = 0; j < inner_length; j++) {
         array[i][j] = T (0.0);
       }
     }
   }
 
   /// Default constructor
   inline matrix2d()
   {
     this->alloc();
     reset();
   }
- 
+
   /// Constructor from a 2-d C array
   inline matrix2d (T const **m)
   {
     this->alloc();
     for (size_t i = 0; i < outer_length; i++) {
       for (size_t j = 0; j < inner_length; j++)
         array[i][j] = m[i][j];
     }
   }
 
   /// Copy constructor
   inline matrix2d (matrix2d<T, outer_length, inner_length> const &m)
   {
     this->alloc();
     for (size_t i = 0; i < outer_length; i++) {
       for (size_t j = 0; j < inner_length; j++)
         this->array[i][j] = m.array[i][j];
     }
   }
 
   /// Assignment
   inline matrix2d<T, outer_length, inner_length> &
   operator = (matrix2d<T, outer_length, inner_length> const &m)
   {
     for (size_t i = 0; i < outer_length; i++) {
       for (size_t j = 0; j < inner_length; j++)
         this->array[i][j] = m.array[i][j];
     }
     return *this;
   }
 
   /// Destructor
   inline ~matrix2d() {
     for (size_t i = 0; i < outer_length; i++) {
       delete [] array[i];
     }
     delete [] array;
   }
 
   /// Return the 2-d C array
   inline T **c_array() { return array; }
 
   /// Return the 2-d C array
   inline operator T **() { return array; }
 
 //   /// Matrix addi(c)tion
 //   inline friend matrix2d<T, outer_length, inner_length>
 //   operator + (matrix2d<T, outer_length, inner_length> const &mat1,
 //               matrix2d<T, outer_length, inner_length> const &mat2) {
 //     matrix2d<T, outer_length, inner_length> sum;
 //     for (size_t i = 0; i < outer_length; i++) {
 //       for (size_t j = 0; j < inner_length; j++) {
 //         sum[i][j] = mat1[i][j] + mat2[i][j];
 //       }
 //     }
 //   }
 
 //   /// Matrix subtraction
 //   inline friend matrix2d<T, outer_length, inner_length>
 //   operator - (matrix2d<T, outer_length, inner_length> const &mat1,
 //               matrix2d<T, outer_length, inner_length> const &mat2) {
 //     matrix2d<T, outer_length, inner_length> sum;
 //     for (size_t i = 0; i < outer_length; i++) {
 //       for (size_t j = 0; j < inner_length; j++) {
 //         sum[i][j] = mat1[i][j] - mat2[i][j];
 //       }
 //     }
 //   }
 
-  /// Formatted output 
+  /// Formatted output
   friend std::ostream & operator << (std::ostream &os,
                                      matrix2d<T, outer_length, inner_length> const &m)
   {
     std::streamsize const w = os.width();
     std::streamsize const p = os.precision();
 
     os << "(";
     for (size_t i = 0; i < outer_length; i++) {
       os << " ( ";
       for (size_t j = 0; j < inner_length-1; j++) {
         os.width (w);
         os.precision (p);
         os << m.array[i][j] << " , ";
       }
       os.width (w);
       os.precision (p);
       os << m.array[i][inner_length-1] << " )";
     }
 
     os << " )";
     return os;
   }
 
 };
 
 
 /// \brief 2-dimensional array of real numbers with three components
 /// along each dimension (works with colvarmodule::rvector)
 class colvarmodule::rmatrix
   : public colvarmodule::matrix2d<colvarmodule::real, 3, 3> {
 private:
 
 public:
 
   /// Return the xx element
   inline cvm::real & xx() { return array[0][0]; }
   /// Return the xy element
   inline cvm::real & xy() { return array[0][1]; }
   /// Return the xz element
   inline cvm::real & xz() { return array[0][2]; }
   /// Return the yx element
   inline cvm::real & yx() { return array[1][0]; }
   /// Return the yy element
   inline cvm::real & yy() { return array[1][1]; }
   /// Return the yz element
   inline cvm::real & yz() { return array[1][2]; }
   /// Return the zx element
   inline cvm::real & zx() { return array[2][0]; }
   /// Return the zy element
   inline cvm::real & zy() { return array[2][1]; }
   /// Return the zz element
   inline cvm::real & zz() { return array[2][2]; }
 
   /// Return the xx element
   inline cvm::real xx() const { return array[0][0]; }
   /// Return the xy element
   inline cvm::real xy() const { return array[0][1]; }
   /// Return the xz element
   inline cvm::real xz() const { return array[0][2]; }
   /// Return the yx element
   inline cvm::real yx() const { return array[1][0]; }
   /// Return the yy element
   inline cvm::real yy() const { return array[1][1]; }
   /// Return the yz element
   inline cvm::real yz() const { return array[1][2]; }
   /// Return the zx element
   inline cvm::real zx() const { return array[2][0]; }
   /// Return the zy element
   inline cvm::real zy() const { return array[2][1]; }
   /// Return the zz element
   inline cvm::real zz() const { return array[2][2]; }
 
   /// Constructor from a 2-d C array
-  inline rmatrix (cvm::real const **m) 
-    : cvm::matrix2d<cvm::real, 3, 3> (m) 
+  inline rmatrix (cvm::real const **m)
+    : cvm::matrix2d<cvm::real, 3, 3> (m)
   {}
 
   /// Default constructor
-  inline rmatrix() 
+  inline rmatrix()
     : cvm::matrix2d<cvm::real, 3, 3>()
   {}
 
-  /// Constructor component by component 
+  /// Constructor component by component
   inline rmatrix (cvm::real const &xxi,
                   cvm::real const &xyi,
                   cvm::real const &xzi,
                   cvm::real const &yxi,
                   cvm::real const &yyi,
                   cvm::real const &yzi,
                   cvm::real const &zxi,
                   cvm::real const &zyi,
-                  cvm::real const &zzi) 
+                  cvm::real const &zzi)
     : cvm::matrix2d<cvm::real, 3, 3>()
   {
     this->xx() = xxi;
     this->xy() = xyi;
     this->xz() = xzi;
     this->yx() = yxi;
     this->yy() = yyi;
     this->yz() = yzi;
     this->zx() = zxi;
     this->zy() = zyi;
     this->zz() = zzi;
   }
 
   /// Destructor
   inline ~rmatrix()
-  {}    
+  {}
 
   /// Return the determinant
   inline cvm::real determinant() const
   {
     return
       (  xx() * (yy()*zz() - zy()*yz()))
       - (yx() * (xy()*zz() - zy()*xz()))
       + (zx() * (xy()*yz() - yy()*xz()));
   }
 
   inline cvm::rmatrix transpose() const
   {
     return cvm::rmatrix (this->xx(),
                          this->yx(),
                          this->zx(),
                          this->xy(),
                          this->yy(),
                          this->zy(),
                          this->xz(),
                          this->yz(),
                          this->zz());
   }
 
   friend cvm::rvector operator * (cvm::rmatrix const &m, cvm::rvector const &r);
 
   //   friend inline cvm::rmatrix const operator * (cvm::rmatrix const &m1, cvm::rmatrix const &m2) {
   //     return cvm::rmatrix (m1.xx()*m2.xx() + m1.xy()*m2.yx() + m1.xz()*m2.yz(),
   //                     m1.xx()*m2.xy() + m1.xy()*m2.yy() + m1.xz()*m2.zy(),
   //                     m1.xx()*m2.xz() + m1.xy()*m2.yz() + m1.xz()*m2.zz(),
   //                     m1.yx()*m2.xx() + m1.yy()*m2.yx() + m1.yz()*m2.yz(),
   //                     m1.yx()*m2.xy() + m1.yy()*m2.yy() + m1.yz()*m2.yy(),
   //                     m1.yx()*m2.xz() + m1.yy()*m2.yz() + m1.yz()*m2.yz(),
   //                     m1.zx()*m2.xx() + m1.zy()*m2.yx() + m1.zz()*m2.yz(),
   //                     m1.zx()*m2.xy() + m1.zy()*m2.yy() + m1.zz()*m2.yy(),
   //                     m1.zx()*m2.xz() + m1.zy()*m2.yz() + m1.zz()*m2.yz());
   //   }
 
 };
 
-                    
+
 inline cvm::rvector operator * (cvm::rmatrix const &m,
                                 cvm::rvector const &r)
 {
   return cvm::rvector (m.xx()*r.x + m.xy()*r.y + m.xz()*r.z,
                        m.yx()*r.x + m.yy()*r.y + m.yz()*r.z,
                        m.zx()*r.x + m.zy()*r.y + m.zz()*r.z);
 }
 
 
 /// Numerical recipes diagonalization
 void jacobi (cvm::real **a, int n, cvm::real d[], cvm::real **v, int *nrot);
 
 /// Eigenvector sort
 void eigsrt (cvm::real d[], cvm::real **v, int n);
 
 /// Transpose the matrix
 void transpose (cvm::real **v, int n);
 
 
 
 
 /// \brief 1-dimensional vector of real numbers with four components and
 /// a quaternion algebra
 class colvarmodule::quaternion {
 
 public:
 
   cvm::real q0, q1, q2, q3;
 
   /// Constructor from a 3-d vector
   inline quaternion (cvm::real const &x, cvm::real const &y, cvm::real const &z)
     : q0 (0.0), q1 (x), q2 (y), q3 (z)
   {}
 
   /// Constructor component by component
   inline quaternion (cvm::real const qv[4])
     : q0 (qv[0]), q1 (qv[1]), q2 (qv[2]), q3 (qv[3])
   {}
 
   /// Constructor component by component
   inline quaternion (cvm::real const &q0i,
                      cvm::real const &q1i,
                      cvm::real const &q2i,
                      cvm::real const &q3i)
     : q0 (q0i), q1 (q1i), q2 (q2i), q3 (q3i)
   {}
 
   /// "Constructor" after Euler angles (in radians)
   ///
   /// http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
   inline void set_from_euler_angles (cvm::real const &phi_in,
                                      cvm::real const &theta_in,
                                      cvm::real const &psi_in)
   {
     q0 = ( (std::cos (phi_in/2.0)) * (std::cos (theta_in/2.0)) * (std::cos (psi_in/2.0)) +
            (std::sin (phi_in/2.0)) * (std::sin (theta_in/2.0)) * (std::sin (psi_in/2.0)) );
 
     q1 = ( (std::sin (phi_in/2.0)) * (std::cos (theta_in/2.0)) * (std::cos (psi_in/2.0)) -
            (std::cos (phi_in/2.0)) * (std::sin (theta_in/2.0)) * (std::sin (psi_in/2.0)) );
 
     q2 = ( (std::cos (phi_in/2.0)) * (std::sin (theta_in/2.0)) * (std::cos (psi_in/2.0)) +
            (std::sin (phi_in/2.0)) * (std::cos (theta_in/2.0)) * (std::sin (psi_in/2.0)) );
 
     q3 = ( (std::cos (phi_in/2.0)) * (std::cos (theta_in/2.0)) * (std::sin (psi_in/2.0)) -
            (std::sin (phi_in/2.0)) * (std::sin (theta_in/2.0)) * (std::cos (psi_in/2.0)) );
   }
 
   /// \brief Default constructor
   inline quaternion()
   {
     reset();
   }
 
   /// \brief Set all components to a scalar
   inline void set (cvm::real const value = 0.0)
   {
     q0 = q1 = q2 = q3 = value;
   }
 
   /// \brief Set all components to zero (null quaternion)
   inline void reset()
   {
     q0 = q1 = q2 = q3 = 0.0;
   }
 
   /// \brief Set the q0 component to 1 and the others to 0 (quaternion
   /// representing no rotation)
   inline void reset_rotation()
   {
     q0 = 1.0;
     q1 = q2 = q3 = 0.0;
   }
 
   /// Tell the number of characters required to print a quaternion, given that of a real number
   static inline size_t output_width (size_t const &real_width)
   {
     return 4*real_width + 13;
   }
 
   /// \brief Formatted output operator
   friend std::ostream & operator << (std::ostream &os, cvm::quaternion const &q);
   /// \brief Formatted input operator
   friend std::istream & operator >> (std::istream &is, cvm::quaternion &q);
 
   /// Access the quaternion as a 4-d array (return a reference)
   inline cvm::real & operator [] (int const &i) {
     switch (i) {
     case 0:
       return this->q0;
     case 1:
       return this->q1;
     case 2:
       return this->q2;
     case 3:
       return this->q3;
     default:
       cvm::fatal_error ("Error: incorrect quaternion component.\n");
       return q0;
     }
   }
 
   /// Access the quaternion as a 4-d array (return a value)
   inline cvm::real operator [] (int const &i) const {
     switch (i) {
     case 0:
       return this->q0;
     case 1:
       return this->q1;
     case 2:
       return this->q2;
     case 3:
       return this->q3;
     default:
       cvm::fatal_error ("Error: trying to access a quaternion "
                         "component which is not between 0 and 3.\n");
       return this->q0;
     }
   }
 
   /// Square norm of the quaternion
   inline cvm::real norm2() const
   {
     return q0*q0 + q1*q1 + q2*q2 + q3*q3;
   }
 
   /// Norm of the quaternion
   inline cvm::real norm() const
   {
     return std::sqrt (this->norm2());
   }
 
-  /// Return the conjugate quaternion 
+  /// Return the conjugate quaternion
   inline cvm::quaternion conjugate() const
   {
     return cvm::quaternion (q0, -q1, -q2, -q3);
   }
 
   inline void operator *= (cvm::real const &a)
   {
     q0 *= a; q1 *= a; q2 *= a; q3 *= a;
   }
 
   inline void operator /= (cvm::real const &a)
   {
     q0 /= a; q1 /= a; q2 /= a; q3 /= a;
   }
 
   inline void set_positive()
   {
     if (q0 > 0.0) return;
     q0 = -q0;
     q1 = -q1;
     q2 = -q2;
     q3 = -q3;
   }
 
   inline void operator += (cvm::quaternion const &h)
   {
     q0+=h.q0; q1+=h.q1; q2+=h.q2; q3+=h.q3;
   }
   inline void operator -= (cvm::quaternion const &h)
   {
     q0-=h.q0; q1-=h.q1; q2-=h.q2; q3-=h.q3;
   }
 
   /// Promote a 3-vector to a quaternion
   static inline cvm::quaternion promote (cvm::rvector const &v)
   {
     return cvm::quaternion (0.0, v.x, v.y, v.z);
   }
   /// Return the vector component
-  inline cvm::rvector get_vector() const 
+  inline cvm::rvector get_vector() const
   {
     return cvm::rvector (q1, q2, q3);
   }
 
 
   friend inline cvm::quaternion operator + (cvm::quaternion const &h, cvm::quaternion const &q)
   {
     return cvm::quaternion (h.q0+q.q0, h.q1+q.q1, h.q2+q.q2, h.q3+q.q3);
   }
 
   friend inline cvm::quaternion operator - (cvm::quaternion const &h, cvm::quaternion const &q)
   {
     return cvm::quaternion (h.q0-q.q0, h.q1-q.q1, h.q2-q.q2, h.q3-q.q3);
   }
 
   /// \brief Provides the quaternion product.  \b NOTE: for the inner
   /// product use: \code h.inner (q); \endcode
   friend inline cvm::quaternion operator * (cvm::quaternion const &h, cvm::quaternion const &q)
   {
     return cvm::quaternion (h.q0*q.q0 - h.q1*q.q1 - h.q2*q.q2 - h.q3*q.q3,
                             h.q0*q.q1 + h.q1*q.q0 + h.q2*q.q3 - h.q3*q.q2,
                             h.q0*q.q2 + h.q2*q.q0 + h.q3*q.q1 - h.q1*q.q3,
                             h.q0*q.q3 + h.q3*q.q0 + h.q1*q.q2 - h.q2*q.q1);
   }
 
   friend inline cvm::quaternion operator * (cvm::real const &c,
                                             cvm::quaternion const &q)
   {
     return cvm::quaternion (c*q.q0, c*q.q1, c*q.q2, c*q.q3);
   }
   friend inline cvm::quaternion operator * (cvm::quaternion const &q,
                                             cvm::real const &c)
   {
     return cvm::quaternion (q.q0*c, q.q1*c, q.q2*c, q.q3*c);
   }
   friend inline cvm::quaternion operator / (cvm::quaternion const &q,
                                             cvm::real const &c)
   {
     return cvm::quaternion (q.q0/c, q.q1/c, q.q2/c, q.q3/c);
   }
 
 
   /// \brief Rotate v through this quaternion (put it in the rotated
   /// reference frame)
   inline cvm::rvector rotate (cvm::rvector const &v) const
   {
     return ((*this) * promote (v) * ((*this).conjugate())).get_vector();
   }
 
   /// \brief Rotate Q2 through this quaternion (put it in the rotated
   /// reference frame)
   inline cvm::quaternion rotate (cvm::quaternion const &Q2) const
   {
     cvm::rvector const vq_rot = this->rotate (Q2.get_vector());
     return cvm::quaternion (Q2.q0, vq_rot.x, vq_rot.y, vq_rot.z);
   }
 
   /// Return the 3x3 matrix associated to this quaternion
   inline cvm::rmatrix rotation_matrix() const
   {
     cvm::rmatrix R;
 
     R.xx() = q0*q0 + q1*q1 - q2*q2 - q3*q3;
     R.yy() = q0*q0 - q1*q1 + q2*q2 - q3*q3;
     R.zz() = q0*q0 - q1*q1 - q2*q2 + q3*q3;
 
     R.xy() = 2.0 * (q1*q2 - q0*q3);
     R.xz() = 2.0 * (q0*q2 + q1*q3);
 
     R.yx() = 2.0 * (q0*q3 + q1*q2);
     R.yz() = 2.0 * (q2*q3 - q0*q1);
 
     R.zx() = 2.0 * (q1*q3 - q0*q2);
     R.zy() = 2.0 * (q0*q1 + q2*q3);
 
     return R;
   }
 
 
   /// \brief Multiply the given vector by the derivative of the given
   /// (rotated) position with respect to the quaternion
   cvm::quaternion position_derivative_inner (cvm::rvector const &pos,
                                              cvm::rvector const &vec) const;
 
 
   /// \brief Return the cosine between the orientation frame
   /// associated to this quaternion and another
   inline cvm::real cosine (cvm::quaternion const &q) const
   {
     cvm::real const iprod = this->inner (q);
     return 2.0*iprod*iprod - 1.0;
   }
 
   /// \brief Square distance from another quaternion on the
   /// 4-dimensional unit sphere: returns the square of the angle along
   /// the shorter of the two geodesics
   inline cvm::real dist2 (cvm::quaternion const &Q2) const
   {
     cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 +
       this->q2*Q2.q2 + this->q3*Q2.q3;
 
     cvm::real const omega = std::acos ( (cos_omega > 1.0) ? 1.0 :
                                      ( (cos_omega < -1.0) ? -1.0 : cos_omega) );
 
     // get the minimum distance: x and -x are the same quaternion
     if (cos_omega > 0.0)
       return omega * omega;
     else
       return (PI-omega) * (PI-omega);
   }
 
   /// Gradient of the square distance: returns a 4-vector equivalent
   /// to the one provided by slerp
   inline cvm::quaternion dist2_grad (cvm::quaternion const &Q2) const
   {
     cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 + this->q2*Q2.q2 + this->q3*Q2.q3;
     cvm::real const omega = std::acos ( (cos_omega > 1.0) ? 1.0 :
                                      ( (cos_omega < -1.0) ? -1.0 : cos_omega) );
     cvm::real const sin_omega = std::sin (omega);
 
     if (std::fabs (sin_omega) < 1.0E-14) {
       // return a null 4d vector
       return cvm::quaternion (0.0, 0.0, 0.0, 0.0);
     }
 
     cvm::quaternion const
       grad1 ((-1.0)*sin_omega*Q2.q0 + cos_omega*(this->q0-cos_omega*Q2.q0)/sin_omega,
              (-1.0)*sin_omega*Q2.q1 + cos_omega*(this->q1-cos_omega*Q2.q1)/sin_omega,
              (-1.0)*sin_omega*Q2.q2 + cos_omega*(this->q2-cos_omega*Q2.q2)/sin_omega,
              (-1.0)*sin_omega*Q2.q3 + cos_omega*(this->q3-cos_omega*Q2.q3)/sin_omega);
 
     if (cos_omega > 0.0) {
       return 2.0*omega*grad1;
     }
     else {
       return -2.0*(PI-omega)*grad1;
     }
   }
 
   /// \brief Choose the closest between Q2 and -Q2 and save it back.
   /// Not required for dist2() and dist2_grad()
   inline void match (cvm::quaternion &Q2) const
   {
     cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 +
       this->q2*Q2.q2 + this->q3*Q2.q3;
     if (cos_omega < 0.0) Q2 *= -1.0;
   }
 
   /// \brief Inner product (as a 4-d vector) with Q2; requires match()
   /// if the largest overlap is looked for
   inline cvm::real inner (cvm::quaternion const &Q2) const
   {
     cvm::real const prod = this->q0*Q2.q0 + this->q1*Q2.q1 +
       this->q2*Q2.q2 + this->q3*Q2.q3;
     return prod;
   }
 
 
 };
 
 
 /// \brief A rotation between two sets of coordinates (for the moment
 /// a wrapper for colvarmodule::quaternion)
 class colvarmodule::rotation
 {
 public:
 
   /// \brief The rotation itself (implemented as a quaternion)
   cvm::quaternion q;
 
   /// \brief Eigenvalue corresponding to the optimal rotation
   cvm::real lambda;
 
   /// \brief Perform gradient tests
   bool b_debug_gradients;
 
   /// \brief Positions to superimpose: the rotation should brings pos1
   /// into pos2
   std::vector< cvm::atom_pos > pos1, pos2;
 
   /// Derivatives of S
   std::vector< cvm::matrix2d<cvm::rvector, 4, 4> > dS_1,  dS_2;
   /// Derivatives of leading eigenvalue
   std::vector< cvm::rvector >                      dL0_1, dL0_2;
   /// Derivatives of leading eigenvector
   std::vector< cvm::vector1d<cvm::rvector, 4> >    dQ0_1, dQ0_2;
 
   /// Allocate space for the derivatives of the rotation
   inline void request_group1_gradients (size_t const &n)
   {
     dS_1.resize  (n, cvm::matrix2d<cvm::rvector, 4, 4>());
     dL0_1.resize (n, cvm::rvector (0.0, 0.0, 0.0));
     dQ0_1.resize (n, cvm::vector1d<cvm::rvector, 4>());
   }
 
   inline void request_group2_gradients (size_t const &n)
   {
     dS_2.resize  (n, cvm::matrix2d<cvm::rvector, 4, 4>());
     dL0_2.resize (n, cvm::rvector (0.0, 0.0, 0.0));
     dQ0_2.resize (n, cvm::vector1d<cvm::rvector, 4>());
   }
 
   /// \brief Calculate the optimal rotation and store the
   /// corresponding eigenvalue and eigenvector in the arguments l0 and
   /// q0; if the gradients have been previously requested, calculate
   /// them as well
   ///
   /// The method to derive the optimal rotation is defined in:
   /// Coutsias EA, Seok C, Dill KA.
   /// Using quaternions to calculate RMSD.
   /// J Comput Chem. 25(15):1849-57 (2004)
   /// DOI: 10.1002/jcc.20110  PubMed: 15376254
   void calc_optimal_rotation (std::vector<atom_pos> const &pos1,
                               std::vector<atom_pos> const &pos2);
 
   /// Default constructor
   inline rotation()
     : b_debug_gradients (false)
   {}
 
   /// Constructor after a quaternion
   inline rotation (cvm::quaternion const &qi)
     : b_debug_gradients (false)
   {
     q = qi;
   }
 
   /// Constructor after an axis of rotation and an angle (in radians)
   inline rotation (cvm::real const &angle, cvm::rvector const &axis)
     : b_debug_gradients (false)
   {
     cvm::rvector const axis_n = axis.unit();
     cvm::real const sina = std::sin (angle/2.0);
     q = cvm::quaternion (std::cos (angle/2.0),
                          sina * axis_n.x, sina * axis_n.y, sina * axis_n.z);
   }
 
   /// Destructor
   inline ~rotation()
   {}
 
   /// Return the rotated vector
   inline cvm::rvector rotate (cvm::rvector const &v) const
   {
     return q.rotate (v);
   }
 
   /// Return the inverse of this rotation
   inline cvm::rotation inverse() const
   {
     return cvm::rotation (this->q.conjugate());
   }
 
   /// Return the associated 3x3 matrix
   inline cvm::rmatrix matrix() const
   {
     return q.rotation_matrix();
   }
 
 
   /// \brief Return the spin angle (in degrees) with respect to the
   /// provided axis (which MUST be normalized)
   inline cvm::real spin_angle (cvm::rvector const &axis) const
   {
     cvm::rvector const q_vec = q.get_vector();
     cvm::real alpha = (180.0/PI) * 2.0 * std::atan2 (axis * q_vec, q.q0);
     while (alpha >  180.0) alpha -= 360;
     while (alpha < -180.0) alpha += 360;
     return alpha;
   }
 
   /// \brief Return the derivative of the spin angle with respect to
   /// the quaternion
   inline cvm::quaternion dspin_angle_dq (cvm::rvector const &axis) const
   {
     cvm::rvector const q_vec = q.get_vector();
     cvm::real const iprod = axis * q_vec;
 
     if (q.q0 != 0.0) {
 
       // cvm::real const x = iprod/q.q0;
-      
+
       cvm::real const dspindx = (180.0/PI) * 2.0 * (1.0 / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
 
-      return 
-        cvm::quaternion ( dspindx * (iprod * (-1.0) / (q.q0*q.q0)), 
+      return
+        cvm::quaternion ( dspindx * (iprod * (-1.0) / (q.q0*q.q0)),
                           dspindx * ((1.0/q.q0) * axis.x),
                           dspindx * ((1.0/q.q0) * axis.y),
                           dspindx * ((1.0/q.q0) * axis.z));
     } else {
       // (1/(1+x^2)) ~ (1/x)^2
       return
         cvm::quaternion ((180.0/PI) * 2.0 * ((-1.0)/iprod), 0.0, 0.0, 0.0);
       // XX TODO: What if iprod == 0? XX
     }
   }
 
   /// \brief Return the projection of the orientation vector onto a
   /// predefined axis
   inline cvm::real cos_theta (cvm::rvector const &axis) const
   {
     cvm::rvector const q_vec = q.get_vector();
-    cvm::real const alpha = 
+    cvm::real const alpha =
       (180.0/PI) * 2.0 * std::atan2 (axis * q_vec, q.q0);
 
     cvm::real const cos_spin_2 = std::cos (alpha * (PI/180.0) * 0.5);
-    cvm::real const cos_theta_2 = ( (cos_spin_2 != 0.0) ? 
+    cvm::real const cos_theta_2 = ( (cos_spin_2 != 0.0) ?
                                     (q.q0 / cos_spin_2) :
                                     (0.0) );
     // cos(2t) = 2*cos(t)^2 - 1
     return 2.0 * (cos_theta_2*cos_theta_2) - 1.0;
   }
 
    /// Return the derivative of the tilt wrt the quaternion
   inline cvm::quaternion dcos_theta_dq (cvm::rvector const &axis) const
   {
     cvm::rvector const q_vec = q.get_vector();
     cvm::real const iprod = axis * q_vec;
 
     cvm::real const cos_spin_2 = std::cos (std::atan2 (iprod, q.q0));
 
     if (q.q0 != 0.0)  {
 
-      cvm::real const d_cos_theta_dq0 = 
+      cvm::real const d_cos_theta_dq0 =
         (4.0 * q.q0 / (cos_spin_2*cos_spin_2)) *
         (1.0 - (iprod*iprod)/(q.q0*q.q0) / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
 
       cvm::real const d_cos_theta_dqn =
         (4.0 * q.q0 / (cos_spin_2*cos_spin_2) *
          (iprod/q.q0) / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
 
-      return cvm::quaternion (d_cos_theta_dq0, 
+      return cvm::quaternion (d_cos_theta_dq0,
                               d_cos_theta_dqn * axis.x,
                               d_cos_theta_dqn * axis.y,
                               d_cos_theta_dqn * axis.z);
     } else {
 
       cvm::real const d_cos_theta_dqn =
         (4.0 / (cos_spin_2*cos_spin_2 * iprod));
 
       return cvm::quaternion (0.0,
                               d_cos_theta_dqn * axis.x,
                               d_cos_theta_dqn * axis.y,
                               d_cos_theta_dqn * axis.z);
     }
   }
 
   /// \brief Threshold for the eigenvalue crossing test
   static cvm::real crossing_threshold;
 
 protected:
 
   /// \brief Previous value of the rotation (used to warn the user
   /// when the structure changes too much, and there may be an
   /// eigenvalue crossing)
   cvm::quaternion q_old;
 
   /// Build the overlap matrix S (used by calc_optimal_rotation())
   void build_matrix (std::vector<cvm::atom_pos> const &pos1,
                      std::vector<cvm::atom_pos> const &pos2,
                      cvm::matrix2d<real, 4, 4>        &S);
 
   /// Diagonalize the overlap matrix S (used by calc_optimal_rotation())
   void diagonalize_matrix (cvm::matrix2d<cvm::real, 4, 4> &S,
                            cvm::real                       S_eigval[4],
                            cvm::matrix2d<cvm::real, 4, 4> &S_eigvec);
 };
 
 
 #endif
 
 // Emacs
 // Local Variables:
 // mode: C++
 // End:
diff --git a/lib/colvars/colvarvalue.cpp b/lib/colvars/colvarvalue.cpp
index 25f888c00..18a3bd00c 100644
--- a/lib/colvars/colvarvalue.cpp
+++ b/lib/colvars/colvarvalue.cpp
@@ -1,261 +1,261 @@
 #include <vector>
 
 #include "colvarmodule.h"
 #include "colvarvalue.h"
 
 
 
 std::string const colvarvalue::type_desc[colvarvalue::type_quaternion+1] =
   { "not_set",
     "scalar number",
     "3-dimensional vector",
     "3-dimensional unit vector",
     "4-dimensional unit vector" };
 
 size_t const      colvarvalue::dof_num[  colvarvalue::type_quaternion+1] =
   { 0, 1, 3, 2, 3 };
 
 
 void colvarvalue::undef_op() const
 {
   cvm::fatal_error ("Error: Undefined operation on a colvar of type \""+
                     colvarvalue::type_desc[this->value_type]+"\".\n");
 }
 
 void colvarvalue::error_rside
 (colvarvalue::Type const &vt) const
 {
   cvm::fatal_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::fatal_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:
     while (xvi != xv_end) {
       *(ii++) += (xvi++)->rvector_value * x.rvector_value;
     }
     break;
   case colvarvalue::type_quaternion:
     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:
     while (xvi != xv_end) {
       *(ii++) += (xvi++)->rvector_value * x.rvector_value;
     }
     break;
   case colvarvalue::type_quaternion:
     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::fatal_error ("Error: cannot calculate Legendre polynomials "
                       "for scalar variables.\n");
     break;
   case colvarvalue::type_vector:
     while (xvi != xv_end) {
-      cvm::real const cosine = 
+      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_unitvector:
     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:
     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();
   };
 }
 
 void colvarvalue::p2leg_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:
     cvm::fatal_error ("Error: cannot calculate Legendre polynomials "
                       "for scalar variables.\n");
     break;
   case colvarvalue::type_vector:
     while (xvi != xv_end) {
-      cvm::real const cosine = 
+      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_unitvector:
     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:
     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();
   };
 }
 
 
 std::ostream & operator << (std::ostream &os, colvarvalue const &x)
 {
   switch (x.type()) {
   case colvarvalue::type_scalar:
     os << x.real_value; break;
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
     os << x.rvector_value; break;
   case colvarvalue::type_quaternion:
     os << x.quaternion_value; break;
   case colvarvalue::type_notset:
     os << "not set"; break;
   }
   return os;
 }
 
 
 std::ostream & operator << (std::ostream &os, std::vector<colvarvalue> const &v)
 {
   for (size_t i = 0; i < v.size(); i++) os << v[i];
   return os;
 }
 
 
 std::istream & operator >> (std::istream &is, colvarvalue &x)
 {
   if (x.type() == colvarvalue::type_notset) {
     cvm::fatal_error ("Trying to read from a stream a colvarvalue, "
                       "which has not yet been assigned a data type.\n");
   }
 
   switch (x.type()) {
   case colvarvalue::type_scalar:
-    is >> x.real_value; 
+    is >> x.real_value;
     break;
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
-    is >> x.rvector_value; 
+    is >> x.rvector_value;
     break;
   case colvarvalue::type_quaternion:
     is >> x.quaternion_value;
     break;
   default:
     x.undef_op();
   }
   x.apply_constraints();
   return is;
 }
 
 
 size_t colvarvalue::output_width (size_t const &real_width) const
 {
   switch (this->value_type) {
   case colvarvalue::type_scalar:
     return real_width;
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
     return cvm::rvector::output_width (real_width);
   case colvarvalue::type_quaternion:
     return cvm::quaternion::output_width (real_width);
   case colvarvalue::type_notset:
   default:
     return 0;
   }
 }
 
 
diff --git a/lib/colvars/colvarvalue.h b/lib/colvars/colvarvalue.h
index eb4459345..e262e7feb 100644
--- a/lib/colvars/colvarvalue.h
+++ b/lib/colvars/colvarvalue.h
@@ -1,727 +1,727 @@
 #ifndef COLVARVALUE_H
 #define COLVARVALUE_H
 
 #include "colvarmodule.h"
 
 
 /// \brief Value of a collective variable: this is a metatype which
 /// can be set at runtime.  By default it is set to be a scalar
 /// number, and can be treated like that in all operations (this is
 /// done by most \link cvc \endlink implementations).
 ///
 /// \link colvarvalue \endlink allows \link colvar \endlink to be
 /// treat different data types.  By default, a \link colvarvalue
 /// \endlink variable is a scalar number.  If you want to use it as
 /// another type, you should declare and initialize a variable as
 /// \code colvarvalue x (colvarvalue::type_xxx); \endcode where
 /// type_xxx is a value within the \link Type \endlink enum.
 /// Alternatively, initialize x with \link x.type
 /// (colvarvalue::type_xxx) \endlink at a later stage.
 ///
 /// Given a colvarvalue variable x which is not yet assigned (and
 /// thus has not yet a type) it is also possible to correctly assign
 /// the type with \code x = y; \endcode if y is correctly set.
 /// Otherwise, an error will be raised if the \link Type \endlink of x
 /// is different from the \link Type \endlink of y.
 ///
 /// Also, every operator (either unary or binary) on a \link
 /// colvarvalue \endlink object performs one or more checks on the
 /// \link Type \endlink to avoid errors such as initializing a
 /// three-dimensional vector with a scalar number (legal otherwise).
 ///
 /// \b Special \b case: when reading from a stream, there is no way to
 /// detect the \link Type \endlink and safely handle errors at the
 /// same time.  Hence, when using \code is >> x; \endcode x \b MUST
 /// already have a type correcly set up for properly parsing the
 /// stream.  An error will be raised otherwise.  Usually this is not
 /// the problem, because \link colvarvalue \endlink objects are first
 /// initialized in the configuration, and the stream operation will be
 /// performed only when reading restart files.
-/// 
+///
 /// No problem of course with the output streams: \code os << x;
 /// \endcode will print a different output according to the value of
 /// colvarvalue::value_type, and the width of such output is returned
 /// by colvarvalue::output_width()
 ///
 /// \em Note \em on \em performance: at every operation between two
 /// \link colvarvalue \endlink objects, their two \link Type \endlink
 /// flags will be checked for a match.  In a long array of \link
 /// colvarvalue \endlink objects this is time consuming: a few static
 /// functions are defined ("xxx_opt" functions) within the \link
 /// colvarvalue \endlink class, which only check the matching once for
 /// a large array, and execute different loops according to the type.
 /// You should do the same for every time consuming loop involving
 /// operations on \link colvarvalue \endlink objects if you want
 /// e.g. to optimize your colvar bias.
 
 class colvarvalue {
 
 public:
 
   /// \brief Possible types of value
   ///
   /// These three cover most possibilities of data type one can
   /// devise.  If you need to implement a new colvar with a very
   /// complex data type, it's better to put an allocatable class here
   enum Type {
     /// Undefined type
     type_notset,
     /// Scalar number, implemented as \link colvarmodule::real \endlink (default)
     type_scalar,
     /// 3-dimensional vector, implemented as \link colvarmodule::rvector \endlink
     type_vector,
     /// 3-dimensional unit vector, implemented as \link colvarmodule::rvector \endlink
     type_unitvector,
     /// 4-dimensional unit vector representing a rotation, implemented as \link colvarmodule::quaternion \endlink
     type_quaternion
   };
 
   /// Runtime description of value types
   std::string static const type_desc[colvarvalue::type_quaternion+1];
 
   /// Number of degrees of freedom for each type
   size_t static const      dof_num[  colvarvalue::type_quaternion+1];
 
   /// \brief Real data member
   cvm::real       real_value;
 
   /// \brief Vector data member
   cvm::rvector    rvector_value;
 
   /// \brief Quaternion data member
   cvm::quaternion quaternion_value;
 
   /// Current type of this colvarvalue object
-  Type  value_type; 
+  Type  value_type;
 
   static inline bool type_checking()
   {
     return true;
   }
 
   /// \brief Default constructor: this class defaults to a scalar
   /// number and always behaves like it unless you change its type
   inline colvarvalue()
     : real_value (0.0), value_type (type_scalar)
   {}
 
   /// Constructor from a type specification
   inline colvarvalue (Type const &vti)
     : value_type (vti)
   {
     reset();
   }
 
   /// Copy constructor from real base type
   inline colvarvalue (cvm::real const &x)
     : real_value (x), value_type (type_scalar)
   {}
 
   /// \brief Copy constructor from rvector base type (Note: this sets
   /// automatically a type \link type_vector \endlink , if you want a
   /// \link type_unitvector \endlink you must set it explicitly)
   inline colvarvalue (cvm::rvector const &v)
     : rvector_value (v), value_type (type_vector)
   {}
 
   /// \brief Copy constructor from rvector base type (additional
   /// argument to make possible to choose a \link type_unitvector
   /// \endlink
   inline colvarvalue (cvm::rvector const &v, Type const &vti)
     : rvector_value (v), value_type (vti)
   {}
 
   /// \brief Copy constructor from quaternion base type
   inline colvarvalue (cvm::quaternion const &q)
     : quaternion_value (q), value_type (type_quaternion)
   {}
 
   /// Copy constructor from another \link colvarvalue \endlink
   inline colvarvalue (colvarvalue const &x)
     : value_type (x.value_type)
   {
     reset();
 
     switch (x.value_type) {
     case type_scalar:
       real_value = x.real_value;
       break;
-    case type_vector: 
+    case type_vector:
     case type_unitvector:
       rvector_value = x.rvector_value;
       break;
     case type_quaternion:
       quaternion_value = x.quaternion_value;
       break;
     case type_notset:
     default:
       break;
     }
   }
 
 
 
   /// Set to the null value for the data type currently defined
   void reset();
 
 
   /// \brief If the variable has constraints (e.g. unitvector or
   /// quaternion), transform it to satisfy them; use it when the \link
   /// colvarvalue \endlink is not calculated from \link cvc
   /// \endlink objects, but manipulated by you
   void apply_constraints();
 
 
   /// Get the current type
   inline Type type() const
   {
     return value_type;
   }
 
   /// Set the type explicitly
   inline void type (Type const &vti)
   {
     reset();
     value_type = vti;
     reset();
   }
 
   /// Set the type after another \link colvarvalue \endlink
   inline void type (colvarvalue const &x)
   {
     reset();
     value_type = x.value_type;
     reset();
   }
 
   /// Square norm of this colvarvalue
   cvm::real norm2() const;
 
   /// Norm of this colvarvalue
   inline cvm::real norm() const
   {
     return std::sqrt (this->norm2());
   }
 
   /// \brief Return the value whose scalar product with this value is
   /// 1
   inline colvarvalue inverse() const;
 
   /// Square distance between this \link colvarvalue \endlink and another
   cvm::real dist2 (colvarvalue const &x2) const;
 
   /// Derivative with respect to this \link colvarvalue \endlink of the square distance
   colvarvalue dist2_grad (colvarvalue const &x2) const;
 
   /// Assignment operator (type of x is checked)
   colvarvalue & operator = (colvarvalue const &x);
 
   void operator += (colvarvalue const &x);
   void operator -= (colvarvalue const &x);
   void operator *= (cvm::real const &a);
   void operator /= (cvm::real const &a);
 
 
   // Casting operator
   inline operator cvm::real() const
   {
     if (value_type != type_scalar) error_rside (type_scalar);
     return real_value;
   }
 
   // Casting operator
   inline operator cvm::rvector() const
   {
     if ( (value_type != type_vector) && (value_type != type_unitvector))
       error_rside (type_vector);
     return rvector_value;
   }
 
   // Casting operator
   inline operator cvm::quaternion() const
   {
     if (value_type != type_quaternion) error_rside (type_quaternion);
     return quaternion_value;
   }
 
   /// Special case when the variable is a real number, and all operations are defined
   inline bool is_scalar()
   {
     return (value_type == type_scalar);
   }
 
 
   /// Ensure that the two types are the same within a binary operator
   void static check_types (colvarvalue const &x1, colvarvalue const &x2);
 
-  /// Undefined operation 
+  /// Undefined operation
   void undef_op() const;
 
   /// Trying to assign this \link colvarvalue \endlink object to
   /// another object set with a different type
   void error_lside (Type const &vt) const;
 
   /// Trying to assign another \link colvarvalue \endlink object set
   /// with a different type to this object
   void error_rside (Type const &vt) const;
 
   /// Give the number of characters required to output this
   /// colvarvalue, given the current type assigned and the number of
   /// characters for a real number
   size_t output_width (size_t const &real_width) const;
 
 
   // optimized routines for operations with an array; xv and inner as
   // vectors are assumed to have the same number of elements (i.e. the
   // end for inner comes together with xv_end in the loop)
 
   /// \brief Optimized routine for the inner product of one collective
   /// variable with an array
   void static inner_opt (colvarvalue const                        &x,
                          std::vector<colvarvalue>::iterator       &xv,
                          std::vector<colvarvalue>::iterator const &xv_end,
                          std::vector<cvm::real>::iterator         &inner);
 
   /// \brief Optimized routine for the inner product of one collective
   /// variable with an array
   void static inner_opt (colvarvalue const                        &x,
                          std::list<colvarvalue>::iterator         &xv,
                          std::list<colvarvalue>::iterator const   &xv_end,
                          std::vector<cvm::real>::iterator         &inner);
 
   /// \brief Optimized routine for the second order Legendre
   /// polynomial, (3cos^2(w)-1)/2, of one collective variable with an
   /// array
   void static p2leg_opt (colvarvalue const                        &x,
                          std::vector<colvarvalue>::iterator       &xv,
                          std::vector<colvarvalue>::iterator const &xv_end,
                          std::vector<cvm::real>::iterator         &inner);
 
   /// \brief Optimized routine for the second order Legendre
   /// polynomial of one collective variable with an array
   void static p2leg_opt (colvarvalue const                        &x,
                          std::list<colvarvalue>::iterator         &xv,
                          std::list<colvarvalue>::iterator const   &xv_end,
                          std::vector<cvm::real>::iterator         &inner);
 
 };
 
 
 
 inline void colvarvalue::reset()
 {
   switch (value_type) {
   case colvarvalue::type_scalar:
     real_value = cvm::real (0.0);
     break;
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
     rvector_value = cvm::rvector (0.0, 0.0, 0.0);
     break;
   case colvarvalue::type_quaternion:
     quaternion_value = cvm::quaternion (0.0, 0.0, 0.0, 0.0);
     break;
   case colvarvalue::type_notset:
   default:
     break;
-  }  
+  }
 }
 
 
 inline void colvarvalue::apply_constraints()
 {
   switch (value_type) {
   case colvarvalue::type_scalar:
     break;
   case colvarvalue::type_vector:
     break;
   case colvarvalue::type_unitvector:
     rvector_value /= std::sqrt (rvector_value.norm2());
     break;
   case colvarvalue::type_quaternion:
     quaternion_value /= std::sqrt (quaternion_value.norm2());
     break;
   case colvarvalue::type_notset:
   default:
     break;
-  }  
+  }
 }
 
 
 
 inline cvm::real colvarvalue::norm2() const
 {
   switch (value_type) {
   case colvarvalue::type_scalar:
     return (this->real_value)*(this->real_value);
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
     return (this->rvector_value).norm2();
   case colvarvalue::type_quaternion:
     return (this->quaternion_value).norm2();
   case colvarvalue::type_notset:
   default:
     return 0.0;
-  }  
+  }
 }
 
 
 inline colvarvalue colvarvalue::inverse() const
 {
   switch (value_type) {
   case colvarvalue::type_scalar:
     return colvarvalue (1.0/real_value);
   case colvarvalue::type_vector:
     return colvarvalue (cvm::rvector (1.0/rvector_value.x,
                                       1.0/rvector_value.y,
                                       1.0/rvector_value.z));
   case colvarvalue::type_quaternion:
     return colvarvalue (cvm::quaternion (1.0/quaternion_value.q0,
                                          1.0/quaternion_value.q1,
                                          1.0/quaternion_value.q2,
                                          1.0/quaternion_value.q3));
   case colvarvalue::type_notset:
   default:
     undef_op();
-  }  
+  }
   return colvarvalue();
 }
 
 
 inline colvarvalue & colvarvalue::operator = (colvarvalue const &x)
 {
   if (this->value_type != type_notset)
-    if (this->value_type != x.value_type) 
+    if (this->value_type != x.value_type)
       error_lside (x.value_type);
 
   this->value_type = x.value_type;
-  
+
   switch (this->value_type) {
   case colvarvalue::type_scalar:
     this->real_value = x.real_value;
     break;
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
     this->rvector_value = x.rvector_value;
     break;
   case colvarvalue::type_quaternion:
     this->quaternion_value = x.quaternion_value;
     break;
   case colvarvalue::type_notset:
   default:
     undef_op();
     break;
   }
   return *this;
 }
 
 inline void colvarvalue::operator += (colvarvalue const &x)
 {
   if (colvarvalue::type_checking())
     colvarvalue::check_types (*this, x);
 
   switch (this->value_type) {
   case colvarvalue::type_scalar:
     this->real_value += x.real_value;
     break;
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
     this->rvector_value += x.rvector_value;
     break;
   case colvarvalue::type_quaternion:
     this->quaternion_value += x.quaternion_value;
     break;
   case colvarvalue::type_notset:
   default:
     undef_op();
   }
 }
 
 inline void colvarvalue::operator -= (colvarvalue const &x)
 {
   if (colvarvalue::type_checking())
     colvarvalue::check_types (*this, x);
 
   switch (value_type) {
   case colvarvalue::type_scalar:
     real_value -= x.real_value; break;
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
     rvector_value -= x.rvector_value; break;
   case colvarvalue::type_quaternion:
     quaternion_value -= x.quaternion_value; break;
   case colvarvalue::type_notset:
   default:
     undef_op();
   }
 }
 
 inline void colvarvalue::operator *= (cvm::real const &a)
 {
   switch (value_type) {
   case colvarvalue::type_scalar:
     real_value *= a;
     break;
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
     rvector_value *= a;
     break;
   case colvarvalue::type_quaternion:
     quaternion_value *= a;
     break;
   case colvarvalue::type_notset:
   default:
     undef_op();
   }
 }
 
 inline void colvarvalue::operator /= (cvm::real const &a)
 {
   switch (value_type) {
   case colvarvalue::type_scalar:
     real_value /= a; break;
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
     rvector_value /= a; break;
   case colvarvalue::type_quaternion:
     quaternion_value /= a; break;
   case colvarvalue::type_notset:
   default:
     undef_op();
   }
 }
 
 
 // binary operations between two colvarvalues
 
 inline colvarvalue operator + (colvarvalue const &x1,
                                colvarvalue const &x2)
 {
   if (colvarvalue::type_checking())
     colvarvalue::check_types (x1, x2);
 
   switch (x1.value_type) {
   case colvarvalue::type_scalar:
     return colvarvalue (x1.real_value + x2.real_value);
   case colvarvalue::type_vector:
     return colvarvalue (x1.rvector_value + x2.rvector_value);
   case colvarvalue::type_unitvector:
     return colvarvalue (x1.rvector_value + x2.rvector_value,
                         colvarvalue::type_unitvector);
   case colvarvalue::type_quaternion:
     return colvarvalue (x1.quaternion_value + x2.quaternion_value);
   case colvarvalue::type_notset:
   default:
     x1.undef_op();
     return colvarvalue (colvarvalue::type_notset);
   };
 }
 
 inline colvarvalue operator - (colvarvalue const &x1,
                                colvarvalue const &x2)
 {
   if (colvarvalue::type_checking())
     colvarvalue::check_types (x1, x2);
 
   switch (x1.value_type) {
   case colvarvalue::type_scalar:
     return colvarvalue (x1.real_value - x2.real_value);
   case colvarvalue::type_vector:
     return colvarvalue (x1.rvector_value - x2.rvector_value);
   case colvarvalue::type_unitvector:
     return colvarvalue (x1.rvector_value - x2.rvector_value,
                         colvarvalue::type_unitvector);
   case colvarvalue::type_quaternion:
     return colvarvalue (x1.quaternion_value - x2.quaternion_value);
   default:
     x1.undef_op();
     return colvarvalue (colvarvalue::type_notset);
   };
 }
 
 
 // binary operations with real numbers
 
 inline colvarvalue operator * (cvm::real const &a,
                                colvarvalue const &x)
 {
   switch (x.value_type) {
   case colvarvalue::type_scalar:
     return colvarvalue (a * x.real_value);
   case colvarvalue::type_vector:
     return colvarvalue (a * x.rvector_value);
   case colvarvalue::type_unitvector:
     return colvarvalue (a * x.rvector_value,
                         colvarvalue::type_unitvector);
   case colvarvalue::type_quaternion:
     return colvarvalue (a * x.quaternion_value);
   case colvarvalue::type_notset:
   default:
     x.undef_op();
     return colvarvalue (colvarvalue::type_notset);
   }
 }
 
 inline 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_vector:
     return colvarvalue (x.rvector_value * a);
   case colvarvalue::type_unitvector:
     return colvarvalue (x.rvector_value * a,
                         colvarvalue::type_unitvector);
   case colvarvalue::type_quaternion:
     return colvarvalue (x.quaternion_value * a);
   case colvarvalue::type_notset:
   default:
     x.undef_op();
     return colvarvalue (colvarvalue::type_notset);
   }
 }
 
 inline 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_vector:
     return colvarvalue (x.rvector_value / a);
   case colvarvalue::type_unitvector:
     return colvarvalue (x.rvector_value / a,
                         colvarvalue::type_unitvector);
   case colvarvalue::type_quaternion:
     return colvarvalue (x.quaternion_value / a);
   case colvarvalue::type_notset:
   default:
     x.undef_op();
     return colvarvalue (colvarvalue::type_notset);
   }
 }
 
 
 // inner product between two colvarvalues
 
 inline cvm::real operator * (colvarvalue const &x1,
                              colvarvalue const &x2)
 {
   if (colvarvalue::type_checking())
     colvarvalue::check_types (x1, x2);
 
   switch (x1.value_type) {
   case colvarvalue::type_scalar:
     return (x1.real_value * x2.real_value);
   case colvarvalue::type_vector:
   case colvarvalue::type_unitvector:
     return (x1.rvector_value * x2.rvector_value);
   case colvarvalue::type_quaternion:
     // 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_notset:
   default:
     x1.undef_op();
     return 0.0;
   };
 }
 
 
 
 inline cvm::real colvarvalue::dist2 (colvarvalue const &x2) const
 {
   if (colvarvalue::type_checking())
     colvarvalue::check_types (*this, x2);
 
   switch (this->value_type) {
   case colvarvalue::type_scalar:
     return (this->real_value - x2.real_value)*(this->real_value - x2.real_value);
   case colvarvalue::type_vector:
     return (this->rvector_value - x2.rvector_value).norm2();
   case colvarvalue::type_unitvector:
     // angle between (*this) and x2 is the distance
     return std::acos (this->rvector_value * x2.rvector_value) * std::acos (this->rvector_value * x2.rvector_value);
   case colvarvalue::type_quaternion:
     // angle between (*this) and x2 is the distance, the quaternion
     // object has it implemented internally
     return this->quaternion_value.dist2 (x2.quaternion_value);
   case colvarvalue::type_notset:
   default:
     this->undef_op();
     return 0.0;
   };
 }
 
 
 inline colvarvalue colvarvalue::dist2_grad (colvarvalue const &x2) const
 {
   if (colvarvalue::type_checking())
     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_vector:
     return 2.0 * (this->rvector_value - x2.rvector_value);
   case colvarvalue::type_unitvector:
     {
       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_unitvector );
     }
   case colvarvalue::type_quaternion:
     return this->quaternion_value.dist2_grad (x2.quaternion_value);
   case colvarvalue::type_notset:
   default:
     this->undef_op();
     return colvarvalue (colvarvalue::type_notset);
   };
 }
 
 
 inline void colvarvalue::check_types (colvarvalue const &x1,
                                       colvarvalue const &x2)
 {
   if (x1.value_type != x2.value_type) {
     cvm::log ("x1 type = "+cvm::to_str (x1.value_type)+
               ", x2 type = "+cvm::to_str (x2.value_type)+"\n");
     cvm::fatal_error ("Performing an operation between two colvar "
                       "values with different types, \""+
                       colvarvalue::type_desc[x1.value_type]+
                       "\" and \""+
                       colvarvalue::type_desc[x2.value_type]+
                       "\".\n");
   }
 }
 
 
 
 
 std::ostream & operator << (std::ostream &os, colvarvalue const &x);
 std::ostream & operator << (std::ostream &os, std::vector<colvarvalue> const &v);
 
 std::istream & operator >> (std::istream &is, colvarvalue &x);
 
 
 
 
 
 #endif
 
 
 // Emacs
 // Local Variables:
 // mode: C++
 // End: