From a0479f21bbb215c1df38f74fbb415eca0385b86c Mon Sep 17 00:00:00 2001
From: Gareth Tribello <gareth.tribello@gmail.com>
Date: Thu, 31 Dec 2015 09:46:03 +0000
Subject: [PATCH] Using new grid infrastructure for histogram

---
 regtest/analysis/rt0/plumed.dat       |  47 ++++---
 src/analysis/Analysis.cpp             |  39 ++++--
 src/analysis/Analysis.h               |   3 +-
 src/analysis/Histogram.cpp            | 170 ++++++++------------------
 src/analysis/Makefile                 |   2 +-
 src/core/ActionPilot.cpp              |   5 +
 src/core/ActionPilot.h                |   1 +
 src/gridtools/ActionWithInputGrid.cpp |  19 ++-
 src/gridtools/ActionWithInputGrid.h   |   5 +-
 src/gridtools/ConvertToFES.cpp        |  99 +++++++++++++++
 src/gridtools/GridFunction.cpp        |  48 ++++++++
 src/gridtools/GridFunction.h          |  41 +++++++
 src/gridtools/GridVessel.cpp          |  50 +++++++-
 src/gridtools/GridVessel.h            |  19 ++-
 src/gridtools/HistogramOnGrid.cpp     |  69 +++++++----
 src/gridtools/HistogramOnGrid.h       |   1 +
 src/gridtools/PrintCube.cpp           |   3 +
 src/gridtools/PrintGrid.cpp           |   8 +-
 src/vesselbase/ActionWithVessel.h     |   2 +
 19 files changed, 428 insertions(+), 203 deletions(-)
 create mode 100644 src/gridtools/ConvertToFES.cpp
 create mode 100644 src/gridtools/GridFunction.cpp
 create mode 100644 src/gridtools/GridFunction.h

diff --git a/regtest/analysis/rt0/plumed.dat b/regtest/analysis/rt0/plumed.dat
index bba4549e6..22ba7aca7 100755
--- a/regtest/analysis/rt0/plumed.dat
+++ b/regtest/analysis/rt0/plumed.dat
@@ -9,11 +9,11 @@ HISTOGRAM ...
   GRID_MAX=3.0
   GRID_BIN=100
   BANDWIDTH=0.1
-  GRID_WFILE=histoA
-  FMT=%8.4f
-  RUN=1
+  LABEL=hA
 ... HISTOGRAM
 
+PRINT_GRID GRID=hA FILE=histoA STRIDE=1 FMT=%8.4f
+
 HISTOGRAM ...
   ARG=x
   TEMP=300
@@ -21,83 +21,80 @@ HISTOGRAM ...
   GRID_MAX=3.0
   GRID_BIN=100
   BANDWIDTH=0.1
-  GRID_WFILE=histoB
-  FMT=%8.4f
   REWEIGHT_BIAS
-  RUN=1
+  LABEL=hB
 ... HISTOGRAM
 
+PRINT_GRID GRID=hB FILE=histoB STRIDE=1 FMT=%8.4f
+
 HISTOGRAM ...
   ARG=x
-  USE_ALL_DATA
   GRID_MIN=0.0
   GRID_MAX=3.0
   GRID_BIN=100
   BANDWIDTH=0.1
-  GRID_WFILE=histoC
+  LABEL=hC
 ... HISTOGRAM
 
+PRINT_GRID GRID=hC FILE=histoC USE_ALL_DATA 
+
 HISTOGRAM ...
   ARG=x
   TEMP=300
-  USE_ALL_DATA
   GRID_MIN=0.0
   GRID_MAX=3.0
   GRID_BIN=100
   KERNEL=DISCRETE
-  FMT=%8.4f
   REWEIGHT_BIAS
-  GRID_WFILE=histoD
-  UNNORMALIZED
+  LABEL=hD
 ... HISTOGRAM
 
+PRINT_GRID GRID=hD FILE=histoD FMT=%8.4f UNNORMALIZED USE_ALL_DATA
+
 HISTOGRAM ...
   ARG=x
   TEMP=10000
-  USE_ALL_DATA
   GRID_MIN=0.0
   GRID_MAX=3.0
   GRID_BIN=100
   KERNEL=DISCRETE
-  FMT=%8.4f
   REWEIGHT_BIAS
-  GRID_WFILE=histoE
-  FREE-ENERGY
-  UNNORMALIZED
+  LABEL=hE
 ... HISTOGRAM
 
+fE: CONVERT_TO_FES GRID=hE TEMP=10000 UNNORMALIZED
+PRINT_GRID GRID=fE FMT=%8.4f USE_ALL_DATA FILE=histoE 
+
 HISTOGRAM ...
   ARG=x
   TEMP=300
-  USE_ALL_DATA
   GRID_MIN=0.0
   GRID_MAX=3.0
   GRID_BIN=100
   KERNEL=DISCRETE
-  FMT=%8.4f
   REWEIGHT_BIAS
-  GRID_WFILE=histoD1
-  UNNORMALIZED
   UPDATE_FROM=0
   UPDATE_UNTIL=1
+  LABEL=hD1
 ... HISTOGRAM
 
+PRINT_GRID GRID=hD1 FILE=histoD1 FMT=%8.4f UNNORMALIZED USE_ALL_DATA
+
 HISTOGRAM ...
   ARG=x
   TEMP=300
-  USE_ALL_DATA
   GRID_MIN=0.0
   GRID_MAX=3.0
   GRID_BIN=100
   KERNEL=DISCRETE
-  FMT=%8.4f
   REWEIGHT_BIAS
-  GRID_WFILE=histoD2
-  UNNORMALIZED
   UPDATE_FROM=1
   UPDATE_UNTIL=2
+  LABEL=hD2
 ... HISTOGRAM
 
+PRINT_GRID GRID=hD2 FILE=histoD2 FMT=%8.4f UNNORMALIZED USE_ALL_DATA
+
 
 
 
diff --git a/src/analysis/Analysis.cpp b/src/analysis/Analysis.cpp
index 648f3e1e2..6c8e86712 100644
--- a/src/analysis/Analysis.cpp
+++ b/src/analysis/Analysis.cpp
@@ -94,6 +94,7 @@ nomemory(true),
 write_chq(false),
 reusing_data(false),
 ignore_reweight(false),
+freq(0),
 needeng(false),
 idata(0),
 firstAnalysisDone(false),
@@ -175,20 +176,16 @@ argument_names(getNumberOfArguments())
          if(simtemp==0) error("The MD engine does not pass the temperature to plumed so you have to specify it using TEMP");
       }
 
-      parseFlag("USE_ALL_DATA",single_run); 
-      if( !single_run ){
-          parse("RUN",freq );
-          log.printf("  running analysis every %u steps\n",freq);
-          if( freq%getStride()!= 0 ) error("Frequncy of running is not a multiple of the stride");
-          ndata=freq/getStride();
-          data.resize( ndata );
-          for(unsigned i=0;i<ndata;++i){ 
-             data[i]=metricRegister().create<ReferenceConfiguration>( metricname ); 
-             data[i]->setNamesAndAtomNumbers( atom_numbers, argument_names );
+      single_run=true;
+      if( keywords.exists("USE_ALL_DATA") ){
+          parseFlag("USE_ALL_DATA",single_run); 
+          if( !single_run ){
+              unsigned astride; parse("RUN",astride);
+              log.printf("  running analysis every %u steps\n",astride);
+              setAnalysisStride( false, astride );
+          } else {       
+              log.printf("  analyzing all data in trajectory\n");
           }
-          logweights.resize( ndata );
-      } else {       
-          log.printf("  analyzing all data in trajectory\n");
       }
       if( keywords.exists("NOMEMORY") ){ nomemory=false; parseFlag("NOMEMORY",nomemory); }
       if(nomemory) log.printf("  doing a separate analysis for each block of data\n");
@@ -221,6 +218,20 @@ argument_names(getNumberOfArguments())
   }
 }
 
+void Analysis::setAnalysisStride( const bool& use_all, const unsigned& astride ){
+  if( freq>0 && astride!=freq ) error("frequency for output does not match frequency for run"); 
+  else if( freq>0 || use_all ) return;
+
+  freq=astride; single_run=false;
+  if( astride%getStride()!= 0 ) error("Frequncy of running is not a multiple of the stride");
+  ndata=freq/getStride(); data.resize( ndata );
+  for(unsigned i=0;i<ndata;++i){
+     data[i]=metricRegister().create<ReferenceConfiguration>( metricname );
+     data[i]->setNamesAndAtomNumbers( getAbsoluteIndexes(), argument_names );
+  }
+  logweights.resize( ndata );
+}
+
 void Analysis::readDataFromFile( const std::string& filename ){
   FILE* fp=fopen(filename.c_str(),"r"); double tstep, oldtstep; 
   if(fp!=NULL){
@@ -394,6 +405,8 @@ void Analysis::runAnalysis(){
      mydatastash->finalizeWeights( ignore_reweight );
      norm=mydatastash->retrieveNorm();
   }
+  // This ensures everything is set up to run the calculation
+  setAnalysisStride( single_run, freq );
   // And run the analysis
   performAnalysis(); idata=0;
   // Update total normalization constant
diff --git a/src/analysis/Analysis.h b/src/analysis/Analysis.h
index de5f69d11..27f7f9fb4 100644
--- a/src/analysis/Analysis.h
+++ b/src/analysis/Analysis.h
@@ -148,7 +148,8 @@ public:
   void unlockRequests();
   void calculateNumericalDerivatives( ActionWithValue* a=NULL ){ plumed_error(); }
   bool isPeriodic(){ plumed_error(); return false; }
-  unsigned getNumberOfDerivatives(){ plumed_error(); return 0; }
+  unsigned getNumberOfDerivatives(){ return 0; }
+  virtual void setAnalysisStride( const bool& use_all, const unsigned& astride );
 };
 
 inline
diff --git a/src/analysis/Histogram.cpp b/src/analysis/Histogram.cpp
index 1ae64bf30..d2519e7f9 100644
--- a/src/analysis/Histogram.cpp
+++ b/src/analysis/Histogram.cpp
@@ -26,6 +26,7 @@
 #include "tools/KernelFunctions.h"
 #include "tools/IFile.h"
 #include "tools/OFile.h"
+#include "gridtools/HistogramOnGrid.h"
 
 namespace PLMD{
 namespace analysis{
@@ -115,7 +116,7 @@ HISTOGRAM ...
 
 class Histogram : public Analysis {
 private:
-  std::vector<std::string> gmin, gmax; 
+  gridtools::HistogramOnGrid* mygrid;
   std::vector<double> point, bw;
   std::vector<unsigned> gbin;
   std::string gridfname;
@@ -126,7 +127,9 @@ public:
   static void registerKeywords( Keywords& keys );
   explicit Histogram(const ActionOptions&ao);
   void performAnalysis();
+  unsigned getNumberOfQuantities() const ;
   void performTask( const unsigned& , const unsigned& , MultiValue& ) const ;
+  void setAnalysisStride( const bool& use_all, const unsigned& astride );
 };
 
 PLUMED_REGISTER_ACTION(Histogram,"HISTOGRAM")
@@ -134,6 +137,7 @@ PLUMED_REGISTER_ACTION(Histogram,"HISTOGRAM")
 void Histogram::registerKeywords( Keywords& keys ){
   Analysis::registerKeywords( keys ); keys.reset_style("METRIC","hidden");
   keys.remove("ATOMS"); keys.reset_style("ARG","compulsory");
+  keys.remove("RUN"); keys.remove("USE_ALL_DATA");
   keys.add("compulsory","GRID_MIN","the lower bounds for the grid");
   keys.add("compulsory","GRID_MAX","the upper bounds for the grid");
   keys.add("optional","GRID_BIN","the number of bins for the grid");
@@ -141,148 +145,70 @@ void Histogram::registerKeywords( Keywords& keys ){
   keys.add("compulsory","KERNEL","gaussian","the kernel function you are using. Use discrete/DISCRETE if you want to accumulate a discrete histogram. \
                                              More details on the kernels available in plumed can be found in \\ref kernelfunctions.");
   keys.add("optional","BANDWIDTH","the bandwdith for kernel density estimation");
-  keys.addFlag("FREE-ENERGY",false,"Set to TRUE if you want a FREE ENERGY instead of a probabilty density (you need to set TEMP).");
   keys.addFlag("UNNORMALIZED",false,"Set to TRUE if you don't want histogram to be normalized or free energy to be shifted.");
-  keys.add("compulsory","GRID_WFILE","histogram","the file on which to write the grid");
   keys.use("NOMEMORY");
 }
 
 Histogram::Histogram(const ActionOptions&ao):
 PLUMED_ANALYSIS_INIT(ao),
+mygrid(NULL),
 point(getNumberOfArguments()),
 fenergy(false),
 unnormalized(false)
 {
-  // Read stuff for Grid
-  parseVector("GRID_MIN",gmin);
-  if(gmin.size()!=getNumberOfArguments()) error("Wrong number of values for GRID_MIN: they should be equal to the number of arguments");
-  parseVector("GRID_MAX",gmax);
-  if(gmax.size()!=getNumberOfArguments()) error("Wrong number of values for GRID_MAX: they should be equal to the number of arguments");
-  parseVector("GRID_BIN",gbin);
-  if(gbin.size()!=getNumberOfArguments() && gbin.size()!=0) error("Wrong number of values for GRID_BIN: they should be equal to the number of arguments");
-  std::vector<double>  gspacing;
-  parseVector("GRID_SPACING",gspacing);
-  if(gspacing.size()!=getNumberOfArguments() && gspacing.size()!=0) 
-    error("Wrong number of for GRID_SPACING: they should be equal to the number of arguments");
-  if(gbin.size()==0 && gspacing.size()==0)  { error("At least one among GRID_BIN and GRID_SPACING should be used");
-  } else if(gspacing.size()!=0 && gbin.size()==0) {
-    log<<"  The number of bins will be estimated from GRID_SPACING\n";
-  } else if(gspacing.size()!=0 && gbin.size()!=0) {
-    log<<"  You specified both GRID_BIN and GRID_SPACING\n";
-    log<<"  The more conservative (highest) number of bins will be used for each variable\n";
+  // Read stuff for grid
+  std::vector<std::string> gmin( getNumberOfArguments() ), gmax( getNumberOfArguments() );
+  parseVector("GRID_MIN",gmin); parseVector("GRID_MAX",gmax);
+
+  // Setup input for grid vessel
+  std::string dmin, dmax, vstring = getKeyword("KERNEL") + " " + getKeyword("BANDWIDTH");
+  if( getPeriodicityInformation(0, dmin, dmax) ) vstring+=" PBC=T";
+  else vstring+=" PBC=F";
+  for(unsigned i=1;i<getNumberOfArguments();++i){
+     if( getPeriodicityInformation(i, dmin, dmax) ) vstring+=",T";
+     else vstring+=",F";
   }
-  if(gbin.size()==0) gbin.assign(getNumberOfArguments(),1);
-  if(gspacing.size()!=0) for(unsigned i=0;i<getNumberOfArguments();i++){
-      double a,b;
-      Tools::convert(gmin[i],a);
-      Tools::convert(gmax[i],b);
-      unsigned n=((b-a)/gspacing[i])+1;
-      if(gbin[i]<n) gbin[i]=n;
+  vstring += " STORE_NORMED COMPONENTS=" + getLabel();
+  vstring += " COORDINATES=" + getPntrToArgument(0)->getName();
+  for(unsigned i=1;i<getNumberOfArguments();++i) vstring += "," + getPntrToArgument(i)->getName(); 
+  if( !usingMemory() ) vstring += " NOMEMORY";
+  std::vector<unsigned> nbin; parseVector("GRID_BIN",nbin);
+  std::vector<double> gspacing; parseVector("GRID_SPACING",gspacing);
+  if( nbin.size()!=getNumberOfArguments() && gspacing.size()!=getNumberOfArguments() ){
+      error("GRID_BIN or GRID_SPACING must be set");
   }
-  parseOutputFile("GRID_WFILE",gridfname); 
 
-  // Read the type of kernel we are using
-  parse("KERNEL",kerneltype);
-  if(kerneltype=="DISCRETE") kerneltype="discrete";
-  // Read stuff for window functions
-  parseVector("BANDWIDTH",bw);
-  if(bw.size()!=getNumberOfArguments()&&kerneltype!="discrete") 
-    error("Wrong number of values for BANDWIDTH: they should be equal to the number of arguments");
+  // Create a grid
+  vesselbase::VesselOptions da("mygrid","",-1,vstring,this);
+  Keywords keys; gridtools::HistogramOnGrid::registerKeywords( keys );
+  vesselbase::VesselOptions dar( da, keys );
+  mygrid = new gridtools::HistogramOnGrid(dar); addVessel( mygrid );
+  mygrid->setBounds( gmin, gmax, nbin, gspacing );
+  resizeFunctions();
 
-  parseFlag("FREE-ENERGY",fenergy);
-  if(getTemp()<=0 && fenergy) error("Set the temperature (TEMP) if you want a free energy.");
-
-  parseFlag("UNNORMALIZED",unnormalized);
-  if(unnormalized){
-    if(fenergy) log<<"  free energy will not be shifted to set its minimum to zero\n";
-    else        log<<"  histogram will not be normalized\n";
-  } else {
-    if(fenergy) log<<"  free energy will be shifted to set its minimum to zero\n";
-    else        log<<"  histogram will be normalized\n";
-  }
   checkRead();
-
-  log.printf("  Using %s kernel functions\n",kerneltype.c_str() );
-  log.printf("  Grid min");
-  for(unsigned i=0;i<gmin.size();++i) log.printf(" %s",gmin[i].c_str() );
-  log.printf("\n");
-  log.printf("  Grid max");
-  for(unsigned i=0;i<gmax.size();++i) log.printf(" %s",gmax[i].c_str() );
-  log.printf("\n");
-  log.printf("  Grid bin");
-  for(unsigned i=0;i<gbin.size();++i) log.printf(" %u",gbin[i]);
-  log.printf("\n");
 }
 
-void Histogram::performTask( const unsigned& , const unsigned& , MultiValue& ) const { plumed_error(); }
-
-void Histogram::performAnalysis(){
-  // Back up old histogram files
-  //  std::string oldfname=saveResultsFromPreviousAnalyses( gridfname );
-
-  // Get pbc stuff for grid
-  std::vector<bool> pbc; std::string dmin,dmax; std::vector<double> pmin,pmax;
-  pmin.resize(getNumberOfArguments());
-  pmax.resize(getNumberOfArguments());
-  for(unsigned i=0;i<getNumberOfArguments();++i){
-     pbc.push_back( getPeriodicityInformation(i,dmin,dmax) );
-     if(pbc[i]){ 
-       Tools::convert(dmin,gmin[i]); 
-       Tools::convert(dmax,gmax[i]);
-       Tools::convert(dmin,pmin[i]);
-       Tools::convert(dmax,pmax[i]);
-     }
-  }
+void Histogram::setAnalysisStride( const bool& use_all, const unsigned& astride ){
+  if( getFullNumberOfTasks()>0 && getFullNumberOfTasks()==getNumberOfDataPoints() ) return;
+  Analysis::setAnalysisStride( use_all, astride ); plumed_assert( getFullNumberOfTasks()==0 );
+  for(unsigned i=0;i<getNumberOfDataPoints();++i) addTaskToList( i );
+}
 
-  Grid* gg; IFile oldf; oldf.link(*this); 
-  if( usingMemory() && oldf.FileExist(gridfname) ){
-      if(fenergy) error("FREE-ENERGY only works with USE_ALL_DATA");
-      if(unnormalized) error("UNNORMALIZED only works with USE_ALL_DATA");
-      oldf.open(gridfname);
-      gg = Grid::create( "probs", getArguments(), oldf, gmin, gmax, gbin, false, false, false );
-      oldf.close();
-  } else {
-      gg = new Grid( "probs", getArguments(), gmin, gmax, gbin,false,false);
-  }
-  // Set output format for grid
-  gg->setOutputFmt( getOutputFormat() );
+unsigned Histogram::getNumberOfQuantities() const {
+  return getNumberOfArguments() + 2;
+}
 
-  // Now build the histogram
+void Histogram::performTask( const unsigned& task_index, const unsigned& current, MultiValue& myvals ) const {  
   double weight; std::vector<double> point( getNumberOfArguments() );
-  if(kerneltype!="discrete") {
-    for(unsigned i=0;i<getNumberOfDataPoints();++i){
-      getDataPoint( i, point, weight );
-      KernelFunctions kernel( point, bw, kerneltype, false, weight, true);
-      gg->addKernel( kernel );
-    }
-  } else {
-    for(unsigned i=0;i<getNumberOfDataPoints();++i){
-      getDataPoint( i, point, weight );
-      // Without KERNEL the point are assigned with a lower approximation (floor)
-      // in order to have a correct assigmnet points must be translated of half
-      // the mesh
-      std::vector<double> dx_;
-      dx_ = gg->getDx();
-      for(unsigned j=0;j<point.size();j++) { 
-         point[j]+=0.5*dx_[j];
-         if(pbc[j]&&point[j]>pmax[j]) point[j] -= (pmax[j]-pmin[j]);
-      }
-      gg->addValue(gg->getIndex(point), weight);
-    }  
-  }
-
-  // Normalize the histogram
-  if(!unnormalized) gg->scaleAllValuesAndDerivatives( 1.0 / getNormalization() );
-  if(fenergy) {
-    gg->logAllValuesAndDerivatives( -getTemp() );
-    if(!unnormalized) gg->setMinToZero();
-  }
+  getDataPoint( current, point, weight );
+  myvals.setValue( 0, 1.0 );
+  for(unsigned j=0;j<getNumberOfArguments();++j) myvals.setValue( 1+j, point[j] );
+  myvals.setValue( 1+getNumberOfArguments(), weight );
+}
 
-  // Write the grid to a file
-  OFile gridfile; gridfile.link(*this); gridfile.setBackupString("analysis");
-  gridfile.open( gridfname ); gg->writeToFile( gridfile );
-  // Close the file 
-  gridfile.close(); delete gg;
+void Histogram::performAnalysis(){
+  runAllTasks(); mygrid->setNorm( getNormalization() );
 }
 
 }
diff --git a/src/analysis/Makefile b/src/analysis/Makefile
index 5e8a0d81a..bdf98d20a 100644
--- a/src/analysis/Makefile
+++ b/src/analysis/Makefile
@@ -1,4 +1,4 @@
-USE=core tools reference vesselbase
+USE=core tools reference vesselbase gridtools
 
 #generic makefile
 include ../maketools/make.module
diff --git a/src/core/ActionPilot.cpp b/src/core/ActionPilot.cpp
index 0b17378f4..539e1d7ed 100644
--- a/src/core/ActionPilot.cpp
+++ b/src/core/ActionPilot.cpp
@@ -42,6 +42,11 @@ bool ActionPilot::onStep()const{
 int ActionPilot::getStride()const{
   return stride;
 }
+
+void ActionPilot::setStride( const unsigned& ss ){
+  stride=ss;
+}
+
 }
 
 
diff --git a/src/core/ActionPilot.h b/src/core/ActionPilot.h
index 61e7bede2..a4a1d74a0 100644
--- a/src/core/ActionPilot.h
+++ b/src/core/ActionPilot.h
@@ -42,6 +42,7 @@ class ActionPilot:
   int stride; // multiple time step
 protected:
   int getStride()const;
+  void setStride( const unsigned& ss );
 public:
   explicit ActionPilot(const ActionOptions&);
 /// Create the keywords for actionPilot
diff --git a/src/gridtools/ActionWithInputGrid.cpp b/src/gridtools/ActionWithInputGrid.cpp
index f0dfe559e..7ee8323ba 100644
--- a/src/gridtools/ActionWithInputGrid.cpp
+++ b/src/gridtools/ActionWithInputGrid.cpp
@@ -29,15 +29,17 @@ namespace gridtools {
 void ActionWithInputGrid::registerKeywords( Keywords& keys ){
   Action::registerKeywords( keys );
   ActionPilot::registerKeywords( keys );
+  vesselbase::ActionWithVessel::registerKeywords( keys );
   keys.add("compulsory","GRID","the action that creates the input grid you would like to use");
-  keys.add("compulsory","STRIDE","the frequency with which to output the grid");
+  keys.add("optional","STRIDE","the frequency with which to output the grid");
   keys.addFlag("USE_ALL_DATA",false,"use the data from the entire trajectory to perform the analysis");
-  keys.addFlag("UNORMALISED",false,"output an unormalised grid"); 
+  keys.addFlag("UNNORMALIZED",false,"output an unormalised grid"); 
 }
 
 ActionWithInputGrid::ActionWithInputGrid(const ActionOptions&ao):
 Action(ao),
 ActionPilot(ao),
+ActionWithVessel(ao),
 norm(0.0),
 mygrid(NULL)
 {
@@ -53,7 +55,7 @@ mygrid(NULL)
   }
   if( !mygrid ) error("input action does not calculate a grid");
 
-  parseFlag("UNORMALISED",unormalised);
+  parseFlag("UNNORMALIZED",unormalised);
   if( unormalised ){
      log.printf("  working with unormalised grid \n");
      mygrid->switchOffNormalisation(); 
@@ -61,11 +63,18 @@ mygrid(NULL)
 
   if( keywords.exists("USE_ALL_DATA") ){
      parseFlag("USE_ALL_DATA",single_run);
-     if( !single_run ) log.printf("  outputting grid every %u steps \n", getStride() );
-     else log.printf("  outputting grid at end of calculation\n");
+     if( !single_run ){
+        mves->setAnalysisStride( false, getStride() ); 
+        log.printf("  outputting grid every %u steps \n", getStride() );
+     } else log.printf("  outputting grid at end of calculation\n");
   }
 }
 
+void ActionWithInputGrid::setAnalysisStride( const bool& use_all, const unsigned& astride ){
+  single_run=use_all;
+  if( !single_run ) setStride( astride );
+}
+
 void ActionWithInputGrid::update(){
   if( unormalised ) norm = 1.0;
   else norm=1.0/mygrid->getNorm();
diff --git a/src/gridtools/ActionWithInputGrid.h b/src/gridtools/ActionWithInputGrid.h
index 3016bee2c..9b5251641 100644
--- a/src/gridtools/ActionWithInputGrid.h
+++ b/src/gridtools/ActionWithInputGrid.h
@@ -29,7 +29,9 @@ namespace PLMD {
 namespace gridtools {
 
 class ActionWithInputGrid : 
-public ActionPilot {
+public ActionPilot,
+public vesselbase::ActionWithVessel
+{
 private:
   double norm;
   bool unormalised;
@@ -46,6 +48,7 @@ public:
   void update();
   void runFinalJobs();
   virtual void performOperationsWithGrid( const bool& from_update )=0;
+  void setAnalysisStride( const bool& use_all, const unsigned& astride );
 };
 
 inline
diff --git a/src/gridtools/ConvertToFES.cpp b/src/gridtools/ConvertToFES.cpp
new file mode 100644
index 000000000..eef7fd498
--- /dev/null
+++ b/src/gridtools/ConvertToFES.cpp
@@ -0,0 +1,99 @@
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   Copyright (c) 2011-2015 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 "core/ActionRegister.h"
+#include "core/PlumedMain.h"
+#include "core/Atoms.h"
+#include "ActionWithInputGrid.h"
+#include "GridFunction.h"
+
+namespace PLMD {
+namespace gridtools {
+
+class ConvertToFES : public ActionWithInputGrid {
+private:
+  double simtemp;
+  GridFunction* outgrid;
+public:
+  static void registerKeywords( Keywords& keys );
+  explicit ConvertToFES(const ActionOptions&ao);
+  void performOperationsWithGrid( const bool& from_update );
+  unsigned getNumberOfDerivatives(){ return 0; }
+  unsigned getNumberOfQuantities() const ;
+  void performTask( const unsigned& task_index, const unsigned& current, MultiValue& myvals ) const ;
+  bool isPeriodic(){ return false; }
+};
+
+PLUMED_REGISTER_ACTION(ConvertToFES,"CONVERT_TO_FES")
+
+void ConvertToFES::registerKeywords( Keywords& keys ){
+  ActionWithInputGrid::registerKeywords( keys );
+  keys.add("optional","TEMP","the temperature at which you are operating");
+  keys.reset_style("STRIDE","hidden"); keys.remove("USE_ALL_DATA");
+}
+
+ConvertToFES::ConvertToFES(const ActionOptions&ao):
+Action(ao),
+ActionWithInputGrid(ao)
+{
+  if( mygrid->getNumberOfComponents()!=1 ) error("input grid is vector field and cannot be converted to FES");
+  // Create the input from the old string
+  std::string vstring = "NOMEMORY COMPONENTS=" + getLabel() + " " + mygrid->getInputString();
+
+  // Create a grid
+  vesselbase::VesselOptions da("mygrid","",-1,vstring,this);
+  Keywords keys; GridFunction::registerKeywords( keys );
+  vesselbase::VesselOptions dar( da, keys );
+  outgrid = new GridFunction(dar); addVessel( outgrid ); std::vector<double> fspacing;
+  outgrid->setBounds( mygrid->getMin(), mygrid->getMax(), mygrid->getNbin(), fspacing);
+  if( mygrid->noDerivatives() ) outgrid->setNoDerivatives();
+  resizeFunctions();
+
+  simtemp=0.; parse("TEMP",simtemp);
+  if(simtemp>0) simtemp*=plumed.getAtoms().getKBoltzmann();
+  else simtemp=plumed.getAtoms().getKbT();
+
+  // Now create task list
+  for(unsigned i=0;i<mygrid->getNumberOfPoints();++i) addTaskToList(i);
+}
+
+unsigned ConvertToFES::getNumberOfQuantities() const {
+  if( mygrid->noDerivatives() ) return 2;
+  return 2 + mygrid->getDimension();
+}
+
+void ConvertToFES::performOperationsWithGrid( const bool& from_update ){
+  outgrid->clear(); runAllTasks();
+}
+
+void ConvertToFES::performTask( const unsigned& task_index, const unsigned& current, MultiValue& myvals ) const {
+  double val=getGridElement(current, 0);
+  myvals.setValue( 0, 1.0 ); myvals.setValue(1, -simtemp*std::log(val) );
+  if( !mygrid->noDerivatives() ){
+     for(unsigned i=0;i<mygrid->getDimension();++i) myvals.setValue( 2+i, -(simtemp/val)*getGridElement(current,i+1) );
+  }
+}
+
+
+
+
+}
+}
diff --git a/src/gridtools/GridFunction.cpp b/src/gridtools/GridFunction.cpp
new file mode 100644
index 000000000..056775b49
--- /dev/null
+++ b/src/gridtools/GridFunction.cpp
@@ -0,0 +1,48 @@
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   Copyright (c) 2012-2015 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 "GridFunction.h"
+
+namespace PLMD {
+namespace gridtools {
+
+void GridFunction::registerKeywords( Keywords& keys ){
+  GridVessel::registerKeywords( keys );
+}
+
+GridFunction::GridFunction( const vesselbase::VesselOptions& da ):
+GridVessel(da)
+{
+}
+
+bool GridFunction::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
+  plumed_dbg_assert( myvals.getNumberOfValues()==(nper+1) );
+  for(unsigned i=0;i<myvals.getNumberOfValues();++i) buffer[bufstart + nper*current + i] += myvals.get(i+1);
+  return true;
+}
+
+
+void GridFunction::finish( const std::vector<double>& buffer ){
+  for(unsigned i=0;i<data.size();++i) data[i]+=buffer[bufstart + i];
+}
+
+}
+}
diff --git a/src/gridtools/GridFunction.h b/src/gridtools/GridFunction.h
new file mode 100644
index 000000000..7f8d7f69b
--- /dev/null
+++ b/src/gridtools/GridFunction.h
@@ -0,0 +1,41 @@
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   Copyright (c) 2012 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.0.
+
+   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/>.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+#ifndef __PLUMED_gridtools_HistogramOnGrid_h
+#define __PLUMED_gridtools_HistogramOnGrid_h
+
+#include "GridVessel.h"
+
+namespace PLMD {
+namespace gridtools {
+
+class GridFunction : public GridVessel {
+public:
+  static void registerKeywords( Keywords& keys );
+  explicit GridFunction( const vesselbase::VesselOptions& da );
+  bool calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const ;
+  void finish( const std::vector<double>& );
+  bool applyForce(  std::vector<double>& forces ){ return false; }
+};
+
+}
+}
+#endif
diff --git a/src/gridtools/GridVessel.cpp b/src/gridtools/GridVessel.cpp
index 9b424a516..e0496faac 100644
--- a/src/gridtools/GridVessel.cpp
+++ b/src/gridtools/GridVessel.cpp
@@ -31,12 +31,12 @@ void GridVessel::registerKeywords( Keywords& keys ){
   keys.add("compulsory","COMPONENTS","the names of the components in the vector");
   keys.add("compulsory","COORDINATES","the names of the coordinates of the grid");
   keys.add("compulsory","PBC","is the grid periodic in each direction or not");
-  keys.add("compulsory","NBINS","number of bins in each direction for the grid");
   keys.addFlag("NOMEMORY",false,"should the data in the grid be deleted after print/analysis");
 }
 
 GridVessel::GridVessel( const vesselbase::VesselOptions& da ):
 Vessel(da),
+noderiv(false),
 bounds_set(false),
 bold(0),
 cube_units(1.0)
@@ -67,6 +67,16 @@ cube_units(1.0)
   }
 }
 
+void GridVessel::setNoDerivatives(){
+  nper = ( nper/(1+dimension) ); noderiv=true;
+  std::vector<std::string> tnames( dimension ), cnames(nper);
+  for(unsigned i=0;i<dimension;++i) tnames[i]=arg_names[i];
+  unsigned k=dimension; for(unsigned i=0;i<nper;++i){ cnames[i]=arg_names[k]; k+=(1+dimension); }
+  arg_names.resize( dimension + nper );
+  for(unsigned i=0;i<dimension;++i) arg_names[i]=tnames[i];
+  for(unsigned i=0;i<nper;++i) arg_names[dimension+i]=cnames[i];
+}
+
 void GridVessel::setBounds( const std::vector<std::string>& smin, const std::vector<std::string>& smax,
                             const std::vector<unsigned>& binsin, const std::vector<double>& spacing ){
   plumed_dbg_assert( smin.size()==dimension && smax.size()==dimension );
@@ -126,6 +136,16 @@ unsigned GridVessel::getIndex( const std::vector<unsigned>& indices ) const {
   return index;
 }
 
+unsigned GridVessel::getIndex( const std::vector<double>& point ) const {
+  plumed_dbg_assert( bounds_set && point.size()==dimension );
+  std::vector<unsigned> indices(dimension);
+  for(unsigned i=0;i<dimension;++i){
+      indices[i]=std::floor( (point[i] - min[i])/dx[i] ); 
+      if( pbc[i] ) indices[i]=indices[i]%nbin[i];
+  }
+  return getIndex( indices );
+}
+
 void GridVessel::convertIndexToIndices( const unsigned& index, const std::vector<unsigned>& nnbin, std::vector<unsigned>& indices ) const {
  unsigned kk=index;
  indices[0]=index%nnbin[0];
@@ -232,7 +252,8 @@ std::vector<unsigned> GridVessel::getNbin() const {
   return ngrid;
 }
 
-void GridVessel::getNeighbors( const std::vector<double>& pp, const std::vector<unsigned>& nneigh, std::vector<unsigned>& neighbors ) const {
+void GridVessel::getNeighbors( const std::vector<double>& pp, const std::vector<unsigned>& nneigh, 
+                               unsigned& num_neighbors, std::vector<unsigned>& neighbors ) const {
   plumed_dbg_assert( bounds_set && nneigh.size()==dimension );
 
   std::vector<unsigned> indices( dimension );  
@@ -244,19 +265,23 @@ void GridVessel::getNeighbors( const std::vector<double>& pp, const std::vector<
      num_neigh *=small_bin[i];
   }
 
-  neighbors.resize( num_neigh );
+  neighbors.resize( num_neigh ); num_neighbors=0;
   std::vector<unsigned> s_indices(dimension), t_indices(dimension);
   for(unsigned index=0;index<num_neigh;++index){
+      bool found=true;
       convertIndexToIndices( index, small_bin, s_indices );
       for(unsigned i=0;i<dimension;++i){
           int i0=s_indices[i]-nneigh[i]+indices[i];
-          if(!pbc[i] && i0<0)        plumed_merror("grid is not large enough");
-          if(!pbc[i] && i0>=nbin[i]) plumed_merror("grid is not large engouh");
+          if(!pbc[i] && i0<0)        found=false;
+          if(!pbc[i] && i0>=nbin[i]) found=false;
           if( pbc[i] && i0<0)        i0=nbin[i]-(-i0)%nbin[i];
           if( pbc[i] && i0>=nbin[i]) i0%=nbin[i];
           t_indices[i]=static_cast<unsigned>(i0);
       }
-      neighbors[index]=getIndex( t_indices );
+      if( found ){
+          neighbors[num_neighbors]=getIndex( t_indices );
+          num_neighbors++;
+      }
   }
 }
 
@@ -273,6 +298,19 @@ double GridVessel::getCubeUnits() const {
   return cube_units;
 }
 
+std::string GridVessel::getInputString() const {
+  std::string mstring="COORDINATES="+arg_names[0];
+  for(unsigned i=1;i<dimension;++i) mstring+="," + arg_names[i];
+  mstring += " PBC=";
+  if( pbc[0] ) mstring +="T";
+  else mstring +="F";
+  for(unsigned i=1;i<dimension;++i){
+     if( pbc[i] ) mstring +=",T";
+     else mstring +=",F";
+  }
+  return mstring;
+}
+
 }
 }
 
diff --git a/src/gridtools/GridVessel.h b/src/gridtools/GridVessel.h
index 9dfdd8952..84684c3f2 100644
--- a/src/gridtools/GridVessel.h
+++ b/src/gridtools/GridVessel.h
@@ -32,6 +32,8 @@ namespace gridtools {
 
 class GridVessel : public vesselbase::Vessel {
 private:
+/// Do we have derivatives
+ bool noderiv;
 /// Have the minimum and maximum for the grid been set
  bool bounds_set;
 /// These two variables are used to 
@@ -74,12 +76,17 @@ protected:
 /// The grid with all the data values on it
  std::vector<double> data;
 /// Get the set of points neighouring a particular location in space
- void getNeighbors( const std::vector<double>& pp, const std::vector<unsigned>& nneigh, std::vector<unsigned>& neighbors ) const ;
+ void getNeighbors( const std::vector<double>& pp, const std::vector<unsigned>& nneigh, 
+                    unsigned& num_neighbours, std::vector<unsigned>& neighbors ) const ;
+/// Convert a point in space the the correspoinding grid point
+ unsigned getIndex( const std::vector<double>& p ) const ;
 public:
 /// keywords
  static void registerKeywords( Keywords& keys );
 /// Constructor
  explicit GridVessel( const vesselbase::VesselOptions& );
+/// Remove the derivatives 
+ void setNoDerivatives();
 /// Set the minimum and maximum of the grid
  virtual void setBounds( const std::vector<std::string>& smin, const std::vector<std::string>& smax, const std::vector<unsigned>& nbins, const std::vector<double>& spacing );
 /// Get a description of the grid to output to the log
@@ -140,6 +147,10 @@ public:
 /// This gives the normalisation of histograms
  virtual double getNorm() const ;
  virtual void switchOffNormalisation(){}
+/// Return a string containing the input to the grid so we can clone it
+ std::string getInputString() const ;
+/// Does this have derivatives
+ bool noDerivatives() const ;
 };
 
 inline
@@ -180,6 +191,7 @@ std::string GridVessel::getComponentName( const unsigned& i ) const {
 
 inline
 unsigned GridVessel::getNumberOfComponents() const {
+  if( noderiv ) return nper;
   return nper / ( dimension + 1 );
 }
 
@@ -193,6 +205,11 @@ double GridVessel::getNorm() const {
   return 1.0;
 }
 
+inline
+bool GridVessel::noDerivatives() const {
+  return noderiv;
+}
+
 }
 }
 #endif
diff --git a/src/gridtools/HistogramOnGrid.cpp b/src/gridtools/HistogramOnGrid.cpp
index 6ca321c07..edb89d003 100644
--- a/src/gridtools/HistogramOnGrid.cpp
+++ b/src/gridtools/HistogramOnGrid.cpp
@@ -36,9 +36,15 @@ HistogramOnGrid::HistogramOnGrid( const vesselbase::VesselOptions& da ):
 GridVessel(da),
 norm(0),
 store_normed(false),
-bandwidths(dimension)
+bandwidths(dimension),
+discrete(false)
 {
-  parseFlag("STORE_NORMED",store_normed); parse("KERNEL",kerneltype); parseVector("BANDWIDTH",bandwidths);
+  parseFlag("STORE_NORMED",store_normed); parse("KERNEL",kerneltype); 
+  if( kerneltype=="discrete" || kerneltype=="DISCRETE" ){
+      discrete=true; setNoDerivatives();
+  } else {
+      parseVector("BANDWIDTH",bandwidths);
+  }
 }
 
 void HistogramOnGrid::switchOffNormalisation(){
@@ -47,10 +53,12 @@ void HistogramOnGrid::switchOffNormalisation(){
 
 void HistogramOnGrid::setBounds( const std::vector<std::string>& smin, const std::vector<std::string>& smax,
                                  const std::vector<unsigned>& nbins, const std::vector<double>& spacing ){
-  GridVessel::setBounds( smin, smax, nbins, spacing ); 
-  std::vector<double> point(dimension,0);
-  KernelFunctions kernel( point, bandwidths, kerneltype, false, 1.0, true );
-  nneigh=kernel.getSupport( dx );
+  GridVessel::setBounds( smin, smax, nbins, spacing );
+  if( !discrete ){ 
+      std::vector<double> point(dimension,0);
+      KernelFunctions kernel( point, bandwidths, kerneltype, false, 1.0, true );
+      nneigh=kernel.getSupport( dx );
+  }
 }
 
 bool HistogramOnGrid::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
@@ -58,27 +66,34 @@ bool HistogramOnGrid::calculate( const unsigned& current, MultiValue& myvals, st
   // Create a kernel function at the point of interest
   std::vector<double> point( dimension ); double weight=myvals.get(0)*myvals.get( 1+dimension );
   for(unsigned i=0;i<dimension;++i) point[i]=myvals.get( 1+i );
-  KernelFunctions kernel( point, bandwidths, kerneltype, false, weight, true );
-
-  std::vector<unsigned> neighbors; getNeighbors( kernel.getCenter(), nneigh, neighbors );
-  std::vector<double> xx( dimension ); std::vector<Value*> vv;
-  for(unsigned i=0;i<dimension;++i){
-      vv.push_back(new Value());
-      if( pbc[i] ) vv[i]->setDomain( str_min[i], str_max[i] );
-      else vv[i]->setNotPeriodic();
+  
+  if( discrete ){
+      for(unsigned i=0;i<dimension;++i) point[i] += 0.5*dx[i];
+      buffer[bufstart + nper*getIndex( point )] += weight;
+  } else {
+      KernelFunctions kernel( point, bandwidths, kerneltype, false, weight, true );
+
+      unsigned num_neigh; std::vector<unsigned> neighbors; 
+      getNeighbors( kernel.getCenter(), nneigh, num_neigh, neighbors );
+      std::vector<double> xx( dimension ); std::vector<Value*> vv;
+      for(unsigned i=0;i<dimension;++i){
+          vv.push_back(new Value());
+          if( pbc[i] ) vv[i]->setDomain( str_min[i], str_max[i] );
+          else vv[i]->setNotPeriodic();
+      }
+
+      double newval; std::vector<double> der( dimension );
+      for(unsigned i=0;i<num_neigh;++i){
+          unsigned ineigh=neighbors[i];
+          getGridPointCoordinates( ineigh, xx );
+          for(unsigned j=0;j<dimension;++j) vv[j]->set(xx[j]);
+          newval = kernel.evaluate( vv, der, true );
+          buffer[bufstart+nper*ineigh ] += newval;
+          for(unsigned j=0;j<dimension;++j) buffer[bufstart+nper*ineigh + 1 + j] += der[j];   
+      }
+
+      for(unsigned i=0;i<dimension;++i) delete vv[i];
   }
-
-  double newval; std::vector<double> der( dimension );
-  for(unsigned i=0;i<neighbors.size();++i){
-      unsigned ineigh=neighbors[i];
-      getGridPointCoordinates( ineigh, xx );
-      for(unsigned j=0;j<dimension;++j) vv[j]->set(xx[j]);
-      newval = kernel.evaluate( vv, der, true );
-      buffer[ nper*ineigh ] += newval;
-      for(unsigned j=0;j<dimension;++j) buffer[ nper*ineigh + 1 + j] += der[j];   
-  }
-
-  for(unsigned i=0;i<dimension;++i) delete vv[i];
   return true;
 }
 
@@ -91,7 +106,7 @@ void HistogramOnGrid::clear(){
   if( nomemory ){
      norm = 0.; GridVessel::clear(); return;
   }
-  if( store_normed ){
+  if( norm>0 && store_normed ){
      for(unsigned i=0;i<data.size();++i) data[i] /= norm;
   }
 }
diff --git a/src/gridtools/HistogramOnGrid.h b/src/gridtools/HistogramOnGrid.h
index cea0b9c02..55438778d 100644
--- a/src/gridtools/HistogramOnGrid.h
+++ b/src/gridtools/HistogramOnGrid.h
@@ -33,6 +33,7 @@ private:
   bool store_normed;
   std::string kerneltype;
   std::vector<double> bandwidths;
+  bool discrete;
   std::vector<unsigned> nneigh;
 public:
   static void registerKeywords( Keywords& keys );
diff --git a/src/gridtools/PrintCube.cpp b/src/gridtools/PrintCube.cpp
index 993bad2c3..f4955a9f5 100644
--- a/src/gridtools/PrintCube.cpp
+++ b/src/gridtools/PrintCube.cpp
@@ -33,6 +33,9 @@ public:
   static void registerKeywords( Keywords& keys );
   explicit PrintCube(const ActionOptions&ao); 
   void performOperationsWithGrid( const bool& from_update );
+  unsigned getNumberOfDerivatives(){ return 0; }
+  void performTask( const unsigned& , const unsigned& , MultiValue& ) const {}
+  bool isPeriodic(){ return false; }
 };
 
 PLUMED_REGISTER_ACTION(PrintCube,"PRINT_CUBE")
diff --git a/src/gridtools/PrintGrid.cpp b/src/gridtools/PrintGrid.cpp
index 8ae5f491c..a1ab19260 100644
--- a/src/gridtools/PrintGrid.cpp
+++ b/src/gridtools/PrintGrid.cpp
@@ -34,6 +34,9 @@ public:
   static void registerKeywords( Keywords& keys );
   explicit PrintGrid(const ActionOptions&ao); 
   void performOperationsWithGrid( const bool& from_update );
+  unsigned getNumberOfDerivatives(){ return 0; }
+  void performTask( const unsigned& , const unsigned& , MultiValue& ) const {}
+  bool isPeriodic(){ return false; }
 };
 
 PLUMED_REGISTER_ACTION(PrintGrid,"PRINT_GRID")
@@ -62,6 +65,7 @@ void PrintGrid::performOperationsWithGrid( const bool& from_update ){
   if( from_update ) ofile.setBackupString("analysis");
   ofile.open( filename );
 
+  ofile.addConstantField("normalisation");
   for(unsigned i=0;i<mygrid->getDimension();++i){
      ofile.addConstantField("min_" + mygrid->getComponentName(i) );
      ofile.addConstantField("max_" + mygrid->getComponentName(i) );
@@ -69,11 +73,13 @@ void PrintGrid::performOperationsWithGrid( const bool& from_update ){
      ofile.addConstantField("periodic_" + mygrid->getComponentName(i) );
   }
 
+  double norm = mygrid->getNorm();
   std::vector<double> xx( mygrid->getDimension() );
   std::vector<unsigned> ind( mygrid->getDimension() );
   for(unsigned i=0;i<mygrid->getNumberOfPoints();++i){
      mygrid->getIndices( i, ind );
-     if(i>0 && mygrid->getDimension()==2 && ind[mygrid->getDimension()-2]==0) ofile.printf("\n");
+     if(i>0 && mygrid->getDimension()>1 && ind[mygrid->getDimension()-2]==0) ofile.printf("\n");
+     ofile.fmtField(fmt); ofile.printField("normalisation", norm );
      for(unsigned j=0;j<mygrid->getDimension();++j){
          ofile.printField("min_" + mygrid->getComponentName(j), mygrid->getMin()[j] );
          ofile.printField("max_" + mygrid->getComponentName(j), mygrid->getMax()[j] );
diff --git a/src/vesselbase/ActionWithVessel.h b/src/vesselbase/ActionWithVessel.h
index 63d4df645..46dfb26ac 100644
--- a/src/vesselbase/ActionWithVessel.h
+++ b/src/vesselbase/ActionWithVessel.h
@@ -199,6 +199,8 @@ public:
   Vessel* getVesselWithName( const std::string& mynam );
 /// Does the weight have derivatives
   bool weightWithDerivatives() const ;
+/// This is used to set the stride for the output of histograms
+  virtual void setAnalysisStride( const bool& use_all, const unsigned& astride ){}
 };
 
 inline
-- 
GitLab