diff --git a/CHANGES/v2.5.md b/CHANGES/v2.5.md
index dbbed1220c19fa592c036be91508ce3d6b8ead32..0dedfb37c4ef471099abb7d7446395df4910837f 100644
--- a/CHANGES/v2.5.md
+++ b/CHANGES/v2.5.md
@@ -2,3 +2,11 @@
 
 This page contains changes that will end up in 2.5
 
+Changes from version 2.4 which are relevant for users:
+- Changes leading to incompatible behavior:
+- New actions:
+  - \ref PAMM
+  - \ref HBPAMM_MATRIX
+  - \ref HBPAMM_SH
+
+Changes from version 2.4 which are relevant for developers:
diff --git a/src/multicolvar/VolumeBetweenContours.cpp b/src/multicolvar/VolumeBetweenContours.cpp
index afe7b0da2cd97ebaaf7b5f2909b25f16adf5bef9..737c77ffca2bd3ed681faf0be18461e7591cf897 100644
--- a/src/multicolvar/VolumeBetweenContours.cpp
+++ b/src/multicolvar/VolumeBetweenContours.cpp
@@ -104,7 +104,7 @@ VolumeInEnvelope::VolumeInEnvelope(const ActionOptions& ao):
 
   std::vector<double> pp(3,0.0), bandwidth(3); parseVector("BANDWIDTH",bandwidth);
   log.printf("  using %s kernel with bandwidths %f %f %f \n",getKernelType().c_str(),bandwidth[0],bandwidth[1],bandwidth[2] );
-  kernel = new KernelFunctions( pp, bandwidth, getKernelType(), "DIAGONAL", 1.0 ); 
+  kernel = new KernelFunctions( pp, bandwidth, getKernelType(), "DIAGONAL", 1.0 );
   for(unsigned i=0; i<3; ++i) { pos.push_back(new Value()); pos[i]->setNotPeriodic(); }
   std::vector<double> csupport( kernel->getContinuousSupport() );
   double maxs = csupport[0];
diff --git a/src/pamm/PammObject.cpp b/src/pamm/PammObject.cpp
index e0528dba7934bace34f222b3958b2377f25540a5..4147cadb10ceaa41a81d0cf7d6f9504bd4e8851c 100644
--- a/src/pamm/PammObject.cpp
+++ b/src/pamm/PammObject.cpp
@@ -34,7 +34,8 @@ PammObject::PammObject( const PammObject& in ):
   regulariser(in.regulariser),
   pbc(in.pbc),
   min(in.min),
-  max(in.max)
+  max(in.max),
+  kgroup_start(in.kgroup_start)
 {
   for(unsigned i=0; i<in.kernels.size(); ++i) kernels.push_back( new KernelFunctions( in.kernels[i] ) );
 }
@@ -63,13 +64,15 @@ void PammObject::setup( const std::string& filename, const double& reg, const st
     else pos[i]->setDomain( min[i], max[i] );
   }
 
-  ifile.open(filename); ifile.allowIgnoredFields(); kernels.resize(0);
+  ifile.open(filename); ifile.allowIgnoredFields();
+  kernels.resize(0); kgroup_start.resize(0); kgroup_start.push_back(0);
   for(unsigned k=0;; ++k) {
     KernelFunctions* kk = KernelFunctions::read( &ifile, false, valnames );
     if( !kk ) break ;
     kk->normalize( pos );
     kernels.push_back( kk );
     ifile.scanField();
+    kgroup_start.push_back( kernels.size() );
   }
   ifile.close();
   for(unsigned i=0; i<valnames.size(); ++i) delete pos[i];
@@ -86,15 +89,19 @@ void PammObject::evaluate( const std::vector<double>& invar, std::vector<double>
   }
 
   // Evaluate the set of kernels
-  double denom=regulariser;
-  std::vector<double> dderiv( der[0].size(), 0 );
-  for(unsigned i=0; i<kernels.size(); ++i) {
-    outvals[i]=kernels[i]->evaluate( pos, der[i] );
-    denom+=outvals[i];
-    for(unsigned j=0; j<der[i].size(); ++j) dderiv[j] += der[i][j];
+  double denom=regulariser; unsigned ikernel=0;
+  std::vector<double> tmpder( der[0].size() ), dderiv( der[0].size(), 0 );
+  for(unsigned i=0; i<kgroup_start.size()-1; ++i) {
+    outvals[i]=0;
+    for(unsigned k=kgroup_start[i]; k<kgroup_start[i+1]; ++k) {
+      outvals[i] += kernels[ikernel]->evaluate( pos, tmpder );
+      denom+=outvals[i];
+      for(unsigned j=0; j<der[i].size(); ++j) { der[i][j] += tmpder[j]; dderiv[j] += tmpder[j]; }
+      ikernel++;
+    }
   }
   // Evaluate the set of derivatives
-  for(unsigned i=0; i<kernels.size(); ++i) {
+  for(unsigned i=0; i<kgroup_start.size()-1; ++i) {
     outvals[i]/=denom;
     for(unsigned j=0; j<der[i].size(); ++j) der[i][j]=der[i][j]/denom - outvals[i]*dderiv[j]/denom;
   }