diff --git a/src/analysis/AnalysisWithLandmarks.cpp b/src/analysis/AnalysisWithLandmarks.cpp
index 32df489ef81ee3acbd4677d0629e7c01bb6f91be..4a4548b884a11ec9317ba71c904d336be0426fbc 100644
--- a/src/analysis/AnalysisWithLandmarks.cpp
+++ b/src/analysis/AnalysisWithLandmarks.cpp
@@ -71,7 +71,7 @@ void AnalysisWithLandmarks::performAnalysis(){
   analyzeLandmarks();
 }
 
-void AnalysisWithLandmarks::performTask( const unsigned& taskIndex, const unsigned& current, vesselbase::MultiValue& myvals ){
+void AnalysisWithLandmarks::performTask( const unsigned& taskIndex, const unsigned& current, MultiValue& myvals ) const {
   plumed_merror("Should not be here");
 }
 
diff --git a/src/analysis/AnalysisWithLandmarks.h b/src/analysis/AnalysisWithLandmarks.h
index bd9842ddd8e5ad488ee684671b545284440a3acc..86426fc7961c612b86af1e9c0bf6ad25cd96991b 100644
--- a/src/analysis/AnalysisWithLandmarks.h
+++ b/src/analysis/AnalysisWithLandmarks.h
@@ -53,7 +53,7 @@ public:
   void performAnalysis();
   virtual void analyzeLandmarks()=0;
 /// This does nothing
-  void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& );
+  void performTask( const unsigned& , const unsigned& , MultiValue& ) const ;
 };
 
 }
diff --git a/src/analysis/Histogram.cpp b/src/analysis/Histogram.cpp
index a6fb5ff3ccaaa9bcc5ef9dc095276b947bbe9135..c3a3899947aa00bec6b03ac13d01dc202ec8ab55 100644
--- a/src/analysis/Histogram.cpp
+++ b/src/analysis/Histogram.cpp
@@ -124,7 +124,7 @@ public:
   static void registerKeywords( Keywords& keys );
   Histogram(const ActionOptions&ao);
   void performAnalysis();
-  void performTask(  const unsigned& , const unsigned& , vesselbase::MultiValue& );
+  void performTask( const unsigned& , const unsigned& , MultiValue& ) const ;
 };
 
 PLUMED_REGISTER_ACTION(Histogram,"HISTOGRAM")
@@ -212,7 +212,7 @@ unnormalized(false)
   log.printf("\n");
 }
 
-void Histogram::performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& ){ plumed_error(); }
+void Histogram::performTask( const unsigned& , const unsigned& , MultiValue& ) const { plumed_error(); }
 
 void Histogram::performAnalysis(){
   // Back up old histogram files
diff --git a/src/colvar/DRMSD.cpp b/src/colvar/DRMSD.cpp
index 4d45a32977717841b99bc4c604a4f3663473decb..b5693e74e04b6ba42570508396cdfdb22c70ef20 100644
--- a/src/colvar/DRMSD.cpp
+++ b/src/colvar/DRMSD.cpp
@@ -75,9 +75,11 @@ DRMSD REFERENCE=file.pdb LOWER_CUTOFF=0.1 UPPER_CUTOFF=0.8
 
    
 class DRMSD : public Colvar {
-	
+
+  bool pbc_;	
+  MultiValue myvals;
+  ReferenceValuePack mypack;
   PLMD::DRMSD* drmsd_;
-  bool pbc_;
 
 public:
   DRMSD(const ActionOptions&);
@@ -96,7 +98,7 @@ void DRMSD::registerKeywords(Keywords& keys){
 }
 
 DRMSD::DRMSD(const ActionOptions&ao):
-PLUMED_COLVAR_INIT(ao), pbc_(true)
+PLUMED_COLVAR_INIT(ao), pbc_(true), myvals(1,0), mypack(0,0,myvals)
 {
   string reference;
   parse("REFERENCE",reference);
@@ -125,9 +127,14 @@ PLUMED_COLVAR_INIT(ao), pbc_(true)
 
   std::vector<AtomNumber> atoms; 
   drmsd_->getAtomRequests( atoms );
-  drmsd_->setNumberOfAtoms( atoms.size() );
+//   drmsd_->setNumberOfAtoms( atoms.size() );
   requestAtoms( atoms );
 
+  // Setup the derivative pack
+  myvals.resize( 1, 3*atoms.size()+9 );
+  mypack.resize( 0, atoms.size() ); mypack.setValIndex(0);
+  for(unsigned i=0;i<atoms.size();++i) mypack.setAtomIndex( i, i );
+
   log.printf("  reference from file %s\n",reference.c_str());
   log.printf("  which contains %d atoms\n",getNumberOfAtoms());
 
@@ -140,14 +147,15 @@ DRMSD::~DRMSD(){
 // calculator
 void DRMSD::calculate(){
 
- double drmsd; Tensor virial;
+ double drmsd; Tensor virial; mypack.clear();
 
- drmsd=drmsd_->calculate(getPositions(), getPbc(), false);
+ drmsd=drmsd_->calculate(getPositions(), getPbc(), mypack, false);
 
  setValue(drmsd);
- for(unsigned i=0;i<getNumberOfAtoms();++i) { setAtomsDerivatives( i, drmsd_->getAtomDerivative(i) ); }
- 
- drmsd_->getVirial( virial ); setBoxDerivatives(virial);
+ for(unsigned i=0;i<getNumberOfAtoms();++i) { setAtomsDerivatives( i, mypack.getAtomDerivative(i) ); }
+ setBoxDerivatives( mypack.getBoxDerivatives() );   
+
+ // drmsd_->getVirial( virial ); setBoxDerivatives(virial);
 
 }
 
diff --git a/src/colvar/MultiRMSD.cpp b/src/colvar/MultiRMSD.cpp
index 977151dc3c254d79b3b6ecf72f6344354d171861..a52aa688ee29b263d8dc717e56243abeb0b000aa 100644
--- a/src/colvar/MultiRMSD.cpp
+++ b/src/colvar/MultiRMSD.cpp
@@ -37,6 +37,8 @@ class MultiRMSD : public Colvar {
 	
   PLMD::MultiDomainRMSD* rmsd;
   bool squared; 
+  MultiValue myvals;
+  ReferenceValuePack mypack;
 
 public:
   MultiRMSD(const ActionOptions&);
@@ -124,7 +126,7 @@ void MultiRMSD::registerKeywords(Keywords& keys){
 }
 
 MultiRMSD::MultiRMSD(const ActionOptions&ao):
-PLUMED_COLVAR_INIT(ao),squared(false)
+PLUMED_COLVAR_INIT(ao),squared(false),myvals(1,0), mypack(0,0,myvals)
 {
   string reference;
   parse("REFERENCE",reference);
@@ -147,9 +149,13 @@ PLUMED_COLVAR_INIT(ao),squared(false)
   
   std::vector<AtomNumber> atoms;
   rmsd->getAtomRequests( atoms );
-  rmsd->setNumberOfAtoms( atoms.size() );
+//   rmsd->setNumberOfAtoms( atoms.size() );
   requestAtoms( atoms );
 
+  myvals.resize( 1, 3*atoms.size()+9 );
+  mypack.resize( 0, atoms.size() ); mypack.setValIndex(0);
+  for(unsigned i=0;i<atoms.size();++i) mypack.setAtomIndex( i, i );
+
   log.printf("  reference from file %s\n",reference.c_str());
   log.printf("  which contains %d atoms\n",getNumberOfAtoms());
   log.printf("  method for alignment : %s \n",type.c_str() );
@@ -163,14 +169,13 @@ MultiRMSD::~MultiRMSD(){
 
 // calculator
 void MultiRMSD::calculate(){
-  double r=rmsd->calculate( getPositions(), getPbc(), squared );
+  mypack.clear(); double r=rmsd->calculate( getPositions(), getPbc(), mypack, squared );
 
   setValue(r); 
-  for(unsigned i=0;i<getNumberOfAtoms();i++) setAtomsDerivatives( i, rmsd->getAtomDerivative(i) );
+  for(unsigned i=0;i<getNumberOfAtoms();i++) setAtomsDerivatives( i, mypack.getAtomDerivative(i) );
 
-  Tensor virial; 
-  if( !rmsd->getVirial( virial ) ) setBoxDerivativesNoPbc();
-  else setBoxDerivatives( virial );
+  if( !mypack.virialWasSet() ) setBoxDerivativesNoPbc();
+  else setBoxDerivatives( mypack.getBoxDerivatives() );
 }
 
 }
diff --git a/src/colvar/RMSD.cpp b/src/colvar/RMSD.cpp
index 33d040994a6167ab9d9992c2c4a0f4b1bdb1b113..8e9333e42bcc1654109ef0e8d77f54e0b89ed6cb 100644
--- a/src/colvar/RMSD.cpp
+++ b/src/colvar/RMSD.cpp
@@ -35,6 +35,8 @@ namespace colvar{
    
 class RMSD : public Colvar {
 	
+  MultiValue myvals;
+  ReferenceValuePack mypack;
   PLMD::RMSDBase* rmsd;
   bool squared; 
 
@@ -150,7 +152,7 @@ void RMSD::registerKeywords(Keywords& keys){
 }
 
 RMSD::RMSD(const ActionOptions&ao):
-PLUMED_COLVAR_INIT(ao),squared(false)
+PLUMED_COLVAR_INIT(ao),myvals(1,0), mypack(0,0,myvals),squared(false)
 {
   string reference;
   parse("REFERENCE",reference);
@@ -173,9 +175,14 @@ PLUMED_COLVAR_INIT(ao),squared(false)
   
   std::vector<AtomNumber> atoms;
   rmsd->getAtomRequests( atoms );
-  rmsd->setNumberOfAtoms( atoms.size() );
+//  rmsd->setNumberOfAtoms( atoms.size() );
   requestAtoms( atoms );
 
+  // Setup the derivative pack
+  myvals.resize( 1, 3*atoms.size()+9 );
+  mypack.resize( 0, atoms.size() ); mypack.setValIndex(0);
+  for(unsigned i=0;i<atoms.size();++i) mypack.setAtomIndex( i, i );
+
   log.printf("  reference from file %s\n",reference.c_str());
   log.printf("  which contains %d atoms\n",getNumberOfAtoms());
   log.printf("  method for alignment : %s \n",type.c_str() );
@@ -189,12 +196,12 @@ RMSD::~RMSD(){
 
 // calculator
 void RMSD::calculate(){
-  double r=rmsd->calculate( getPositions(), squared );
+  mypack.clear(); double r=rmsd->calculate( getPositions(), mypack, squared );
 
   setValue(r); 
-  for(unsigned i=0;i<getNumberOfAtoms();i++) setAtomsDerivatives( i, rmsd->getAtomDerivative(i) );
+  for(unsigned i=0;i<getNumberOfAtoms();i++) setAtomsDerivatives( i, mypack.getAtomDerivative(i) );
 
-  Tensor virial; plumed_dbg_assert( !rmsd->getVirial(virial) );
+  Tensor virial; plumed_dbg_assert( !mypack.virialWasSet() );
   setBoxDerivativesNoPbc();
 }
 
diff --git a/src/core/ActionWithArguments.h b/src/core/ActionWithArguments.h
index 3db42230bb8016533b6dceb660dc67a072980964..feef08a6da5f054e6c3d043e1ec1ebffb81d07cd 100644
--- a/src/core/ActionWithArguments.h
+++ b/src/core/ActionWithArguments.h
@@ -78,7 +78,7 @@ public:
   void lockRequests();
   void unlockRequests();
 /// Returns an array of pointers to the arguments
-  std::vector<Value*>    & getArguments();
+  const std::vector<Value*>    & getArguments() const ;
 /// Convert a list of argument names into a list of pointers to the values
   void interpretArgumentList(const std::vector<std::string>& c, std::vector<Value*>&arg);
 };
@@ -120,7 +120,7 @@ void ActionWithArguments::unlockRequests(){
 }
 
 inline
-std::vector<Value*> & ActionWithArguments::getArguments(){
+const std::vector<Value*> & ActionWithArguments::getArguments() const {
   return arguments;
 }
 
diff --git a/src/crystallization/DFSClustering.cpp b/src/crystallization/DFSClustering.cpp
index 174ebb4433fd01575ff1dc4b60ab987d4afe81b7..3ba1a0d4a3d203adfb9327e0f7dc827787f88ff4 100644
--- a/src/crystallization/DFSClustering.cpp
+++ b/src/crystallization/DFSClustering.cpp
@@ -66,7 +66,7 @@ public:
   void completeCalculation();
 /// Derivatives of elements of adjacency matrix are unimportant.  We thus
 /// overwrite this routine as this makes the code faster
-  void updateActiveAtoms( multicolvar::AtomValuePack& myatoms ){}
+  void updateActiveAtoms( multicolvar::AtomValuePack& myatoms ) const {}
 };
 
 PLUMED_REGISTER_ACTION(DFSClustering,"DFSCLUSTERING")
@@ -151,8 +151,8 @@ void DFSClustering::completeCalculation(){
    // Get size for buffer
    unsigned bsize=0; std::vector<double> buffer( getSizeOfBuffer( bsize ), 0.0 );
    std::vector<double> vals( getNumberOfQuantities() ); std::vector<unsigned> der_index;
-   vesselbase::MultiValue myvals( getNumberOfQuantities(), getNumberOfDerivatives() );
-   vesselbase::MultiValue bvals( getNumberOfQuantities(), getNumberOfDerivatives() );
+   MultiValue myvals( getNumberOfQuantities(), getNumberOfDerivatives() );
+   MultiValue bvals( getNumberOfQuantities(), getNumberOfDerivatives() );
    // Get rid of bogus derivatives
    clearDerivatives(); getAdjacencyVessel()->setFinishedTrue(); 
    for(unsigned j=rank;j<myatoms.size();j+=size){
diff --git a/src/crystallization/Fccubic.cpp b/src/crystallization/Fccubic.cpp
index a7d40a05e8743a93c805826e00e97f8b6f59c116..3511b6c37fa6e0ded8eb980c867ae575df38873e 100644
--- a/src/crystallization/Fccubic.cpp
+++ b/src/crystallization/Fccubic.cpp
@@ -47,7 +47,7 @@ public:
   static void registerKeywords( Keywords& keys );
   Fccubic(const ActionOptions&);
 // active methods:
-  virtual double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ); 
+  virtual double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const ; 
 /// Returns the number of coordinates of the field
   bool isPeriodic(){ return false; }
 };
@@ -95,7 +95,7 @@ PLUMED_MULTICOLVAR_INIT(ao)
   checkRead();
 }
 
-double Fccubic::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ){
+double Fccubic::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const {
    double value=0, norm=0, dfunc; Vector distance;
 
    // Calculate the coordination number
diff --git a/src/crystallization/Gradient.cpp b/src/crystallization/Gradient.cpp
index 498664c3ab45b829d6e16eef27a02bbbde4db79f..ea4f1a389d79a6c04cce80518399e1468a5aa835 100644
--- a/src/crystallization/Gradient.cpp
+++ b/src/crystallization/Gradient.cpp
@@ -89,9 +89,7 @@ nbins(3)
   std::transform( functype.begin(), functype.end(), functype.begin(), tolower );
   log.printf("  calculating gradient of %s in %s direction \n",functype.c_str(), direction.c_str() ); 
 
-  parse("SIGMA",sigma); 
-  bead.isNotPeriodic(); std::string kerneltype; 
-  parse("KERNEL",kerneltype); bead.setKernelType( kerneltype );
+  parse("SIGMA",sigma); parse("KERNEL",kerneltype); 
   checkRead(); requestAtoms(atom);
 
   // And setup the vessel
@@ -104,7 +102,10 @@ void Gradient::setupRegions(){
 //  if( !getPbc().isOrthorombic() ) error("cell must be orthorhombic when using gradient");
 }
 
-void Gradient::calculateAllVolumes( const unsigned& curr, vesselbase::MultiValue& outvals ){
+void Gradient::calculateAllVolumes( const unsigned& curr, MultiValue& outvals ) const {
+  // Setup the bead
+  HistogramBead bead; bead.isNotPeriodic(); bead.setKernelType( kerneltype );  
+
   Vector cpos = pbcDistance( getPosition(0), getPntrToMultiColvar()->getCentralAtomPos( curr ) );
   // Note we use the pbc from base multicolvar so that we get numerical derivatives correct
   Vector oderiv, fpos = (getPntrToMultiColvar()->getPbc()).realToScaled( cpos );  
diff --git a/src/crystallization/Gradient.h b/src/crystallization/Gradient.h
index b16d0376d9d5dceb29675a01e0892136aee328b8..7a8b6a8e1754e029c96f05b2e51547231c990822 100644
--- a/src/crystallization/Gradient.h
+++ b/src/crystallization/Gradient.h
@@ -36,8 +36,8 @@ private:
   unsigned vend, nquantities;
 /// Number of bins in each direction
   std::vector<unsigned> nbins;
-/// The bead for the histogram
-  HistogramBead bead;
+/// The type of kernel for the histogram
+  std::string kerneltype;
 public:
   static void registerKeywords( Keywords& keys );
   Gradient(const ActionOptions&);
@@ -46,7 +46,7 @@ public:
 /// Check on pbc - is it orthorhombic
   void setupRegions();
 /// Calculate whats in the volume
-  void calculateAllVolumes( const unsigned& curr, vesselbase::MultiValue& outvals );
+  void calculateAllVolumes( const unsigned& curr, MultiValue& outvals ) const ;
 };
 
 inline
diff --git a/src/crystallization/GradientVessel.cpp b/src/crystallization/GradientVessel.cpp
index fbbb2adbced0d282228130a6fb31d712d52d6c2d..31d9c34e163efa44f54f5f3e448d188533c5ec5a 100644
--- a/src/crystallization/GradientVessel.cpp
+++ b/src/crystallization/GradientVessel.cpp
@@ -40,7 +40,7 @@ public:
   GradientVessel( const vesselbase::VesselOptions& da );
   std::string function_description();
   void resize();
-  bool calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const ;
+  bool calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const ;
   void finish( const std::vector<double>& buffer );
 };
 
@@ -99,7 +99,7 @@ void GradientVessel::resize(){
   }
 }
 
-bool GradientVessel::calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
+bool GradientVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
   unsigned nder=getAction()->getNumberOfDerivatives();
   unsigned wstart, cstart; if( ncomponents==1 ){ cstart=1; wstart=2; } else { cstart=2; wstart=2+ncomponents; }
 
diff --git a/src/crystallization/MoleculeOrientation.cpp b/src/crystallization/MoleculeOrientation.cpp
index 9517bd0ca6b8a50ba2c584fc0439af62bd4c002e..c47a9143593bdba079ef587cf8980d5429bcd76a 100644
--- a/src/crystallization/MoleculeOrientation.cpp
+++ b/src/crystallization/MoleculeOrientation.cpp
@@ -54,7 +54,7 @@ private:
 public:
   static void registerKeywords( Keywords& keys );
   MoleculeOrientation( const ActionOptions& ao );
-  void calculateVector( multicolvar::AtomValuePack& myatoms );
+  void calculateVector( multicolvar::AtomValuePack& myatoms ) const;
 };
 
 PLUMED_REGISTER_ACTION(MoleculeOrientation,"MOLECULES")
@@ -87,7 +87,7 @@ VectorMultiColvar(ao)
   } 
 }
 
-void MoleculeOrientation::calculateVector( multicolvar::AtomValuePack& myatoms ){
+void MoleculeOrientation::calculateVector( multicolvar::AtomValuePack& myatoms ) const {
   Vector distance; distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
 
   myatoms.addAtomsDerivatives( 2, 0, Vector(-1.0,0,0) ); 
diff --git a/src/crystallization/MoleculePlane.cpp b/src/crystallization/MoleculePlane.cpp
index b38129161bcc46b792fff08698136c1da69a512e..e9c0c74d1dd4a282d75fc3dfdc23a6d46c6ab718 100644
--- a/src/crystallization/MoleculePlane.cpp
+++ b/src/crystallization/MoleculePlane.cpp
@@ -41,7 +41,7 @@ private:
 public:
   static void registerKeywords( Keywords& keys );
   MoleculePlane( const ActionOptions& ao );
-  void calculateVector( multicolvar::AtomValuePack& myatoms );
+  void calculateVector( multicolvar::AtomValuePack& myatoms ) const ;
 };
 
 PLUMED_REGISTER_ACTION(MoleculePlane,"PLANES")
@@ -71,7 +71,7 @@ VectorMultiColvar(ao)
   setVectorDimensionality( 3, natoms );
 }
 
-void MoleculePlane::calculateVector( multicolvar::AtomValuePack& myatoms ){
+void MoleculePlane::calculateVector( multicolvar::AtomValuePack& myatoms ) const { 
   Vector d1, d2, cp; 
   if( myatoms.getNumberOfAtoms()==3 ){
      d1=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) );
diff --git a/src/crystallization/OrientationSphere.cpp b/src/crystallization/OrientationSphere.cpp
index a6d8042b881c795b5fe48d6032eb0e38f231e564..4bdf3807d47182d220e14cd50d2c9f519b5892c3 100644
--- a/src/crystallization/OrientationSphere.cpp
+++ b/src/crystallization/OrientationSphere.cpp
@@ -65,20 +65,20 @@ MultiColvarFunction(ao)
   buildSymmetryFunctionLists();
 }
 
-double OrientationSphere::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ){
+double OrientationSphere::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const {
    // Make sure derivatives for central atom are only calculated once
    VectorMultiColvar* vv = dynamic_cast<VectorMultiColvar*>( getBaseMultiColvar(0) );
    vv->firstcall=true;
 
    double d2, sw, value=0, denom=0, dot, f_dot, dot_df, dfunc; Vector distance;
    unsigned ncomponents=getBaseMultiColvar(0)->getNumberOfQuantities();
-   unsigned nder=getNumberOfDerivatives();
+   unsigned nder=myatoms.getNumberOfDerivatives();
    std::vector<double> catom_orient( ncomponents ), this_orient( ncomponents ), catom_der( ncomponents ); 
 
    Vector catom_pos = myatoms.getPosition(0);
    getVectorForTask( myatoms.getIndex(0), true, catom_orient );
    multicolvar::CatomPack atom0; 
-   vesselbase::MultiValue myder0(ncomponents,nder), myder1(ncomponents,nder); 
+   MultiValue myder0(ncomponents,nder), myder1(ncomponents,nder); 
    if( !doNotCalculateDerivatives() ){
        atom0=getCentralAtomPackFromInput( myatoms.getIndex(0) );
        getVectorDerivatives( myatoms.getIndex(0), true, myder0 );
@@ -121,7 +121,7 @@ double OrientationSphere::compute( const unsigned& tindex, multicolvar::AtomValu
    
    // Now divide everything
    double denom2=denom*denom;
-   updateActiveAtoms( myatoms ); vesselbase::MultiValue& myvals=myatoms.getUnderlyingMultiValue();
+   updateActiveAtoms( myatoms ); MultiValue& myvals=myatoms.getUnderlyingMultiValue();
    for(unsigned i=0;i<myvals.getNumberActive();++i){
        unsigned ider=myvals.getActiveIndex(i);
        myvals.setDerivative( 1, ider, myvals.getDerivative(1,ider)/denom - (value*myvals.getDerivative(0,ider))/denom2 );
diff --git a/src/crystallization/OrientationSphere.h b/src/crystallization/OrientationSphere.h
index 1b137910ae3e1c8b14efc11b6baf38d3d52902e1..53473b5ef5341796f73547ee273f3c6ecd3f195e 100644
--- a/src/crystallization/OrientationSphere.h
+++ b/src/crystallization/OrientationSphere.h
@@ -38,13 +38,13 @@ private:
 public:
   static void registerKeywords( Keywords& keys );
   OrientationSphere(const ActionOptions&);
-  double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms );
-  virtual double transformDotProduct( const double& dot, double& df );
+  double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const ;
+  virtual double transformDotProduct( const double& dot, double& df ) const ;
   bool isPeriodic(){ return false; }
 };
 
 inline
-double OrientationSphere::transformDotProduct( const double& dot, double& df ){
+double OrientationSphere::transformDotProduct( const double& dot, double& df ) const {
   df=1.0; return dot;
 }
 
diff --git a/src/crystallization/SMAC.cpp b/src/crystallization/SMAC.cpp
index be67b9f581464cf30499059f915c8a8525540b04..9437d0288cdd0aaf2dec1ac2ca6689678033f446 100644
--- a/src/crystallization/SMAC.cpp
+++ b/src/crystallization/SMAC.cpp
@@ -29,13 +29,10 @@ namespace crystallization {
 class SMAC : public OrientationSphere {
 private:
   std::vector<KernelFunctions> kernels;
-  std::vector<double> deriv;
-  std::vector<Value*> pos;
 public:
   static void registerKeywords( Keywords& keys ); 
   SMAC(const ActionOptions& ao); 
-  ~SMAC();
-  double transformDotProduct( const double& dot, double& df ); 
+  double transformDotProduct( const double& dot, double& df ) const ; 
 };
 
 PLUMED_REGISTER_ACTION(SMAC,"SMAC")
@@ -48,8 +45,7 @@ void SMAC::registerKeywords( Keywords& keys ){
 
 SMAC::SMAC(const ActionOptions& ao):
 Action(ao),
-OrientationSphere(ao),
-deriv(1)
+OrientationSphere(ao)
 {
    std::string kernelinpt;
    for(int i=1;;i++){
@@ -58,21 +54,17 @@ deriv(1)
       kernels.push_back( mykernel ); 
    }
    if( kernels.size()==0 ) error("no kernels defined");
-
-   pos.push_back( new Value() ); 
-   pos[0]->setNotPeriodic();
-}
-
-SMAC::~SMAC(){
-   delete pos[0];
 }
 
-double SMAC::transformDotProduct( const double& dot, double& df ){
-  double ans=0; df=0; pos[0]->set( acos( dot ) ); double dcos=-1./sqrt( 1. - dot*dot );
+double SMAC::transformDotProduct( const double& dot, double& df ) const {
+  std::vector<Value*> pos; pos.push_back( new Value() ); std::vector<double> deriv(1);
+  pos[0]->setNotPeriodic(); pos[0]->set( acos( dot ) ); 
+  double ans=0; df=0; double dcos=-1./sqrt( 1. - dot*dot );
   for(unsigned i=0;i<kernels.size();++i){
       ans += kernels[i].evaluate( pos, deriv );
       df += deriv[0]*dcos;
   }
+  delete pos[0];
   return ans;
 }
 
diff --git a/src/crystallization/SimpleCubic.cpp b/src/crystallization/SimpleCubic.cpp
index 09ab4b73fc83cc8eab7c7f434c499afaf1b01115..f53a1d4e87e6c10086fb32e47be10eb173e20048 100644
--- a/src/crystallization/SimpleCubic.cpp
+++ b/src/crystallization/SimpleCubic.cpp
@@ -64,7 +64,7 @@ public:
   static void registerKeywords( Keywords& keys );
   SimpleCubic(const ActionOptions&);
 // active methods:
-  virtual double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ); 
+  virtual double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const ; 
 /// Returns the number of coordinates of the field
   bool isPeriodic(){ return false; }
 };
@@ -112,7 +112,7 @@ PLUMED_MULTICOLVAR_INIT(ao)
   checkRead();
 }
 
-double SimpleCubic::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ){
+double SimpleCubic::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const { 
    double d2, value=0, norm=0, dfunc; Vector distance;
 
    // Calculate the coordination number
diff --git a/src/crystallization/Steinhardt.cpp b/src/crystallization/Steinhardt.cpp
index 61382e07519f5c290397e9a969f970a8fbe968ae..30c372a413a0ebac40152bd25e6d71080b5aa370 100644
--- a/src/crystallization/Steinhardt.cpp
+++ b/src/crystallization/Steinhardt.cpp
@@ -64,7 +64,7 @@ void Steinhardt::setAngularMomentum( const unsigned& ang ){
   tmom=ang; setVectorDimensionality( 2*(2*ang + 1), 2 );
 } 
 
-void Steinhardt::calculateVector( multicolvar::AtomValuePack& myatoms ){
+void Steinhardt::calculateVector( multicolvar::AtomValuePack& myatoms ) const {
   double dfunc, dpoly_ass, md, tq6, itq6, real_z, imag_z; 
   Vector distance, dz, myrealvec, myimagvec, real_dz, imag_dz;
   // The square root of -1
@@ -163,7 +163,7 @@ void Steinhardt::calculateVector( multicolvar::AtomValuePack& myatoms ){
   myatoms.getUnderlyingMultiValue().clear(1);
 }
 
-double Steinhardt::deriv_poly( const unsigned& m, const double& val, double& df ){
+double Steinhardt::deriv_poly( const unsigned& m, const double& val, double& df ) const { 
   double fact=1.0;
   for(unsigned j=1;j<=m;++j) fact=fact*j;
   double res=coeff_poly[m]*fact;
diff --git a/src/crystallization/Steinhardt.h b/src/crystallization/Steinhardt.h
index 542ccc3582b076691fe2f5bec3090dd1600a8145..06d06618c57b1a3e57ed9b752edd9ac24ff9c9fd 100644
--- a/src/crystallization/Steinhardt.h
+++ b/src/crystallization/Steinhardt.h
@@ -41,8 +41,8 @@ protected:
 public:
   static void registerKeywords( Keywords& keys );
   Steinhardt( const ActionOptions& ao );
-  void calculateVector( multicolvar::AtomValuePack& myatoms );
-  double deriv_poly( const unsigned&, const double&, double& );
+  void calculateVector( multicolvar::AtomValuePack& myatoms ) const ;
+  double deriv_poly( const unsigned&, const double&, double& ) const ;
 };
 
 }
diff --git a/src/crystallization/Tetrahedral.cpp b/src/crystallization/Tetrahedral.cpp
index 886075a556fb74ca2b26bb1d0e26b33a7cea5489..ba0ecda48ca2203ace1b084c61f0fb441245f53f 100644
--- a/src/crystallization/Tetrahedral.cpp
+++ b/src/crystallization/Tetrahedral.cpp
@@ -50,7 +50,7 @@ public:
   static void registerKeywords( Keywords& keys );
   Tetrahedral(const ActionOptions&);
 // active methods:
-  virtual double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ); 
+  virtual double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const ; 
 /// Returns the number of coordinates of the field
   bool isPeriodic(){ return false; }
 };
@@ -98,7 +98,7 @@ PLUMED_MULTICOLVAR_INIT(ao)
   checkRead();
 }
 
-double Tetrahedral::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ){
+double Tetrahedral::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const {
    double value=0, norm=0, dfunc; Vector distance;
 
    // Calculate the coordination number
diff --git a/src/crystallization/VectorMean.cpp b/src/crystallization/VectorMean.cpp
index 965ab55eb9195b73608060f2974225c016946e44..c4c99db2b8a0db622e353f64b4dec0619497bfb4 100644
--- a/src/crystallization/VectorMean.cpp
+++ b/src/crystallization/VectorMean.cpp
@@ -35,7 +35,7 @@ public:
   VectorMean( const vesselbase::VesselOptions& da );
   std::string function_description();
   void resize();
-  bool calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const ;
+  bool calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const ;
   void finish( const std::vector<double>& buffer );
 };
 
@@ -73,7 +73,7 @@ void VectorMean::resize(){
   }
 }
 
-bool VectorMean::calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
+bool VectorMean::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
   unsigned ncomp=getAction()->getNumberOfQuantities()-2, nder=getAction()->getNumberOfDerivatives();
 
   double weight=myvals.get(0); plumed_dbg_assert( weight>=getTolerance() ); 
diff --git a/src/crystallization/VectorMultiColvar.cpp b/src/crystallization/VectorMultiColvar.cpp
index 414cf8962cb9a162cdac30b540d191e8bd37744e..39927875ecbfe2509d1e8ddc1422031701a62e01 100644
--- a/src/crystallization/VectorMultiColvar.cpp
+++ b/src/crystallization/VectorMultiColvar.cpp
@@ -43,23 +43,13 @@ void VectorMultiColvar::setVectorDimensionality( const unsigned& ncomp, const in
   ncomponents = ncomp;  
   // Read in the atoms if we are using multicolvar reading
   int natoms=nat; readAtoms( natoms );
-  // Create the store vector object
-//   std::string param; vesselbase::VesselOptions da("","",0,param,this);
-//   Keywords keys; StoreVectorsVessel::registerKeywords( keys );
-//   vesselbase::VesselOptions da2(da,keys);
-//   vecs = new StoreVectorsVessel(da2);
-//   // Add the vessel to the base
-//   addVessel(vecs);
-//  // Read in any vessels
-//  readVesselKeywords();
-  // Resize a holder for the derivatives of the norm of the vector
 }
 
 void VectorMultiColvar::doNotCalculateDirector(){
   store_director=false;    // Need a sanity check in here  so that you don't use the same instance of Q4 to calcualte vectors and directors 
 }
 
-double VectorMultiColvar::doCalculation( const unsigned& taskIndex, multicolvar::AtomValuePack& myatoms ){
+double VectorMultiColvar::doCalculation( const unsigned& taskIndex, multicolvar::AtomValuePack& myatoms ) const {
   // Now calculate the vector
   calculateVector( myatoms );
   // Sort out the active derivatives
@@ -74,139 +64,16 @@ double VectorMultiColvar::doCalculation( const unsigned& taskIndex, multicolvar:
       double inorm = 1.0 / norm; std::vector<double> dervec( ncomponents );
       for(unsigned i=0;i<ncomponents;++i) dervec[i] = inorm*myatoms.getValue(2+i);
  
-      vesselbase::MultiValue& myvals=myatoms.getUnderlyingMultiValue();
+      MultiValue& myvals=myatoms.getUnderlyingMultiValue();
       for(unsigned j=0;j<myvals.getNumberActive();++j){
           unsigned jder=myvals.getActiveIndex(j);
           for(unsigned i=0;i<ncomponents;++i) myvals.addDerivative( 1, jder, dervec[i]*myvals.getDerivative( 2+i, jder ) );
       }
   }
-  // if(complexvec){
-  //    for(unsigned i=0;i<ncomponents;++i) norm += getComponent(i)*getComponent(i) + getImaginaryComponent(i)*getImaginaryComponent(i); 
-  //    norm=sqrt(norm); inorm = 1.0 / norm;
-  //    for(unsigned i=0;i<ncomponents;++i){ dervec[i] = inorm*getComponent(i); dervec[ncomponents+i] = inorm*getImaginaryComponent(i); } 
-  // } else {
-  //    for(unsigned i=0;i<ncomponents;++i) norm += getComponent(i)*getComponent(i);
-  //    norm=sqrt(norm); inorm = 1.0 / norm;
-  //    for(unsigned i=0;i<ncomponents;++i) dervec[i] = inorm*getComponent(i); 
-  // }
-
-  // if( !doNotCalculateDerivatives() ){
-  //     if( usingLowMem() ){
-  //        vecs->storeDerivativesLowMem( 0 );
-  //        vecs->chainRule( 0, dervec );
-  //     } else {
-  //        //vecs->storeDerivativesHighMem( getCurrentPositionInTaskList() );
-  //        vecs->chainRule( getCurrentPositionInTaskList(), dervec );
-  //     }
-
-  //     // Add derivatives to base multicolvars
-  //     Vector tmpd;
-  //     for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){
-  //          unsigned k=atoms_with_derivatives[i];
-  //          tmpd[0]=vecs->getFinalDerivative(3*i+0); 
-  //          tmpd[1]=vecs->getFinalDerivative(3*i+1); 
-  //          tmpd[2]=vecs->getFinalDerivative(3*i+2); 
-  //          MultiColvarBase::addAtomsDerivatives( 0, k, tmpd );
-  //     }   
-  //     unsigned vvbase=3*atoms_with_derivatives.getNumberActive(); Tensor tmpv;
-  //     for(unsigned i=0;i<3;++i){
-  //         for(unsigned j=0;j<3;++j){
-  //             tmpv(i,j) = vecs->getFinalDerivative( vvbase+3*i+j ); 
-  //         }   
-  //     }   
-  //     MultiColvarBase::addBoxDerivatives( 0, tmpv );
-  // }
   
   return norm;
 }
 
-// vesselbase::StoreDataVessel* VectorMultiColvar::buildDataStashes( const bool& allow_wcutoff, const double& wtol ){
-//   // Build everyting for the multicolvar
-//   vesselbase::StoreDataVessel* vsv=MultiColvarBase::buildDataStashes( allow_wcutoff, wtol );
-//   if( allow_wcutoff ) vsv->setHardCutoffOnWeight( wtol );
-//   // Resize the variable
-//   vecs->resize();
-//   // And make sure we set up the vector storage correctly
-//   vv1.resize( 1 ); vv2.resize( getNumberOfQuantities() - 5 );
-//   // And return
-//   return vsv;
-// }
-// 
-// void VectorMultiColvar::getValueForTask( const unsigned& iatom, std::vector<double>& vals ){
-//   plumed_dbg_assert( vecs && vals.size()==(getNumberOfQuantities()-4) ); 
-//   MultiColvarBase::getValueForTask( iatom, vv1 ); vecs->getVector( iatom, vv2 );
-//   vals[0]=vv1[0]; for(unsigned i=0;i<vv2.size();++i) vals[i+1]=vv2[i];
-// }
-
-// void VectorMultiColvar::addWeightedValueDerivatives( const unsigned& iatom, const unsigned& base_cv_no, const double& weight, multicolvar::MultiColvarFunction* func ){
-//   if( usingLowMem() ){
-//      vecs->recompute( iatom, 1 ); 
-//      for(unsigned j=0;j<getNumberOfQuantities()-5;++j) vecs->chainRuleForComponent( 1, j, 5+j, base_cv_no, weight, func );
-//   } else {
-//      for(unsigned j=0;j<getNumberOfQuantities()-5;++j) vecs->chainRuleForComponent( iatom, j, 5+j, base_cv_no, weight, func );
-//   }
-// }
-
-// void VectorMultiColvar::finishWeightedAverageCalculation( multicolvar::MultiColvarFunction* func ){
-//   // And calculate the norm of the vector
-//   double norm=0, inorm; std::vector<unsigned> tmpindices( 1 + func->getNumberOfDerivatives() );
-//   if(complexvec){
-//      for(unsigned i=0;i<ncomponents;++i){
-//         // Calculate average vector
-//         func->quotientRule(5+i, 1, 5+i); func->quotientRule(5+ncomponents+i, 1, 5+ncomponents+i);
-//         // Calculate length of vector
-//         norm += func->getElementValue(5+i)*func->getElementValue(5+i) + func->getElementValue(5+ncomponents+i)*func->getElementValue(5+ncomponents+i);
-//      }
-//      norm=sqrt(norm); inorm = 1.0 / norm;
-//      for(unsigned i=0;i<ncomponents;++i){ 
-//         dervec[i] = inorm*func->getElementValue(5+i); dervec[ncomponents+i] = inorm*func->getElementValue(5+ncomponents+i); 
-//      }
-//      func->getIndexList( 1, 0, func->getNumberOfDerivatives(), tmpindices );
-//      unsigned nder = func->getNumberOfDerivatives();
-//      for(unsigned i=0;i<tmpindices[0];++i){
-//          unsigned ind = tmpindices[1+i];
-//          for(unsigned j=0;j<ncomponents;++j){
-//              func->addElementDerivative( ind, dervec[j]*func->getElementDerivative(nder*(5+j) + ind) );
-//              func->addElementDerivative( ind, dervec[ncomponents+j]*func->getElementDerivative(nder*(5+ncomponents+j) + ind) );
-//          }
-//      }
-//   } else {
-//      for(unsigned i=0;i<ncomponents;++i){
-//          // Calculate average vector
-//          func->quotientRule(5+i, 1, 5+i);
-//          // Calculate length of vector
-//          norm += func->getElementValue(5+i)*func->getElementValue(5+i);
-//      }
-//      norm=sqrt(norm); inorm = 1.0 / norm;
-//      for(unsigned i=0;i<ncomponents;++i) dervec[i] = inorm*func->getElementValue(5+i); 
-//      func->getIndexList( 1, 0, func->getNumberOfDerivatives(), tmpindices );
-//      // And set derivatives given magnitude of the vector
-//      unsigned nder = func->getNumberOfDerivatives();
-//      for(unsigned i=0;i<tmpindices[0];++i){
-//          unsigned ind = tmpindices[1+i];
-//          for(unsigned j=0;j<ncomponents;++j){
-//              func->addElementDerivative( ind, dervec[j]*func->getElementDerivative(nder*(5+j) + ind) );
-//          }
-//      }
-//   }
-//   func->setElementValue( 0, norm );
-// }
-
-// void VectorMultiColvar::addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, 
-//                                                          const std::vector<double>& der, multicolvar::MultiColvarFunction* func ){
-//   if( usingLowMem() ){
-//       if(jstore==1){
-//          if(firstcall){ vecs->recompute( iatom, jstore ); firstcall=false; }
-//          vecs->chainRuleForVector( jstore, 0, base_cv_no, der, func );
-//       } else {
-//          vecs->recompute( iatom, jstore );
-//          vecs->chainRuleForVector( jstore, 0, base_cv_no, der, func );
-//       }
-//   } else {
-//       vecs->chainRuleForVector( iatom, 0, base_cv_no, der, func );
-//   }
-// }
-
 void VectorMultiColvar::addForcesOnAtoms( const std::vector<double>& inforces ){
   plumed_dbg_assert( inforces.size()==getNumberOfDerivatives() );
   std::vector<double> oldforces( getNumberOfDerivatives() ); 
@@ -215,25 +82,5 @@ void VectorMultiColvar::addForcesOnAtoms( const std::vector<double>& inforces ){
   setForcesOnAtoms( oldforces );
 }
 
-// void VectorMultiColvar::copyElementsToBridgedColvar( multicolvar::BridgedMultiColvarFunction* func ){
-//   MultiColvarBase::copyElementsToBridgedColvar( func );
-// 
-//   for(unsigned icomp=5;icomp<getNumberOfQuantities();++icomp){
-//       func->setElementValue( icomp-4, getElementValue(icomp) );
-//       unsigned nbase =  icomp * getNumberOfDerivatives();
-//       unsigned nbasev = (icomp-4) * func->getNumberOfDerivatives();
-//       for(unsigned jatom=0;jatom<atoms_with_derivatives.getNumberActive();++jatom){
-//           unsigned n=atoms_with_derivatives[jatom], nx=nbase + 3*n, ny=nbasev + 3*n;
-//           func->addElementDerivative( ny+0, getElementDerivative(nx+0) );
-//           func->addElementDerivative( ny+1, getElementDerivative(nx+1) );
-//           func->addElementDerivative( ny+2, getElementDerivative(nx+2) );
-//      }
-//      unsigned nwvir=nbase + 3*getNumberOfAtoms(), nwvirv=nbasev + 3*getNumberOfAtoms();
-//      for(unsigned k=0;k<9;++k){
-//         func->addElementDerivative( nwvirv, getElementDerivative(nwvir) ); nwvir++; nwvirv++;
-//      }
-//   }
-// }
-
 }
 }
diff --git a/src/crystallization/VectorMultiColvar.h b/src/crystallization/VectorMultiColvar.h
index e0324a27383193aa7bfce83204d9d7c08e4b8288..37db089aa83b4632c155717a30c34b08ae867bd0 100644
--- a/src/crystallization/VectorMultiColvar.h
+++ b/src/crystallization/VectorMultiColvar.h
@@ -44,36 +44,6 @@ private:
 protected:
 /// Set the dimensionality of the vector
   void setVectorDimensionality( const unsigned&, const int& );
-//  /// Add some value to the ith component of the vector
-//    void addComponent( const unsigned&, const double& );
-//  /// Get the ith component
-//    double getComponent( const unsigned& ) const ;
-//  /// Set the ith component
-//    void setComponent( const unsigned&, const double& );
-//  /// Add derivatives of ith component of vector with repect to jth atom
-//    void addAtomsDerivative( const unsigned&, const unsigned&, const Vector& );
-//  /// Add atomic derivatives to all components of matrix (note iatom is treated literally here - cf above)
-//    void addAtomDerivativeToAllRealComponents( const unsigned& iatom, const std::vector<double>& vec, const Vector& avec );
-//  /// Add derivatives of ith component of vector with respect to the box 
-//    void addBoxDerivatives( const unsigned&, const Tensor& );
-//  /// Add box derivatives to all components of matrix
-//    void addBoxDerivativesToAllRealComponents( const std::vector<double>& vec, const Tensor& avec );
-//  /// Add some value to the imaginary part of the ith component of the vector
-//    void addImaginaryComponent( const unsigned&, const double& );
-//  /// Get the ith component
-//    double getImaginaryComponent( const unsigned& ) const ;
-//  /// Set the ith component
-//    void setImaginaryComponent( const unsigned&, const double& );
-//  /// Add derivatives of the imaginary part of the ith component of vector with repect to jth atom
-//    void addImaginaryAtomsDerivative( const unsigned&, const unsigned&, const Vector& );
-//  /// Add atomic derivatives to all components of matrix (note iatom is treated literally here - cf above)
-//    void addAtomDerivativeToAllImagComponents( const unsigned& iatom, const std::vector<double>& vec, const Vector& avec );
-//  /// Add derivatives of the imaginary part of the ith component of vector with respect to the box 
-//    void addImaginaryBoxDerivatives( const unsigned&, const Tensor& );
-//  /// Add box derivatives to all components of matrix
-//    void addBoxDerivativesToAllImagComponents( const std::vector<double>& vec, const Tensor& avec );
-//  /// This can be used to accumulate derivative from a store of vectors
-//    void accumulateDerivativesFromVector( const unsigned& ivec, const unsigned& base_cv_no, const double& weight, StoreVectorsVessel* vectors );
 /// Used in vector average to add forces from vector the the forces from here
   void addForcesOnAtoms( const std::vector<double>& inforces );
 public:
@@ -83,32 +53,19 @@ public:
 /// The norm of a vector is not periodic
   virtual bool isPeriodic(){ return false; }
 /// Calculate the multicolvar
-  double doCalculation( const unsigned& taskIndex, multicolvar::AtomValuePack& myatoms );
+  double doCalculation( const unsigned& taskIndex, multicolvar::AtomValuePack& myatoms ) const ;
 /// This shouldn't do anything
-  double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ){ plumed_error(); }
+  double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const { plumed_error(); }
 /// Calculate the vector
-  virtual void calculateVector( multicolvar::AtomValuePack& myatoms )=0;
+  virtual void calculateVector( multicolvar::AtomValuePack& myatoms ) const=0;
 /// Get the number of components in the vector
   unsigned getNumberOfComponentsInVector() const ;
 /// Get the number of quantities we are calculating per step
   unsigned getNumberOfQuantities();
-/// Create places to store the data
-//  vesselbase::StoreDataVessel* buildDataStashes( const bool& allow_wcutoff, const double& wtol );
-/// Get the vector
-//  void getValueForTask( const unsigned& iatom, std::vector<double>& vals );
-/// Used to accumulate values
-//  void addWeightedValueDerivatives( const unsigned& iatom, const unsigned& base_cv_no, const double& weight, multicolvar::MultiColvarFunction* func );
-/// Used for calculating weighted averages
-//  void finishWeightedAverageCalculation( multicolvar::MultiColvarFunction* func );
-/// Used in functions to add derivatives to the orientation vector
-//  void addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, 
-//                                        const std::vector<double>& der, multicolvar::MultiColvarFunction* func );
 /// Can we differentiate the orientation - yes we can the multicolvar is a vector
   bool hasDifferentiableOrientation() const { return true; }
 ///  This makes sure we are not calculating the director when we do LocalAverage
   virtual void doNotCalculateDirector();
-/// Used by ActionVolume
-//  void copyElementsToBridgedColvar( multicolvar::BridgedMultiColvarFunction* func );
 };
 
 inline
@@ -116,67 +73,6 @@ unsigned VectorMultiColvar::getNumberOfComponentsInVector() const {
   return ncomponents; 
 }
 
-// inline
-// void VectorMultiColvar::addComponent( const unsigned& icomp, const double& val ){
-//   plumed_dbg_assert( icomp<ncomponents );
-//   addElementValue( 5 + icomp, val );
-// }
-// 
-// inline
-// void VectorMultiColvar::setComponent( const unsigned& icomp, const double& val ){
-//   plumed_dbg_assert( icomp<ncomponents );
-//   setElementValue( 5 + icomp, val );
-// } 
-//   
-// inline
-// double VectorMultiColvar::getComponent( const unsigned& icomp ) const {
-//   plumed_dbg_assert( icomp<ncomponents );
-//   return getElementValue( 5 + icomp );
-// } 
-// 
-// 
-// inline
-// void VectorMultiColvar::addAtomsDerivative( const unsigned& icomp, const unsigned& jatom, const Vector& der ){
-//   plumed_dbg_assert( icomp<ncomponents && jatom<getNAtoms() );
-//   MultiColvarBase::addAtomsDerivatives( 5 + icomp, current_atoms[jatom], der );
-// }
-
-// inline
-// void VectorMultiColvar::addBoxDerivatives( const unsigned& icomp, const Tensor& vir ){
-//   plumed_dbg_assert( icomp<ncomponents );
-//   MultiColvarBase::addBoxDerivatives( 5 + icomp, vir );
-// }
-// 
-// inline
-// void VectorMultiColvar::addImaginaryComponent( const unsigned& icomp, const double& val ){
-//   plumed_dbg_assert( icomp<ncomponents && complexvec );
-//   addElementValue( 5 + ncomponents + icomp, val );
-// }
-// 
-// inline
-// void VectorMultiColvar::setImaginaryComponent( const unsigned& icomp, const double& val ){
-//   plumed_dbg_assert( icomp<ncomponents && complexvec );
-//   setElementValue( 5 + ncomponents + icomp, val );
-// }
-// 
-// inline 
-// double VectorMultiColvar::getImaginaryComponent( const unsigned& icomp ) const {
-//   plumed_dbg_assert( icomp<ncomponents && complexvec );
-//   return getElementValue( 5 + ncomponents + icomp );
-// } 
-// 
-// inline
-// void VectorMultiColvar::addImaginaryAtomsDerivative( const unsigned& icomp, const unsigned& jatom, const Vector& der){
-//   plumed_dbg_assert( icomp<ncomponents && complexvec && jatom<getNAtoms() );
-//   MultiColvarBase::addAtomsDerivatives( 5 + ncomponents + icomp, current_atoms[jatom], der );
-// }
-// 
-// inline
-// void VectorMultiColvar::addImaginaryBoxDerivatives( const unsigned& icomp, const Tensor& vir ){
-//   plumed_dbg_assert( icomp<ncomponents && complexvec );
-//   MultiColvarBase::addBoxDerivatives( 5 + ncomponents + icomp, vir ); 
-// }
-
 inline
 unsigned VectorMultiColvar::getNumberOfQuantities(){
   return 2 + ncomponents;
diff --git a/src/crystallization/VectorSum.cpp b/src/crystallization/VectorSum.cpp
index 1c6b3bf7d8c5727213994653dfb2329baa9c451b..52a6e3f4439226adbcf92cbf6747987aec92326f 100644
--- a/src/crystallization/VectorSum.cpp
+++ b/src/crystallization/VectorSum.cpp
@@ -35,7 +35,7 @@ public:
   VectorSum( const vesselbase::VesselOptions& da );
   std::string function_description();
   void resize();
-  bool calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const ;
+  bool calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const ;
   void finish( const std::vector<double>& buffer );
 };
 
@@ -73,7 +73,7 @@ void VectorSum::resize(){
   }
 }
 
-bool VectorSum::calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
+bool VectorSum::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const {
   unsigned ncomp=getAction()->getNumberOfQuantities()-2, nder=getAction()->getNumberOfDerivatives();
 
   double weight=myvals.get(0); 
diff --git a/src/function/Target.cpp b/src/function/Target.cpp
index 2f416fc4ad0199a71305454cabecaabc2e6c2036..b9eef4c2bc006ae9238b5a8903a0784f7ea49e6f 100644
--- a/src/function/Target.cpp
+++ b/src/function/Target.cpp
@@ -45,6 +45,8 @@ set of collective variables.
 
 class Target : public Function {
 private:
+  MultiValue myvals;
+  ReferenceValuePack mypack;
   PLMD::ArgumentOnlyDistance* target;
 public:
   Target(const ActionOptions&);
@@ -67,7 +69,9 @@ void Target::registerKeywords(Keywords& keys){
 
 Target::Target(const ActionOptions&ao):
 Action(ao),
-Function(ao)
+Function(ao),
+myvals(1,0),
+mypack(0,0,myvals)
 {
   std::string type; parse("TYPE",type);
   std::string reference; parse("REFERENCE",reference); 
@@ -84,13 +88,17 @@ Function(ao)
   // Get the argument names
   std::vector<std::string> args_to_retrieve;
   target->getArgumentRequests( args_to_retrieve, false );
-  target->setNumberOfArguments( args_to_retrieve.size() );
 
   // Get the arguments
   std::vector<Value*> myargs;
   interpretArgumentList( args_to_retrieve, myargs );
   requestArguments( myargs );
 
+  // Now create packs
+  myvals.resize( 1, myargs.size() );
+  mypack.resize( myargs.size(), 0 );
+  mypack.setValIndex( 0 );
+
   // Create the value
   addValueWithDerivatives(); setNotPeriodic();
 }
@@ -100,8 +108,8 @@ Target::~Target(){
 }
 
 void Target::calculate(){
-  double r=target->calculate( getArguments(), false ); setValue(r);
-  for(unsigned i=0;i<getNumberOfArguments();i++) setDerivative( i, target->getArgumentDerivative(i) );
+  mypack.clear(); double r=target->calculate( getArguments(), mypack, false ); setValue(r);
+  for(unsigned i=0;i<getNumberOfArguments();i++) setDerivative( i, mypack.getArgumentDerivative(i) );
 }
 
 }
diff --git a/src/manyrestraints/ManyRestraintsBase.cpp b/src/manyrestraints/ManyRestraintsBase.cpp
index f2bc0b9981e9042c25e2bc5d9afe0016ee2a1fc6..bc7a999f3a1019589a0983a87218a9ff2af4259c 100644
--- a/src/manyrestraints/ManyRestraintsBase.cpp
+++ b/src/manyrestraints/ManyRestraintsBase.cpp
@@ -65,7 +65,7 @@ void ManyRestraintsBase::doJobsRequiredBeforeTaskList(){
   ActionWithValue::clearDerivatives();
 }
 
-void ManyRestraintsBase::transformBridgedDerivatives( const unsigned& current, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ){
+void ManyRestraintsBase::transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const {
   outvals.setValue( 0, invals.get(0) );
   
   // Get the potential
diff --git a/src/manyrestraints/ManyRestraintsBase.h b/src/manyrestraints/ManyRestraintsBase.h
index 468e01508690def8f0b60a05d0e74e2f65fea503..2cf2b38eefb2f62c2c17c6112a43a2fc0e9dc79d 100644
--- a/src/manyrestraints/ManyRestraintsBase.h
+++ b/src/manyrestraints/ManyRestraintsBase.h
@@ -53,13 +53,13 @@ public:
 /// Do jobs required before tasks are undertaken
   void doJobsRequiredBeforeTaskList();
 /// This actually does the calculation
-  void transformBridgedDerivatives( const unsigned& current, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals );
+  void transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const ;
 /// Calculate the potential
-  virtual double calcPotential( const double& val, double& df )=0;
+  virtual double calcPotential( const double& val, double& df ) const=0;
 // Calculate does nothing
   void calculate(){};
 /// This should never be called
-  void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& ){ plumed_error(); }
+  void performTask( const unsigned& , const unsigned& , MultiValue& ) const { plumed_error(); }
 /// Deactivate task now does nothing
   void apply();
   void applyBridgeForces( const std::vector<double>& bb ){ plumed_assert( bb.size()==0 ); }
diff --git a/src/manyrestraints/UWalls.cpp b/src/manyrestraints/UWalls.cpp
index 7292a7872853f4776c57393a961ec21865e0dbee..0fda53ec788da377f11c9e87e0cd161a1544b6c3 100644
--- a/src/manyrestraints/UWalls.cpp
+++ b/src/manyrestraints/UWalls.cpp
@@ -69,7 +69,7 @@ private:
 public:
   static void registerKeywords( Keywords& keys );
   UWalls( const ActionOptions& );
-  double calcPotential( const double& val, double& df );
+  double calcPotential( const double& val, double& df ) const ;
 };
 
 PLUMED_REGISTER_ACTION(UWalls,"UWALLS")
@@ -95,7 +95,7 @@ ManyRestraintsBase(ao)
   checkRead();
 }
 
-double UWalls::calcPotential( const double& val, double& df ){ 
+double UWalls::calcPotential( const double& val, double& df ) const { 
   double uscale = (val - at + offset)/eps;
   if( uscale > 0. ){
      double power = pow( uscale, exp );
diff --git a/src/mapping/Mapping.cpp b/src/mapping/Mapping.cpp
index 25fc1a0dfd98f3849048d80f3d8c8d231bd0b312..be3bc0aadf27ce7d8a1acf4b19184e0d02467d4b 100644
--- a/src/mapping/Mapping.cpp
+++ b/src/mapping/Mapping.cpp
@@ -22,6 +22,7 @@
 #include "Mapping.h"
 #include "vesselbase/Vessel.h"
 #include "reference/MetricRegister.h"
+#include "reference/ReferenceAtoms.h"
 #include "tools/PDB.h"
 #include "tools/Matrix.h"
 #include "core/PlumedMain.h"
@@ -106,10 +107,10 @@ ActionWithVessel(ao)
   interpretArgumentList( args, req_args ); requestArguments( req_args );
   // Duplicate all frames (duplicates are used by sketch-map)
   mymap->duplicateFrameList(); 
-  fframes.resize( 2*nfram, 0.0 ); dfframes.resize( 2*nfram, 0.0 );
+  // fframes.resize( 2*nfram, 0.0 ); dfframes.resize( 2*nfram, 0.0 );
   plumed_assert( !mymap->mappingNeedsSetup() );
   // Resize all derivative arrays
-  mymap->setNumberOfAtomsAndArguments( atoms.size(), args.size() );
+  // mymap->setNumberOfAtomsAndArguments( atoms.size(), args.size() );
   // Resize forces array
   if( getNumberOfAtoms()>0 ){ 
      forcesToApply.resize( 3*getNumberOfAtoms() + 9 + getNumberOfArguments() );
@@ -138,10 +139,10 @@ void Mapping::prepare(){
       mymap->duplicateFrameList();
       // Get the number of frames in the path
       unsigned nfram=getNumberOfReferencePoints();
-      fframes.resize( 2*nfram, 0.0 ); dfframes.resize( 2*nfram, 0.0 ); 
+      // fframes.resize( 2*nfram, 0.0 ); dfframes.resize( 2*nfram, 0.0 ); 
       plumed_assert( !mymap->mappingNeedsSetup() );
       // Resize all derivative arrays
-      mymap->setNumberOfAtomsAndArguments( atoms.size(), args.size() );
+      // mymap->setNumberOfAtomsAndArguments( atoms.size(), args.size() );
       // Resize forces array
       forcesToApply.resize( 3*getNumberOfAtoms() + 9 + getNumberOfArguments() );
   }
@@ -165,12 +166,28 @@ std::string Mapping::getArgumentName( unsigned& iarg ){
   return "pos" + atnum + "z"; 
 } 
 
-double Mapping::calculateDistanceFunction( const unsigned& ifunc, const bool& squared ){
+void Mapping::finishPackSetup( const unsigned& ifunc, ReferenceValuePack& mypack ) const {
+   ReferenceConfiguration* myref=mymap->getFrame(ifunc); mypack.setValIndex(0);
+   unsigned nargs2=myref->getNumberOfReferenceArguments(); unsigned nat2=myref->getNumberOfReferencePositions();
+   if( mypack.getNumberOfAtoms()!=nat2 || mypack.getNumberOfArguments()!=nargs2 ) mypack.resize( nargs2, nat2 );
+   if( nat2>0 ){
+      ReferenceAtoms* myat2=dynamic_cast<ReferenceAtoms*>( myref ); plumed_dbg_assert( myat2 );
+      for(unsigned i=0;i<nat2;++i) mypack.setAtomIndex( i, myat2->getAtomIndex(i) );
+   }
+}
+
+double Mapping::calculateDistanceFunction( const unsigned& ifunc, ReferenceValuePack& myder, const bool& squared ) const {
   // Calculate the distance
-  double dd = mymap->calcDistanceFromConfiguration( ifunc, getPositions(), getPbc(), getArguments(), squared );     
+  double dd = mymap->calcDistanceFromConfiguration( ifunc, getPositions(), getPbc(), getArguments(), myder, squared );     
   // Transform distance by whatever
-  fframes[ifunc]=transformHD( dd, dfframes[ifunc] );
-  return fframes[ifunc];
+  double df, ff=transformHD( dd, df ); myder.scaleAllDerivatives( df );
+  // And the virial
+  if( !myder.virialWasSet() ){
+      Tensor tvir; tvir.zero(); 
+      for(unsigned i=0;i<myder.getNumberOfAtoms();++i) tvir +=-1.0*Tensor( getPosition( myder.getAtomIndex(i) ), myder.getAtomDerivative(i) );
+      myder.addBoxDerivatives( tvir );
+  }
+  return ff;
 }
 
 void Mapping::calculateNumericalDerivatives( ActionWithValue* a ){
@@ -189,36 +206,6 @@ void Mapping::calculateNumericalDerivatives( ActionWithValue* a ){
   }
 }
 
-void Mapping::transferDerivatives( const unsigned& ider, const unsigned& fno, const unsigned& cur, vesselbase::MultiValue& myvals ){
-  if( !derivativesAreRequired() ) return;
-
-  unsigned frameno=fno*getNumberOfReferencePoints() + cur;
-  for(unsigned i=0;i<getNumberOfArguments();++i) myvals.addDerivative( ider, i, dfframes[frameno]*mymap->getArgumentDerivative(cur,i) ); 
-
-  if( getNumberOfAtoms()>0 ){
-      Vector ader; Tensor tmpvir; tmpvir.zero();
-      unsigned n=getNumberOfArguments();
-      for(unsigned i=0;i<getNumberOfAtoms();++i){
-          ader=mymap->getAtomDerivatives( cur, i );
-          myvals.addDerivative( ider, n, dfframes[frameno]*ader[0] ); n++;
-          myvals.addDerivative( ider, n, dfframes[frameno]*ader[1] ); n++;
-          myvals.addDerivative( ider, n, dfframes[frameno]*ader[2] ); n++;
-          tmpvir += -1.0*Tensor( getPosition(i), ader );
-      }
-      Tensor vir;
-      if( !mymap->getVirial( cur, vir ) ) vir=tmpvir;
-      myvals.addDerivative( ider, n, dfframes[frameno]*vir(0,0) ); n++;
-      myvals.addDerivative( ider, n, dfframes[frameno]*vir(0,1) ); n++;
-      myvals.addDerivative( ider, n, dfframes[frameno]*vir(0,2) ); n++;
-      myvals.addDerivative( ider, n, dfframes[frameno]*vir(1,0) ); n++;
-      myvals.addDerivative( ider, n, dfframes[frameno]*vir(1,1) ); n++;
-      myvals.addDerivative( ider, n, dfframes[frameno]*vir(1,2) ); n++;
-      myvals.addDerivative( ider, n, dfframes[frameno]*vir(2,0) ); n++;
-      myvals.addDerivative( ider, n, dfframes[frameno]*vir(2,1) ); n++;
-      myvals.addDerivative( ider, n, dfframes[frameno]*vir(2,2) );
-  }
-}
-
 void Mapping::apply(){
   if( getForcesFromVessels( forcesToApply ) ){
      addForcesOnArguments( forcesToApply );
diff --git a/src/mapping/Mapping.h b/src/mapping/Mapping.h
index 25ab9dad96eb7d0dcb5d3eeb09dc8c8133338d1e..f02769fed90d301fbeb33f43c24f90b2cf25ff45 100644
--- a/src/mapping/Mapping.h
+++ b/src/mapping/Mapping.h
@@ -53,14 +53,14 @@ protected:
   std::vector<double> fframes;
 /// Get the number of frames in the path
   unsigned getNumberOfReferencePoints() const ;
+/// Finish the setup of the referenceValuePack by transfering atoms and args
+  void finishPackSetup( const unsigned& ifunc, ReferenceValuePack& mypack ) const ;
 /// Calculate the value of the distance from the ith frame
-  double calculateDistanceFunction( const unsigned& ifunc, const bool& squared );
+  double calculateDistanceFunction( const unsigned& ifunc, ReferenceValuePack& myder, const bool& squared ) const ;
 /// Store the distance function
   void storeDistanceFunction( const unsigned& ifunc );
 /// Get the value of the weight
   double getWeight( const unsigned& weight ) const ;
-/// Transfer the derivatives to a MultiValue object
-  void transferDerivatives( const unsigned& ider, const unsigned& fno, const unsigned& cur, vesselbase::MultiValue& myvals );
 public:
   static void registerKeywords( Keywords& keys );
   Mapping(const ActionOptions&);
@@ -77,7 +77,7 @@ public:
 /// Get the value of lambda for paths and property maps 
   virtual double getLambda();
 /// This does the transformation of the distance by whatever function is required
-  virtual double transformHD( const double& dist, double& df )=0;
+  virtual double transformHD( const double& dist, double& df ) const=0;
 /// Get the number of properties we are projecting onto
   unsigned getNumberOfProperties() const ;
 /// Get the name of the ith property we are projecting
diff --git a/src/mapping/PathBase.cpp b/src/mapping/PathBase.cpp
index 789edae8e310fcb4b3577b8aae1cf93eefa3b7db..00ae362019c90604717dd9a65ce2ec443d066b67 100644
--- a/src/mapping/PathBase.cpp
+++ b/src/mapping/PathBase.cpp
@@ -55,16 +55,18 @@ void PathBase::calculate(){
   runAllTasks();
 }
 
-void PathBase::performTask( const unsigned& task_index, const unsigned& current, vesselbase::MultiValue& myvals ){
+void PathBase::performTask( const unsigned& task_index, const unsigned& current, MultiValue& myvals ) const {
+  // This builds a pack to hold the derivatives
+  ReferenceValuePack mypack( getNumberOfArguments(), getNumberOfAtoms(), myvals );
+  finishPackSetup( current, mypack );
   // Calculate the distance from the frame
-  double val=calculateDistanceFunction( current, true );
+  double val=calculateDistanceFunction( current, mypack, true );
   // Put the element value in element zero
   myvals.setValue( 0, val ); myvals.setValue( 1, 1.0 );
-  transferDerivatives( 0, 0, current, myvals ); 
   return;
 }
 
-double PathBase::transformHD( const double& dist, double& df ){
+double PathBase::transformHD( const double& dist, double& df ) const {
   double val = exp( -dist*lambda );
   df = -lambda*val; 
   return val;
diff --git a/src/mapping/PathBase.h b/src/mapping/PathBase.h
index 238a80d07b074e4984d4a02fb13733b31851a296..da36cd41ab7845a45d701e0bb044661362ad815c 100644
--- a/src/mapping/PathBase.h
+++ b/src/mapping/PathBase.h
@@ -35,8 +35,8 @@ public:
   PathBase(const ActionOptions&);
   double getLambda();
   void calculate();
-  void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& );
-  double transformHD( const double& dist, double& df );
+  void performTask( const unsigned& , const unsigned& , MultiValue& ) const ;
+  double transformHD( const double& dist, double& df ) const ;
 };
 
 }
diff --git a/src/mapping/SpathVessel.cpp b/src/mapping/SpathVessel.cpp
index 2ca3ad40c908c680c5e8dcf95a44f568d695f24a..0bf7045814701328b0d03e3716e69b4c8a897cb8 100644
--- a/src/mapping/SpathVessel.cpp
+++ b/src/mapping/SpathVessel.cpp
@@ -38,7 +38,7 @@ public:
   SpathVessel( const vesselbase::VesselOptions& da );
   std::string function_description();
   void prepare();
-  bool calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_index ) const ;
+  bool calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_index ) const ;
 };
 
 PLUMED_REGISTER_VESSEL(SpathVessel,"SPATH")
@@ -74,7 +74,7 @@ void SpathVessel::prepare(){
   foundoneclose=false;
 }
 
-bool SpathVessel::calculate( const unsigned& current, vesselbase::MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_index ) const {
+bool SpathVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_index ) const {
   double pp=mymap->getPropertyValue( current, mycoordnumber ), weight=myvals.get(0);
   if( weight<getTolerance() ) return false;
   buffer[bufstart] += weight*pp; buffer[bufstart+1+nderiv] += weight; 
diff --git a/src/multicolvar/ActionVolume.cpp b/src/multicolvar/ActionVolume.cpp
index 2ef73aec2bce36a17fca94e101c9071ea730cddf..cdfbde1152a27f37bdcf846fa99fdc24f4de0979 100644
--- a/src/multicolvar/ActionVolume.cpp
+++ b/src/multicolvar/ActionVolume.cpp
@@ -49,9 +49,7 @@ VolumeGradientBase(ao)
   log.printf("  calculating %s inside region of insterest\n",functype.c_str() ); 
 
   parseFlag("OUTSIDE",not_in); parse("SIGMA",sigma); 
-  bead.isNotPeriodic(); 
-  std::string kerneltype; parse("KERNEL",kerneltype); 
-  bead.setKernelType( kerneltype );
+  parse("KERNEL",kerneltype); 
   
   if( getPntrToMultiColvar()->isDensity() ){
      std::string input;
@@ -61,11 +59,11 @@ VolumeGradientBase(ao)
   }
 }
 
-void ActionVolume::calculateAllVolumes( const unsigned& curr, vesselbase::MultiValue& outvals ){
+void ActionVolume::calculateAllVolumes( const unsigned& curr, MultiValue& outvals ) const {
   Vector catom_pos=getPntrToMultiColvar()->getCentralAtomPos( curr );
 
   double weight; Vector wdf; Tensor vir; std::vector<Vector> refders( getNumberOfAtoms() );  
-  weight=calculateNumberInside( catom_pos, bead, wdf, vir, refders ); 
+  weight=calculateNumberInside( catom_pos, wdf, vir, refders ); 
   if( not_in ){ 
     weight = 1.0 - weight; wdf *= -1.; vir *=-1; 
     for(unsigned i=0;i<refders.size();++i) refders[i]*=-1;
diff --git a/src/multicolvar/ActionVolume.h b/src/multicolvar/ActionVolume.h
index 10a459b341b19d594fd36fc20c409b03a0d93f1a..e1868802e3c7800523b696bb486b40c2d678c7cc 100644
--- a/src/multicolvar/ActionVolume.h
+++ b/src/multicolvar/ActionVolume.h
@@ -43,18 +43,19 @@ private:
   double sigma;
 /// Are we interested in the area outside the colvar
   bool not_in;
-/// The bead for the histogram
-  HistogramBead bead;
+/// The kernel type for this histogram
+  std::string kerneltype;
 protected:
   double getSigma() const ;
+  std::string getKernelType() const ;
 public:
   static void registerKeywords( Keywords& keys );
   ActionVolume(const ActionOptions&);
 /// Get the number of quantities that are calculated each time
   virtual unsigned getNumberOfQuantities();
 /// Calculate whats in the volume
-  void calculateAllVolumes( const unsigned& curr, vesselbase::MultiValue& outvals );
-  virtual double calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders )=0;
+  void calculateAllVolumes( const unsigned& curr, MultiValue& outvals ) const ;
+  virtual double calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders ) const=0;
   unsigned getCentralAtomElementIndex();
 };
 
@@ -68,6 +69,11 @@ double ActionVolume::getSigma() const {
   return sigma;
 }
 
+inline
+std::string ActionVolume::getKernelType() const {
+  return kerneltype;
+}
+
 inline
 unsigned ActionVolume::getCentralAtomElementIndex(){
  return 1;
diff --git a/src/multicolvar/AdjacencyMatrixAction.cpp b/src/multicolvar/AdjacencyMatrixAction.cpp
index 0b2664b6467f8a0b8f802dc66befe025a004554b..159cacfc7dac7163bd2a7d073bd5c33018bf95aa 100644
--- a/src/multicolvar/AdjacencyMatrixAction.cpp
+++ b/src/multicolvar/AdjacencyMatrixAction.cpp
@@ -83,7 +83,6 @@ tmpdf(1)
 
   // Build active elements array
   for(unsigned i=0;i<getFullNumberOfTasks();++i) active_elements.addIndexToList( i );
-  active_elements.setupMPICommunication( comm );
 
   // Find the largest sf cutoff
   double sfmax=switchingFunction(0,0).get_dmax();
@@ -101,6 +100,8 @@ tmpdf(1)
   Keywords keys; AdjacencyMatrixVessel::registerKeywords( keys );
   vesselbase::VesselOptions da2(da,keys);
   mat = new AdjacencyMatrixVessel(da2);
+  // Set a cutoff for clustering
+  mat->setHardCutoffOnWeight( getTolerance() );
   // Add the vessel to the base
   addVessel( mat );
   // And resize everything
@@ -111,20 +112,20 @@ void AdjacencyMatrixAction::doJobsRequiredBeforeTaskList(){
   // Do jobs required by ActionWithVessel
   ActionWithVessel::doJobsRequiredBeforeTaskList();
   // Make it possible only to go through loop once
-  gathered=false; active_elements.deactivateAll();
+  gathered=false; 
   // Dont calculate derivatives on first loop
   if( usingLowMem() ) dertime=false;
   else dertime=true;
 }
 
-void AdjacencyMatrixAction::calculateWeight( AtomValuePack& myatoms ){
+void AdjacencyMatrixAction::calculateWeight( AtomValuePack& myatoms ) const {
   Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
   double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ),getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( distance.modulo(), dfunc );
   myatoms.setValue(0,sw);
 }
 
-double AdjacencyMatrixAction::compute( const unsigned& tindex, AtomValuePack& myatoms ){
-  active_elements.activate( tindex );
+double AdjacencyMatrixAction::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
+//  active_elements.activate( tindex );
 
   double f_dot, dot_df; 
   unsigned ncomp=getBaseMultiColvar(0)->getNumberOfQuantities();
@@ -160,9 +161,9 @@ double AdjacencyMatrixAction::compute( const unsigned& tindex, AtomValuePack& my
         for(unsigned k=2;k<orient0.size();++k){
            orient0[k]*=sw*dot_df; orient1[k]*=sw*dot_df;
         }
-        vesselbase::MultiValue myder0(0,0); getVectorDerivatives( myatoms.getIndex(0), true, myder0 );
+        MultiValue myder0(0,0); getVectorDerivatives( myatoms.getIndex(0), true, myder0 );
         mergeVectorDerivatives( 1, 2, orient1.size(), myatoms.getIndex(0), orient1, myder0, myatoms );
-        vesselbase::MultiValue myder1(0,0); getVectorDerivatives( myatoms.getIndex(1), true, myder1 );
+        MultiValue myder1(0,0); getVectorDerivatives( myatoms.getIndex(1), true, myder1 );
         mergeVectorDerivatives( 1, 2, orient0.size(), myatoms.getIndex(1), orient0, myder1, myatoms );
      }
   }
@@ -171,8 +172,13 @@ double AdjacencyMatrixAction::compute( const unsigned& tindex, AtomValuePack& my
 
 void AdjacencyMatrixAction::retrieveMatrix( Matrix<double>& mymatrix ){
   // Gather active elements in matrix
-  if(!gathered) active_elements.mpi_gatherActiveMembers( comm ); 
-  gathered=true;
+  if(!gathered){
+     active_elements.deactivateAll();
+     for(unsigned i=0;i<getFullNumberOfTasks();++i){
+        if( mat->storedValueIsActive(i) ) active_elements.activate(i);
+     }
+     active_elements.updateActiveMembers(); gathered=true;
+  }
  
   std::vector<unsigned> myatoms(2); std::vector<double> vals(2);
   for(unsigned i=0;i<active_elements.getNumberActive();++i){
@@ -187,8 +193,13 @@ void AdjacencyMatrixAction::retrieveAdjacencyLists( std::vector<unsigned>& nneig
   plumed_dbg_assert( nneigh.size()==getFullNumberOfBaseTasks() && adj_list.nrows()==getFullNumberOfBaseTasks() && 
                        adj_list.ncols()==getFullNumberOfBaseTasks() );
   // Gather active elements in matrix
-  if(!gathered) active_elements.mpi_gatherActiveMembers( comm );
-  gathered=true;
+  if(!gathered){
+     active_elements.deactivateAll();
+     for(unsigned i=0;i<getFullNumberOfTasks();++i){
+        if( mat->storedValueIsActive(i) ) active_elements.activate(i);
+     }
+     active_elements.updateActiveMembers(); gathered=true;
+  }
 
   // Currently everything has zero neighbors
   for(unsigned i=0;i<nneigh.size();++i) nneigh[i]=0;
diff --git a/src/multicolvar/AdjacencyMatrixAction.h b/src/multicolvar/AdjacencyMatrixAction.h
index e397e89c0a62a1f684695a9c682f7f10c4d394ad..39a96a3a672eb180ec5bd02cb94e916d4fe78dec 100644
--- a/src/multicolvar/AdjacencyMatrixAction.h
+++ b/src/multicolvar/AdjacencyMatrixAction.h
@@ -64,8 +64,8 @@ protected:
 public:
   static void registerKeywords( Keywords& keys );
   AdjacencyMatrixAction(const ActionOptions&);
-  double compute( const unsigned& tindex, AtomValuePack& myatoms );
-  void calculateWeight( AtomValuePack& myatoms );
+  double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ;
+  void calculateWeight( AtomValuePack& myatoms ) const ;
   void doJobsRequiredBeforeTaskList();
 /// Finish the calculation
   virtual void completeCalculation()=0;
diff --git a/src/multicolvar/AlphaBeta.cpp b/src/multicolvar/AlphaBeta.cpp
index 085fd49c123d609300a0976aeb85ccc9365a2c5f..b203e5b55d79f26b5799fcf7db668aa977869719 100644
--- a/src/multicolvar/AlphaBeta.cpp
+++ b/src/multicolvar/AlphaBeta.cpp
@@ -98,7 +98,7 @@ private:
 public:
   static void registerKeywords( Keywords& keys );
   AlphaBeta(const ActionOptions&);
-  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms );
+  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ;
   bool isPeriodic(){ return false; }
 };
 
@@ -148,7 +148,7 @@ PLUMED_MULTICOLVAR_INIT(ao)
   checkRead();
 }
 
-double AlphaBeta::compute( const unsigned& tindex, AtomValuePack& myatoms ){
+double AlphaBeta::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
   Vector d0,d1,d2;
   d0=getSeparation(myatoms.getPosition(1),myatoms.getPosition(0));
   d1=getSeparation(myatoms.getPosition(2),myatoms.getPosition(1));
diff --git a/src/multicolvar/Angles.cpp b/src/multicolvar/Angles.cpp
index 5d412c9fe8329f5751e6fcfc26c5816d9ce22edd..cb640f9974b901809fb156386a8f71a22f519415 100644
--- a/src/multicolvar/Angles.cpp
+++ b/src/multicolvar/Angles.cpp
@@ -87,16 +87,15 @@ class Angles : public MultiColvar {
 private:
   bool use_sf;
   double rcut2_1, rcut2_2;
-  Vector dij, dik;
   SwitchingFunction sf1;
   SwitchingFunction sf2;
 public:
   static void registerKeywords( Keywords& keys );
   Angles(const ActionOptions&);
 /// Updates neighbor list
-  virtual double compute( const unsigned& tindex, AtomValuePack& );
+  virtual double compute( const unsigned& tindex, AtomValuePack& ) const ;
 /// Returns the number of coordinates of the field
-  void calculateWeight( AtomValuePack& );
+  void calculateWeight( AtomValuePack& ) const ;
   bool isPeriodic(){ return false; }
 };
 
@@ -169,10 +168,10 @@ use_sf(false)
   setAtomsForCentralAtom( catom_ind );
 }
 
-void Angles::calculateWeight( AtomValuePack& myatoms ){
-  dij=getSeparation( myatoms.getPosition(0), myatoms.getPosition(2) );
-  dik=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
+void Angles::calculateWeight( AtomValuePack& myatoms ) const {
   if(!use_sf){ myatoms.setValue( 0, 1.0 ); return; }
+  Vector dij=getSeparation( myatoms.getPosition(0), myatoms.getPosition(2) );
+  Vector dik=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
 
   double w1, w2, dw1, dw2, wtot;
   double ldij = dij.modulo2(), ldik = dik.modulo2(); 
@@ -192,7 +191,10 @@ void Angles::calculateWeight( AtomValuePack& myatoms ){
   myatoms.addBoxDerivatives( 0, (-dw1)*Tensor(dij,dij) + (-dw2)*Tensor(dik,dik) );
 }
 
-double Angles::compute( const unsigned& tindex, AtomValuePack& myatoms ){
+double Angles::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
+  Vector dij=getSeparation( myatoms.getPosition(0), myatoms.getPosition(2) );
+  Vector dik=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
+
   Vector ddij,ddik; PLMD::Angle a; 
   double angle=a.compute(dij,dik,ddij,ddik);
 
diff --git a/src/multicolvar/AtomValuePack.cpp b/src/multicolvar/AtomValuePack.cpp
index a42dab9a8946ec6a60b8ffd7faf057f0e43689dd..651ee3de12da33c0b0902f92d83b4367597b5c0b 100644
--- a/src/multicolvar/AtomValuePack.cpp
+++ b/src/multicolvar/AtomValuePack.cpp
@@ -25,11 +25,11 @@
 namespace PLMD {
 namespace multicolvar {
 
-AtomValuePack::AtomValuePack( vesselbase::MultiValue& vals, MultiColvarBase* mcolv ):
+AtomValuePack::AtomValuePack( MultiValue& vals, MultiColvarBase const * mcolv ):
 myvals(vals),
 mycolv(mcolv)
 {
-  indices.resize( mycolv->getNumberOfDerivatives() );
+  indices.resize( vals.getNumberOfDerivatives() ); // mycolv->getNumberOfDerivatives() );
 }
 
 void AtomValuePack::updateUsingIndices(){
diff --git a/src/multicolvar/AtomValuePack.h b/src/multicolvar/AtomValuePack.h
index ffe0bbe0f6be42e639b764ba71ca6cd2077b0b82..c7b7d9a8a8a00920f12c8ec658cec63c2e9f27e4 100644
--- a/src/multicolvar/AtomValuePack.h
+++ b/src/multicolvar/AtomValuePack.h
@@ -22,7 +22,7 @@
 #ifndef __PLUMED_multicolvar_AtomValuePack_h
 #define __PLUMED_multicolvar_AtomValuePack_h
 
-#include "vesselbase/MultiValue.h"
+#include "tools/MultiValue.h"
 #include "MultiColvarBase.h"
 
 namespace PLMD {
@@ -33,15 +33,15 @@ class CatomPack;
 class AtomValuePack {
 private:
 /// Copy of the values that we are adding to
-  vesselbase::MultiValue& myvals;
+  MultiValue& myvals;
 /// Copy of the underlying multicolvar
-  MultiColvarBase* mycolv;
+  MultiColvarBase const * mycolv;
 /// Number of atoms at the moment
   unsigned natoms;
 /// Atom indices
   std::vector<unsigned> indices;
 public:
-  AtomValuePack( vesselbase::MultiValue& vals, MultiColvarBase* mcolv );
+  AtomValuePack( MultiValue& vals, MultiColvarBase const * mcolv );
 /// Set the number of atoms
   void setNumberOfAtoms( const unsigned& );
 /// Set the index for one of the atoms
@@ -50,6 +50,8 @@ public:
   unsigned getIndex( const unsigned& j ) const ;
 ///
   unsigned getNumberOfAtoms() const ;
+///
+  unsigned getNumberOfDerivatives() const ;
 /// Get the position of the ith atom
   Vector getPosition( const unsigned& );
 ///
@@ -71,7 +73,7 @@ public:
 ///
   void addComDerivatives( const unsigned& , const Vector& , CatomPack& );
 ///
-  vesselbase::MultiValue& getUnderlyingMultiValue();
+  MultiValue& getUnderlyingMultiValue();
 };
 
 inline
@@ -84,6 +86,11 @@ unsigned AtomValuePack::getNumberOfAtoms() const {
   return natoms;
 }
 
+inline
+unsigned AtomValuePack::getNumberOfDerivatives() const {
+  return myvals.getNumberOfDerivatives();
+}
+
 inline
 void AtomValuePack::setIndex( const unsigned& j, const unsigned& ind ){
   plumed_dbg_assert( j<natoms ); indices[j]=ind; 
@@ -141,7 +148,7 @@ void AtomValuePack::updateDynamicList(){
 }
 
 inline
-vesselbase::MultiValue& AtomValuePack::getUnderlyingMultiValue(){
+MultiValue& AtomValuePack::getUnderlyingMultiValue(){
   return myvals;
 } 
 
diff --git a/src/multicolvar/Bridge.cpp b/src/multicolvar/Bridge.cpp
index 21ed24ecdb48d138c053e2dde56c5dbee1fb5c8c..9acb1484c669b0aee46ecd047929e66da042365e 100644
--- a/src/multicolvar/Bridge.cpp
+++ b/src/multicolvar/Bridge.cpp
@@ -68,8 +68,8 @@ public:
   static void registerKeywords( Keywords& keys );
   Bridge(const ActionOptions&);
 // active methods:
-  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms );
-  void calculateWeight( AtomValuePack& myatoms );
+  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ;
+  void calculateWeight( AtomValuePack& myatoms ) const ;
   bool isPeriodic(){ return false; }
 };
 
@@ -138,7 +138,7 @@ PLUMED_MULTICOLVAR_INIT(ao)
   checkRead();
 }
 
-void Bridge::calculateWeight( AtomValuePack& myatoms ){
+void Bridge::calculateWeight( AtomValuePack& myatoms ) const {
   Vector dij=getSeparation( myatoms.getPosition(0), myatoms.getPosition(2) );
   double ldij = dij.modulo2();
   if( ldij>rcut2 ) { myatoms.setValue(0,0); return; }
@@ -150,7 +150,7 @@ void Bridge::calculateWeight( AtomValuePack& myatoms ){
   myatoms.addBoxDerivatives( 0, (-dw)*Tensor(dij,dij) );
 }
 
-double Bridge::compute( const unsigned& tindex, AtomValuePack& myatoms ){
+double Bridge::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
   Vector dik=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
   double dw, w=sf1.calculateSqr( dik.modulo2(), dw );
 
diff --git a/src/multicolvar/BridgedMultiColvarFunction.cpp b/src/multicolvar/BridgedMultiColvarFunction.cpp
index 6b82ce32298ac15bf99387eef3e65c8f9095b699..83e032e08531afcf848ebc7d317bd1f3fd3df28e 100644
--- a/src/multicolvar/BridgedMultiColvarFunction.cpp
+++ b/src/multicolvar/BridgedMultiColvarFunction.cpp
@@ -51,7 +51,7 @@ MultiColvarBase(ao)
   for(unsigned i=0;i<mycolv->getFullNumberOfTasks();++i) addTaskToList( mycolv->getTaskCode(i) );
 }
 
-void BridgedMultiColvarFunction::transformBridgedDerivatives( const unsigned& current, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ){
+void BridgedMultiColvarFunction::transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const {
   completeTask( current, invals, outvals );
   
   // Now update the outvals derivatives lists
@@ -66,8 +66,8 @@ void BridgedMultiColvarFunction::transformBridgedDerivatives( const unsigned& cu
   outvals.sortActiveList(); 
 }
 
-void BridgedMultiColvarFunction::performTask( const unsigned& taskIndex, const unsigned& current, vesselbase::MultiValue& myvals ){
-  vesselbase::MultiValue invals( mycolv->getNumberOfQuantities(), mycolv->getNumberOfDerivatives() );
+void BridgedMultiColvarFunction::performTask( const unsigned& taskIndex, const unsigned& current, MultiValue& myvals ) const {
+  MultiValue invals( mycolv->getNumberOfQuantities(), mycolv->getNumberOfDerivatives() );
   mycolv->performTask( taskIndex, current, invals );
   transformBridgedDerivatives( taskIndex, invals, myvals ); 
 }
diff --git a/src/multicolvar/BridgedMultiColvarFunction.h b/src/multicolvar/BridgedMultiColvarFunction.h
index 192c16c2272425d7544c6556d04456f180975076..e59d7dcce6ab1c4768c1c4d2aa78e1f42e330aff 100644
--- a/src/multicolvar/BridgedMultiColvarFunction.h
+++ b/src/multicolvar/BridgedMultiColvarFunction.h
@@ -64,9 +64,9 @@ public:
   void deactivate_task( const unsigned& taskno );
   void calculate(){}
 /// This does the task
-  void transformBridgedDerivatives( const unsigned& current, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals );
-  void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& );
-  virtual void completeTask( const unsigned& curr, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals )=0;
+  void transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const ;
+  void performTask( const unsigned& , const unsigned& , MultiValue& ) const ;
+  virtual void completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const=0;
 /// Get the central atom position
   Vector retrieveCentralAtomPos();
 /// We need our own calculate numerical derivatives here
@@ -76,9 +76,9 @@ public:
   bool isCurrentlyActive( const unsigned& );
 /// This should not be called
   Vector calculateCentralAtomPosition(){ plumed_error(); }
-  double compute( const unsigned& tindex, AtomValuePack& myvals ){ plumed_error(); }
-  Vector getPositionOfAtomForLinkCells( const unsigned& iatom ){ plumed_error(); }
-  void updateActiveAtoms(){ plumed_error(); }
+  double compute( const unsigned& tindex, AtomValuePack& myvals ) const { plumed_error(); }
+  Vector getPositionOfAtomForLinkCells( const unsigned& iatom ) const ;
+  void updateActiveAtoms( AtomValuePack& myatoms ) const { plumed_error(); }
   void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices );
   void applyBridgeForces( const std::vector<double>& bb );
 };
@@ -104,7 +104,7 @@ unsigned BridgedMultiColvarFunction::getSizeOfAtomsWithDerivatives(){
 }
 
 inline 
-Vector BridgedMultiColvarFunction::getPositionOfAtomForLinkCells( const unsigned& iatom ){
+Vector BridgedMultiColvarFunction::getPositionOfAtomForLinkCells( const unsigned& iatom ) const { 
   return mycolv->getPositionOfAtomForLinkCells(iatom);
 }
 
diff --git a/src/multicolvar/CoordinationNumbers.cpp b/src/multicolvar/CoordinationNumbers.cpp
index 7545b773a21c6790e39173deaf3ed915b6a0f68f..1738046c487349af167300b3e7f3d21828494528 100644
--- a/src/multicolvar/CoordinationNumbers.cpp
+++ b/src/multicolvar/CoordinationNumbers.cpp
@@ -71,7 +71,7 @@ public:
   static void registerKeywords( Keywords& keys );
   CoordinationNumbers(const ActionOptions&);
 // active methods:
-  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ); 
+  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; 
 /// Returns the number of coordinates of the field
   bool isPeriodic(){ return false; }
 };
@@ -119,7 +119,7 @@ PLUMED_MULTICOLVAR_INIT(ao)
   checkRead();
 }
 
-double CoordinationNumbers::compute( const unsigned& tindex, AtomValuePack& myatoms ){
+double CoordinationNumbers::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
    double value=0, dfunc; Vector distance;
 
    // Calculate the coordination number
diff --git a/src/multicolvar/Density.cpp b/src/multicolvar/Density.cpp
index 149db001ce2133a266a32f20300bd8e97df39203..32794ad573b485dabf71cbe8119380793401e4de 100644
--- a/src/multicolvar/Density.cpp
+++ b/src/multicolvar/Density.cpp
@@ -54,10 +54,10 @@ public:
   static void registerKeywords( Keywords& keys );
   Density(const ActionOptions&);
 // active methods:
-  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms );
+  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ;
   /// Returns the number of coordinates of the field
   bool isPeriodic(){ return false; }
-  bool isDensity(){ return true; }
+  bool isDensity() const { return true; }
   bool hasDifferentiableOrientation() const { return true; }
 //  void addOrientationDerivativesToBase( const unsigned& iatom, const unsigned& jstore, const unsigned& base_cv_no, 
 //                                        const std::vector<double>& weight, MultiColvarFunction* func ){}
@@ -81,7 +81,7 @@ PLUMED_MULTICOLVAR_INIT(ao)
   checkRead(); 
 }
 
-double Density::compute( const unsigned& tindex, AtomValuePack& myvals ){
+double Density::compute( const unsigned& tindex, AtomValuePack& myvals ) const {
   return 1.0;
 }
 
diff --git a/src/multicolvar/DihedralCorrelation.cpp b/src/multicolvar/DihedralCorrelation.cpp
index 579f737b51446ae510f2e84f47c6e7ed59ad91f2..14b72c4339c169c3b16acc0fcb2bb9764f313997 100644
--- a/src/multicolvar/DihedralCorrelation.cpp
+++ b/src/multicolvar/DihedralCorrelation.cpp
@@ -85,7 +85,7 @@ private:
 public:
   static void registerKeywords( Keywords& keys );
   DihedralCorrelation(const ActionOptions&);
-  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms );
+  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ;
   bool isPeriodic(){ return false; }
 };
 
@@ -117,7 +117,7 @@ PLUMED_MULTICOLVAR_INIT(ao)
   checkRead();
 }
 
-double DihedralCorrelation::compute( const unsigned& tindex, AtomValuePack& myatoms ){
+double DihedralCorrelation::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
   Vector d10,d11,d12;
   d10=getSeparation(myatoms.getPosition(1),myatoms.getPosition(0));
   d11=getSeparation(myatoms.getPosition(2),myatoms.getPosition(1));
diff --git a/src/multicolvar/Distances.cpp b/src/multicolvar/Distances.cpp
index 207f74029b859ba83c5785e19e816c27a0393612..420fc3fb5d4ca6c636affab4da49e31b9f99cea5 100644
--- a/src/multicolvar/Distances.cpp
+++ b/src/multicolvar/Distances.cpp
@@ -82,7 +82,7 @@ public:
   static void registerKeywords( Keywords& keys );
   Distances(const ActionOptions&);
 // active methods:
-  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms );
+  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ;
 /// Returns the number of coordinates of the field
   bool isPeriodic(){ return false; }
 };
@@ -138,7 +138,7 @@ PLUMED_MULTICOLVAR_INIT(ao)
   }
 }
 
-double Distances::compute( const unsigned& tindex, AtomValuePack& myatoms ){
+double Distances::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
    Vector distance; 
    distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
    const double value=distance.modulo();
diff --git a/src/multicolvar/FilterBetween.cpp b/src/multicolvar/FilterBetween.cpp
index 2359c7b42b871ca85986c6bc2cf5a30f6922a678..e2e2822a7004346fa67694f5adafe81396b5c508 100644
--- a/src/multicolvar/FilterBetween.cpp
+++ b/src/multicolvar/FilterBetween.cpp
@@ -42,7 +42,7 @@ private:
 public:
   static void registerKeywords( Keywords& keys );
   FilterBetween(const ActionOptions& ao);
-  double applyFilter( const double& val, double& df );
+  double applyFilter( const double& val, double& df ) const ;
 }; 
 
 PLUMED_REGISTER_ACTION(FilterBetween,"MFILTER_BETWEEN")
@@ -86,7 +86,7 @@ MultiColvarFilter(ao)
   checkRead();  
 }
 
-double FilterBetween::applyFilter( const double& val, double& df ){
+double FilterBetween::applyFilter( const double& val, double& df ) const {
   double f = hb.calculate( val, df ); 
   return f;
 }
diff --git a/src/multicolvar/FilterLessThan.cpp b/src/multicolvar/FilterLessThan.cpp
index a9cb12ebb3f4edfa37336e76b6dce141a7f3a017..17acee9182a5435e064160d7296d93161f467539 100644
--- a/src/multicolvar/FilterLessThan.cpp
+++ b/src/multicolvar/FilterLessThan.cpp
@@ -42,7 +42,7 @@ private:
 public:
   static void registerKeywords( Keywords& keys );
   FilterLess(const ActionOptions& ao);
-  double applyFilter( const double& val, double& df );
+  double applyFilter( const double& val, double& df ) const ;
 }; 
 
 PLUMED_REGISTER_ACTION(FilterLess,"MFILTER_LESS")
@@ -79,7 +79,7 @@ MultiColvarFilter(ao)
   checkRead();  
 }
 
-double FilterLess::applyFilter( const double& val, double& df ){
+double FilterLess::applyFilter( const double& val, double& df ) const {
   double f = sf.calculate( val, df ); df*=val;
   return f;
 }
diff --git a/src/multicolvar/FilterMoreThan.cpp b/src/multicolvar/FilterMoreThan.cpp
index 7bf3c4b888950a107619b8c2cd3292d5f177cb67..d22fb6c968d58ab40a3953ee3b58b7d101af4ecc 100644
--- a/src/multicolvar/FilterMoreThan.cpp
+++ b/src/multicolvar/FilterMoreThan.cpp
@@ -42,7 +42,7 @@ private:
 public:
   static void registerKeywords( Keywords& keys );
   FilterMore(const ActionOptions& ao);
-  double applyFilter( const double& val, double& df );
+  double applyFilter( const double& val, double& df ) const ;
 }; 
 
 PLUMED_REGISTER_ACTION(FilterMore,"MFILTER_MORE")
@@ -79,7 +79,7 @@ MultiColvarFilter(ao)
   checkRead();  
 }
 
-double FilterMore::applyFilter( const double& val, double& df ){
+double FilterMore::applyFilter( const double& val, double& df ) const {
   double f = 1.0 - sf.calculate( val, df ); df*=-val;
   return f;
 }
diff --git a/src/multicolvar/LocalAverage.cpp b/src/multicolvar/LocalAverage.cpp
index ea0536c559f3fc9476ebda02ef215572f5a8721c..aa1359af53f0946f104348af4cbdc84c14c6bc41 100644
--- a/src/multicolvar/LocalAverage.cpp
+++ b/src/multicolvar/LocalAverage.cpp
@@ -92,7 +92,7 @@ public:
 /// We have to overwrite this here
   unsigned getNumberOfQuantities();
 /// Actually do the calculation
-  double compute( const unsigned& tindex, AtomValuePack& myatoms );
+  double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ;
 /// Is the variable periodic
   bool isPeriodic(){ return false; }   
 };
@@ -140,10 +140,10 @@ unsigned LocalAverage::getNumberOfQuantities(){
   return getBaseMultiColvar(0)->getNumberOfQuantities();
 }
 
-double LocalAverage::compute( const unsigned& tindex, AtomValuePack& myatoms ){
+double LocalAverage::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
   Vector distance; double d2, sw, dfunc, nbond=1; CatomPack atom0, atom1;
   std::vector<double> values( getBaseMultiColvar(0)->getNumberOfQuantities() );
-  vesselbase::MultiValue myder(values.size(), getNumberOfDerivatives());
+  MultiValue myder(values.size(), myatoms.getNumberOfDerivatives());
 
   getVectorForTask( myatoms.getIndex(0), false, values );
   if( values.size()>2 ){
@@ -219,7 +219,7 @@ double LocalAverage::compute( const unsigned& tindex, AtomValuePack& myatoms ){
   myatoms.setValue( 0, nbond ); updateActiveAtoms( myatoms );
   if( values.size()>2){
       double norm=0;
-      vesselbase::MultiValue& myvals=myatoms.getUnderlyingMultiValue(); 
+      MultiValue& myvals=myatoms.getUnderlyingMultiValue(); 
       for(unsigned i=2;i<values.size();++i){
           myvals.quotientRule( i, 0, i );
           // Calculate length of vector
diff --git a/src/multicolvar/MultiColvar.cpp b/src/multicolvar/MultiColvar.cpp
index d44c61a1e593f83f6bd34bd1a9dcd3af5f9536f0..618778204ce175dfbfff8300c311e49919a77446 100644
--- a/src/multicolvar/MultiColvar.cpp
+++ b/src/multicolvar/MultiColvar.cpp
@@ -363,7 +363,7 @@ void MultiColvar::calculate(){
   runAllTasks();
 }
 
-void MultiColvar::updateActiveAtoms( AtomValuePack& myatoms ){
+void MultiColvar::updateActiveAtoms( AtomValuePack& myatoms ) const {
   myatoms.updateUsingIndices();
 }
      
diff --git a/src/multicolvar/MultiColvar.h b/src/multicolvar/MultiColvar.h
index 3b1c728e233588157f5f6c54667e2cb3b3ebda81..5bc5f2f63e93322cb40756313fbf1fe3d4c7597a 100644
--- a/src/multicolvar/MultiColvar.h
+++ b/src/multicolvar/MultiColvar.h
@@ -66,15 +66,15 @@ public:
 /// Calculate the multicolvar
   virtual void calculate();
 /// Update the atoms that have derivatives
-  void updateActiveAtoms( AtomValuePack& myatoms );
+  void updateActiveAtoms( AtomValuePack& myatoms ) const ;
 /// This is used in MultiColvarBase only - it is used to setup the link cells
-  Vector getPositionOfAtomForLinkCells( const unsigned& iatom );
+  Vector getPositionOfAtomForLinkCells( const unsigned& iatom ) const ;
 /// Atoms are always active
   bool isCurrentlyActive( const unsigned& code ){ return true; }
 };
 
 inline
-Vector MultiColvar::getPositionOfAtomForLinkCells( const unsigned& iatom ){
+Vector MultiColvar::getPositionOfAtomForLinkCells( const unsigned& iatom ) const {
   return ActionAtomistic::getPosition( iatom );
 }
 
diff --git a/src/multicolvar/MultiColvarBase.cpp b/src/multicolvar/MultiColvarBase.cpp
index 62e9ef8a559cd27d0c27eaee865dbf3a5b1e3ca1..38f4a27fc8c7d4911a3af40f60d85fff254c90b4 100644
--- a/src/multicolvar/MultiColvarBase.cpp
+++ b/src/multicolvar/MultiColvarBase.cpp
@@ -193,7 +193,7 @@ void MultiColvarBase::setupLinkCells(){
   }
 }
 
-void MultiColvarBase::decodeIndexToAtoms( const unsigned& taskCode, std::vector<unsigned>& atoms ){
+void MultiColvarBase::decodeIndexToAtoms( const unsigned& taskCode, std::vector<unsigned>& atoms ) const {
   plumed_dbg_assert( atoms.size()==ablocks.size() && !usespecies && ablocks.size()<4 );
   unsigned scode = taskCode;
   for(unsigned i=0;i<ablocks.size();++i){
@@ -203,7 +203,7 @@ void MultiColvarBase::decodeIndexToAtoms( const unsigned& taskCode, std::vector<
   }
 }
 
-bool MultiColvarBase::setupCurrentAtomList( const unsigned& taskCode, AtomValuePack& myatoms ){
+bool MultiColvarBase::setupCurrentAtomList( const unsigned& taskCode, AtomValuePack& myatoms ) const {
   if( usespecies ){
      unsigned natomsper=1; std::vector<unsigned> current_atoms( getNumberOfAtoms() );
      if( isDensity() ) return true;
@@ -223,7 +223,7 @@ bool MultiColvarBase::setupCurrentAtomList( const unsigned& taskCode, AtomValueP
   return true;
 }
 
-void MultiColvarBase::performTask( const unsigned& task_index, const unsigned& current, vesselbase::MultiValue& myvals ){
+void MultiColvarBase::performTask( const unsigned& task_index, const unsigned& current, MultiValue& myvals ) const {
 
   AtomValuePack myatoms( myvals, this );
   // Retrieve the atom list
@@ -242,11 +242,11 @@ void MultiColvarBase::performTask( const unsigned& task_index, const unsigned& c
   return;
 }
 
-void MultiColvarBase::calculateWeight( AtomValuePack& myatoms ){
+void MultiColvarBase::calculateWeight( AtomValuePack& myatoms ) const {
   myatoms.setValue( 0, 1.0 );
 }
 
-double MultiColvarBase::doCalculation( const unsigned& taskIndex, AtomValuePack& myatoms ){
+double MultiColvarBase::doCalculation( const unsigned& taskIndex, AtomValuePack& myatoms ) const {
   double val=compute( taskIndex, myatoms ); updateActiveAtoms( myatoms );
   return val;
 }
diff --git a/src/multicolvar/MultiColvarBase.h b/src/multicolvar/MultiColvarBase.h
index 06b2cdf93620e878de06abc8df6cbb4d0188f850..ecd60f3f2875ac435b218a2fa74b9d48195858cd 100644
--- a/src/multicolvar/MultiColvarBase.h
+++ b/src/multicolvar/MultiColvarBase.h
@@ -27,8 +27,6 @@
 #include "tools/DynamicList.h"
 #include "tools/LinkCells.h"
 #include "vesselbase/ActionWithVessel.h"
-// #include "StoreColvarVessel.h"
-// #include "StoreCentralAtomsVessel.h"
 #include <vector>
 
 namespace PLMD {
@@ -92,9 +90,9 @@ protected:
 /// Get the number of atoms in this particular colvar
   unsigned getNAtoms() const;
 /// This sets up the list of atoms that are involved in this colvar
-  bool setupCurrentAtomList( const unsigned& taskCode, AtomValuePack& myatoms );
+  bool setupCurrentAtomList( const unsigned& taskCode, AtomValuePack& myatoms ) const ;
 /// Decode indices if there are 2 or 3 atoms involved
-  void decodeIndexToAtoms( const unsigned& taskCode, std::vector<unsigned>& atoms );
+  void decodeIndexToAtoms( const unsigned& taskCode, std::vector<unsigned>& atoms ) const ;
 public:
   MultiColvarBase(const ActionOptions&);
   ~MultiColvarBase(){}
@@ -103,15 +101,15 @@ public:
   virtual void turnOnDerivatives();
 /// Prepare for the calculation
 /// Perform one of the tasks
-  virtual void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& );
+  virtual void performTask( const unsigned& , const unsigned& , MultiValue& ) const ;
 /// This gets the position of an atom for the link cell setup
-  virtual Vector getPositionOfAtomForLinkCells( const unsigned& iatom )=0;
+  virtual Vector getPositionOfAtomForLinkCells( const unsigned& iatom ) const=0;
 /// And a virtual function which actually computes the colvar
-  virtual double doCalculation( const unsigned& tindex, AtomValuePack& myatoms );  
+  virtual double doCalculation( const unsigned& tindex, AtomValuePack& myatoms ) const ;  
 /// Update the atoms that have derivatives
-  virtual void updateActiveAtoms( AtomValuePack& myatoms ){};
+  virtual void updateActiveAtoms( AtomValuePack& myatoms ) const {};
 /// This is replaced once we have a function to calculate the cv
-  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms )=0;
+  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const=0;
 /// Apply the forces from this action
   virtual void apply();
 /// Get the number of derivatives for this action
@@ -123,11 +121,11 @@ public:
 /// Get the index where the central atom is stored
   virtual Vector getCentralAtomPos( const unsigned& curr );
 /// You can use this to screen contributions that are very small so we can avoid expensive (and pointless) calculations
-  virtual void calculateWeight( AtomValuePack& myatoms );
+  virtual void calculateWeight( AtomValuePack& myatoms ) const ;
 /// Get the list of indices that have derivatives
 // virtual void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices );
 /// Is this a density?
-  virtual bool isDensity(){ return false; }
+  virtual bool isDensity() const { return false; }
 /// Store central atoms so that this can be used in a function
 //  virtual vesselbase::StoreDataVessel* buildDataStashes( const bool& allow_wcutoff, const double& wtol );
 /// Calculate and store getElementValue(uder)/getElementValue(vder) and its derivatives in getElementValue(iout)
diff --git a/src/multicolvar/MultiColvarDensity.cpp b/src/multicolvar/MultiColvarDensity.cpp
index 6edac4cacd89d8417a1c12175c8c2f61236cbafa..cadb11b843d5b704e2ff9ce98c7b29e884efde6a 100644
--- a/src/multicolvar/MultiColvarDensity.cpp
+++ b/src/multicolvar/MultiColvarDensity.cpp
@@ -34,6 +34,7 @@
 #include "tools/Grid.h"
 #include "tools/KernelFunctions.h"
 #include "vesselbase/ActionWithInputVessel.h"
+#include "vesselbase/StoreDataVessel.h"
 
 using namespace std;
 
@@ -181,16 +182,16 @@ MultiColvarDensity::~MultiColvarDensity(){
 
 void MultiColvarDensity::update(){
 
+  vesselbase::StoreDataVessel* stash=dynamic_cast<vesselbase::StoreDataVessel*>( getPntrToArgument() );
+  plumed_dbg_assert( stash ); std::vector<double> cvals( mycolv->getNumberOfQuantities() );
   Vector origin = getPosition(0); std::vector<double> pp( directions.size() );
-  std::vector<double> cvals( mycolv->getNumberOfQuantities()-4 );
   for(unsigned i=0;i<mycolv->getFullNumberOfTasks();++i){
-      mycolv->getValueForTask( i, cvals );
-      Vector apos = pbcDistance( mycolv->getCentralAtomPosition(i), origin );
+      stash->retrieveValue( i, false, cvals );
+      Vector apos = pbcDistance( mycolv->getCentralAtomPos( mycolv->getTaskCode(i) ), origin );
       Vector fpos = getPbc().realToScaled( apos );
       for(unsigned j=0;j<directions.size();++j) pp[j]=fpos[ directions[j] ];
-      KernelFunctions kernel( pp, bw, kerneltype, false, cvals[0], true );
-      gg->addKernel( kernel );
-      norm += 1.0;    // This should be replaced by the proper weight
+      KernelFunctions kernel( pp, bw, kerneltype, false, cvals[0]*cvals[1], true );
+      gg->addKernel( kernel ); norm += cvals[0];    
   }
 
   // Output and reset the counter if required
diff --git a/src/multicolvar/MultiColvarFilter.cpp b/src/multicolvar/MultiColvarFilter.cpp
index 8e583713309da03f66e53424a8adabdab90a4976..d30976b6ab63df7eedfc8fe1425468a5e44edd7c 100644
--- a/src/multicolvar/MultiColvarFilter.cpp
+++ b/src/multicolvar/MultiColvarFilter.cpp
@@ -43,7 +43,7 @@ void MultiColvarFilter::doJobsRequiredBeforeTaskList(){
   ActionWithVessel::doJobsRequiredBeforeTaskList();
 }
 
-void MultiColvarFilter::completeTask( const unsigned& curr, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ){
+void MultiColvarFilter::completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const {
   invals.copyValues( outvals );
   if( derivativesAreRequired() ) invals.copyDerivatives( outvals );
  
diff --git a/src/multicolvar/MultiColvarFilter.h b/src/multicolvar/MultiColvarFilter.h
index 5fa523ede97ba2f521e714288c71d422b1ba874c..51a889d7f3a50b9511c676e2065017266a7a85ca 100644
--- a/src/multicolvar/MultiColvarFilter.h
+++ b/src/multicolvar/MultiColvarFilter.h
@@ -43,9 +43,9 @@ public:
 /// Get the number of quantities in the colvar
   unsigned getNumberOfQuantities();
 /// Actually do what we are asked
-  void completeTask( const unsigned& curr, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals );
+  void completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const ;
 /// Do the filtering
-  virtual double applyFilter( const double& val, double& df )=0;
+  virtual double applyFilter( const double& val, double& df ) const=0;
 /// Just checks there are no bridging forces
   void addBridgeForces( const std::vector<double>& bb );
 };
diff --git a/src/multicolvar/MultiColvarFunction.cpp b/src/multicolvar/MultiColvarFunction.cpp
index a562c64db80fef731b8f6b5bb0fab8b524a5f0f4..130a5467f94685a56d134c34cc5e87a3f7e82929 100644
--- a/src/multicolvar/MultiColvarFunction.cpp
+++ b/src/multicolvar/MultiColvarFunction.cpp
@@ -241,11 +241,11 @@ void MultiColvarFunction::calculateNumericalDerivatives( ActionWithValue* a ){
   }
 }
 
-void MultiColvarFunction::updateActiveAtoms( AtomValuePack& myatoms ){
+void MultiColvarFunction::updateActiveAtoms( AtomValuePack& myatoms ) const {
   myatoms.updateDynamicList();
 }
 
-void MultiColvarFunction::getVectorDerivatives( const unsigned& ind, const bool& normed, vesselbase::MultiValue& myder ){
+void MultiColvarFunction::getVectorDerivatives( const unsigned& ind, const bool& normed, MultiValue& myder ) const {
   plumed_dbg_assert( ind<getFullNumberOfBaseTasks() ); unsigned mmc=colvar_label[ind];
   plumed_dbg_assert( mybasedata[mmc]->storedValueIsActive( convertToLocalIndex(ind,mmc) ) );
   myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() );
@@ -254,7 +254,7 @@ void MultiColvarFunction::getVectorDerivatives( const unsigned& ind, const bool&
 
 void MultiColvarFunction::mergeVectorDerivatives( const unsigned& ival, const unsigned& start, const unsigned& end, 
                                                   const unsigned& jatom, const std::vector<double>& der, 
-                                                  vesselbase::MultiValue& myder, AtomValuePack& myatoms ){
+                                                  MultiValue& myder, AtomValuePack& myatoms ) const {
   plumed_dbg_assert( ival<myatoms.getUnderlyingMultiValue().getNumberOfValues() );
   plumed_dbg_assert( start<myder.getNumberOfValues() && end<=myder.getNumberOfValues() );
   plumed_dbg_assert( der.size()==myder.getNumberOfValues() && jatom<getFullNumberOfBaseTasks() );
@@ -266,7 +266,7 @@ void MultiColvarFunction::mergeVectorDerivatives( const unsigned& ival, const un
   // Now get the start of the virial
   unsigned virbas = 3*getNumberOfAtoms();
 
-  vesselbase::MultiValue& myvals=myatoms.getUnderlyingMultiValue();
+  MultiValue& myvals=myatoms.getUnderlyingMultiValue();
   for(unsigned j=0;j<myder.getNumberActive();++j){
      unsigned jder=myder.getActiveIndex(j);
      if( jder<3*mybasemulticolvars[mmc]->getNumberOfAtoms() ){
diff --git a/src/multicolvar/MultiColvarFunction.h b/src/multicolvar/MultiColvarFunction.h
index cd8e95ab1b4a5c31d945dff97d8f530b23fb75fb..b7204a014c76dc81b4bee6715161fa7212992e99 100644
--- a/src/multicolvar/MultiColvarFunction.h
+++ b/src/multicolvar/MultiColvarFunction.h
@@ -49,37 +49,17 @@ protected:
 /// Get the total number of tasks that this calculation is based on
   unsigned getFullNumberOfBaseTasks() const ;
 /// Get the derivatives for the central atom with index ind
-  CatomPack getCentralAtomPackFromInput( const unsigned& ind );
+  CatomPack getCentralAtomPackFromInput( const unsigned& ind ) const ;
 ///
-  void getVectorForTask( const unsigned& ind, const bool& normed, std::vector<double>& orient0 );
+  void getVectorForTask( const unsigned& ind, const bool& normed, std::vector<double>& orient0 ) const ;
 ///
-  void getVectorDerivatives( const unsigned& ind, const bool& normed, vesselbase::MultiValue& myder0 );
+  void getVectorDerivatives( const unsigned& ind, const bool& normed, MultiValue& myder0 ) const ;
 ///
   void mergeVectorDerivatives( const unsigned& ival, const unsigned& start, const unsigned& end,
                                const unsigned& jatom, const std::vector<double>& der, 
-                               vesselbase::MultiValue& myder, AtomValuePack& myatoms );
-/// Get the index of the ith colvar we are using
-//  unsigned getColvarIndex( const unsigned& ) const;
-/// Get the position of one of the central atoms
-//  Vector getPositionOfCentralAtom(const unsigned&) const;
-/// Add derivatives of value wrt to an atomic position 
-//  void addCentralAtomsDerivatives( const unsigned& , const unsigned& , const Vector& );
-/// Extract the value for the iatom th base task (this ignores current_atoms)
-//  void extractValueForBaseTask( const unsigned& iatom, std::vector<double>& vals );
-/// Retrieve the value calculated by the iatom th base task (this uses current_atoms)
-//  void getValueForBaseTask( const unsigned& iatom, std::vector<double>& vals );
-/// Retrieve the vector calculated by the iatom th base task (this uses current_atoms)
-//  void getVectorForBaseTask( const unsigned& iatom, std::vector<double>& vecs );
-/// Add the derivatives of this quantity (this ignores current_atoms)
-//  void extractWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight );
-/// Add the value and derivatives of this quantity (this uses current_atoms)
-//  void accumulateWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight );
-/// Add derivative wrt to the position of the central atom
-//  void addDerivativeOfCentralAtomPos( const unsigned& iatom, const Tensor& der );
+                               MultiValue& myder, AtomValuePack& myatoms ) const ;
 /// Convert an index in the global array to an index in the individual base colvars
   unsigned convertToLocalIndex( const unsigned& index, const unsigned& mcv_code ) const ;
-/// Add derivatives to the orientation
-//  void addOrientationDerivatives( const unsigned& iatom, const std::vector<double>& der );
 /// Build sets by taking one multicolvar from each base
   void buildSets();
 /// Build colvars for atoms as if they were symmetry functions
@@ -89,30 +69,20 @@ protected:
 /// Get the number of base multicolvars 
   unsigned getNumberOfBaseMultiColvars() const ;
 /// Get an example of the underlying multicolvar
-  MultiColvarBase* getBaseMultiColvar( const unsigned& icolv );
+  MultiColvarBase* getBaseMultiColvar( const unsigned& icolv ) const ;
 /// Return the base multicolvar index that this colvar is a part of
   unsigned getBaseColvarNumber( const unsigned& iatom ) const ;
 public:
   MultiColvarFunction(const ActionOptions&);
   static void registerKeywords( Keywords& keys );
-/// Active element in atoms_with_derivatives
-//  void atomHasDerivative( const unsigned& iatom );
-/// Resize the dynamic arrays 
-//  void resizeDynamicArrays();
 /// Update the atoms that are active
-  virtual void updateActiveAtoms( AtomValuePack& myatoms );
+  virtual void updateActiveAtoms( AtomValuePack& myatoms ) const ;
 /// Regular calculate
   void calculate();
 /// Calculate the numerical derivatives for this action
   void calculateNumericalDerivatives( ActionWithValue* a=NULL );
-/// Calculate the position of the central atom
-//  Vector calculateCentralAtomPosition();
-/// Get the position of the central atom
-//  virtual Vector getCentralAtom()=0;
-/// Add derivatives from storage vessels in MultiColvarBase
-//  void addStoredDerivative( const unsigned&, const unsigned&, const unsigned&, const double& );
 /// This is used in MultiColvarBase only - it is used to setup the link cells
-  Vector getPositionOfAtomForLinkCells( const unsigned& iatom );
+  Vector getPositionOfAtomForLinkCells( const unsigned& iatom ) const ;
 /// Some things can be inactive in functions
   bool isCurrentlyActive( const unsigned& code );
 };
@@ -135,7 +105,7 @@ unsigned MultiColvarFunction::getNumberOfBaseMultiColvars() const {
 }
 
 inline
-MultiColvarBase* MultiColvarFunction::getBaseMultiColvar( const unsigned& icolv ){
+MultiColvarBase* MultiColvarFunction::getBaseMultiColvar( const unsigned& icolv ) const {
   plumed_dbg_assert( icolv<mybasemulticolvars.size() );
   return mybasemulticolvars[icolv];
 } 
@@ -153,13 +123,13 @@ unsigned MultiColvarFunction::getBaseColvarNumber( const unsigned& iatom ) const
 }
 
 inline
-Vector MultiColvarFunction::getPositionOfAtomForLinkCells( const unsigned& iatom ){
+Vector MultiColvarFunction::getPositionOfAtomForLinkCells( const unsigned& iatom ) const {
   plumed_dbg_assert( iatom<getFullNumberOfBaseTasks() ); unsigned mmc=colvar_label[ iatom ];
   return mybasemulticolvars[mmc]->getCentralAtomPos( convertToLocalIndex(iatom,mmc) );
 }
 
 inline
-CatomPack MultiColvarFunction::getCentralAtomPackFromInput( const unsigned& ind ){
+CatomPack MultiColvarFunction::getCentralAtomPackFromInput( const unsigned& ind ) const {
   plumed_dbg_assert( ind<getFullNumberOfBaseTasks() ); unsigned mmc=colvar_label[ind];
   unsigned basen=0;
   for(unsigned i=0;i<mmc;++i) basen+=mybasemulticolvars[i]->getNumberOfAtoms();
@@ -167,81 +137,12 @@ CatomPack MultiColvarFunction::getCentralAtomPackFromInput( const unsigned& ind
 }
 
 inline
-void MultiColvarFunction::getVectorForTask( const unsigned& ind, const bool& normed, std::vector<double>& orient ){
+void MultiColvarFunction::getVectorForTask( const unsigned& ind, const bool& normed, std::vector<double>& orient ) const {
   plumed_dbg_assert( ind<getFullNumberOfBaseTasks() ); unsigned mmc=colvar_label[ind];
   plumed_dbg_assert( mybasedata[mmc]->storedValueIsActive( convertToLocalIndex(ind,mmc) ) );
   mybasedata[mmc]->retrieveValue( convertToLocalIndex(ind,mmc), normed, orient );
 }
 
-// inline
-// Vector MultiColvarFunction::getPositionOfCentralAtom( const unsigned& iatom ) const {
-//   plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ];
-//   return mybasemulticolvars[mmc]->getCentralAtomPosition( convertToLocalIndex(current_atoms[iatom],mmc) );   
-// }
-// 
-// inline
-// void MultiColvarFunction::addCentralAtomsDerivatives( const unsigned& iatom, const unsigned& jout, const Vector& der ){
-//   if( doNotCalculateDerivatives() ) return ;
-// 
-//   plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ]; 
-//   mybasemulticolvars[mmc]->addCentralAtomDerivativeToFunction( convertToLocalIndex(current_atoms[iatom],mmc), jout, mmc, der, this );
-// }
-
-// inline
-// void MultiColvarFunction::atomHasDerivative( const unsigned& iatom ){
-//   plumed_dbg_assert( !doNotCalculateDerivatives() );
-//   atoms_with_derivatives.activate( iatom );
-// }
-
-// inline
-// void MultiColvarFunction::addDerivativeOfCentralAtomPos( const unsigned& iatom, const Tensor& der ){
-//   if( doNotCalculateDerivatives() ) return;
-// 
-//   plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ]; Vector tmpder;
-//   for(unsigned i=0;i<3;++i){
-//       for(unsigned j=0;j<3;++j) tmpder[j]=der(i,j);
-//       mybasemulticolvars[mmc]->addCentralAtomDerivativeToFunction( convertToLocalIndex(current_atoms[iatom],mmc), (2+i), mmc, tmpder, this );
-//   }
-// }
-
-// inline
-// void MultiColvarFunction::extractValueForBaseTask( const unsigned& iatom, std::vector<double>& vals ){
-//   unsigned mmc = colvar_label[iatom]; mybasemulticolvars[mmc]->getValueForTask( convertToLocalIndex(iatom,mmc), vals ); 
-// }
-// 
-// inline
-// void MultiColvarFunction::getValueForBaseTask( const unsigned& iatom, std::vector<double>& vals ){
-//   plumed_dbg_assert( iatom<natomsper ); extractValueForBaseTask( current_atoms[iatom], vals );
-// }
-
-// inline
-// void MultiColvarFunction::getVectorForBaseTask( const unsigned& iatom, std::vector<double>& vec ){
-//   plumed_dbg_assert( vec.size()==mybasemulticolvars[0]->getNumberOfQuantities()-5 && tvals.size()>1 );
-//   getValueForBaseTask( iatom, tvals ); for(unsigned i=0;i<vec.size();++i) vec[i]=tvals[i+1];
-// }
-
-// inline
-// void MultiColvarFunction::extractWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight ){
-//   if( doNotCalculateDerivatives() ) return;
-//   unsigned mmc = colvar_label[iatom];
-//   mybasemulticolvars[mmc]->addWeightedValueDerivatives( convertToLocalIndex(iatom, mmc), mmc, weight, this );
-// }
-// 
-// inline
-// void MultiColvarFunction::accumulateWeightedAverageAndDerivatives( const unsigned& iatom, const double& weight ){
-//   if( doNotCalculateDerivatives() ) return;
-//   plumed_dbg_assert( iatom<natomsper ); extractWeightedAverageAndDerivatives( current_atoms[iatom], weight ); 
-// }
-// 
-// inline
-// void MultiColvarFunction::addOrientationDerivatives( const unsigned& iatom , const std::vector<double>& der ){
-//   if( doNotCalculateDerivatives() ) return;
-// 
-//   plumed_dbg_assert( iatom<natomsper ); unsigned mmc = colvar_label[ current_atoms[iatom] ];
-//   unsigned jout=2; if( usespecies && iatom==0 ) jout=1;
-//   mybasemulticolvars[mmc]->addOrientationDerivativesToBase( convertToLocalIndex(current_atoms[iatom],mmc), jout, mmc, der, this );
-// }
-
 }
 }
 #endif
diff --git a/src/multicolvar/NumberOfLinks.cpp b/src/multicolvar/NumberOfLinks.cpp
index dbc11d8b89556408456f3f7f070da0f58fd92bbb..99d1589854ddff6d487f109c0bf34dda2074325b 100644
--- a/src/multicolvar/NumberOfLinks.cpp
+++ b/src/multicolvar/NumberOfLinks.cpp
@@ -75,9 +75,9 @@ public:
   static void registerKeywords( Keywords& keys );
   NumberOfLinks(const ActionOptions&);
 /// Do the stuff with the switching functions
-  void calculateWeight( AtomValuePack& myatoms );
+  void calculateWeight( AtomValuePack& myatoms ) const ;
 /// Actually do the calculation
-  double compute( const unsigned& tindex, AtomValuePack& myatoms );
+  double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ;
 /// Is the variable periodic
   bool isPeriodic(){ return false; }
 };
@@ -130,7 +130,7 @@ MultiColvarFunction(ao)
   readVesselKeywords();
 }
 
-void NumberOfLinks::calculateWeight( AtomValuePack& myatoms ){
+void NumberOfLinks::calculateWeight( AtomValuePack& myatoms ) const {
   Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
   double dfunc, sw = switchingFunction.calculateSqr( distance.modulo2(), dfunc );
   myatoms.setValue(0,sw);
@@ -144,7 +144,7 @@ void NumberOfLinks::calculateWeight( AtomValuePack& myatoms ){
   }
 }
 
-double NumberOfLinks::compute( const unsigned& tindex, AtomValuePack& myatoms ){
+double NumberOfLinks::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
    if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0; 
 
    unsigned ncomp=getBaseMultiColvar(0)->getNumberOfQuantities();
@@ -159,8 +159,8 @@ double NumberOfLinks::compute( const unsigned& tindex, AtomValuePack& myatoms ){
    }
 
    if( !doNotCalculateDerivatives() ){
-     unsigned nder=getNumberOfDerivatives();
-     vesselbase::MultiValue myder0(ncomp,nder), myder1(ncomp,nder);
+     unsigned nder=myatoms.getNumberOfDerivatives();   //getNumberOfDerivatives();
+     MultiValue myder0(ncomp,nder), myder1(ncomp,nder);
      getVectorDerivatives( myatoms.getIndex(0), true, myder0 );
      mergeVectorDerivatives( 1, 2, orient1.size(), myatoms.getIndex(0), orient1, myder0, myatoms );
      getVectorDerivatives( myatoms.getIndex(1), true, myder1 ); 
diff --git a/src/multicolvar/Sprint.cpp b/src/multicolvar/Sprint.cpp
index c007ef84a4ecafcbef025aad55612eab2dd9a04d..918042f6c935f62f71431a7643f9e75a23b00b84 100644
--- a/src/multicolvar/Sprint.cpp
+++ b/src/multicolvar/Sprint.cpp
@@ -169,7 +169,7 @@ void Sprint::completeCalculation(){
    else { rank=comm.Get_rank(); stride=comm.Get_size(); } 
 
    // Derivatives
-   vesselbase::MultiValue myvals( 2, getNumberOfDerivatives() );
+   MultiValue myvals( 2, getNumberOfDerivatives() );
    Matrix<double> mymat_ders( getNumberOfComponents(), getNumberOfDerivatives() );  
    std::vector<unsigned> catoms(2); unsigned nval = getFullNumberOfBaseTasks(); mymat_ders=0; 
    for(unsigned i=rank;i<getNumberOfActiveMatrixElements();i+=stride){
diff --git a/src/multicolvar/Torsions.cpp b/src/multicolvar/Torsions.cpp
index 154547a4964784b28e9b37c1070e7077077f98c7..709e7991208fc6d85fb6bd1b90be88dd1e1ee83b 100644
--- a/src/multicolvar/Torsions.cpp
+++ b/src/multicolvar/Torsions.cpp
@@ -75,7 +75,7 @@ class Torsions : public MultiColvar {
 public:
   static void registerKeywords( Keywords& keys );
   Torsions(const ActionOptions&);
-  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms );
+  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ;
   bool isPeriodic(){ return true; }
   void retrieveDomain( std::string& min, std::string& max ){ min="-pi"; max="pi"; }
 };
@@ -101,7 +101,7 @@ PLUMED_MULTICOLVAR_INIT(ao)
   checkRead();
 }
 
-double Torsions::compute( const unsigned& tindex, AtomValuePack& myatoms ){
+double Torsions::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
   Vector d0,d1,d2;
   d0=getSeparation(myatoms.getPosition(1),myatoms.getPosition(0));
   d1=getSeparation(myatoms.getPosition(2),myatoms.getPosition(1));
diff --git a/src/multicolvar/VolumeAround.cpp b/src/multicolvar/VolumeAround.cpp
index 1a70cabb8bea7f2f27f6b94b564236a4448adc0e..0883d9186b57aff87e672c839eefec81b335738d 100644
--- a/src/multicolvar/VolumeAround.cpp
+++ b/src/multicolvar/VolumeAround.cpp
@@ -78,7 +78,7 @@ public:
   static void registerKeywords( Keywords& keys );
   VolumeAround(const ActionOptions& ao);
   void setupRegions();
-  double calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders );
+  double calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders ) const ;
 }; 
 
 PLUMED_REGISTER_ACTION(VolumeAround,"AROUND")
@@ -116,10 +116,12 @@ ActionVolume(ao)
 
 void VolumeAround::setupRegions(){ }
 
-double VolumeAround::calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders ){
+double VolumeAround::calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders ) const {
+  // Setup the histogram bead
+  HistogramBead bead; bead.isNotPeriodic(); bead.setKernelType( getKernelType() );
+
   // Calculate position of atom wrt to origin
   Vector fpos=pbcDistance( getPosition(0), cpos );
-
   double xcontr, ycontr, zcontr, xder, yder, zder; 
   if( dox ){
      bead.set( xlow, xhigh, getSigma() );
diff --git a/src/multicolvar/VolumeCavity.cpp b/src/multicolvar/VolumeCavity.cpp
index d0f5b59a95560c9ccbcd4cf0013800394f5f7acd..78cb96be2fb92689a7df9d2239f3c40011a69daf 100644
--- a/src/multicolvar/VolumeCavity.cpp
+++ b/src/multicolvar/VolumeCavity.cpp
@@ -122,7 +122,7 @@ public:
   ~VolumeCavity();
   void setupRegions();
   void update();
-  double calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders );
+  double calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector<Vector>& refders ) const ;
 };
 
 PLUMED_REGISTER_ACTION(VolumeCavity,"CAVITY")
@@ -340,7 +340,10 @@ void VolumeCavity::update(){
   }
 }
 
-double VolumeCavity::calculateNumberInside( const Vector& cpos, HistogramBead& bead, Vector& derivatives, Tensor& vir, std::vector<Vector>& rderiv ){
+double VolumeCavity::calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector<Vector>& rderiv ) const {
+  // Setup the histogram bead
+  HistogramBead bead; bead.isNotPeriodic(); bead.setKernelType( getKernelType() );
+
   // Calculate distance of atom from origin of new coordinate frame
   Vector datom=pbcDistance( origin, cpos );
   double ucontr, uder, vcontr, vder, wcontr, wder;
diff --git a/src/multicolvar/VolumeGradientBase.cpp b/src/multicolvar/VolumeGradientBase.cpp
index 3f08a5e63b9ff76f5276ae480829d26d7e0b65c2..a817c24f72930d91b83673e03a5190a4955a180c 100644
--- a/src/multicolvar/VolumeGradientBase.cpp
+++ b/src/multicolvar/VolumeGradientBase.cpp
@@ -47,7 +47,7 @@ void VolumeGradientBase::doJobsRequiredBeforeTaskList(){
   ActionWithVessel::doJobsRequiredBeforeTaskList();
 }
 
-void VolumeGradientBase::completeTask( const unsigned& curr, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals ){
+void VolumeGradientBase::completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const {
   if( getPntrToMultiColvar()->isDensity() ){ 
      outvals.setValue(0, 1.0); outvals.setValue(1, 1.0);
   } else {
@@ -60,7 +60,7 @@ void VolumeGradientBase::completeTask( const unsigned& curr, vesselbase::MultiVa
 
 void VolumeGradientBase::setNumberInVolume( const unsigned& ivol, const unsigned& curr, const double& weight, 
                                             const Vector& wdf, const Tensor& virial, const std::vector<Vector>& refders, 
-                                            vesselbase::MultiValue& outvals ){
+                                            MultiValue& outvals ) const { 
   MultiColvarBase* mcolv=getPntrToMultiColvar(); 
   if( !mcolv->weightHasDerivatives ){
       outvals.setValue(ivol, weight ); 
diff --git a/src/multicolvar/VolumeGradientBase.h b/src/multicolvar/VolumeGradientBase.h
index 12a9c09344acd345b1118a94c3b79f5a0950fd6a..3e773585444ef5f9b31e6f9c934b902d5f3bc4f1 100644
--- a/src/multicolvar/VolumeGradientBase.h
+++ b/src/multicolvar/VolumeGradientBase.h
@@ -30,8 +30,6 @@ namespace multicolvar {
 class VolumeGradientBase : public BridgedMultiColvarFunction {
 friend class MultiColvarBase;   
 private:
-/// This is used for storing positions properly
-  Vector tmp_p;
 /// This is used to store forces temporarily in apply
   std::vector<double> tmpforces;
 protected:
@@ -42,20 +40,20 @@ protected:
 /// Calculate distance between two points
   Vector pbcDistance( const Vector& v1, const Vector& v2) const;
 /// Get position of atom
-  const Vector & getPosition( int iatom );
+  Vector getPosition( int iatom ) const ;
 /// Request the atoms 
   void requestAtoms( const std::vector<AtomNumber>& atoms );
 /// Set the number in the volume
-  void setNumberInVolume( const unsigned& , const unsigned& , const double& , const Vector& , const Tensor& , const std::vector<Vector>& , vesselbase::MultiValue& );
+  void setNumberInVolume( const unsigned& , const unsigned& , const double& , const Vector& , const Tensor& , const std::vector<Vector>& , MultiValue& ) const ;
 public:
   static void registerKeywords( Keywords& keys );
   VolumeGradientBase(const ActionOptions&);
 /// Do jobs required before tasks are undertaken
   void doJobsRequiredBeforeTaskList();
 /// Actually do what we are asked
-  void completeTask( const unsigned& curr, vesselbase::MultiValue& invals, vesselbase::MultiValue& outvals );
+  void completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const ;
 /// Calculate what is in the volumes
-  virtual void calculateAllVolumes( const unsigned& curr, vesselbase::MultiValue& outvals )=0;
+  virtual void calculateAllVolumes( const unsigned& curr, MultiValue& outvals ) const=0;
 /// Setup the regions that this is based on 
   virtual void setupRegions()=0;
 /// Forces here are applied through the bridge
@@ -78,10 +76,10 @@ Vector VolumeGradientBase::pbcDistance( const Vector& v1, const Vector& v2) cons
 }
 
 inline
-const Vector & VolumeGradientBase::getPosition( int iatom ){
+Vector VolumeGradientBase::getPosition( int iatom ) const {
  if( !checkNumericalDerivatives() ) return ActionAtomistic::getPosition(iatom);
  // This is for numerical derivatives of quantity wrt to the local atoms
- tmp_p = ActionAtomistic::getPosition(iatom);
+ Vector tmp_p = ActionAtomistic::getPosition(iatom);
  if( bridgeVariable<3*getNumberOfAtoms() ){
     if( bridgeVariable>=3*iatom && bridgeVariable<(iatom+1)*3 ) tmp_p[bridgeVariable%3]+=sqrt(epsilon);
  }
diff --git a/src/multicolvar/XDistances.cpp b/src/multicolvar/XDistances.cpp
index c6ac26e960b9ad975cb29837b61b8797e947ebae..7612be128337327057f55c0ab00479b886194fb9 100644
--- a/src/multicolvar/XDistances.cpp
+++ b/src/multicolvar/XDistances.cpp
@@ -115,7 +115,7 @@ public:
   static void registerKeywords( Keywords& keys );
   XDistances(const ActionOptions&);
 // active methods:
-  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms );
+  virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ;
 /// Returns the number of coordinates of the field
   bool isPeriodic(){ return false; }
 };
@@ -150,7 +150,7 @@ PLUMED_MULTICOLVAR_INIT(ao)
   checkRead();
 }
 
-double XDistances::compute( const unsigned& tindex, AtomValuePack& myatoms ){
+double XDistances::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
    Vector distance; 
    distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
    const double value=distance[myc];
diff --git a/src/reference/ArgumentOnlyDistance.cpp b/src/reference/ArgumentOnlyDistance.cpp
index f0bef55eeccfcb32aa0e6eedd37d2f44ce9facb9..947ae450d0f50e6fc6c19f68b57df2b1498555d3 100644
--- a/src/reference/ArgumentOnlyDistance.cpp
+++ b/src/reference/ArgumentOnlyDistance.cpp
@@ -30,16 +30,24 @@ ReferenceArguments(ro)
 {
 }
 
-double ArgumentOnlyDistance::calculate( const std::vector<Value*>& vals, const bool& squared ){
-  clearDerivatives();
-  if( tmparg.size()!=vals.size() ) tmparg.resize( vals.size() );
+void ArgumentOnlyDistance::read( const PDB& pdb ){
+  readArgumentsFromPDB( pdb );
+}
+
+double ArgumentOnlyDistance::calculate( const std::vector<Value*>& vals, ReferenceValuePack& myder, const bool& squared ) const {
+  std::vector<double> tmparg( vals.size() );
   for(unsigned i=0;i<vals.size();++i) tmparg[i]=vals[i]->get();
-  return calc( vals, tmparg, squared );
+  double d=calculateArgumentDistance( vals, tmparg, myder, squared );
+  if( !myder.updateComplete() ) myder.updateDynamicLists();
+  return d;
 }
 
-double ArgumentOnlyDistance::calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared ){
+double ArgumentOnlyDistance::calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, 
+                                   ReferenceValuePack& myder, const bool& squared ) const {
   plumed_dbg_assert( pos.size()==0 );
-  return calc( vals, arg, squared );
+  double d=calculateArgumentDistance( vals, arg, myder, squared );
+  if( !myder.updateComplete() ) myder.updateDynamicLists();
+  return d;
 }
 
 }
diff --git a/src/reference/ArgumentOnlyDistance.h b/src/reference/ArgumentOnlyDistance.h
index 9a761daa079f8179f5cc4c9262d79199a5985e46..1ff130c8173c01b7abcdd6eb16dd32de8d54bd9c 100644
--- a/src/reference/ArgumentOnlyDistance.h
+++ b/src/reference/ArgumentOnlyDistance.h
@@ -32,13 +32,11 @@ class PDB;
 class Pbc;
 
 class ArgumentOnlyDistance : public ReferenceArguments {
-private:
-  std::vector<double> tmparg;
 public:
   ArgumentOnlyDistance( const ReferenceConfigurationOptions& ro );
-  double calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared );
-  double calculate( const std::vector<Value*>& vals, const bool& squared );
-  virtual double calc( const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared )=0;
+  void read( const PDB& pdb );
+  double calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, ReferenceValuePack& myder, const bool& squared ) const ;
+  double calculate( const std::vector<Value*>& vals, ReferenceValuePack& myder, const bool& squared ) const ;
 };
 
 }
diff --git a/src/reference/DRMSD.cpp b/src/reference/DRMSD.cpp
index 8ffa7d3d1a16dfcfbfcbad5c7b317b4af69bf76a..3aff7fe58129a8be39c06a66611a3c36fca43b13 100644
--- a/src/reference/DRMSD.cpp
+++ b/src/reference/DRMSD.cpp
@@ -72,7 +72,7 @@ void DRMSD::setup_targets(){
   if( targets.size()==0 ) error("drmsd will compare no distances - check upper and lower bounds are sensible");  
 }
 
-double DRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, const bool& squared ){
+double DRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const {
   plumed_dbg_assert( targets.size()>0 );
 
   Vector distance; 
@@ -89,9 +89,9 @@ double DRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, const bool&
       double diff = len - it->second;
 
       drmsd += diff * diff;
-      addAtomicDerivatives( i, -( diff / len ) * distance );
-      addAtomicDerivatives( j, ( diff / len ) * distance );
-      addBoxDerivatives( -( diff / len ) * Tensor(distance,distance) );
+      myder.addAtomDerivatives( i, -( diff / len ) * distance );
+      myder.addAtomDerivatives( j, ( diff / len ) * distance );
+      myder.addBoxDerivatives( -( diff / len ) * Tensor(distance,distance) );
   }
 
   double npairs = static_cast<double>(targets.size());
@@ -105,8 +105,9 @@ double DRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, const bool&
      idrmsd = 1.0/( drmsd * npairs );
   }
 
-  virial *= idrmsd; 
-  for(unsigned i=0;i<getNumberOfAtoms();++i){atom_ders[i] *= idrmsd;}
+  myder.scaleAllDerivatives( idrmsd );
+  // virial *= idrmsd; 
+  // for(unsigned i=0;i<getNumberOfAtoms();++i){atom_ders[i] *= idrmsd;}
 
   return drmsd;
 }
diff --git a/src/reference/DRMSD.h b/src/reference/DRMSD.h
index a766c86d2982b22ac77264f8ad0818fed2e1e15a..217d484819c8c4223250a90402e620b29528d450 100644
--- a/src/reference/DRMSD.h
+++ b/src/reference/DRMSD.h
@@ -44,7 +44,7 @@ public:
 //  void check( ReferenceConfiguration* , ReferenceConfiguration* );
   void read( const PDB& );
   void setReferenceAtoms( const std::vector<Vector>& conf, const std::vector<double>& align_in, const std::vector<double>& displace_in );
-  double calc( const std::vector<Vector>& pos, const Pbc& pbc, const bool& squared );
+  double calc( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const ;
 };
 
 }
diff --git a/src/reference/EuclideanDistance.cpp b/src/reference/EuclideanDistance.cpp
index ecf2acbe6b05cba615a0342e9a05faeadf87d2ae..d035782024217c5f80b0db21a090dafc935118ee 100644
--- a/src/reference/EuclideanDistance.cpp
+++ b/src/reference/EuclideanDistance.cpp
@@ -27,8 +27,6 @@ namespace PLMD {
 class EuclideanDistance : public ArgumentOnlyDistance {
 public:
   EuclideanDistance( const ReferenceConfigurationOptions& ro );
-  void read( const PDB& );
-  double calc( const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared );
 };
 
 PLUMED_REGISTER_METRIC(EuclideanDistance,"EUCLIDEAN")
@@ -39,13 +37,4 @@ ArgumentOnlyDistance(ro)
 {
 }
 
-void EuclideanDistance::read( const PDB& pdb ){
-  readArgumentsFromPDB( pdb );
-}
-
-double EuclideanDistance::calc( const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared ){
-  return calculateArgumentDistance( vals, arg, squared );
-}
-
-
 }
diff --git a/src/reference/FakeFrame.h b/src/reference/FakeFrame.h
index f5bdcd1752fe82cb32c51bb275b26986fc1e1c5d..79e9e5354aa72176fc1c370ce2049b691ced95c3 100644
--- a/src/reference/FakeFrame.h
+++ b/src/reference/FakeFrame.h
@@ -32,7 +32,7 @@ public PLMD::ReferenceConfiguration
 public:
   FakeFrame( const ReferenceConfigurationOptions& ro ) : ReferenceConfiguration(ro) {}
   void read( const PDB& ){ plumed_merror("should not be called"); }
-  double calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared ){ 
+  double calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, ReferenceValuePack& myder, const bool& squared ) const { 
      plumed_merror("should not be called"); return 1.0; 
   }
 };
diff --git a/src/reference/MahalanobisDistance.cpp b/src/reference/MahalanobisDistance.cpp
index 21885ddf5af7ef4d881ebf4c995a92362ae495f4..2c6fd1f453711428b67c04963ce597261228c090 100644
--- a/src/reference/MahalanobisDistance.cpp
+++ b/src/reference/MahalanobisDistance.cpp
@@ -27,8 +27,6 @@ namespace PLMD {
 class MahalanobisDistance : public ArgumentOnlyDistance {
 public:
   MahalanobisDistance( const ReferenceConfigurationOptions& ro );
-  void read( const PDB& );
-  double calc( const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared );
 };
 
 PLUMED_REGISTER_METRIC(MahalanobisDistance,"MAHALANOBIS")
@@ -40,13 +38,4 @@ ArgumentOnlyDistance(ro)
   hasmetric=true;
 }
 
-void MahalanobisDistance::read( const PDB& pdb ){
-  readArgumentsFromPDB( pdb );
-}
-
-double MahalanobisDistance::calc( const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared ){
-  return calculateArgumentDistance( vals, arg, squared );
-}
-
-
 }
diff --git a/src/reference/MultiDomainRMSD.cpp b/src/reference/MultiDomainRMSD.cpp
index 017cc4203f9937267d11b38a529e973512661101..2d8c8a768b5991550171fc4103cf6f17e1d41f64 100644
--- a/src/reference/MultiDomainRMSD.cpp
+++ b/src/reference/MultiDomainRMSD.cpp
@@ -60,9 +60,9 @@ void MultiDomainRMSD::read( const PDB& pdb ){
           if( !parse("UPPER_CUTTOFF"+num,upper,true) ) upper=std::numeric_limits<double>::max( );
        }
        domains.push_back( metricRegister().create<SingleDomainRMSD>( ftype ) );
-       positions.resize( blocks[i] - blocks[i-1] + 1 );
-       align.resize( blocks[i] - blocks[i-1] + 1 );
-       displace.resize( blocks[i] - blocks[i-1] + 1 );
+       positions.resize( blocks[i] - blocks[i-1] );
+       align.resize( blocks[i] - blocks[i-1] );
+       displace.resize( blocks[i] - blocks[i-1] );
        unsigned n=0;
        for(unsigned j=blocks[i-1];j<blocks[i];++j){
            positions[n]=pdb.getPositions()[j];
@@ -72,7 +72,7 @@ void MultiDomainRMSD::read( const PDB& pdb ){
        }
        domains[i-1]->setBoundsOnDistances( true, lower, upper );  // Currently no option for nopbc
        domains[i-1]->setReferenceAtoms( positions, align, displace );
-       domains[i-1]->setNumberOfAtoms( positions.size() );
+       // domains[i-1]->setNumberOfAtoms( positions.size() );
        
        double ww=0; parse("WEIGHT"+num, ww, true );
        if( ww==0 ) weights.push_back( 1.0 );
@@ -86,37 +86,38 @@ void MultiDomainRMSD::setReferenceAtoms( const std::vector<Vector>& conf, const
   plumed_error();
 }
 
-double MultiDomainRMSD::calculate( const std::vector<Vector>& pos, const Pbc& pbc,  const bool& squared ){
-  clearDerivatives(); double totd=0.; Tensor tvirial; std::vector<Vector> mypos;
+double MultiDomainRMSD::calculate( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const {
+  //clearDerivatives(); 
+  double totd=0.; Tensor tvirial; std::vector<Vector> mypos;
+  MultiValue tvals( 2, myder.getNumberOfDerivatives() ); ReferenceValuePack tder( 0, 0, tvals );
   for(unsigned i=0;i<domains.size();++i){
      // Must extract appropriate positions here
-     mypos.resize( blocks[i+1] - blocks[i] + 1 );
-     unsigned n=0;
-     for(unsigned j=blocks[i];j<blocks[i+1];++j){ mypos[n]=pos[j]; n++; }
+     mypos.resize( blocks[i+1] - blocks[i] ); 
+     unsigned n=0; tder.resize( 0, mypos.size() );
+     for(unsigned j=blocks[i];j<blocks[i+1];++j){ tder.setAtomIndex(n,j); mypos[n]=pos[j]; n++; }
 
      // This actually does the calculation
-     totd += weights[i]*domains[i]->calculate( mypos, pbc, true );
-
-     // Must extract derivatives here
-     n=0;
-     for(unsigned j=blocks[i];j<blocks[i+1];++j){
-         addAtomicDerivatives( j, weights[i]*domains[i]->getAtomDerivative(n) ); n++;
-     }
-     if( domains[i]->getVirial( tvirial ) ){
-         addBoxDerivatives( weights[i]*tvirial );
-     }
+     totd += weights[i]*domains[i]->calculate( mypos, pbc, tder, true );
+     // Now merge the derivative
+     myder.copyScaledDerivatives( 1, weights[i], tvals );
+     // Make sure virial status is set correctly in output derivative pack
+     // This is only done here so I do this by using class friendship
+     if( tder.virialWasSet() ) myder.boxWasSet=true;
+     // And clear
+     tder.clear();
   }
   if( !squared ){
      totd=sqrt(totd); double xx=0.5/totd;
-     for(unsigned iat=0;iat<atom_ders.size();iat++) atom_ders[iat]*=xx;
-     if( virialWasSet ) virial*=xx;
+     myder.scaleAllDerivatives( xx );
   }
+  if( !myder.updateComplete() ) myder.updateDynamicLists();
   return totd;
 }
 
-double MultiDomainRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared ){
+double MultiDomainRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, 
+                              ReferenceValuePack& myder, const bool& squared ) const {
   plumed_dbg_assert( vals.size()==0 && pos.size()==getNumberOfAtoms() && arg.size()==0 );
-  return calculate( pos, pbc, squared );
+  return calculate( pos, pbc, myder, squared );
 }
 
 }
diff --git a/src/reference/MultiDomainRMSD.h b/src/reference/MultiDomainRMSD.h
index 957cfcd8c74365f0fc539cea10ff4a9e3751e219..876bfd46df7873b8efb7fd515eebadd0c83c2ae1 100644
--- a/src/reference/MultiDomainRMSD.h
+++ b/src/reference/MultiDomainRMSD.h
@@ -46,8 +46,8 @@ public:
 /// Set the input from an analysis object (don't know how this will work yet so currently just a plumed_error)
   void setReferenceAtoms( const std::vector<Vector>& conf, const std::vector<double>& align_in, const std::vector<double>& displace_in );
 /// Calculate
-  double calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared );
-  double calculate( const std::vector<Vector>& pos, const Pbc& pbc,  const bool& squared );
+  double calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, ReferenceValuePack& myder, const bool& squared ) const ;
+  double calculate( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const ;
 };
 
 }
diff --git a/src/reference/MultiReferenceBase.cpp b/src/reference/MultiReferenceBase.cpp
index bc010684566c1349bcc8b1ac9652187bfd29338a..fcfdd2337ccee5e687be1c70190e3cd3d0f35940 100644
--- a/src/reference/MultiReferenceBase.cpp
+++ b/src/reference/MultiReferenceBase.cpp
@@ -63,12 +63,12 @@ void MultiReferenceBase::getAtomAndArgumentRequirements( std::vector<AtomNumber>
   }
 }
 
-void MultiReferenceBase::setNumberOfAtomsAndArguments( const unsigned& natoms, const unsigned& nargs ){
-  for(unsigned i=0;i<frames.size();++i){
-      frames[i]->setNumberOfAtoms( natoms );
-      frames[i]->setNumberOfArguments( nargs );
-  }
-}
+// void MultiReferenceBase::setNumberOfAtomsAndArguments( const unsigned& natoms, const unsigned& nargs ){
+//   for(unsigned i=0;i<frames.size();++i){
+//       frames[i]->setNumberOfAtoms( natoms );
+//       frames[i]->setNumberOfArguments( nargs );
+//   }
+// }
 
 void MultiReferenceBase::copyFrame( ReferenceConfiguration* frameToCopy ){
   // Create a reference configuration of the appropriate type
diff --git a/src/reference/MultiReferenceBase.h b/src/reference/MultiReferenceBase.h
index 031407f12aa4b75d0d47812b491f35da4863d5cd..fddb71530216985fe3edd9fa885ba7b20236f827 100644
--- a/src/reference/MultiReferenceBase.h
+++ b/src/reference/MultiReferenceBase.h
@@ -53,7 +53,7 @@ public:
 /// Find what is required of us from the reference frames
   void getAtomAndArgumentRequirements( std::vector<AtomNumber>& atoms, std::vector<std::string>& args );
 /// Finish setup of frames
-  void setNumberOfAtomsAndArguments( const unsigned& natoms, const unsigned& nargs );
+//  void setNumberOfAtomsAndArguments( const unsigned& natoms, const unsigned& nargs );
 /// Do additional reading required by derived class
   virtual void readRestOfFrame(){}
 /// Do additional resizing required by derived class
@@ -62,7 +62,7 @@ public:
   unsigned getNumberOfReferenceFrames() const ;  
 /// Calculate the distance from one of the reference points
   double calcDistanceFromConfiguration( const unsigned& ifunc, const std::vector<Vector>& pos, const Pbc& pbc,
-                                                        const std::vector<Value*>& arg, const bool& squared );
+                                        const std::vector<Value*>& arg, ReferenceValuePack& myder, const bool& squared ) const ;
 /// Return the ith reference frame
   ReferenceConfiguration* getFrame( const unsigned& iframe );
 /// Copy a reference configuration into the multi reference object
@@ -82,8 +82,8 @@ void MultiReferenceBase::parse(const std::string& key, T& val ){
 
 inline
 double MultiReferenceBase::calcDistanceFromConfiguration( const unsigned& ifunc, const std::vector<Vector>& pos, const Pbc& pbc,
-                                                        const std::vector<Value*>& arg, const bool& squared ){
-   return frames[ifunc]->calculate( pos, pbc, arg, squared );
+                                                        const std::vector<Value*>& arg, ReferenceValuePack& myder, const bool& squared ) const {
+   return frames[ifunc]->calculate( pos, pbc, arg, myder, squared );
 }
 
 inline
diff --git a/src/reference/NormalizedEuclideanDistance.cpp b/src/reference/NormalizedEuclideanDistance.cpp
index 4e82bc9419cb2b8d60ed2f38052a0b9b12afa6d4..51ee3be55fe3dea0191f5f6c0fc605c78dd42418 100644
--- a/src/reference/NormalizedEuclideanDistance.cpp
+++ b/src/reference/NormalizedEuclideanDistance.cpp
@@ -27,8 +27,6 @@ namespace PLMD {
 class NormalizedEuclideanDistance : public ArgumentOnlyDistance {
 public:
   NormalizedEuclideanDistance( const ReferenceConfigurationOptions& ro );
-  void read( const PDB& );
-  double calc( const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared );
 };
 
 PLUMED_REGISTER_METRIC(NormalizedEuclideanDistance,"NORM-EUCLIDEAN")
@@ -40,13 +38,4 @@ ArgumentOnlyDistance(ro)
   hasweights=true;
 }
 
-void NormalizedEuclideanDistance::read( const PDB& pdb ){
-  readArgumentsFromPDB( pdb );
-}
-
-double NormalizedEuclideanDistance::calc( const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared ){
-  return calculateArgumentDistance( vals, arg, squared );
-}
-
-
 }
diff --git a/src/reference/OptimalRMSD.cpp b/src/reference/OptimalRMSD.cpp
index 639a0c258a4db9d46cb7232c5d955847758dda64..a158d281d02f5f54dbc67ee5b7265c6d54f0472e 100644
--- a/src/reference/OptimalRMSD.cpp
+++ b/src/reference/OptimalRMSD.cpp
@@ -33,7 +33,7 @@ private:
 public:
   OptimalRMSD(const ReferenceConfigurationOptions& ro);
   void read( const PDB& );
-  double calc( const std::vector<Vector>& pos, const bool& squared );
+  double calc( const std::vector<Vector>& pos, ReferenceValuePack& myder, const bool& squared ) const ;
 };
 
 PLUMED_REGISTER_METRIC(OptimalRMSD,"OPTIMAL")
@@ -49,14 +49,18 @@ void OptimalRMSD::read( const PDB& pdb ){
   readReference( pdb ); 
 }
 
-double OptimalRMSD::calc( const std::vector<Vector>& pos, const bool& squared ){
+double OptimalRMSD::calc( const std::vector<Vector>& pos, ReferenceValuePack& myder, const bool& squared ) const {
+  double d; std::vector<Vector> atom_ders( pos.size() );
   if( fast ){
-     if( getAlign()==getDisplace() ) return myrmsd.optimalAlignment<false,true>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared); 
-     return myrmsd.optimalAlignment<false,false>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared);
+     if( getAlign()==getDisplace() ) d=myrmsd.optimalAlignment<false,true>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared); 
+     d=myrmsd.optimalAlignment<false,false>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared);
   } else {
-     if( getAlign()==getDisplace() ) return myrmsd.optimalAlignment<true,true>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared);
-     return myrmsd.optimalAlignment<true,false>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared);
+     if( getAlign()==getDisplace() ) d=myrmsd.optimalAlignment<true,true>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared);
+     d=myrmsd.optimalAlignment<true,false>(getAlign(),getDisplace(),pos,getReferencePositions(),atom_ders,squared);
   }
+  for(unsigned i=0;i<atom_ders.size();++i) myder.addAtomDerivatives( i, atom_ders[i] ); 
+  if( !myder.updateComplete() ) myder.updateDynamicLists();
+  return d;
 }
 
 }
diff --git a/src/reference/PointWiseMapping.h b/src/reference/PointWiseMapping.h
index 7dc23d41c0318c10b68267a6d887b4cb43a8cc1c..b5358f5133cc70af63f38879635c67536e7ec14f 100644
--- a/src/reference/PointWiseMapping.h
+++ b/src/reference/PointWiseMapping.h
@@ -61,11 +61,11 @@ public:
 /// Get the value of the ith property for th jth frame
   double getPropertyValue( const unsigned& iframe, const unsigned& jprop ) const ;
 /// Get the derivatives wrt to the position of an atom
-  Vector getAtomDerivatives( const unsigned& iframe, const unsigned& jatom );
+//  Vector getAtomDerivatives( const unsigned& iframe, const unsigned& jatom );
 /// Get the derivatives wrt to the box
-  bool getVirial( const unsigned& iframe, Tensor& vir );
+//  bool getVirial( const unsigned& iframe, Tensor& vir );
 /// Ge the derivatives wrt to one of the arguments
-  double getArgumentDerivative( const unsigned& iframe, const unsigned& jarg );
+//  double getArgumentDerivative( const unsigned& iframe, const unsigned& jarg );
 /// Copy derivative information from frame number from to frame number to
   void copyFrameDerivatives( const unsigned& from, const unsigned& to );
 /// Get a pointer to the matrix of pairwise distances
@@ -112,20 +112,20 @@ double PointWiseMapping::getPropertyValue( const unsigned& iframe, const unsigne
   return low_dim[iframe][jprop];
 }
 
-inline
-Vector PointWiseMapping::getAtomDerivatives( const unsigned& iframe, const unsigned& jatom ){
-  return frames[iframe]->getAtomDerivative(jatom);
-}
-
-inline
-bool PointWiseMapping::getVirial( const unsigned& iframe, Tensor& vir ){
-  return frames[iframe]->getVirial( vir );
-}
-
-inline
-double PointWiseMapping::getArgumentDerivative( const unsigned& iframe, const unsigned& jarg ){
-  return frames[iframe]->getArgumentDerivative(jarg);
-}
+// inline
+// Vector PointWiseMapping::getAtomDerivatives( const unsigned& iframe, const unsigned& jatom ){
+//   return frames[iframe]->getAtomDerivative(jatom);
+// }
+// 
+// inline
+// bool PointWiseMapping::getVirial( const unsigned& iframe, Tensor& vir ){
+//   return frames[iframe]->getVirial( vir );
+// }
+
+// inline
+// double PointWiseMapping::getArgumentDerivative( const unsigned& iframe, const unsigned& jarg ){
+//   return frames[iframe]->getArgumentDerivative(jarg);
+// }
 
 inline
 Matrix<double>& PointWiseMapping::modifyDmat(){
diff --git a/src/reference/RMSDBase.cpp b/src/reference/RMSDBase.cpp
index d8e436962f83b7dc9027e83730fe9f6bd9200bb9..e562fb851160cc3335804311c044414a80f82eb5 100644
--- a/src/reference/RMSDBase.cpp
+++ b/src/reference/RMSDBase.cpp
@@ -29,14 +29,14 @@ SingleDomainRMSD(ro)
 {
 }
 
-double RMSDBase::calculate( const std::vector<Vector>& pos, const bool& squared ){
-  clearDerivatives(); 
-  return calc( pos, squared );
+double RMSDBase::calculate( const std::vector<Vector>& pos, ReferenceValuePack& myder, const bool& squared ) const {
+//  clearDerivatives(); 
+  return calc( pos, myder, squared );
 }    
 
-double RMSDBase::calc( const std::vector<Vector>& pos, const Pbc& pbc, const bool& squared ){
+double RMSDBase::calc( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const {
   plumed_dbg_assert( pos.size()==getNumberOfAtoms() );
-  return calc( pos, squared );
+  return calc( pos, myder, squared );
 }
 
 }
diff --git a/src/reference/RMSDBase.h b/src/reference/RMSDBase.h
index f722acd1dee920586dad22f1e2db5269f7c2606d..b055e467f5e3f0568283ecbcbb9f6cd1191011ed 100644
--- a/src/reference/RMSDBase.h
+++ b/src/reference/RMSDBase.h
@@ -33,9 +33,9 @@ class Pbc;
 class RMSDBase : public SingleDomainRMSD {
 public:
   RMSDBase( const ReferenceConfigurationOptions& ro );
-  double calc( const std::vector<Vector>& pos, const Pbc& pbc, const bool& squared );
-  double calculate( const std::vector<Vector>& pos, const bool& squared );
-  virtual double calc( const std::vector<Vector>& pos, const bool& squared )=0;
+  double calc( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const;
+  double calculate( const std::vector<Vector>& pos, ReferenceValuePack& myder, const bool& squared ) const ; 
+  virtual double calc( const std::vector<Vector>& pos, ReferenceValuePack& myder, const bool& squared ) const=0;
 };
 
 }
diff --git a/src/reference/ReferenceArguments.cpp b/src/reference/ReferenceArguments.cpp
index 3788d23938f32fe1441e454e9a6334e8585a8e71..3e30caed5bc5f3cb48e78103b5092be023518d53 100644
--- a/src/reference/ReferenceArguments.cpp
+++ b/src/reference/ReferenceArguments.cpp
@@ -159,8 +159,9 @@ const std::vector<double>& ReferenceArguments::getReferenceMetric(){
   return trig_metric;
 }
 
-double ReferenceArguments::calculateArgumentDistance( const std::vector<Value*> & vals, const std::vector<double>& arg, const bool& squared ){
-  double r=0;
+double ReferenceArguments::calculateArgumentDistance( const std::vector<Value*> & vals, const std::vector<double>& arg, 
+                                                      ReferenceValuePack& myder, const bool& squared ) const {
+  double r=0; std::vector<double> arg_ders( vals.size() );
   if( hasmetric ){
       double dp_i, dp_j;
       for(unsigned i=0;i<reference_args.size();++i){
@@ -185,7 +186,7 @@ double ReferenceArguments::calculateArgumentDistance( const std::vector<Value*>
   }
   if(!squared){ 
     r=sqrt(r); double ir=1.0/(2.0*r); 
-    for(unsigned i=0;i<arg_ders.size();++i) arg_ders[i]*=ir; 
+    for(unsigned i=0;i<arg_ders.size();++i) myder.addArgumentDerivatives( i, arg_ders[i]*ir ); 
   }
   return r;
 }
diff --git a/src/reference/ReferenceArguments.h b/src/reference/ReferenceArguments.h
index 92ee822178574f680d2103589460dc87cb5780ac..b2f8bde4b03b2633d394f11d92f6c54ccfedfa95 100644
--- a/src/reference/ReferenceArguments.h
+++ b/src/reference/ReferenceArguments.h
@@ -66,9 +66,11 @@ protected:
   void setReferenceArguments();
 /// Calculate the euclidean/malanobius distance the atoms have moved from the reference
 /// configuration in CV space
-  double calculateArgumentDistance( const std::vector<Value*> & vals, const std::vector<double>& arg, const bool& squared );
+  double calculateArgumentDistance( const std::vector<Value*> & vals, const std::vector<double>& arg, ReferenceValuePack& myder, const bool& squared ) const ;
 public:
   ReferenceArguments( const ReferenceConfigurationOptions& ro );
+/// Get the number of reference arguments
+  unsigned getNumberOfReferenceArguments() const ;
 /// Get the arguments required 
   void getArgumentRequests( std::vector<std::string>&, bool disable_checks=false );
 /// Set the names of the arguments
@@ -102,6 +104,11 @@ const std::vector<std::string>& ReferenceArguments::getArgumentNames(){
   return arg_names;
 }
 
+inline
+unsigned ReferenceArguments::getNumberOfReferenceArguments() const {
+  return reference_args.size();
+}
+
 }
 #endif
 
diff --git a/src/reference/ReferenceAtoms.h b/src/reference/ReferenceAtoms.h
index acbc69f8a755884c66ad67d91ba1888da3a44c2d..69af7004facad6ebc65e89014e4be60a8b2e9fdf 100644
--- a/src/reference/ReferenceAtoms.h
+++ b/src/reference/ReferenceAtoms.h
@@ -75,23 +75,21 @@ protected:
 /// Get the position of the ith atom
   Vector getReferencePosition( const unsigned& iatom ) const ;  
 /// Get the reference positions
-  const std::vector<Vector> & getReferencePositions();
+  const std::vector<Vector> & getReferencePositions() const ; 
 /// Add derivatives to iatom th atom in list
-  void addAtomicDerivatives( const unsigned& , const Vector& );
+//  void addAtomicDerivatives( const unsigned& , const Vector& );
 /// Get the atomic derivatives on the ith atom in the list
-  Vector retrieveAtomicDerivatives( const unsigned& ) const ;
+//  Vector retrieveAtomicDerivatives( const unsigned& ) const ;
 /// Add derivatives to the viral
-  void addBoxDerivatives( const Tensor& );
+//  void addBoxDerivatives( const Tensor& );
 /// This does the checks that are always required
   void singleDomainRequests( std::vector<AtomNumber>&, bool disable_checks );
+public:
+  ReferenceAtoms( const ReferenceConfigurationOptions& ro );
 /// This returns the number of reference atom positions
   unsigned getNumberOfReferencePositions() const ;
-/// This returns how many atoms there should be
-  unsigned getNumberOfAtoms() const ;
 /// This allows us to use a single pos array with RMSD objects using different atom indexes
   unsigned getAtomIndex( const unsigned& ) const ;
-public:
-  ReferenceAtoms( const ReferenceConfigurationOptions& ro );
 /// Get the atoms required (additional checks are required when we have multiple domains)
   virtual void getAtomRequests( std::vector<AtomNumber>&, bool disable_checks=false );
 /// Set the indices of the reference atoms
@@ -102,6 +100,8 @@ public:
   void printAtoms( OFile& ofile ) const ;
 /// Return all atom indexes
   const std::vector<AtomNumber>& getAbsoluteIndexes();
+/// This returns how many atoms there should be
+  unsigned getNumberOfAtoms() const ;
 };
 
 inline
@@ -122,13 +122,13 @@ unsigned ReferenceAtoms::getNumberOfReferencePositions() const {
 
 inline
 unsigned ReferenceAtoms::getNumberOfAtoms() const {
-  return atom_ders.size();
+  return reference_atoms.size();
 }
 
 inline
 unsigned ReferenceAtoms::getAtomIndex( const unsigned& iatom ) const {
   plumed_dbg_assert( iatom<der_index.size() );
-  plumed_dbg_assert( der_index[iatom]<atom_ders.size() );
+  plumed_dbg_assert( der_index[iatom]<reference_atoms.size() );
   return der_index[iatom];
 }
 
@@ -139,24 +139,24 @@ Vector ReferenceAtoms::getReferencePosition( const unsigned& iatom ) const {
 }
 
 inline
-const std::vector<Vector> & ReferenceAtoms::getReferencePositions(){
+const std::vector<Vector> & ReferenceAtoms::getReferencePositions() const {
   return reference_atoms;
 }
 
-inline
-void ReferenceAtoms::addAtomicDerivatives( const unsigned& iatom, const Vector& der ){
-  atom_ders[ getAtomIndex(iatom) ]+=der;
-}
+// inline
+// void ReferenceAtoms::addAtomicDerivatives( const unsigned& iatom, const Vector& der ){
+//   atom_ders[ getAtomIndex(iatom) ]+=der;
+// }
 
-inline
-Vector ReferenceAtoms::retrieveAtomicDerivatives( const unsigned& iatom ) const {
-  return atom_ders[ getAtomIndex(iatom) ];
-}
+// inline
+// Vector ReferenceAtoms::retrieveAtomicDerivatives( const unsigned& iatom ) const {
+//   return atom_ders[ getAtomIndex(iatom) ];
+// }
 
-inline
-void ReferenceAtoms::addBoxDerivatives( const Tensor& vir ){
-  virialWasSet=true; virial+=vir;
-}
+// inline
+// void ReferenceAtoms::addBoxDerivatives( const Tensor& vir ){
+//   virialWasSet=true; virial+=vir;
+// }
 
 inline
 const std::vector<AtomNumber>& ReferenceAtoms::getAbsoluteIndexes(){
diff --git a/src/reference/ReferenceConfiguration.cpp b/src/reference/ReferenceConfiguration.cpp
index f5ec1663995b137bf3511b67b303528fc6410194..7cb7d510d1a29ef77ee8b2c03afdff677f9777f4 100644
--- a/src/reference/ReferenceConfiguration.cpp
+++ b/src/reference/ReferenceConfiguration.cpp
@@ -44,9 +44,9 @@ std::string ReferenceConfigurationOptions::getMultiRMSDType() const {
 }
 
 ReferenceConfiguration::ReferenceConfiguration( const ReferenceConfigurationOptions& ro ):
-name(ro.tt),
-arg_ders(0),
-atom_ders(0)
+name(ro.tt)
+// arg_ders(0),
+// atom_ders(0)
 {
 }
 
@@ -68,18 +68,18 @@ void ReferenceConfiguration::set( const PDB& pdb ){
   read( pdb );
 }
 
-void ReferenceConfiguration::setNumberOfArguments( const unsigned& n ){
-  arg_ders.resize(n); tmparg.resize(n);
-}
+// void ReferenceConfiguration::setNumberOfArguments( const unsigned& n ){
+//   arg_ders.resize(n); tmparg.resize(n);
+// }
 
-void ReferenceConfiguration::setNumberOfAtoms( const unsigned& n ){
-  atom_ders.resize(n);
-}
+// void ReferenceConfiguration::setNumberOfAtoms( const unsigned& n ){
+//   atom_ders.resize(n);
+// }
 
-bool ReferenceConfiguration::getVirial( Tensor& virout ) const {
-  if(virialWasSet) virout=virial;
-  return virialWasSet;
-}
+// bool ReferenceConfiguration::getVirial( Tensor& virout ) const {
+//   if(virialWasSet) virout=virial;
+//   return virialWasSet;
+// }
 
 void ReferenceConfiguration::parseFlag( const std::string&key, bool&t ){
   Tools::parseFlag(line,key,t);
@@ -93,24 +93,24 @@ void ReferenceConfiguration::setNamesAndAtomNumbers( const std::vector<AtomNumbe
    ReferenceAtoms* atoms=dynamic_cast<ReferenceAtoms*>( this );
   if(!atoms){
      plumed_massert( numbers.size()==0, "expecting no atomic positions");
-     setNumberOfAtoms( 0 );
+     //setNumberOfAtoms( 0 );
   } else { 
      atoms->setAtomNumbers( numbers );
-     setNumberOfAtoms( numbers.size() );
+     // setNumberOfAtoms( numbers.size() );
   }
   // Copy the arguments to the reference
   ReferenceArguments* args=dynamic_cast<ReferenceArguments*>( this );
   if(!args){
      plumed_massert( arg.size()==0, "expecting no arguments");
-     setNumberOfArguments(0);
+     // setNumberOfArguments(0);
   } else {
      args->setArgumentNames( arg );
-     setNumberOfArguments( arg.size() );
+     // setNumberOfArguments( arg.size() );
   }
 }
 
 void ReferenceConfiguration::setReferenceConfig( const std::vector<Vector>& pos, const std::vector<double>& arg, const std::vector<double>& metric ){
-  plumed_dbg_assert( pos.size()==atom_ders.size() && arg.size()==arg_ders.size() );
+//  plumed_dbg_assert( pos.size()==atom_ders.size() && arg.size()==arg_ders.size() );
   // Copy the atomic positions to the reference
   ReferenceAtoms* atoms=dynamic_cast<ReferenceAtoms*>( this );
   if(!atoms){
@@ -136,24 +136,26 @@ void ReferenceConfiguration::checkRead(){
   }
 }
 
-void ReferenceConfiguration::clearDerivatives(){
-  for(unsigned i=0;i<atom_ders.size();++i) atom_ders[i].zero();
-  virial.zero(); virialWasSet=false;
-  arg_ders.assign(arg_ders.size(),0.0);
-}
+// void ReferenceConfiguration::clearDerivatives(){
+//   for(unsigned i=0;i<atom_ders.size();++i) atom_ders[i].zero();
+//   virial.zero(); virialWasSet=false;
+//   arg_ders.assign(arg_ders.size(),0.0);
+// }
 
-double ReferenceConfiguration::calculate( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const bool& squared ){
-  clearDerivatives();
+double ReferenceConfiguration::calculate( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, 
+                                          ReferenceValuePack& myder, const bool& squared ) const {
+  // clearDerivatives();
+  std::vector<double> tmparg( vals.size() );
   for(unsigned i=0;i<vals.size();++i) tmparg[i]=vals[i]->get();
-  return calc( pos, pbc, vals, tmparg, squared );
+  return calc( pos, pbc, vals, tmparg, myder, squared );
 }
 
-void ReferenceConfiguration::copyDerivatives( const ReferenceConfiguration* ref ){
-  plumed_dbg_assert( ref->atom_ders.size()==atom_ders.size() && ref->arg_ders.size()==arg_ders.size() );
-  for(unsigned i=0;i<atom_ders.size();++i) atom_ders[i]=ref->atom_ders[i];
-  for(unsigned i=0;i<arg_ders.size();++i) arg_ders[i]=ref->arg_ders[i];
-  virialWasSet=ref->virialWasSet; virial=ref->virial;
-}
+// void ReferenceConfiguration::copyDerivatives( const ReferenceConfiguration* ref ){
+//   plumed_dbg_assert( ref->atom_ders.size()==atom_ders.size() && ref->arg_ders.size()==arg_ders.size() );
+//   for(unsigned i=0;i<atom_ders.size();++i) atom_ders[i]=ref->atom_ders[i];
+//   for(unsigned i=0;i<arg_ders.size();++i) arg_ders[i]=ref->arg_ders[i];
+//   virialWasSet=ref->virialWasSet; virial=ref->virial;
+// }
 
 void ReferenceConfiguration::print( OFile& ofile, const double& time, const double& weight, const double& old_norm ){
   ofile.printf("REMARK TIME=%f LOG_WEIGHT=%f OLD_NORM=%f\n",time, weight, old_norm );
@@ -169,10 +171,12 @@ void ReferenceConfiguration::print( OFile& ofile, const std::string& fmt ){
 }
 
 double distance( const Pbc& pbc, const std::vector<Value*> & vals, ReferenceConfiguration* ref1, ReferenceConfiguration* ref2, const bool& squared ){
-  double dist1=ref1->calc( ref2->getReferencePositions(), pbc, vals, ref2->getReferenceArguments(), squared );
+  MultiValue myvals( 2, ref1->getReferenceArguments().size() + 3*ref1->getReferencePositions().size() + 9 ); 
+  ReferenceValuePack myder( ref1->getReferenceArguments().size() , ref1->getReferencePositions().size() , myvals ); 
+  double dist1=ref1->calc( ref2->getReferencePositions(), pbc, vals, ref2->getReferenceArguments(), myder, squared );
 #ifndef NDEBUG
   // Check that A - B = B - A
-  double dist2=ref2->calc( ref1->getReferencePositions(), pbc, vals, ref1->getReferenceArguments(), squared );
+  double dist2=ref2->calc( ref1->getReferencePositions(), pbc, vals, ref1->getReferenceArguments(), myder, squared );
   plumed_dbg_assert( fabs(dist1-dist2)<epsilon );
 #endif 
   return dist1;
diff --git a/src/reference/ReferenceConfiguration.h b/src/reference/ReferenceConfiguration.h
index 2cf875ba2748e499b30349eb3acfbd02406281ae..a86120d152060951f12e4f20fdb3977212503ed4 100644
--- a/src/reference/ReferenceConfiguration.h
+++ b/src/reference/ReferenceConfiguration.h
@@ -28,6 +28,7 @@
 #include "tools/Tensor.h"
 #include "tools/Tools.h"
 #include "tools/Exception.h"
+#include "ReferenceValuePack.h"
 
 namespace PLMD{
 
@@ -65,7 +66,7 @@ private:
 /// A vector containing all the remarks from the pdb input
   std::vector<std::string> line;
 /// This is used to store the values of arguments
-  std::vector<double> tmparg;
+//  std::vector<double> tmparg;
 /// These are used to do fake things when we copy frames
   std::vector<AtomNumber> fake_atom_numbers;
   std::vector<std::string> fake_arg_names;
@@ -75,12 +76,12 @@ private:
   std::vector<double> fake_metric;
 protected:
 /// Derivatives wrt to the arguments
-  std::vector<double> arg_ders;
+//  std::vector<double> arg_ders;
 /// The virial contribution has to be stored 
-  bool virialWasSet;
-  Tensor virial;
+//  bool virialWasSet;
+//  Tensor virial;
 /// Derivatives wrt to the atoms
-  std::vector<Vector> atom_ders;
+//  std::vector<Vector> atom_ders;
 /// Crash with an error
   void error(const std::string& msg);
 /// Clear the derivatives 
@@ -91,14 +92,17 @@ public:
   virtual ~ReferenceConfiguration();
 /// Return the name of this metric
   std::string getName() const ;
+///
+  virtual unsigned getNumberOfReferencePositions() const ;
+  virtual unsigned getNumberOfReferenceArguments() const ;
 /// Retrieve the atoms that are required for this guy
   virtual void getAtomRequests( std::vector<AtomNumber>&, bool disable_checks=false ){}
 /// Retrieve the arguments that are required for this guy
   virtual void getArgumentRequests( std::vector<std::string>&, bool disable_checks=false ){}
 /// Set the final number of arguments
-  virtual void setNumberOfArguments( const unsigned& );
+//  virtual void setNumberOfArguments( const unsigned& );
 /// Set the final number of atoms
-  virtual void setNumberOfAtoms( const unsigned& );
+//  virtual void setNumberOfAtoms( const unsigned& );
 /// Set the reference configuration using a PDB 
   virtual void set( const PDB& );
 /// Do all local business for setting the configuration 
@@ -108,17 +112,18 @@ public:
 /// Return the weight for this frame
   double getWeight() const ;
 /// Calculate the distance from the reference configuration
-  double calculate( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const bool& squared=false );
+  double calculate( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, ReferenceValuePack& myder, const bool& squared=false ) const ;
 /// Calculate the distance from the reference configuration
-  virtual double calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& args, const bool& squared )=0;
-/// Return the derivative wrt to the ith atom
-  Vector getAtomDerivative( const unsigned& ) const ;
-/// Return the derivative wrt to the ith argument
-  double getArgumentDerivative( const unsigned& ) const ;
+  virtual double calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& args, 
+                       ReferenceValuePack& myder, const bool& squared ) const=0;
+// /// Return the derivative wrt to the ith atom
+//   Vector getAtomDerivative( const unsigned& ) const ;
+// /// Return the derivative wrt to the ith argument
+//   double getArgumentDerivative( const unsigned& ) const ;
 /// Return the derivatives of the distance wrt the cell vectors.  This returns false
 /// for everything other than DRMSD as these sort of calculations have to be done 
 /// separately when you use RMSD 
-  bool getVirial( Tensor& virout ) const ;    
+//   bool getVirial( Tensor& virout ) const ;    
 /// Parse something from the pdb remarks
   template<class T>
   bool parse( const std::string&key, T&t, bool ignore_missing=false );
@@ -142,7 +147,7 @@ public:
   virtual double getReferenceArgument( const unsigned& i ){ plumed_error(); return 0.0; }
 /// These are overwritten in ReferenceArguments and ReferenceAtoms but are required here 
 /// to make PLMD::distance work
-  virtual const std::vector<Vector>& getReferencePositions();
+  virtual const std::vector<Vector>& getReferencePositions() const ; 
   virtual const std::vector<double>& getReferenceArguments(); 
   virtual const std::vector<double>& getReferenceMetric();
 /// These are overwritten in ReferenceArguments and ReferenceAtoms to make frame copying work
@@ -150,17 +155,17 @@ public:
   virtual const std::vector<std::string>& getArgumentNames();
 };
 
-inline
-Vector ReferenceConfiguration::getAtomDerivative( const unsigned& ider ) const {
-  plumed_dbg_assert( ider<atom_ders.size() );
-  return atom_ders[ider];
-}
+// inline
+// Vector ReferenceConfiguration::getAtomDerivative( const unsigned& ider ) const {
+//   plumed_dbg_assert( ider<atom_ders.size() );
+//   return atom_ders[ider];
+// }
 
-inline
-double ReferenceConfiguration::getArgumentDerivative( const unsigned& ider ) const {
-  plumed_dbg_assert( ider<arg_ders.size() );
-  return arg_ders[ider];
-}
+// inline
+// double ReferenceConfiguration::getArgumentDerivative( const unsigned& ider ) const {
+//   plumed_dbg_assert( ider<arg_ders.size() );
+//   return arg_ders[ider];
+// }
 
 inline
 void ReferenceConfiguration::setWeight( const double& ww ){
@@ -187,7 +192,7 @@ bool ReferenceConfiguration::parseVector(const std::string&key,std::vector<T>&t,
 }
 
 inline
-const std::vector<Vector>& ReferenceConfiguration::getReferencePositions(){
+const std::vector<Vector>& ReferenceConfiguration::getReferencePositions() const { 
   return fake_refatoms;
 }
 
@@ -211,6 +216,16 @@ const std::vector<std::string>& ReferenceConfiguration::getArgumentNames(){
   return fake_arg_names;
 }
 
+inline
+unsigned ReferenceConfiguration::getNumberOfReferencePositions() const {
+  return 0;
+}
+
+inline
+unsigned ReferenceConfiguration::getNumberOfReferenceArguments() const {
+  return 0;
+}
+
 
 
 }
diff --git a/src/reference/ReferenceValuePack.cpp b/src/reference/ReferenceValuePack.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7529674bae594c8745f390a43d4be75ccf398b08
--- /dev/null
+++ b/src/reference/ReferenceValuePack.cpp
@@ -0,0 +1,87 @@
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   Copyright (c) 2013,2014 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 "ReferenceValuePack.h"
+
+namespace PLMD {
+
+ReferenceValuePack::ReferenceValuePack( const unsigned& nargs, const unsigned& natoms, MultiValue& vals ):
+boxWasSet(false),
+numberOfArgs(nargs),
+oind(1),
+myvals(vals)
+{
+  atom_indices.resize( natoms );
+}
+
+void ReferenceValuePack::resize( const unsigned& nargs, const unsigned& natoms ){
+  numberOfArgs=nargs; atom_indices.resize( natoms );
+}
+
+void ReferenceValuePack::updateDynamicLists(){
+  myvals.emptyActiveMembers();
+  for(unsigned i=0;i<numberOfArgs;++i) myvals.updateIndex( i );
+  for(unsigned i=0;i<atom_indices.size();++i){
+     unsigned nbase = numberOfArgs + 3*atom_indices[i];
+     myvals.updateIndex( nbase+0 ); myvals.updateIndex( nbase+1 ); myvals.updateIndex( nbase+2 );
+  }
+  unsigned nbase = myvals.getNumberOfDerivatives() - 9;
+  // zero is added to all virial components to ensure that these are active in the dynamic list
+  // if this is not done there is a problem with secondary structure variables
+  if( atom_indices.size()>0 ){
+     for(unsigned i=0;i<9;++i) myvals.addDerivative( oind, nbase+i, 0.0 );
+  } 
+  for(unsigned i=0;i<9;++i) myvals.updateIndex( nbase+i ); 
+  myvals.sortActiveList();
+}
+
+void ReferenceValuePack::clear(){
+  if( !myvals.updateComplete() ) updateDynamicLists();
+  myvals.clearAll(); boxWasSet=false;
+}
+
+void ReferenceValuePack::scaleAllDerivatives( const double& scalef ){
+  if( !myvals.updateComplete() ) updateDynamicLists();
+
+  for(unsigned i=0;i<myvals.getNumberActive();++i){
+      unsigned ider=myvals.getActiveIndex(i);
+      myvals.setDerivative( oind, ider, scalef*myvals.getDerivative( oind, ider ) );
+  }
+}
+
+void ReferenceValuePack::copyScaledDerivatives( const unsigned& from, const double& scalef, const MultiValue& tvals ){
+  plumed_dbg_assert( tvals.getNumberOfDerivatives()==myvals.getNumberOfDerivatives() );
+  for(unsigned i=0;i<tvals.getNumberActive();++i){
+      unsigned ider=tvals.getActiveIndex(i);
+      myvals.addDerivative( oind, ider, scalef*tvals.getDerivative( from, ider ) );
+  }
+}
+
+void ReferenceValuePack::moveDerivatives( const unsigned& from, const unsigned& to ){
+  if( !myvals.updateComplete() ) updateDynamicLists();
+
+  for(unsigned i=0;i<myvals.getNumberActive();++i){
+     unsigned ider=myvals.getActiveIndex(i); 
+     myvals.setDerivative( to, ider, myvals.getDerivative( from, ider ) );
+  } 
+}
+
+}
diff --git a/src/reference/ReferenceValuePack.h b/src/reference/ReferenceValuePack.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c39b8bcb8370773428a879f2981d8d6aed8a4fe
--- /dev/null
+++ b/src/reference/ReferenceValuePack.h
@@ -0,0 +1,170 @@
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   Copyright (c) 2013,2014 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/>.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+#ifndef __PLUMED_reference_ReferenceValuePack_h
+#define __PLUMED_reference_ReferenceValuePack_h
+
+#include "tools/MultiValue.h"
+
+namespace PLMD {
+
+class ReferenceValuePack {
+friend class MultiDomainRMSD;
+private:
+/// Was the virial set
+  bool boxWasSet;
+///
+  unsigned numberOfArgs;
+///
+  unsigned oind;
+/// Copy of the values that we are adding to
+  MultiValue& myvals;
+/// Ths list of atom indices
+  std::vector<unsigned> atom_indices;
+public:
+  ReferenceValuePack( const unsigned& nargs, const unsigned& natoms, MultiValue& vals );
+///
+  void resize( const unsigned& nargs, const unsigned& natoms );
+///
+  void clear();
+///
+  unsigned getNumberOfDerivatives() const ;
+///
+  unsigned getNumberOfArguments() const ;
+///
+  unsigned getNumberOfAtoms() const ;
+///
+  void setAtomIndex( const unsigned& iatom, const unsigned& jindex );
+///
+  unsigned getAtomIndex( const unsigned& iatom ) const ;
+///
+  void copyScaledDerivatives( const unsigned& from, const double& scalef, const MultiValue& tvals );
+///
+  void addArgumentDerivatives( const unsigned& iarg, const double& der );
+///
+  void addAtomDerivatives( const unsigned& iatom, const Vector& der );
+///
+  void addBoxDerivatives( const Tensor& vir );
+/// 
+  bool updateComplete() const ;
+///
+  void updateDynamicLists();
+///
+  void scaleAllDerivatives( const double& scalef );
+///
+  void setValIndex( const unsigned& ind );
+///
+  void moveDerivatives( const unsigned& from, const unsigned& to );
+///
+  bool virialWasSet() const ;
+///
+  Vector getAtomDerivative( const unsigned& iatom ) const ;
+///
+  double getArgumentDerivative( const unsigned& ival ) const ;
+///
+  Tensor getBoxDerivatives() const ;
+};
+
+inline
+unsigned ReferenceValuePack::getNumberOfDerivatives() const {
+  return myvals.getNumberOfDerivatives();
+}
+
+inline
+unsigned ReferenceValuePack::getNumberOfArguments() const {
+  return numberOfArgs;
+}
+
+inline
+unsigned ReferenceValuePack::getNumberOfAtoms() const {
+  return atom_indices.size();
+}
+
+inline
+void ReferenceValuePack::setAtomIndex( const unsigned& iatom, const unsigned& jindex ){
+  plumed_dbg_assert( iatom<atom_indices.size() ); atom_indices[iatom]=jindex;
+}
+
+inline
+unsigned ReferenceValuePack::getAtomIndex( const unsigned& iatom ) const {
+  plumed_dbg_assert( iatom<atom_indices.size() ); 
+  return atom_indices[iatom];
+}
+
+inline
+void ReferenceValuePack::addArgumentDerivatives( const unsigned& iarg, const double& der ){
+  plumed_dbg_assert( iarg<numberOfArgs ); myvals.addDerivative( oind, iarg, der );
+}
+
+inline
+bool ReferenceValuePack::updateComplete() const {
+  return myvals.updateComplete();
+}
+
+inline
+void ReferenceValuePack::addAtomDerivatives( const unsigned& jder, const Vector& der ){
+  plumed_dbg_assert( jder<atom_indices.size() );
+  myvals.addDerivative( oind, numberOfArgs + 3*atom_indices[jder] + 0, der[0] );
+  myvals.addDerivative( oind, numberOfArgs + 3*atom_indices[jder] + 1, der[1] );
+  myvals.addDerivative( oind, numberOfArgs + 3*atom_indices[jder] + 2, der[2] );
+}
+
+inline
+void ReferenceValuePack::addBoxDerivatives( const Tensor& vir ){
+  boxWasSet=true; unsigned nbase = myvals.getNumberOfDerivatives() - 9;
+  for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) myvals.addDerivative( oind, nbase + 3*i + j , vir(i,j) );
+}
+
+inline
+void ReferenceValuePack::setValIndex( const unsigned& ind ){
+  oind=ind;
+}
+
+inline
+bool ReferenceValuePack::virialWasSet() const {
+  return boxWasSet;
+}
+
+inline
+Vector ReferenceValuePack::getAtomDerivative( const unsigned& iatom ) const {
+  Vector tmp; plumed_dbg_assert( iatom<atom_indices.size() );
+  tmp[0]=myvals.getDerivative( oind, numberOfArgs + 3*atom_indices[iatom] + 0 );
+  tmp[1]=myvals.getDerivative( oind, numberOfArgs + 3*atom_indices[iatom] + 1 );
+  tmp[2]=myvals.getDerivative( oind, numberOfArgs + 3*atom_indices[iatom] + 2 ); 
+  return tmp;
+}
+
+inline
+double ReferenceValuePack::getArgumentDerivative( const unsigned& ival ) const {
+  plumed_dbg_assert( ival<numberOfArgs );
+  return myvals.getDerivative( oind, ival );
+}
+
+inline
+Tensor ReferenceValuePack::getBoxDerivatives() const {
+  plumed_dbg_assert( boxWasSet ); Tensor tvir; unsigned nbase = myvals.getNumberOfDerivatives() - 9;
+  for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) tvir(i,j)=myvals.getDerivative( oind, nbase + 3*i + j );
+  return tvir;
+}
+
+}
+
+#endif
diff --git a/src/reference/SimpleRMSD.cpp b/src/reference/SimpleRMSD.cpp
index dfca47a4902cd79e2251019853fbad0661bd20c0..23391e1e4d6017de3dba3c822fe59a5c2085b504 100644
--- a/src/reference/SimpleRMSD.cpp
+++ b/src/reference/SimpleRMSD.cpp
@@ -31,7 +31,7 @@ private:
 public:
   SimpleRMSD( const ReferenceConfigurationOptions& ro );
   void read( const PDB& );
-  double calc( const std::vector<Vector>& pos, const bool& squared );
+  double calc( const std::vector<Vector>& pos, ReferenceValuePack& myder, const bool& squared ) const ;
 };
 
 PLUMED_REGISTER_METRIC(SimpleRMSD,"SIMPLE")
@@ -46,8 +46,12 @@ void SimpleRMSD::read( const PDB& pdb ){
   readReference( pdb );
 }
 
-double SimpleRMSD::calc( const std::vector<Vector>& pos, const bool& squared ){
-  return myrmsd.simpleAlignment( getAlign(), getDisplace(), pos, getReferencePositions(), atom_ders, squared );
+double SimpleRMSD::calc( const std::vector<Vector>& pos, ReferenceValuePack& myder, const bool& squared ) const {
+  std::vector<Vector> atom_ders( pos.size() );
+  double d=myrmsd.simpleAlignment( getAlign(), getDisplace(), pos, getReferencePositions(), atom_ders, squared );
+  for(unsigned i=0;i<pos.size();++i) myder.addAtomDerivatives( i, atom_ders[i] );
+  if( !myder.updateComplete() ) myder.updateDynamicLists();
+  return d;
 }
 
 }
diff --git a/src/reference/SingleDomainRMSD.cpp b/src/reference/SingleDomainRMSD.cpp
index 6e13ff9148cef6dfc16a8da1fb3a76287ff44649..dbfcef053766a5fb3db58d4a83a70231749c98ae 100644
--- a/src/reference/SingleDomainRMSD.cpp
+++ b/src/reference/SingleDomainRMSD.cpp
@@ -56,17 +56,17 @@ void SingleDomainRMSD::setReferenceAtoms( const std::vector<Vector>& conf, const
      center+=conf[i]*align[i]; der_index[i]=i;
   }
   for(unsigned i=0;i<conf.size();++i) reference_atoms[i]=conf[i]-center;
-  setNumberOfAtoms( conf.size() ); setNumberOfArguments( 0 );
+  // setNumberOfAtoms( conf.size() ); setNumberOfArguments( 0 );
 }
 
-double SingleDomainRMSD::calculate( const std::vector<Vector>& pos, const Pbc& pbc,  const bool& squared ){
-  clearDerivatives();
-  return calc( pos, pbc, squared );
+double SingleDomainRMSD::calculate( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const {
+  return calc( pos, pbc, myder, squared );
 }
 
-double SingleDomainRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared ){
+double SingleDomainRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, 
+                               ReferenceValuePack& myder, const bool& squared ) const {
   plumed_dbg_assert( vals.size()==0 && pos.size()==getNumberOfAtoms() && arg.size()==0 );
-  return calc( pos, pbc, squared );
+  return calc( pos, pbc, myder, squared );
 }
 
 }
diff --git a/src/reference/SingleDomainRMSD.h b/src/reference/SingleDomainRMSD.h
index 1f7678c09a3146cfe079188cf439247cd9b17d35..bd906cbd2fce78f78f8390287bf4ee65b129dadc 100644
--- a/src/reference/SingleDomainRMSD.h
+++ b/src/reference/SingleDomainRMSD.h
@@ -36,10 +36,10 @@ public:
 /// Set the reference structure
   virtual void setReferenceAtoms( const std::vector<Vector>& conf, const std::vector<double>& align_in, const std::vector<double>& displace_in );
 /// Calculate
-  double calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, const bool& squared );  
-  double calculate( const std::vector<Vector>& pos, const Pbc& pbc,  const bool& squared );
+  double calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg, ReferenceValuePack& myder, const bool& squared ) const;  
+  double calculate( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const;
 /// Calculate the distance using the input position
-  virtual double calc( const std::vector<Vector>& pos, const Pbc& pbc, const bool& squared )=0;
+  virtual double calc( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const=0;
 /// This sets upper and lower bounds on distances to be used in DRMSD (here it does nothing)
   virtual void setBoundsOnDistances( bool dopbc, double lbound=0.0, double ubound=std::numeric_limits<double>::max( ) ){};
 };
diff --git a/src/secondarystructure/SecondaryStructureRMSD.cpp b/src/secondarystructure/SecondaryStructureRMSD.cpp
index 3eaa972e34cf7495484aa93a63db2682a90df4ce..bc4264d8245f3cc194ce1a2abdd33ecbb18e788d 100644
--- a/src/secondarystructure/SecondaryStructureRMSD.cpp
+++ b/src/secondarystructure/SecondaryStructureRMSD.cpp
@@ -161,7 +161,6 @@ void SecondaryStructureRMSD::setSecondaryStructure( std::vector<Vector>& structu
   }
 
   if( references.size()==0 ){
-     pos.resize( structure.size() ); 
      finishTaskListUpdate();
 
      readVesselKeywords();
@@ -181,7 +180,7 @@ void SecondaryStructureRMSD::setSecondaryStructure( std::vector<Vector>& structu
   std::vector<double> align( structure.size(), 1.0 ), displace( structure.size(), 1.0 );
   references[nn]->setBoundsOnDistances( true , bondlength );  // We always use pbc
   references[nn]->setReferenceAtoms( structure, align, displace );
-  references[nn]->setNumberOfAtoms( structure.size() );
+//  references[nn]->setNumberOfAtoms( structure.size() );
 }
 
 void SecondaryStructureRMSD::prepare(){
@@ -205,8 +204,9 @@ void SecondaryStructureRMSD::calculate(){
   runAllTasks();
 }
 
-void SecondaryStructureRMSD::performTask( const unsigned& task_index, const unsigned& current, vesselbase::MultiValue& myvals ){
+void SecondaryStructureRMSD::performTask( const unsigned& task_index, const unsigned& current, MultiValue& myvals ) const {
   // Retrieve the positions
+  std::vector<Vector> pos( references[0]->getNumberOfAtoms() );
   for(unsigned i=0;i<pos.size();++i) pos[i]=ActionAtomistic::getPosition( getAtomIndex(current,i) );
 
   // This does strands cutoff
@@ -225,42 +225,31 @@ void SecondaryStructureRMSD::performTask( const unsigned& task_index, const unsi
      for(unsigned i=15;i<30;++i){
          pos[i]+=( origin_new - origin_old );
      }
-  } 
+  }
+  // Create a holder for the derivatives
+  ReferenceValuePack mypack( 0, pos.size(), myvals ); mypack.setValIndex( 1 );
+  for(unsigned i=0;i<pos.size();++i) mypack.setAtomIndex( i, getAtomIndex(current,i) );
 
   // And now calculate the RMSD
   double r,nr; const Pbc& pbc=getPbc(); 
-  closest=0; r=references[0]->calculate( pos, pbc, false );
+  unsigned closest=0; r=references[0]->calculate( pos, pbc, mypack, false );
   for(unsigned i=1;i<references.size();++i){
-      nr=references[i]->calculate( pos, pbc, false );
+      mypack.setValIndex( i+1 );
+      nr=references[i]->calculate( pos, pbc, mypack, false );
       if( nr<r ){ closest=i; r=nr; }
   }
 
   // Transfer everything to the value
   myvals.setValue( 0, 1.0 ); myvals.setValue( 1, r );
-  for(unsigned i=0;i<colvar_atoms[current].size();++i){
-     unsigned thisatom=3*getAtomIndex(current,i);
-     Vector ader=references[closest]->getAtomDerivative(i);
-     myvals.addDerivative( 1, thisatom, ader[0] ); thisatom++;
-     myvals.addDerivative( 1, thisatom, ader[1] ); thisatom++;
-     myvals.addDerivative( 1, thisatom, ader[2] );
-  }
-  Tensor virial;
-  if( !references[closest]->getVirial( virial ) ){
-     virial.zero();
-     for(unsigned i=0;i<colvar_atoms[current].size();++i){
-         virial+=(-1.0*Tensor( pos[i], references[closest]->getAtomDerivative(i) ));
-     }
+  if( closest>0 ) mypack.moveDerivatives( closest+1, 1 );
+
+  if( !mypack.virialWasSet() ){
+      Tensor vir; vir.zero();
+      for(unsigned i=0;i<colvar_atoms[current].size();++i){
+         vir+=(-1.0*Tensor( pos[i], mypack.getAtomDerivative(i) ));
+      } 
+      mypack.setValIndex(1); mypack.addBoxDerivatives( vir );
   }
-  unsigned outnat=3*getNumberOfAtoms();
-  myvals.addDerivative( 1, outnat, virial(0,0) ); outnat++;
-  myvals.addDerivative( 1, outnat, virial(0,1) ); outnat++;
-  myvals.addDerivative( 1, outnat, virial(0,2) ); outnat++;
-  myvals.addDerivative( 1, outnat, virial(1,0) ); outnat++;
-  myvals.addDerivative( 1, outnat, virial(1,1) ); outnat++;
-  myvals.addDerivative( 1, outnat, virial(1,2) ); outnat++;
-  myvals.addDerivative( 1, outnat, virial(2,0) ); outnat++;
-  myvals.addDerivative( 1, outnat, virial(2,1) ); outnat++;
-  myvals.addDerivative( 1, outnat, virial(2,2) );
 
   return;
 }
diff --git a/src/secondarystructure/SecondaryStructureRMSD.h b/src/secondarystructure/SecondaryStructureRMSD.h
index 141bedba76e5d309e966f272c2de08e4cb54019f..39f441d3a3d12a3e749f10cce32dacfe440a8b0a 100644
--- a/src/secondarystructure/SecondaryStructureRMSD.h
+++ b/src/secondarystructure/SecondaryStructureRMSD.h
@@ -41,8 +41,6 @@ class SecondaryStructureRMSD :
   public vesselbase::ActionWithVessel
 {
 private:
-/// Tempory integer to say which refernce configuration is the closest
-  unsigned closest;
 /// The type of rmsd we are calculating
   std::string alignType;
 /// List of all the atoms we require
@@ -60,10 +58,9 @@ private:
   unsigned align_atom_1, align_atom_2;
   bool verbose_output;
 /// Tempory variables for getting positions of atoms and applying forces
-  std::vector<Vector> pos;
   std::vector<double> forcesToApply;
 /// Get the index of an atom
-  unsigned getAtomIndex( const unsigned& current, const unsigned& iatom );
+  unsigned getAtomIndex( const unsigned& current, const unsigned& iatom ) const ;
 protected:
 /// Get the atoms in the backbone
   void readBackboneAtoms( const std::string& backnames, std::vector<unsigned>& chain_lengths );
@@ -79,15 +76,22 @@ public:
   virtual ~SecondaryStructureRMSD();
   unsigned getNumberOfFunctionsInAction();
   unsigned getNumberOfDerivatives();
+  unsigned getNumberOfQuantities();
   void turnOnDerivatives();
   void prepare();
   void finishTaskListUpdate();
   void calculate();
-  void performTask( const unsigned& , const unsigned& , vesselbase::MultiValue& );
+  void performTask( const unsigned& , const unsigned& , MultiValue& ) const ; 
   void apply();
   bool isPeriodic(){ return false; }
 };
 
+inline
+unsigned SecondaryStructureRMSD::getNumberOfQuantities(){
+  return 1 + references.size();
+}
+
+
 inline
 unsigned SecondaryStructureRMSD::getNumberOfFunctionsInAction(){
   return colvar_atoms.size();
@@ -99,7 +103,7 @@ unsigned SecondaryStructureRMSD::getNumberOfDerivatives(){
 }
 
 inline
-unsigned SecondaryStructureRMSD::getAtomIndex( const unsigned& current, const unsigned& iatom ){
+unsigned SecondaryStructureRMSD::getAtomIndex( const unsigned& current, const unsigned& iatom ) const {
   return all_atoms.linkIndex( colvar_atoms[current][iatom] );
 }
 
diff --git a/src/tools/LinkCells.cpp b/src/tools/LinkCells.cpp
index 35d3339fe38acc1415078f166e37d24a626d4c7b..849f09016a7f3c039ff99bf932fc303b83bf0f0c 100644
--- a/src/tools/LinkCells.cpp
+++ b/src/tools/LinkCells.cpp
@@ -99,7 +99,7 @@ void LinkCells::buildCellLists( const std::vector<Vector>& pos, const std::vecto
 #define LINKC_MAX(n) ((n<3)? 1 : 2)
 #define LINKC_PBC(n,num) ((n<0)? num-1 : n%num )
 
-void LinkCells::retrieveNeighboringAtoms( const Vector& pos, unsigned& natomsper, std::vector<unsigned>& atoms ){
+void LinkCells::retrieveNeighboringAtoms( const Vector& pos, unsigned& natomsper, std::vector<unsigned>& atoms ) const {
   plumed_assert( natomsper==1 );  // This is really a bug. If you are trying to reuse this ask GAT for help
   std::vector<unsigned> celn( findMyCell( pos ) );
 
diff --git a/src/tools/LinkCells.h b/src/tools/LinkCells.h
index 4c0a2af7095ffbf076558273fbf2bd823490874c..91563482c3bb521621f89b4c516811ed47ac4caf 100644
--- a/src/tools/LinkCells.h
+++ b/src/tools/LinkCells.h
@@ -68,7 +68,7 @@ public:
 /// Build the link cell lists
   void buildCellLists( const std::vector<Vector>& pos, const std::vector<unsigned>& indices, const Pbc& pbc );
 /// Find a list of relevant atoms
-  void retrieveNeighboringAtoms( const Vector& pos, unsigned& natomsper, std::vector<unsigned>& atoms ); 
+  void retrieveNeighboringAtoms( const Vector& pos, unsigned& natomsper, std::vector<unsigned>& atoms ) const ; 
 };
 
 inline
diff --git a/src/vesselbase/MultiValue.cpp b/src/tools/MultiValue.cpp
similarity index 99%
rename from src/vesselbase/MultiValue.cpp
rename to src/tools/MultiValue.cpp
index 3a7823e3fbf1f1a2e7bbbd859e5f292ec86be746..9bf60a3e8ff83da05a6f169de69d991c976c3919 100644
--- a/src/vesselbase/MultiValue.cpp
+++ b/src/tools/MultiValue.cpp
@@ -22,7 +22,6 @@
 #include "MultiValue.h"
 
 namespace PLMD{
-namespace vesselbase{
 
 MultiValue::MultiValue( const unsigned& nvals, const unsigned& nder ):
 values(nvals),
@@ -98,4 +97,3 @@ void MultiValue::quotientRule( const unsigned& nder, const unsigned& dder, const
 }
 
 }
-}
diff --git a/src/vesselbase/MultiValue.h b/src/tools/MultiValue.h
similarity index 94%
rename from src/vesselbase/MultiValue.h
rename to src/tools/MultiValue.h
index 57203c3231e61cf1987ac0e1c0d3ab99c91f6fab..05021198f28277f9ac33e5ddc70910f89bca9222 100644
--- a/src/vesselbase/MultiValue.h
+++ b/src/tools/MultiValue.h
@@ -19,16 +19,15 @@
    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_vesselbase_MultiValue_h
-#define __PLUMED_vesselbase_MultiValue_h
+#ifndef __PLUMED_tools_MultiValue_h
+#define __PLUMED_tools_MultiValue_h
 
 #include <vector>
-#include "tools/Exception.h"
-#include "tools/Matrix.h"
-#include "tools/DynamicList.h"
+#include "Exception.h"
+#include "Matrix.h"
+#include "DynamicList.h"
 
 namespace PLMD{
-namespace vesselbase{
 
 class MultiValue {
 private:
@@ -68,7 +67,7 @@ public:
   void sortActiveList();
   void updateDynamicList();
 ///
-  unsigned getNumberActive();
+  unsigned getNumberActive() const ;
 ///
   unsigned getActiveIndex( const unsigned& ) const ;
 /// Transfer derivatives to buffer
@@ -149,7 +148,7 @@ void MultiValue::sortActiveList(){
 }
 
 inline
-unsigned MultiValue::getNumberActive(){
+unsigned MultiValue::getNumberActive() const {
   return hasDerivatives.getNumberActive();
 }
 
@@ -164,6 +163,5 @@ void MultiValue::updateDynamicList(){
   hasDerivatives.updateActiveMembers();
 }
 
-}
 }
 #endif
diff --git a/src/vesselbase/ActionWithVessel.cpp b/src/vesselbase/ActionWithVessel.cpp
index 9f1639406cdddd7946c4e5d1c5c556b0a47d1951..48854ca6e3fb91865670de85acf88d5702d77b63 100644
--- a/src/vesselbase/ActionWithVessel.cpp
+++ b/src/vesselbase/ActionWithVessel.cpp
@@ -327,7 +327,7 @@ void ActionWithVessel::runAllTasks(){
   finishComputations( buffer );
 }
 
-void ActionWithVessel::transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ){
+void ActionWithVessel::transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const {
   plumed_error();
 }
 
diff --git a/src/vesselbase/ActionWithVessel.h b/src/vesselbase/ActionWithVessel.h
index f8ea4c7987d243a1f6cc2f448470a74deda3f2a2..c5796e539fc26d437bbb9e25937cfcc6d3b5d7c7 100644
--- a/src/vesselbase/ActionWithVessel.h
+++ b/src/vesselbase/ActionWithVessel.h
@@ -26,7 +26,7 @@
 #include "core/ActionAtomistic.h"
 #include "tools/Exception.h"
 #include "tools/DynamicList.h"
-#include "MultiValue.h"
+#include "tools/MultiValue.h"
 #include <vector>
 
 namespace PLMD{
@@ -168,9 +168,9 @@ public:
 /// Get the code for the ii th task in the list
   unsigned getTaskCode( const unsigned& ii ) const ;
 /// Calculate one of the functions in the distribution
-  virtual void performTask( const unsigned& , const unsigned& , MultiValue& )=0;
+  virtual void performTask( const unsigned& , const unsigned& , MultiValue& ) const=0;
 /// Do the task if we have a bridge
-  virtual void transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals );
+  virtual void transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const;
 /// Ensure that data required in other vessels is stored
   StoreDataVessel* buildDataStashes( const bool& allow_wcutoff, const double& wtol );
 /// Apply forces from bridge vessel - this is rarely used - currently only in ActionVolume