Update Colvars to version 2018-05-15
[namd.git] / colvars / src / colvarmodule.cpp
index 780dc28..dc6242c 100644 (file)
@@ -8,7 +8,7 @@
 // Colvars repository at GitHub.
 
 #include <sstream>
-#include <string.h>
+#include <cstring>
 
 #include "colvarmodule.h"
 #include "colvarparse.h"
@@ -22,6 +22,7 @@
 #include "colvarbias_restraint.h"
 #include "colvarscript.h"
 #include "colvaratoms.h"
+#include "colvarcomp.h"
 
 
 colvarmodule::colvarmodule(colvarproxy *proxy_in)
@@ -29,10 +30,10 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in)
   depth_s = 0;
   cv_traj_os = NULL;
 
-  // pointer to the proxy object
   if (proxy == NULL) {
-    proxy = proxy_in;
-    parse = new colvarparse();
+    proxy = proxy_in; // Pointer to the proxy object
+    parse = new colvarparse(); // Parsing object for global options
+    version_int = proxy->get_version_from_string(COLVARS_VERSION);
   } else {
     // TODO relax this error to handle multiple molecules in VMD
     // once the module is not static anymore
@@ -57,22 +58,24 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in)
   // "it_restart" will be set by the input state file, if any;
   // "it" should be updated by the proxy
   colvarmodule::it = colvarmodule::it_restart = 0;
-  colvarmodule::it_restart_from_state_file = true;
 
-  colvarmodule::use_scripted_forces = false;
+  use_scripted_forces = false;
+  scripting_after_biases = false;
 
-  colvarmodule::b_analysis = false;
+  b_analysis = false;
 
   colvarmodule::debug_gradients_step_size = 1.0e-07;
 
   colvarmodule::rotation::monitor_crossings = false;
   colvarmodule::rotation::crossing_threshold = 1.0e-02;
 
-  colvarmodule::cv_traj_freq = 100;
-  colvarmodule::restart_out_freq = proxy->restart_frequency();
+  cv_traj_freq = 100;
+  restart_out_freq = proxy->restart_frequency();
 
   // by default overwrite the existing trajectory file
-  colvarmodule::cv_traj_append = false;
+  cv_traj_append = false;
+
+  cv_traj_write_labels = true;
 }
 
 
@@ -188,26 +191,27 @@ int colvarmodule::parse_config(std::string &conf)
 {
   extra_conf.clear();
 
-  // parse global options
+  // Parse global options
   if (catch_input_errors(parse_global_params(conf))) {
     return get_error();
   }
 
-  // parse the options for collective variables
+  // Parse the options for collective variables
   if (catch_input_errors(parse_colvars(conf))) {
     return get_error();
   }
 
-  // parse the options for biases
+  // Parse the options for biases
   if (catch_input_errors(parse_biases(conf))) {
     return get_error();
   }
 
-  // done parsing known keywords, check that all keywords found were valid ones
+  // Done parsing known keywords, check that all keywords found were valid ones
   if (catch_input_errors(parse->check_keywords(conf, "colvarmodule"))) {
     return get_error();
   }
 
+  // Parse auto-generated configuration (e.g. for back-compatibility)
   if (extra_conf.size()) {
     catch_input_errors(parse_global_params(extra_conf));
     catch_input_errors(parse_colvars(extra_conf));
@@ -221,13 +225,11 @@ int colvarmodule::parse_config(std::string &conf)
   cvm::log("Collective variables module (re)initialized.\n");
   cvm::log(cvm::line_marker);
 
-  // update any necessary proxy data
+  // Update any necessary proxy data
   proxy->setup();
 
-  if (cv_traj_os != NULL) {
-    // configuration might have changed, better redo the labels
-    write_traj_label(*cv_traj_os);
-  }
+  // configuration might have changed, better redo the labels
+  cv_traj_write_labels = true;
 
   return get_error();
 }
@@ -274,19 +276,22 @@ int colvarmodule::parse_global_params(std::string const &conf)
   parse->get_keyval(conf, "colvarsRestartFrequency",
                     restart_out_freq, restart_out_freq);
 
-  // if this is true when initializing, it means
-  // we are continuing after a reset(): default to true
-  parse->get_keyval(conf, "colvarsTrajAppend", cv_traj_append, cv_traj_append);
+  // Deprecate append flag
+  parse->get_keyval(conf, "colvarsTrajAppend",
+                    cv_traj_append, cv_traj_append, colvarparse::parse_silent);
 
-  parse->get_keyval(conf, "scriptedColvarForces", use_scripted_forces, false);
+  parse->get_keyval(conf, "scriptedColvarForces",
+                    use_scripted_forces, use_scripted_forces);
 
-  parse->get_keyval(conf, "scriptingAfterBiases", scripting_after_biases, true);
+  parse->get_keyval(conf, "scriptingAfterBiases",
+                    scripting_after_biases, scripting_after_biases);
 
   if (use_scripted_forces && !proxy->force_script_defined) {
-    cvm::error("User script for scripted colvar forces not found.", INPUT_ERROR);
+    return cvm::error("User script for scripted colvar forces not found.",
+                      INPUT_ERROR);
   }
 
-  return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
+  return cvm::get_error();
 }
 
 
@@ -409,28 +414,18 @@ int colvarmodule::parse_biases(std::string const &conf)
     cvm::decrease_depth();
   }
 
-  size_t i;
-
-  size_t n_hist_dep_biases = 0;
-  std::vector<std::string> hist_dep_biases_names;
-  for (i = 0; i < biases.size(); i++) {
-    if (biases[i]->is_enabled(colvardeps::f_cvb_apply_force) &&
-        biases[i]->is_enabled(colvardeps::f_cvb_history_dependent)) {
-      n_hist_dep_biases++;
-      hist_dep_biases_names.push_back(biases[i]->name);
-    }
-  }
-  if (n_hist_dep_biases > 1) {
-    cvm::log("WARNING: there are "+cvm::to_str(n_hist_dep_biases)+
-             " history-dependent biases with non-zero force parameters:\n"+
-             cvm::to_str(hist_dep_biases_names)+"\n"+
-             "Please make sure that their forces do not counteract each other.\n");
+  std::vector<std::string> const time_biases = time_dependent_biases();
+  if (time_biases.size() > 1) {
+    cvm::log("WARNING: there are "+cvm::to_str(time_biases.size())+
+             " time-dependent biases with non-zero force parameters:\n"+
+             cvm::to_str(time_biases)+"\n"+
+             "Please ensure that their forces do not counteract each other.\n");
   }
 
-  if (biases.size() || use_scripted_forces) {
+  if (num_biases() || use_scripted_forces) {
     cvm::log(cvm::line_marker);
     cvm::log("Collective variables biases initialized, "+
-             cvm::to_str(biases.size())+" in total.\n");
+             cvm::to_str(num_biases())+" in total.\n");
   } else {
     if (!use_scripted_forces) {
       cvm::log("No collective variables biases were defined.\n");
@@ -441,12 +436,37 @@ int colvarmodule::parse_biases(std::string const &conf)
 }
 
 
-int colvarmodule::num_biases_feature(int feature_id)
+size_t colvarmodule::num_variables() const
+{
+  return colvars.size();
+}
+
+
+size_t colvarmodule::num_variables_feature(int feature_id) const
 {
-  colvarmodule *cv = cvm::main();
   size_t n = 0;
-  for (std::vector<colvarbias *>::iterator bi = cv->biases.begin();
-       bi != cv->biases.end();
+  for (std::vector<colvar *>::const_iterator cvi = colvars.begin();
+       cvi != colvars.end();
+       cvi++) {
+    if ((*cvi)->is_enabled(feature_id)) {
+      n++;
+    }
+  }
+  return n;
+}
+
+
+size_t colvarmodule::num_biases() const
+{
+  return biases.size();
+}
+
+
+size_t colvarmodule::num_biases_feature(int feature_id) const
+{
+  size_t n = 0;
+  for (std::vector<colvarbias *>::const_iterator bi = biases.begin();
+       bi != biases.end();
        bi++) {
     if ((*bi)->is_enabled(feature_id)) {
       n++;
@@ -456,12 +476,11 @@ int colvarmodule::num_biases_feature(int feature_id)
 }
 
 
-int colvarmodule::num_biases_type(std::string const &type)
+size_t colvarmodule::num_biases_type(std::string const &type) const
 {
-  colvarmodule *cv = cvm::main();
   size_t n = 0;
-  for (std::vector<colvarbias *>::iterator bi = cv->biases.begin();
-       bi != cv->biases.end();
+  for (std::vector<colvarbias *>::const_iterator bi = biases.begin();
+       bi != biases.end();
        bi++) {
     if ((*bi)->bias_type == type) {
       n++;
@@ -471,6 +490,22 @@ int colvarmodule::num_biases_type(std::string const &type)
 }
 
 
+std::vector<std::string> const colvarmodule::time_dependent_biases() const
+{
+  size_t i;
+  std::vector<std::string> biases_names;
+  for (i = 0; i < num_biases(); i++) {
+    if (biases[i]->is_enabled(colvardeps::f_cvb_apply_force) &&
+        biases[i]->is_enabled(colvardeps::f_cvb_active) &&
+        (biases[i]->is_enabled(colvardeps::f_cvb_history_dependent) ||
+         biases[i]->is_enabled(colvardeps::f_cvb_time_dependent))) {
+      biases_names.push_back(biases[i]->name);
+    }
+  }
+  return biases_names;
+}
+
+
 int colvarmodule::catch_input_errors(int result)
 {
   if (result != COLVARS_OK || get_error()) {
@@ -673,8 +708,15 @@ int colvarmodule::calc()
   }
 
   // write restart files, if needed
-  if (restart_out_freq && restart_out_name.size()) {
-    error_code |= write_restart_files();
+  if (restart_out_freq && (cvm::step_relative() > 0) &&
+      ((cvm::step_absolute() % restart_out_freq) == 0) ) {
+    if (restart_out_name.size()) {
+      // Write restart file, if different from main output
+      error_code |= write_restart_file(restart_out_name);
+    } else {
+      error_code |= write_restart_file(output_prefix()+".colvars.state");
+    }
+    write_output_files();
   }
 
   return error_code;
@@ -777,7 +819,7 @@ int colvarmodule::calc_biases()
 {
   // update the biases and communicate their forces to the collective
   // variables
-  if (cvm::debug() && biases.size())
+  if (cvm::debug() && num_biases())
     cvm::log("Updating collective variable biases.\n");
 
   std::vector<colvarbias *>::iterator bi;
@@ -839,7 +881,7 @@ int colvarmodule::update_colvar_forces()
   std::vector<colvarbias *>::iterator bi;
 
   // sum the forces from all biases for each collective variable
-  if (cvm::debug() && biases.size())
+  if (cvm::debug() && num_biases())
     cvm::log("Collecting forces from all biases.\n");
   cvm::increase_depth();
   for (bi = biases_active()->begin(); bi != biases_active()->end(); bi++) {
@@ -916,21 +958,16 @@ int colvarmodule::calc_scripted_forces()
 }
 
 
-int colvarmodule::write_restart_files()
+int colvarmodule::write_restart_file(std::string const &out_name)
 {
-  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);
-    std::ostream *restart_out_os = proxy->output_stream(restart_out_name);
-    if (!restart_out_os) return cvm::get_error();
-    if (!write_restart(*restart_out_os)) {
-      return cvm::error("Error: in writing restart file.\n", FILE_ERROR);
-    }
-    proxy->close_output_stream(restart_out_name);
+  cvm::log("Saving collective variables state to \""+out_name+"\".\n");
+  proxy->backup_file(out_name);
+  std::ostream *restart_out_os = proxy->output_stream(out_name);
+  if (!restart_out_os) return cvm::get_error();
+  if (!write_restart(*restart_out_os)) {
+    return cvm::error("Error: in writing restart file.\n", FILE_ERROR);
   }
-
+  proxy->close_output_stream(out_name);
   return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
 }
 
@@ -938,13 +975,20 @@ int colvarmodule::write_restart_files()
 int colvarmodule::write_traj_files()
 {
   if (cv_traj_os == NULL) {
-    open_traj_file(cv_traj_name);
+    if (open_traj_file(cv_traj_name) != COLVARS_OK) {
+      return cvm::get_error();
+    } else {
+      cv_traj_write_labels = true;
+    }
   }
 
   // write labels in the traj file every 1000 lines and at first timestep
-  if ((cvm::step_absolute() % (cv_traj_freq * 1000)) == 0 || cvm::step_relative() == 0) {
+  if ((cvm::step_absolute() % (cv_traj_freq * 1000)) == 0 ||
+      cvm::step_relative() == 0 ||
+      cv_traj_write_labels) {
     write_traj_label(*cv_traj_os);
   }
+  cv_traj_write_labels = false;
 
   if ((cvm::step_absolute() % cv_traj_freq) == 0) {
     write_traj(*cv_traj_os);
@@ -1011,7 +1055,15 @@ colvarmodule::~colvarmodule()
 {
   if ((proxy->smp_thread_id() == COLVARS_NOT_IMPLEMENTED) ||
       (proxy->smp_thread_id() == 0)) {
+
     reset();
+
+    // Delete contents of static arrays
+    colvarbias::delete_features();
+    colvar::delete_features();
+    colvar::cvc::delete_features();
+    atom_group::delete_features();
+
     delete parse;
     parse = NULL;
     proxy = NULL;
@@ -1023,7 +1075,7 @@ int colvarmodule::reset()
 {
   parse->init();
 
-  cvm::log("Resetting the Collective Variables Module.\n");
+  cvm::log("Resetting the Collective Variables module.\n");
 
   // Iterate backwards because we are deleting the elements as we go
   for (std::vector<colvarbias *>::reverse_iterator bi = biases.rbegin();
@@ -1032,6 +1084,7 @@ int colvarmodule::reset()
     delete *bi; // the bias destructor updates the biases array
   }
   biases.clear();
+  biases_active_.clear();
 
   // Iterate backwards because we are deleting the elements as we go
   for (std::vector<colvar *>::reverse_iterator cvi = colvars.rbegin();
@@ -1047,7 +1100,7 @@ int colvarmodule::reset()
   proxy->reset();
 
   if (cv_traj_os != NULL) {
-    // Do not close file here, as we might not be done with it yet.
+    // Do not close traj file here, as we might not be done with it yet.
     proxy->flush_output_stream(cv_traj_os);
   }
 
@@ -1057,8 +1110,6 @@ int colvarmodule::reset()
 
 int colvarmodule::setup_input()
 {
-  if (this->size() == 0) return cvm::get_error();
-
   std::string restart_in_name("");
 
   // read the restart configuration, if available
@@ -1091,14 +1142,12 @@ int colvarmodule::setup_input()
     }
   }
 
-  return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
+  return cvm::get_error();
 }
 
 
 int colvarmodule::setup_output()
 {
-  if (this->size() == 0) return cvm::get_error();
-
   int error_code = COLVARS_OK;
 
   // output state file (restart)
@@ -1107,7 +1156,8 @@ int colvarmodule::setup_output()
     std::string("");
 
   if (restart_out_name.size()) {
-    cvm::log("The restart output state file will be \""+restart_out_name+"\".\n");
+    cvm::log("The restart output state file will be \""+
+             restart_out_name+"\".\n");
   }
 
   output_prefix() = proxy->output_prefix();
@@ -1138,7 +1188,7 @@ int colvarmodule::setup_output()
     set_error_bits(FILE_ERROR);
   }
 
-  return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
+  return cvm::get_error();
 }
 
 
@@ -1150,12 +1200,10 @@ 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);
+      parse->get_keyval(restart_conf, "step",
+                        it_restart, (size_t) 0,
+                        colvarparse::parse_silent);
         it = it_restart;
-      }
       std::string restart_version;
       parse->get_keyval(restart_conf, "version",
                         restart_version, std::string(""),
@@ -1261,7 +1309,7 @@ continue the previous simulation.\n\n");
 to:\n\
 \""+ proxy->input_prefix()+".colvars.state\"\n");
     output_prefix() = output_prefix()+".tmp";
-    write_output_files();
+    write_restart_file(output_prefix()+".colvars.state");
     cvm::error("Exiting with error until issue is addressed.\n", FATAL_ERROR);
   }
 
@@ -1277,24 +1325,13 @@ int colvarmodule::backup_file(char const *filename)
 
 int 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");
-
-  std::ostream * os = proxy->output_stream(out_name);
-  os->setf(std::ios::scientific, std::ios::floatfield);
-  this->write_restart(*os);
-  proxy->close_output_stream(out_name);
+  int error_code = COLVARS_OK;
 
   cvm::increase_depth();
   for (std::vector<colvar *>::iterator cvi = colvars.begin();
        cvi != colvars.end();
        cvi++) {
-    (*cvi)->write_output_files();
+    error_code |= (*cvi)->write_output_files();
   }
   cvm::decrease_depth();
 
@@ -1302,8 +1339,8 @@ int colvarmodule::write_output_files()
   for (std::vector<colvarbias *>::iterator bi = biases.begin();
        bi != biases.end();
        bi++) {
-    (*bi)->write_output_files();
-    (*bi)->write_state_to_replicas();
+    error_code |= (*bi)->write_output_files();
+    error_code |= (*bi)->write_state_to_replicas();
   }
   cvm::decrease_depth();
 
@@ -1403,15 +1440,12 @@ std::ostream & colvarmodule::write_restart(std::ostream &os)
        cvi != colvars.end();
        cvi++) {
     (*cvi)->write_restart(os);
-    error_code |= (*cvi)->write_output_files();
   }
 
   for (std::vector<colvarbias *>::iterator bi = biases.begin();
        bi != biases.end();
        bi++) {
     (*bi)->write_state(os);
-    error_code |= (*bi)->write_state_to_replicas();
-    error_code |= (*bi)->write_output_files();
   }
   cvm::decrease_depth();
 
@@ -1664,40 +1698,59 @@ int cvm::read_index_file(char const *filename)
   return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
 }
 
+
 int cvm::load_atoms(char const *file_name,
                     cvm::atom_group &atoms,
                     std::string const &pdb_field,
-                    double const pdb_field_value)
+                    double pdb_field_value)
 {
   return proxy->load_atoms(file_name, atoms, pdb_field, pdb_field_value);
 }
 
+
 int cvm::load_coords(char const *file_name,
-                     std::vector<cvm::atom_pos> &pos,
-                     const std::vector<int> &indices,
+                     std::vector<cvm::rvector> *pos,
+                     cvm::atom_group *atoms,
                      std::string const &pdb_field,
-                     double const pdb_field_value)
+                     double pdb_field_value)
 {
-  // Differentiate between PDB and XYZ files
-  // for XYZ files, use CVM internal parser
-  // otherwise call proxy function for PDB
+  int error_code = COLVARS_OK;
+
+  std::string const ext(strlen(file_name) > 4 ?
+                        (file_name + (strlen(file_name) - 4)) :
+                        file_name);
+
+  atoms->create_sorted_ids();
 
-  std::string const ext(strlen(file_name) > 4 ? (file_name + (strlen(file_name) - 4)) : file_name);
+  std::vector<cvm::rvector> sorted_pos(atoms->size(), cvm::rvector(0.0));
+
+  // Differentiate between PDB and XYZ files
   if (colvarparse::to_lower_cppstr(ext) == std::string(".xyz")) {
-    if ( pdb_field.size() > 0 ) {
-      cvm::error("Error: PDB column may not be specified for XYZ coordinate file.\n", INPUT_ERROR);
-      return COLVARS_ERROR;
+    if (pdb_field.size() > 0) {
+      return cvm::error("Error: PDB column may not be specified "
+                        "for XYZ coordinate files.\n", INPUT_ERROR);
     }
-    return cvm::load_coords_xyz(file_name, pos, indices);
+    // For XYZ files, use internal parser
+    error_code |= cvm::load_coords_xyz(file_name, &sorted_pos, atoms);
   } else {
-    return proxy->load_coords(file_name, pos, indices, pdb_field, pdb_field_value);
+    // Otherwise, call proxy function for PDB
+    error_code |= proxy->load_coords(file_name,
+                                     sorted_pos, atoms->sorted_ids(),
+                                     pdb_field, pdb_field_value);
   }
+
+  std::vector<int> const &map = atoms->sorted_ids_map();
+  for (size_t i = 0; i < atoms->size(); i++) {
+    (*pos)[map[i]] = sorted_pos[i];
+  }
+
+  return error_code;
 }
 
 
 int cvm::load_coords_xyz(char const *filename,
-                         std::vector<atom_pos> &pos,
-                         const std::vector<int> &indices)
+                         std::vector<rvector> *pos,
+                         cvm::atom_group *atoms)
 {
   std::ifstream xyz_is(filename);
   unsigned int natoms;
@@ -1712,12 +1765,12 @@ int cvm::load_coords_xyz(char const *filename,
   cvm::getline(xyz_is, line);
   cvm::getline(xyz_is, line);
   xyz_is.width(255);
-  std::vector<atom_pos>::iterator pos_i = pos.begin();
+  std::vector<atom_pos>::iterator pos_i = pos->begin();
 
-  if (pos.size() != natoms) { // Use specified indices
+  if (pos->size() != natoms) { // Use specified indices
     int next = 0; // indices are zero-based
-    std::vector<int>::const_iterator index = indices.begin();
-    for ( ; pos_i != pos.end() ; pos_i++, index++) {
+    std::vector<int>::const_iterator index = atoms->sorted_ids().begin();
+    for ( ; pos_i != pos->end() ; pos_i++, index++) {
 
       while ( next < *index ) {
         cvm::getline(xyz_is, line);
@@ -1727,7 +1780,7 @@ int cvm::load_coords_xyz(char const *filename,
       xyz_is >> (*pos_i)[0] >> (*pos_i)[1] >> (*pos_i)[2];
     }
   } else {          // Use all positions
-    for ( ; pos_i != pos.end() ; pos_i++) {
+    for ( ; pos_i != pos->end() ; pos_i++) {
       xyz_is >> symbol;
       xyz_is >> (*pos_i)[0] >> (*pos_i)[1] >> (*pos_i)[2];
     }
@@ -1736,6 +1789,85 @@ int cvm::load_coords_xyz(char const *filename,
 }
 
 
+
+// Wrappers to proxy functions: these may go in the future
+
+cvm::real cvm::unit_angstrom()
+{
+  return proxy->unit_angstrom();
+}
+
+
+cvm::real cvm::boltzmann()
+{
+  return proxy->boltzmann();
+}
+
+
+cvm::real cvm::temperature()
+{
+  return proxy->temperature();
+}
+
+
+cvm::real cvm::dt()
+{
+  return proxy->dt();
+}
+
+
+void cvm::request_total_force()
+{
+  proxy->request_total_force(true);
+}
+
+
+cvm::rvector cvm::position_distance(cvm::atom_pos const &pos1,
+                                    cvm::atom_pos const &pos2)
+{
+  return proxy->position_distance(pos1, pos2);
+}
+
+
+cvm::real cvm::rand_gaussian(void)
+{
+  return proxy->rand_gaussian();
+}
+
+
+
+bool cvm::replica_enabled()
+{
+  return proxy->replica_enabled();
+}
+
+int cvm::replica_index()
+{
+  return proxy->replica_index();
+}
+
+int cvm::replica_num()
+{
+  return proxy->replica_num();
+}
+
+void cvm::replica_comm_barrier()
+{
+  return proxy->replica_comm_barrier();
+}
+
+int cvm::replica_comm_recv(char* msg_data, int buf_len, int src_rep)
+{
+  return proxy->replica_comm_recv(msg_data,buf_len,src_rep);
+}
+
+int cvm::replica_comm_send(char* msg_data, int msg_len, int dest_rep)
+{
+  return proxy->replica_comm_send(msg_data,msg_len,dest_rep);
+}
+
+
+
 // shared pointer to the proxy object
 colvarproxy *colvarmodule::proxy = NULL;