diff --git a/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModelList.H b/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModelList.H
index 3d0d015923957f2923eebed5e7625c74acb9bdab..a6c8f2ae9c30f090399d5b011046a0da24aaf798 100644
--- a/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModelList.H
+++ b/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModelList.H
@@ -55,7 +55,7 @@ Ostream& operator<<(Ostream& os, const porosityModelList& models);
 
 class porosityModelList
 :
-    PtrList<porosityModel>
+    public PtrList<porosityModel>
 {
 private:
 
diff --git a/src/fvAgglomerationMethods/MGridGenGamgAgglomeration/MGridGenGAMGAgglomeration.C b/src/fvAgglomerationMethods/MGridGenGamgAgglomeration/MGridGenGAMGAgglomeration.C
index dd912465a0ca32ed9fba08b4bed8ec9402d63759..69dab59023b01472b91e84930a71a600e49492d4 100644
--- a/src/fvAgglomerationMethods/MGridGenGamgAgglomeration/MGridGenGAMGAgglomeration.C
+++ b/src/fvAgglomerationMethods/MGridGenGamgAgglomeration/MGridGenGAMGAgglomeration.C
@@ -25,8 +25,8 @@ License
 
 #include "MGridGenGAMGAgglomeration.H"
 #include "fvMesh.H"
-#include "processorPolyPatch.H"
 #include "addToRunTimeSelectionTable.H"
+#include "processorLduInterface.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -43,6 +43,121 @@ namespace Foam
 }
 
 
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::MGridGenGAMGAgglomeration::swap
+(
+    const lduInterfacePtrsList& interfaces,
+    const labelUList& cellValues,
+    PtrList<labelList>& nbrValues
+) const
+{
+    // Initialise transfer of restrict addressing on the interface
+    forAll(interfaces, inti)
+    {
+        if (interfaces.set(inti))
+        {
+            interfaces[inti].initInternalFieldTransfer
+            (
+                Pstream::nonBlocking,
+                cellValues
+            );
+        }
+    }
+
+    if (Pstream::parRun())
+    {
+        Pstream::waitRequests();
+    }
+
+    // Get the interface agglomeration
+    nbrValues.setSize(interfaces.size());
+    forAll(interfaces, inti)
+    {
+        if (interfaces.set(inti))
+        {
+            nbrValues.set
+            (
+                inti,
+                new labelList
+                (
+                    interfaces[inti].internalFieldTransfer
+                    (
+                        Pstream::nonBlocking,
+                        cellValues
+                    )
+                )
+            );
+        }
+    }
+}
+
+
+void Foam::MGridGenGAMGAgglomeration::getNbrAgglom
+(
+    const lduAddressing& addr,
+    const lduInterfacePtrsList& interfaces,
+    const PtrList<labelList>& nbrGlobalAgglom,
+    labelList& cellToNbrAgglom
+) const
+{
+    cellToNbrAgglom.setSize(addr.size());
+    cellToNbrAgglom = -1;
+
+    forAll(interfaces, inti)
+    {
+        if (interfaces.set(inti))
+        {
+            if (isA<processorLduInterface>(interfaces[inti]))
+            {
+                const processorLduInterface& pldui =
+                    refCast<const processorLduInterface>(interfaces[inti]);
+
+                if (pldui.myProcNo() > pldui.neighbProcNo())
+                {
+                    const labelUList& faceCells =
+                        interfaces[inti].faceCells();
+                    const labelList& nbrData = nbrGlobalAgglom[inti];
+
+                    forAll(faceCells, i)
+                    {
+                        cellToNbrAgglom[faceCells[i]] = nbrData[i];
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+void Foam::MGridGenGAMGAgglomeration::detectSharedFaces
+(
+    const lduMesh& mesh,
+    const labelList& value,
+    labelHashSet& sharedFaces
+) const
+{
+    const lduAddressing& addr = mesh.lduAddr();
+    const labelUList& lower = addr.lowerAddr();
+    const labelUList& upper = addr.upperAddr();
+
+    sharedFaces.clear();
+    sharedFaces.resize(addr.lowerAddr().size()/100);
+
+    // Detect any faces inbetween same value
+    forAll(lower, faceI)
+    {
+        label lowerData = value[lower[faceI]];
+        label upperData = value[upper[faceI]];
+
+        if (lowerData != -1 && lowerData == upperData)
+        {
+            sharedFaces.insert(faceI);
+        }
+    }
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::MGridGenGAMGAgglomeration::MGridGenGAMGAgglomeration
@@ -58,6 +173,13 @@ Foam::MGridGenGAMGAgglomeration::MGridGenGAMGAgglomeration
     label minSize(readLabel(controlDict.lookup("minSize")));
     label maxSize(readLabel(controlDict.lookup("maxSize")));
 
+    // Number of iterations applied to improve agglomeration consistency across
+    // processor boundaries
+    label nProcConsistencyIter
+    (
+        readLabel(controlDict.lookup("nProcConsistencyIter"))
+    );
+
     // Start geometric agglomeration from the cell volumes and areas of the mesh
     scalarField* VPtr = const_cast<scalarField*>(&fvMesh_.cellVolumes());
 
@@ -87,28 +209,6 @@ Foam::MGridGenGAMGAgglomeration::MGridGenGAMGAgglomeration
         }
     }
 
-    /*
-    {
-        scalarField& magSb = *magSbPtr;
-        const polyBoundaryMesh& patches = fvMesh_.boundaryMesh();
-
-        forAll(patches, patchi)
-        {
-            const polyPatch& pp = patches[patchi];
-
-            if (!(Pstream::parRun() && isA<processorPolyPatch>(pp)))
-            {
-                const labelUList& faceCells = pp.faceCells();
-                const vectorField& pSf = pp.faceAreas();
-                forAll(faceCells, pfi)
-                {
-                    magSb[faceCells[pfi]] += mag(pSf[pfi]);
-                }
-            }
-        }
-    }
-    */
-
     // Agglomerate until the required number of cells in the coarsest level
     // is reached
 
@@ -129,6 +229,63 @@ Foam::MGridGenGAMGAgglomeration::MGridGenGAMGAgglomeration
             *magSbPtr
         );
 
+        // Adjust weights only
+        for (int i=0; i<nProcConsistencyIter; i++)
+        {
+            const lduMesh& mesh = meshLevel(nCreatedLevels);
+            const lduAddressing& addr = mesh.lduAddr();
+            const lduInterfacePtrsList interfaces = mesh.interfaces();
+
+            const labelField& agglom = finalAgglomPtr();
+
+            // Global nubmering
+            const globalIndex globalNumbering(nCoarseCells);
+
+            labelField globalAgglom(addr.size());
+            forAll(agglom, cellI)
+            {
+                globalAgglom[cellI] = globalNumbering.toGlobal(agglom[cellI]);
+            }
+
+            // Get the interface agglomeration
+            PtrList<labelList> nbrGlobalAgglom;
+            swap(interfaces, globalAgglom, nbrGlobalAgglom);
+
+
+            // Get the interface agglomeration on a cell basis (-1 for all
+            // other cells)
+            labelList cellToNbrAgglom;
+            getNbrAgglom(addr, interfaces, nbrGlobalAgglom, cellToNbrAgglom);
+
+
+            // Mark all faces inbetween cells with same nbragglomeration
+            labelHashSet sharedFaces(addr.size()/100);
+            detectSharedFaces(mesh, cellToNbrAgglom, sharedFaces);
+
+
+            //- Note: in-place update of weights is more effective it seems?
+            //        Should not be. fluke?
+            //scalarField weights(*faceWeightsPtr);
+            scalarField weights = *magSfPtr;
+            forAllConstIter(labelHashSet, sharedFaces, iter)
+            {
+                label faceI= iter.key();
+                weights[faceI] *= 2.0;
+            }
+
+            // Redo the agglomeration using the new weights
+            finalAgglomPtr = agglomerate
+            (
+                nCoarseCells,
+                minSize,
+                maxSize,
+                meshLevel(nCreatedLevels).lduAddr(),
+                *VPtr,
+                weights,
+                *magSbPtr
+            );
+        }
+
         if (continueAgglomerating(nCoarseCells))
         {
             nCells_[nCreatedLevels] = nCoarseCells;