From 16b9eb8505a7ed765047ff1b1bb61642417e54fd Mon Sep 17 00:00:00 2001
From: Carlo Camilloni <carlo.camilloni@gmail.com>
Date: Mon, 2 Jun 2014 00:55:40 +0100
Subject: [PATCH] ENSEMBLE: perform replica-averaging on any collective
 variable

---
 CHANGES/Unreleased.txt    |   7 +--
 src/function/Ensemble.cpp | 111 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 115 insertions(+), 3 deletions(-)
 create mode 100644 src/function/Ensemble.cpp

diff --git a/CHANGES/Unreleased.txt b/CHANGES/Unreleased.txt
index 12abb139d..e8a2555b2 100644
--- a/CHANGES/Unreleased.txt
+++ b/CHANGES/Unreleased.txt
@@ -20,13 +20,14 @@ Changes from version 2.0 which are relevant for users:
   - \ref NLINKS.
   - \ref DIHCOR.
   - \ref NOE.
-  - \ref RDC.
+  - \ref RDC. 
   - \ref CLASSICAL_MDS
   - \ref XDISTANCES
   - \ref YDISTANCES 
   - \ref ZDISTANCES
   - \ref DUMPMULTICOLVAR
   - Crystallation module, including \ref Q4, \ref Q6, \ref LOCAL_Q4, \ref LOCAL_Q6, \ref MOLECULES, \ref SIMPLECUBIC, \ref TETRAHEDRAL and \ref FCCUBIC.
+  - \ref ENSEMBLE to perform Replica-Averaging on any collective variable.
 - New features for existing actions:
   - \ref METAD : WALKERS_MPI flag (multiple walkers in a mpi-based multi-replica framework),
     ACCELERATION flag (calculate on the fly the Metadynamics acceleration factor),
@@ -40,8 +41,8 @@ Changes from version 2.0 which are relevant for users:
   - \ref GROUP : NDX_FILE and NDX_GROUP options to import atom lists from ndx (gromacs) files.
   - In many multicolvars, MIN and MAX options can be used.
   - \ref HISTOGRAM : GRID_SPACING (alternative to GRID_BIN to set grid spacing),
-    FREQUENCY and FREE-ENERGY flags in addition to standard probability density,
-    additional option for KERNEL=NONE to accumulate standard histograms. 
+    FREE-ENERGY flags in addition to standard probability density,
+    additional option for KERNEL=DISCRETE to accumulate standard histograms. 
   - \ref sum_hills : added options --spacing (alternative to --bin to set grid spacing)
     and --setmintozero to translate the minimum of the output files to zero.
 - New features in MD patches (require repatch):
diff --git a/src/function/Ensemble.cpp b/src/function/Ensemble.cpp
new file mode 100644
index 000000000..757cf03b1
--- /dev/null
+++ b/src/function/Ensemble.cpp
@@ -0,0 +1,111 @@
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   Copyright (c) 2013 The plumed team
+   (see the PEOPLE file at the root of the distribution for a list of names)
+
+   See http://www.plumed-code.org for more information.
+
+   This file is part of plumed, version 2.
+
+   plumed is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   plumed is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with plumed.  If not, see <http://www.gnu.org/licenses/>.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+#include "Function.h"
+#include "ActionRegister.h"
+#include "tools/Communicator.h"
+
+using namespace std;
+
+namespace PLMD{
+namespace function{
+
+//+PLUMEDOC FUNCTION ENSEMBLE
+/*
+Calculates the replica averaging of a collective variable over multiple replicas.
+
+Each collective variable is averaged separately and stored in a component labelled <em>label</em>.cvlabel.  
+
+
+\par Examples
+The following input tells plumed to calculate the distance between atoms 3 and 5
+and the average it over the available replicas.
+\verbatim
+dist: DISTANCE ATOMS=3,5 
+ens: ENSEMBLE ARG=dist
+PRINT ARG=dist,ens.dist
+\endverbatim
+(See also \ref PRINT and \ref DISTANCE).
+
+*/
+//+ENDPLUMEDOC
+
+
+class Ensemble :
+  public Function
+{
+  unsigned  ens_dim;
+  double    fact;
+public:
+  Ensemble(const ActionOptions&);
+  void calculate();
+  static void registerKeywords(Keywords& keys);
+};
+
+
+PLUMED_REGISTER_ACTION(Ensemble,"ENSEMBLE")
+
+void Ensemble::registerKeywords(Keywords& keys){
+  Function::registerKeywords(keys);
+  keys.use("ARG");
+  ActionWithValue::useCustomisableComponents(keys);
+}
+
+Ensemble::Ensemble(const ActionOptions&ao):
+Action(ao),
+Function(ao)
+{
+  if(comm.Get_rank()==0) {
+    if(multi_sim_comm.Get_size()<2) error("You CANNOT run Replica-Averaged simulations without running multiple replicas!\n");
+    else ens_dim=multi_sim_comm.Get_size(); 
+  } else ens_dim=0; 
+  comm.Sum(&ens_dim, 1);
+  fact = 1./((double) ens_dim);
+  for(unsigned i=0;i<getNumberOfArguments();i++) {
+     std::string s=getPntrToArgument(i)->getName();
+     addComponentWithDerivatives(s); 
+     getPntrToComponent(i)->setNotPeriodic();
+  }
+  log.printf("  using %u replicas.\n", ens_dim);
+  checkRead();
+}
+
+void Ensemble::calculate(){
+  for(unsigned i=0;i<getNumberOfArguments();++i){
+    double cv=0.;
+    if(comm.Get_rank()==0) { // I am the master of my replica
+      // among replicas
+      cv = getArgument(i);
+      multi_sim_comm.Sum(&cv, 1);
+      cv *= fact; 
+    }
+    // inside each replica
+    comm.Sum(&cv, 1);
+    Value* v=getPntrToComponent(i);
+    v->set(cv);
+    setDerivative(v,cv,fact);
+  };
+}
+
+}
+}
+
+
-- 
GitLab