diff --git a/applications/test/extendedStencil/testExtendedStencil.C b/applications/test/extendedStencil/testExtendedStencil.C
index b8db2b89bf993552dd8582ba0c77c2cef58b121a..876576b29eab8666ae74c85e9801fb00c7f22324 100644
--- a/applications/test/extendedStencil/testExtendedStencil.C
+++ b/applications/test/extendedStencil/testExtendedStencil.C
@@ -34,7 +34,7 @@ Description
 #include "fvMesh.H"
 #include "volFields.H"
 #include "Time.H"
-#include "mapDistribute.H"
+//#include "mapDistribute.H"
 #include "OFstream.H"
 #include "meshTools.H"
 //#include "FECCellToFaceStencil.H"
diff --git a/applications/test/parallel/parallelTest.C b/applications/test/parallel/parallelTest.C
index bf8440ece62a6e1ac7d488ae8db434c6d08f90ae..6120de31a51670a1d2f2e71ea77004fa45613e61 100644
--- a/applications/test/parallel/parallelTest.C
+++ b/applications/test/parallel/parallelTest.C
@@ -23,19 +23,23 @@ License
     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
 Application
-    icoFoam
+    parallelTest
 
 Description
-    Incompressible laminar CFD code.
+    Test for various parallel routines.
 
 \*---------------------------------------------------------------------------*/
 
+#include "List.H"
+#include "mapDistribute.H"
 #include "argList.H"
 #include "Time.H"
 #include "IPstream.H"
 #include "OPstream.H"
 #include "vector.H"
 #include "IOstreams.H"
+#include "Random.H"
+#include "Tuple2.H"
 
 using namespace Foam;
 
@@ -47,6 +51,99 @@ int main(int argc, char *argv[])
 #   include "setRootCase.H"
 #   include "createTime.H"
 
+
+    // Test mapDistribute
+    // ~~~~~~~~~~~~~~~~~~
+
+    if (false)
+    {
+        Random rndGen(43544*Pstream::myProcNo());
+
+        // Generate random data.
+        List<Tuple2<label, List<scalar> > > complexData(100);
+        forAll(complexData, i)
+        {
+            complexData[i].first() = rndGen.integer(0, Pstream::nProcs()-1);
+            complexData[i].second().setSize(3);
+            complexData[i].second()[0] = 1;
+            complexData[i].second()[1] = 2;
+            complexData[i].second()[2] = 3;
+        }
+
+        // Send all ones to processor indicated by .first()
+
+
+        // Count how many to send
+        labelList nSend(Pstream::nProcs(), 0);
+        forAll(complexData, i)
+        {
+            label procI = complexData[i].first();
+            nSend[procI]++;
+        }
+
+        // Sync how many to send
+        labelListList allNTrans(Pstream::nProcs());
+        allNTrans[Pstream::myProcNo()] = nSend;
+        combineReduce(allNTrans, mapDistribute::listEq());
+
+        // Collect items to be sent
+        labelListList sendMap(Pstream::nProcs());
+        forAll(sendMap, procI)
+        {
+            sendMap[procI].setSize(nSend[procI]);
+        }
+        nSend = 0;
+        forAll(complexData, i)
+        {
+            label procI = complexData[i].first();
+            sendMap[procI][nSend[procI]++] = i;
+        }
+
+        // Collect items to be received
+        labelListList recvMap(Pstream::nProcs());
+        forAll(recvMap, procI)
+        {
+            recvMap[procI].setSize(allNTrans[procI][Pstream::myProcNo()]);
+        }
+
+        label constructSize = 0;
+        // Construct with my own elements first
+        forAll(recvMap[Pstream::myProcNo()], i)
+        {
+            recvMap[Pstream::myProcNo()][i] = constructSize++;
+        }
+        // Construct from other processors
+        forAll(recvMap, procI)
+        {
+            if (procI != Pstream::myProcNo())
+            {
+                forAll(recvMap[procI], i)
+                {
+                    recvMap[procI][i] = constructSize++;
+                }
+            }
+        }
+
+
+
+        // Construct distribute map (destructively)
+        mapDistribute map(constructSize, sendMap.xfer(), recvMap.xfer());
+
+        // Distribute complexData
+        mapDistribute::distribute
+        (
+            Pstream::nonBlocking,
+            List<labelPair>(),
+            map.constructSize(),
+            map.subMap(),
+            map.constructMap(),
+            complexData
+        );
+
+        Pout<< "complexData:" << complexData << endl;
+    }
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
     Perr<< "\nStarting transfers\n" << endl;
@@ -60,13 +157,13 @@ int main(int argc, char *argv[])
             {
                 Perr<< "slave sending to master "
                     << Pstream::masterNo() << endl;
-                OPstream toMaster(Pstream::masterNo());
+                OPstream toMaster(Pstream::blocking, Pstream::masterNo());
                 toMaster << data;
             }
 
             Perr<< "slave receiving from master " 
                 << Pstream::masterNo() << endl;
-            IPstream fromMaster(Pstream::masterNo());
+            IPstream fromMaster(Pstream::blocking, Pstream::masterNo());
             fromMaster >> data;
 
             Perr<< data << endl;
@@ -81,7 +178,7 @@ int main(int argc, char *argv[])
             )
             {
                 Perr << "master receiving from slave " << slave << endl;
-                IPstream fromSlave(slave);
+                IPstream fromSlave(Pstream::blocking, slave);
                 fromSlave >> data;
 
                 Perr<< data << endl;
@@ -95,7 +192,7 @@ int main(int argc, char *argv[])
             )
             {
                 Perr << "master sending to slave " << slave << endl;
-                OPstream toSlave(slave);
+                OPstream toSlave(Pstream::blocking, slave);
                 toSlave << data;
             }
         }
diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.C
index 1bbeb3d077deede92a108a524491dc1b1ff709cf..e2c2dbf773dae044c2af38cea5c8317a0f600c2f 100644
--- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.C
+++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.C
@@ -172,8 +172,8 @@ const Foam::List<Foam::labelPair>& Foam::mapDistribute::schedule() const
 Foam::mapDistribute::mapDistribute
 (
     const label constructSize,
-    const labelListList& subMap,
-    const labelListList& constructMap
+    const Xfer<labelListList>& subMap,
+    const Xfer<labelListList>& constructMap
 )
 :
     constructSize_(constructSize),
@@ -183,22 +183,6 @@ Foam::mapDistribute::mapDistribute
 {}
 
 
-//- (optionally destructively) construct from components
-Foam::mapDistribute::mapDistribute
-(
-    const label constructSize,
-    labelListList& subMap,
-    labelListList& constructMap,
-    const bool reUse                // clone or reuse
-)
-:
-    constructSize_(constructSize),
-    subMap_(subMap, reUse),
-    constructMap_(constructMap, reUse),
-    schedulePtr_()
-{}
-
-
 Foam::mapDistribute::mapDistribute
 (
     const labelList& sendProcs,
diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.H b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.H
index d2cfe64ca53c0dde02c3d424d5236b415728151d..c6962355fdd5c24ce58ce70dcc54b557a72a0fe0 100644
--- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.H
+++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.H
@@ -83,23 +83,36 @@ class mapDistribute
 
 public:
 
+    // Public classes
+
+        //- combineReduce operator for lists. Used for counting.
+        class listEq
+        {
+
+        public:
+
+            template<class T>
+            void operator()(T& x, const T& y) const
+            {
+                forAll(y, i)
+                {
+                    if (y[i].size())
+                    {
+                        x[i] = y[i];
+                    }
+                }
+            }
+        };
+
+
     // Constructors
 
         //- Construct from components
         mapDistribute
         (
             const label constructSize,
-            const labelListList& subMap,
-            const labelListList& constructMap
-        );
-
-        //- (optionally destructively) construct from components
-        mapDistribute
-        (
-            const label constructSize,
-            labelListList& subMap,
-            labelListList& constructMap,
-            const bool reUse                // clone or reuse
+            const Xfer<labelListList>& subMap,
+            const Xfer<labelListList>& constructMap
         );
 
         //- Construct from reverse addressing: per data item the send
@@ -205,11 +218,7 @@ public:
             template<class T>
             void distribute(List<T>& fld) const
             {
-                if
-                (
-                    Pstream::defaultCommsType == Pstream::nonBlocking
-                 && contiguous<T>()
-                )
+                if (Pstream::defaultCommsType == Pstream::nonBlocking)
                 {
                     distribute
                     (
diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeLagrangian.H b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeLagrangian.H
index 5782308d196e59cdabcae247fcc6922a5d8721ec..ce0567390827c8bb12d38b164d8b46cba9b5888d 100644
--- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeLagrangian.H
+++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeLagrangian.H
@@ -68,35 +68,15 @@ public:
         mapDistributeLagrangian
         (
             const label nNewParticles,
-            const labelListList& subParticleMap,
-            const labelListList& constructParticleMap,
-            const labelListList& constructCellLabels
+            const Xfer<labelListList>& subParticleMap,
+            const Xfer<labelListList>& constructParticleMap,
+            const Xfer<labelListList>& constructCellLabels
         )
         :
             particleMap_(nNewParticles, subParticleMap, constructParticleMap),
             constructCellLabels_(constructCellLabels)
         {}
 
-        //- Construct from components and steal storage
-        mapDistributeLagrangian
-        (
-            const label nNewParticles,
-            labelListList& subParticleMap,
-            labelListList& constructParticleMap,
-            labelListList& constructCellLabels,
-            const bool reUse
-        )
-        :
-            particleMap_
-            (
-                nNewParticles,
-                subParticleMap,
-                constructParticleMap,
-                reUse
-            ),
-            constructCellLabels_(constructCellLabels, reUse)
-        {}
-
 
     // Member Functions
 
diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.C
index a5e4f163417ca44e664898569450e5836c2154ec..29649665b4b1473181013802b315d43aa9d8ee6c 100644
--- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.C
+++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.C
@@ -66,27 +66,27 @@ Foam::mapDistributePolyMesh::mapDistributePolyMesh
     const label nOldPoints,
     const label nOldFaces,
     const label nOldCells,
-    const labelList& oldPatchStarts,
-    const labelList& oldPatchNMeshPoints,
+    const Xfer<labelList>& oldPatchStarts,
+    const Xfer<labelList>& oldPatchNMeshPoints,
 
     // how to subset pieces of mesh to send across
-    const labelListList& subPointMap,
-    const labelListList& subFaceMap,
-    const labelListList& subCellMap,
-    const labelListList& subPatchMap,
+    const Xfer<labelListList>& subPointMap,
+    const Xfer<labelListList>& subFaceMap,
+    const Xfer<labelListList>& subCellMap,
+    const Xfer<labelListList>& subPatchMap,
 
     // how to reconstruct received mesh
-    const labelListList& constructPointMap,
-    const labelListList& constructFaceMap,
-    const labelListList& constructCellMap,
-    const labelListList& constructPatchMap
+    const Xfer<labelListList>& constructPointMap,
+    const Xfer<labelListList>& constructFaceMap,
+    const Xfer<labelListList>& constructCellMap,
+    const Xfer<labelListList>& constructPatchMap
 )
 :
     mesh_(mesh),
     nOldPoints_(nOldPoints),
     nOldFaces_(nOldFaces),
     nOldCells_(nOldCells),
-    oldPatchSizes_(oldPatchStarts.size()),
+    oldPatchSizes_(oldPatchStarts().size()),
     oldPatchStarts_(oldPatchStarts),
     oldPatchNMeshPoints_(oldPatchNMeshPoints),
     pointMap_(mesh.nPoints(), subPointMap, constructPointMap),
@@ -98,44 +98,6 @@ Foam::mapDistributePolyMesh::mapDistributePolyMesh
 }
 
 
-//- (optionally destructively) construct from components
-Foam::mapDistributePolyMesh::mapDistributePolyMesh
-(
-    const polyMesh& mesh,
-    const label nOldPoints,
-    const label nOldFaces,
-    const label nOldCells,
-    labelList& oldPatchStarts,
-    labelList& oldPatchNMeshPoints,
-
-    labelListList& subPointMap,
-    labelListList& subFaceMap,
-    labelListList& subCellMap,
-    labelListList& subPatchMap,
-    labelListList& constructPointMap,
-    labelListList& constructFaceMap,
-    labelListList& constructCellMap,
-    labelListList& constructPatchMap,
-    const bool reUse                // clone or reuse
-)
-:
-    mesh_(mesh),
-    nOldPoints_(nOldPoints),
-    nOldFaces_(nOldFaces),
-    nOldCells_(nOldCells),
-    oldPatchSizes_(oldPatchStarts.size()),
-    oldPatchStarts_(oldPatchStarts, reUse),
-    oldPatchNMeshPoints_(oldPatchNMeshPoints, reUse),
-
-    pointMap_(mesh.nPoints(), subPointMap, constructPointMap, reUse),
-    faceMap_(mesh.nFaces(), subFaceMap, constructFaceMap, reUse),
-    cellMap_(mesh.nCells(), subCellMap, constructCellMap, reUse),
-    patchMap_(mesh.boundaryMesh().size(), subPatchMap, constructPatchMap, reUse)
-{
-    calcPatchSizes();
-}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 void Foam::mapDistributePolyMesh::distributePointIndices(labelList& lst) const
diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.H b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.H
index bf5857170b18f41035b7deb902851078b7301561..8fdfe7e8fb51afcd8bb8e8e88151567ed2628b15 100644
--- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.H
+++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.H
@@ -120,42 +120,20 @@ public:
             const label nOldPoints,
             const label nOldFaces,
             const label nOldCells,
-            const labelList& oldPatchStarts,
-            const labelList& oldPatchNMeshPoints,
+            const Xfer<labelList>& oldPatchStarts,
+            const Xfer<labelList>& oldPatchNMeshPoints,
 
             // how to subset pieces of mesh to send across
-            const labelListList& subPointMap,
-            const labelListList& subFaceMap,
-            const labelListList& subCellMap,
-            const labelListList& subPatchMap,
+            const Xfer<labelListList>& subPointMap,
+            const Xfer<labelListList>& subFaceMap,
+            const Xfer<labelListList>& subCellMap,
+            const Xfer<labelListList>& subPatchMap,
 
             // how to reconstruct received mesh
-            const labelListList& constructPointMap,
-            const labelListList& constructFaceMap,
-            const labelListList& constructCellMap,
-            const labelListList& constructPatchMap
-        );
-
-        //- (optionally destructively) construct from components
-        //  Note that mesh has to be changed already!
-        mapDistributePolyMesh
-        (
-            const polyMesh& mesh,
-            const label nOldPoints,
-            const label nOldFaces,
-            const label nOldCells,
-            labelList& oldPatchStarts,
-            labelList& oldPatchNMeshPoints,
-
-            labelListList& subPointMap,
-            labelListList& subFaceMap,
-            labelListList& subCellMap,
-            labelListList& subPatchMap,
-            labelListList& constructPointMap,
-            labelListList& constructFaceMap,
-            labelListList& constructCellMap,
-            labelListList& constructPatchMap,
-            const bool reUse                // clone or reuse
+            const Xfer<labelListList>& constructPointMap,
+            const Xfer<labelListList>& constructFaceMap,
+            const Xfer<labelListList>& constructCellMap,
+            const Xfer<labelListList>& constructPatchMap
         );
 
 
diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C
index 5f5d7a9fcf9793fe4f0c0df04e8c60e87e9c6d4f..da1ed19d1e6365c65fa40794ecec64186a579915 100644
--- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C
+++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C
@@ -25,6 +25,7 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "Pstream.H"
+#include "PstreamCombineReduceOps.H"
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
@@ -184,138 +185,269 @@ void Foam::mapDistribute::distribute
     {
         if (!contiguous<T>())
         {
-            FatalErrorIn
-            (
-                "template<class T>\n"
-                "void mapDistribute::distribute\n"
-                "(\n"
-                "    const Pstream::commsTypes commsType,\n"
-                "    const List<labelPair>& schedule,\n"
-                "    const label constructSize,\n"
-                "    const labelListList& subMap,\n"
-                "    const labelListList& constructMap,\n"
-                "    List<T>& field\n"
-                ")\n"
-            )   << "Non-blocking only supported for contiguous data."
-                << exit(FatalError);
-        }
+            // 1. convert to contiguous buffer
+            // 2. send buffer
+            // 3. receive buffer
+            // 4. read from buffer into List<T>
+
+            List<List<char> > sendFields(Pstream::nProcs());
+            labelListList allNTrans(Pstream::nProcs());
+            labelList& nsTransPs = allNTrans[Pstream::myProcNo()];
+            nsTransPs.setSize(Pstream::nProcs(), 0);
+
+            // Stream data into sendField buffers
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
+            {
+                const labelList& map = subMap[domain];
 
-        // Set up sends to neighbours
+                if (domain != Pstream::myProcNo() && map.size())
+                {
+                    // Put data into send buffer
+                    OPstream toDomain(Pstream::nonBlocking, domain);
+                    toDomain << UIndirectList<T>(field, map);
 
-        List<List<T > > sendFields(Pstream::nProcs());
+                    // Store the size
+                    nsTransPs[domain] = toDomain.bufPosition();
 
-        for (label domain = 0; domain < Pstream::nProcs(); domain++)
-        {
-            const labelList& map = subMap[domain];
+                    // Transfer buffer out
+                    sendFields[domain].transfer(toDomain.buf());
+                    toDomain.bufPosition() = 0;
 
-            if (domain != Pstream::myProcNo() && map.size())
+                }
+            }
+
+            // Send sizes across
+            combineReduce(allNTrans, listEq());
+
+            // Start sending buffers
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
             {
-                List<T>& subField = sendFields[domain];
-                subField.setSize(map.size());
-                forAll(map, i)
+                const labelList& map = subMap[domain];
+
+                if (domain != Pstream::myProcNo() && map.size())
                 {
-                    subField[i] = field[map[i]];
+                    OPstream::write
+                    (
+                        Pstream::nonBlocking,
+                        domain,
+                        reinterpret_cast<const char*>
+                        (
+                            sendFields[domain].begin()
+                        ),
+                        nsTransPs[domain]
+                    );
                 }
-
-                OPstream::write
-                (
-                    Pstream::nonBlocking,
-                    domain,
-                    reinterpret_cast<const char*>(subField.begin()),
-                    subField.size()*sizeof(T)
-                );
             }
-        }
 
-        // Set up receives from neighbours
+            // Set up receives from neighbours
 
-        List<List<T > > recvFields(Pstream::nProcs());
+            PtrList<IPstream> fromSlave(Pstream::nProcs());
 
-        for (label domain = 0; domain < Pstream::nProcs(); domain++)
-        {
-            const labelList& map = constructMap[domain];
-
-            if (domain != Pstream::myProcNo() && map.size())
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
             {
-                recvFields[domain].setSize(map.size());
-                IPstream::read
-                (
-                    Pstream::nonBlocking,
-                    domain,
-                    reinterpret_cast<char*>(recvFields[domain].begin()),
-                    recvFields[domain].size()*sizeof(T)
-                );
+                const labelList& map = constructMap[domain];
+
+                if (domain != Pstream::myProcNo() && map.size())
+                {
+                    // Start receiving
+                    fromSlave.set
+                    (
+                        domain,
+                        new IPstream
+                        (
+                            Pstream::nonBlocking,
+                            domain,
+                            allNTrans[domain][Pstream::myProcNo()]
+                        )
+                    );
+                }
             }
-        }
 
 
-        // Set up 'send' to myself
+            {
+                // Set up 'send' to myself
+                const labelList& mySubMap = subMap[Pstream::myProcNo()];
+                List<T> mySubField(mySubMap.size());
+                forAll(mySubMap, i)
+                {
+                    mySubField[i] = field[mySubMap[i]];
+                }
+                // Combine bits. Note that can reuse field storage
+                field.setSize(constructSize);
+                // Receive sub field from myself
+                {
+                    const labelList& map = constructMap[Pstream::myProcNo()];
 
-        {
-            const labelList& map = subMap[Pstream::myProcNo()];
+                    forAll(map, i)
+                    {
+                        field[map[i]] = mySubField[i];
+                    }
+                }
+            }
 
-            List<T>& subField = sendFields[Pstream::myProcNo()];
-            subField.setSize(map.size());
-            forAll(map, i)
+
+            // Wait till all finished
+            IPstream::waitRequests();
+            OPstream::waitRequests();
+
+            // Consume
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
             {
-                subField[i] = field[map[i]];
+                const labelList& map = constructMap[domain];
+
+                if (domain != Pstream::myProcNo() && map.size())
+                {
+                    List<T> recvField(fromSlave[domain]);
+
+                    if (recvField.size() != map.size())
+                    {
+                        FatalErrorIn
+                        (
+                            "template<class T>\n"
+                            "void mapDistribute::distribute\n"
+                            "(\n"
+                            "    const Pstream::commsTypes commsType,\n"
+                            "    const List<labelPair>& schedule,\n"
+                            "    const label constructSize,\n"
+                            "    const labelListList& subMap,\n"
+                            "    const labelListList& constructMap,\n"
+                            "    List<T>& field\n"
+                            ")\n"
+                        )   << "Expected from processor " << domain
+                            << " " << map.size() << " but received "
+                            << recvField.size() << " elements."
+                            << abort(FatalError);
+                    }
+
+                    forAll(map, i)
+                    {
+                        field[map[i]] = recvField[i];
+                    }
+
+                    // Delete receive buffer
+                    fromSlave.set(domain, NULL);
+                }
             }
         }
+        else
+        {
+            // Set up sends to neighbours
 
+            List<List<T > > sendFields(Pstream::nProcs());
 
-        // Combine bits. Note that can reuse field storage
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
+            {
+                const labelList& map = subMap[domain];
 
-        field.setSize(constructSize);
+                if (domain != Pstream::myProcNo() && map.size())
+                {
+                    List<T>& subField = sendFields[domain];
+                    subField.setSize(map.size());
+                    forAll(map, i)
+                    {
+                        subField[i] = field[map[i]];
+                    }
+
+                    OPstream::write
+                    (
+                        Pstream::nonBlocking,
+                        domain,
+                        reinterpret_cast<const char*>(subField.begin()),
+                        subField.byteSize()
+                    );
+                }
+            }
 
+            // Set up receives from neighbours
 
-        // Receive sub field from myself (sendFields[Pstream::myProcNo()])
-        {
-            const labelList& map = constructMap[Pstream::myProcNo()];
-            const List<T>& subField = sendFields[Pstream::myProcNo()];
+            List<List<T > > recvFields(Pstream::nProcs());
 
-            forAll(map, i)
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
             {
-                field[map[i]] = subField[i];
+                const labelList& map = constructMap[domain];
+
+                if (domain != Pstream::myProcNo() && map.size())
+                {
+                    recvFields[domain].setSize(map.size());
+                    IPstream::read
+                    (
+                        Pstream::nonBlocking,
+                        domain,
+                        reinterpret_cast<char*>(recvFields[domain].begin()),
+                        recvFields[domain].byteSize()
+                    );
+                }
             }
-        }
 
 
-        // Wait for all to finish
+            // Set up 'send' to myself
 
-        OPstream::waitRequests();
-        IPstream::waitRequests();
+            {
+                const labelList& map = subMap[Pstream::myProcNo()];
 
-        // Collect neighbour fields
+                List<T>& subField = sendFields[Pstream::myProcNo()];
+                subField.setSize(map.size());
+                forAll(map, i)
+                {
+                    subField[i] = field[map[i]];
+                }
+            }
 
-        for (label domain = 0; domain < Pstream::nProcs(); domain++)
-        {
-            const labelList& map = constructMap[domain];
 
-            if (domain != Pstream::myProcNo() && map.size())
+            // Combine bits. Note that can reuse field storage
+
+            field.setSize(constructSize);
+
+
+            // Receive sub field from myself (sendFields[Pstream::myProcNo()])
             {
-                if (recvFields[domain].size() != map.size())
+                const labelList& map = constructMap[Pstream::myProcNo()];
+                const List<T>& subField = sendFields[Pstream::myProcNo()];
+
+                forAll(map, i)
                 {
-                    FatalErrorIn
-                    (
-                        "template<class T>\n"
-                        "void mapDistribute::distribute\n"
-                        "(\n"
-                        "    const Pstream::commsTypes commsType,\n"
-                        "    const List<labelPair>& schedule,\n"
-                        "    const label constructSize,\n"
-                        "    const labelListList& subMap,\n"
-                        "    const labelListList& constructMap,\n"
-                        "    List<T>& field\n"
-                        ")\n"
-                    )   << "Expected from processor " << domain
-                        << " " << map.size() << " but received "
-                        << recvFields[domain].size() << " elements."
-                        << abort(FatalError);
+                    field[map[i]] = subField[i];
                 }
+            }
 
-                forAll(map, i)
+
+            // Wait for all to finish
+
+            OPstream::waitRequests();
+            IPstream::waitRequests();
+
+            // Collect neighbour fields
+
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
+            {
+                const labelList& map = constructMap[domain];
+
+                if (domain != Pstream::myProcNo() && map.size())
                 {
-                    field[map[i]] = recvFields[domain][i];
+                    if (recvFields[domain].size() != map.size())
+                    {
+                        FatalErrorIn
+                        (
+                            "template<class T>\n"
+                            "void mapDistribute::distribute\n"
+                            "(\n"
+                            "    const Pstream::commsTypes commsType,\n"
+                            "    const List<labelPair>& schedule,\n"
+                            "    const label constructSize,\n"
+                            "    const labelListList& subMap,\n"
+                            "    const labelListList& constructMap,\n"
+                            "    List<T>& field\n"
+                            ")\n"
+                        )   << "Expected from processor " << domain
+                            << " " << map.size() << " but received "
+                            << recvFields[domain].size() << " elements."
+                            << abort(FatalError);
+                    }
+
+                    forAll(map, i)
+                    {
+                        field[map[i]] = recvFields[domain][i];
+                    }
                 }
             }
         }
@@ -488,137 +620,263 @@ void Foam::mapDistribute::distribute
     {
         if (!contiguous<T>())
         {
-            FatalErrorIn
-            (
-                "template<class T>\n"
-                "void mapDistribute::distribute\n"
-                "(\n"
-                "    const Pstream::commsTypes commsType,\n"
-                "    const List<labelPair>& schedule,\n"
-                "    const label constructSize,\n"
-                "    const labelListList& subMap,\n"
-                "    const labelListList& constructMap,\n"
-                "    List<T>& field\n"
-                ")\n"
-            )   << "Non-blocking only supported for contiguous data."
-                << exit(FatalError);
-        }
+            // 1. convert to contiguous buffer
+            // 2. send buffer
+            // 3. receive buffer
+            // 4. read from buffer into List<T>
+
+            List<List<char> > sendFields(Pstream::nProcs());
+            labelListList allNTrans(Pstream::nProcs());
+            labelList& nsTransPs = allNTrans[Pstream::myProcNo()];
+            nsTransPs.setSize(Pstream::nProcs());
+
+            // Stream data into sendField buffers
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
+            {
+                const labelList& map = subMap[domain];
 
-        // Set up sends to neighbours
+                if (domain != Pstream::myProcNo() && map.size())
+                {
+                    // Put data into send buffer
+                    OPstream toDomain(Pstream::nonBlocking, domain);
+                    toDomain << UIndirectList<T>(field, map);
 
-        List<List<T > > sendFields(Pstream::nProcs());
+                    // Store the size
+                    nsTransPs[domain] = toDomain.bufPosition();
 
-        for (label domain = 0; domain < Pstream::nProcs(); domain++)
-        {
-            const labelList& map = subMap[domain];
+                    // Transfer buffer out
+                    sendFields[domain].transfer(toDomain.buf());
+                    toDomain.bufPosition() = 0;
+                }
+            }
 
-            if (domain != Pstream::myProcNo() && map.size())
+            // Send sizes across
+            combineReduce(allNTrans, listEq());
+
+            // Start sending buffers
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
             {
-                List<T>& subField = sendFields[domain];
-                subField.setSize(map.size());
-                forAll(map, i)
+                const labelList& map = subMap[domain];
+
+                if (domain != Pstream::myProcNo() && map.size())
                 {
-                    subField[i] = field[map[i]];
+                    OPstream::write
+                    (
+                        Pstream::nonBlocking,
+                        domain,
+                        reinterpret_cast<const char*>
+                        (
+                            sendFields[domain].begin()
+                        ),
+                        nsTransPs[domain]
+                    );
                 }
-
-                OPstream::write
-                (
-                    Pstream::nonBlocking,
-                    domain,
-                    reinterpret_cast<const char*>(subField.begin()),
-                    subField.size()*sizeof(T)
-                );
             }
-        }
 
-        // Set up receives from neighbours
+            // Set up receives from neighbours
 
-        List<List<T > > recvFields(Pstream::nProcs());
+            PtrList<IPstream> fromSlave(Pstream::nProcs());
+
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
+            {
+                const labelList& map = constructMap[domain];
+
+                if (domain != Pstream::myProcNo() && map.size())
+                {
+                    // Start receiving
+                    fromSlave.set
+                    (
+                        domain,
+                        new IPstream
+                        (
+                            Pstream::nonBlocking,
+                            domain,
+                            allNTrans[domain][Pstream::myProcNo()]
+                        )
+                    );
+                }
+            }
 
-        for (label domain = 0; domain < Pstream::nProcs(); domain++)
-        {
-            const labelList& map = constructMap[domain];
 
-            if (domain != Pstream::myProcNo() && map.size())
             {
-                recvFields[domain].setSize(map.size());
-                IPstream::read
-                (
-                    Pstream::nonBlocking,
-                    domain,
-                    reinterpret_cast<char*>(recvFields[domain].begin()),
-                    recvFields[domain].size()*sizeof(T)
-                );
+                // Set up 'send' to myself
+                List<T> mySubField(field, subMap[Pstream::myProcNo()]);
+                // Combine bits. Note that can reuse field storage
+                field.setSize(constructSize);
+                field = nullValue;
+                // Receive sub field from myself
+                {
+                    const labelList& map = constructMap[Pstream::myProcNo()];
+
+                    forAll(map, i)
+                    {
+                        cop(field[map[i]], mySubField[i]);
+                    }
+                }
             }
-        }
 
-        // Set up 'send' to myself
 
-        {
-            const labelList& map = subMap[Pstream::myProcNo()];
+            // Wait till all finished
+            IPstream::waitRequests();
+            OPstream::waitRequests();
 
-            List<T>& subField = sendFields[Pstream::myProcNo()];
-            subField.setSize(map.size());
-            forAll(map, i)
+            // Consume
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
             {
-                subField[i] = field[map[i]];
+                const labelList& map = constructMap[domain];
+
+                if (domain != Pstream::myProcNo() && map.size())
+                {
+                    List<T> recvField(fromSlave[domain]);
+
+                    if (recvField.size() != map.size())
+                    {
+                        FatalErrorIn
+                        (
+                            "template<class T>\n"
+                            "void mapDistribute::distribute\n"
+                            "(\n"
+                            "    const Pstream::commsTypes commsType,\n"
+                            "    const List<labelPair>& schedule,\n"
+                            "    const label constructSize,\n"
+                            "    const labelListList& subMap,\n"
+                            "    const labelListList& constructMap,\n"
+                            "    List<T>& field\n"
+                            ")\n"
+                        )   << "Expected from processor " << domain
+                            << " " << map.size() << " but received "
+                            << recvField.size() << " elements."
+                            << abort(FatalError);
+                    }
+
+                    forAll(map, i)
+                    {
+                        cop(field[map[i]], recvField[i]);
+                    }
+
+                    // Delete receive buffer
+                    fromSlave.set(domain, NULL);
+                }
             }
         }
+        else
+        {
+            // Set up sends to neighbours
 
+            List<List<T > > sendFields(Pstream::nProcs());
 
-        // Combine bits. Note that can reuse field storage
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
+            {
+                const labelList& map = subMap[domain];
 
-        field.setSize(constructSize);
-        field = nullValue;
+                if (domain != Pstream::myProcNo() && map.size())
+                {
+                    List<T>& subField = sendFields[domain];
+                    subField.setSize(map.size());
+                    forAll(map, i)
+                    {
+                        subField[i] = field[map[i]];
+                    }
+
+                    OPstream::write
+                    (
+                        Pstream::nonBlocking,
+                        domain,
+                        reinterpret_cast<const char*>(subField.begin()),
+                        subField.size()*sizeof(T)
+                    );
+                }
+            }
 
-        // Receive sub field from myself (subField)
-        {
-            const labelList& map = constructMap[Pstream::myProcNo()];
-            const List<T>& subField = sendFields[Pstream::myProcNo()];
+            // Set up receives from neighbours
+
+            List<List<T > > recvFields(Pstream::nProcs());
 
-            forAll(map, i)
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
             {
-                cop(field[map[i]], subField[i]);
+                const labelList& map = constructMap[domain];
+
+                if (domain != Pstream::myProcNo() && map.size())
+                {
+                    recvFields[domain].setSize(map.size());
+                    IPstream::read
+                    (
+                        Pstream::nonBlocking,
+                        domain,
+                        reinterpret_cast<char*>(recvFields[domain].begin()),
+                        recvFields[domain].size()*sizeof(T)
+                    );
+                }
             }
-        }
 
+            // Set up 'send' to myself
 
-        // Wait for all to finish
+            {
+                const labelList& map = subMap[Pstream::myProcNo()];
 
-        OPstream::waitRequests();
-        IPstream::waitRequests();
+                List<T>& subField = sendFields[Pstream::myProcNo()];
+                subField.setSize(map.size());
+                forAll(map, i)
+                {
+                    subField[i] = field[map[i]];
+                }
+            }
 
-        // Collect neighbour fields
 
-        for (label domain = 0; domain < Pstream::nProcs(); domain++)
-        {
-            const labelList& map = constructMap[domain];
+            // Combine bits. Note that can reuse field storage
 
-            if (domain != Pstream::myProcNo() && map.size())
+            field.setSize(constructSize);
+            field = nullValue;
+
+            // Receive sub field from myself (subField)
             {
-                if (recvFields[domain].size() != map.size())
+                const labelList& map = constructMap[Pstream::myProcNo()];
+                const List<T>& subField = sendFields[Pstream::myProcNo()];
+
+                forAll(map, i)
                 {
-                    FatalErrorIn
-                    (
-                        "template<class T>\n"
-                        "void mapDistribute::distribute\n"
-                        "(\n"
-                        "    const Pstream::commsTypes commsType,\n"
-                        "    const List<labelPair>& schedule,\n"
-                        "    const label constructSize,\n"
-                        "    const labelListList& subMap,\n"
-                        "    const labelListList& constructMap,\n"
-                        "    List<T>& field\n"
-                        ")\n"
-                    )   << "Expected from processor " << domain
-                        << " " << map.size() << " but received "
-                        << recvFields[domain].size() << " elements."
-                        << abort(FatalError);
+                    cop(field[map[i]], subField[i]);
                 }
+            }
 
-                forAll(map, i)
+
+            // Wait for all to finish
+
+            OPstream::waitRequests();
+            IPstream::waitRequests();
+
+            // Collect neighbour fields
+
+            for (label domain = 0; domain < Pstream::nProcs(); domain++)
+            {
+                const labelList& map = constructMap[domain];
+
+                if (domain != Pstream::myProcNo() && map.size())
                 {
-                    cop(field[map[i]], recvFields[domain][i]);
+                    if (recvFields[domain].size() != map.size())
+                    {
+                        FatalErrorIn
+                        (
+                            "template<class T>\n"
+                            "void mapDistribute::distribute\n"
+                            "(\n"
+                            "    const Pstream::commsTypes commsType,\n"
+                            "    const List<labelPair>& schedule,\n"
+                            "    const label constructSize,\n"
+                            "    const labelListList& subMap,\n"
+                            "    const labelListList& constructMap,\n"
+                            "    List<T>& field\n"
+                            ")\n"
+                        )   << "Expected from processor " << domain
+                            << " " << map.size() << " but received "
+                            << recvFields[domain].size() << " elements."
+                            << abort(FatalError);
+                    }
+
+                    forAll(map, i)
+                    {
+                        cop(field[map[i]], recvFields[domain][i]);
+                    }
                 }
             }
         }
diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C
index 1612a23deac026c60ab56110d5061e49a5518e48..cc110c1d406acb0eaf63e2eab720a815edb656d6 100644
--- a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C
+++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C
@@ -28,12 +28,9 @@ License
 #include "fvMesh.H"
 #include "Time.H"
 #include "boundBox.H"
-#include "globalIndex.H"
 #include "wallPolyPatch.H"
-#include "mapDistributePolyMesh.H"
 #include "cellSet.H"
 #include "syncTools.H"
-#include "motionSmoother.H"
 #include "refinementParameters.H"
 #include "snapParameters.H"
 #include "layerParameters.H"
diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.C b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.C
index a9b31b9bd1160800255fa6311b991083a56fcf6d..68d4b3b1e6a68e1f67d29e06f94e54f5db2378ca 100644
--- a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.C
+++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.C
@@ -28,8 +28,6 @@ License
 #include "meshRefinement.H"
 #include "fvMesh.H"
 #include "Time.H"
-#include "boundBox.H"
-#include "mapDistributePolyMesh.H"
 #include "cellSet.H"
 #include "syncTools.H"
 #include "refinementParameters.H"
diff --git a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
index 633c39f4782b13cd273ae0ccd2eaeeb76110f326..f815b46d718c988834f0111b20eee3ecd88a1cec 100644
--- a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
+++ b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
@@ -1418,18 +1418,18 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
                 nOldPoints,
                 nOldFaces,
                 nOldCells,
-                oldPatchStarts,
-                oldPatchNMeshPoints,
-
-                labelListList(1, identity(mesh_.nPoints())),//subPointMap
-                labelListList(1, identity(mesh_.nFaces())), //subFaceMap
-                labelListList(1, identity(mesh_.nCells())), //subCellMap
-                labelListList(1, identity(patches.size())), //subPatchMap
-
-                labelListList(1, identity(mesh_.nPoints())),//constructPointMap
-                labelListList(1, identity(mesh_.nFaces())), //constructFaceMap
-                labelListList(1, identity(mesh_.nCells())), //constructCellMap
-                labelListList(1, identity(patches.size()))  //constructPatchMap
+                oldPatchStarts.xfer(),
+                oldPatchNMeshPoints.xfer(),
+
+                labelListList(1, identity(mesh_.nPoints())).xfer(),//subPointMap
+                labelListList(1, identity(mesh_.nFaces())).xfer(), //subFaceMap
+                labelListList(1, identity(mesh_.nCells())).xfer(), //subCellMap
+                labelListList(1, identity(patches.size())).xfer(), //subPatchMap
+
+                labelListList(1, identity(mesh_.nPoints())).xfer(),//pointMap
+                labelListList(1, identity(mesh_.nFaces())).xfer(), //faceMap
+                labelListList(1, identity(mesh_.nCells())).xfer(), //cellMap
+                labelListList(1, identity(patches.size())).xfer()  //patchMap
             )
         );
     }
@@ -2207,19 +2207,18 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
             nOldPoints,
             nOldFaces,
             nOldCells,
-            oldPatchStarts,
-            oldPatchNMeshPoints,
-
-            subPointMap,
-            subFaceMap,
-            subCellMap,
-            subPatchMap,
-
-            constructPointMap,
-            constructFaceMap,
-            constructCellMap,
-            constructPatchMap,
-            true                // reuse storage
+            oldPatchStarts.xfer(),
+            oldPatchNMeshPoints.xfer(),
+
+            subPointMap.xfer(),
+            subFaceMap.xfer(),
+            subCellMap.xfer(),
+            subPatchMap.xfer(),
+
+            constructPointMap.xfer(),
+            constructFaceMap.xfer(),
+            constructCellMap.xfer(),
+            constructPatchMap.xfer()
         )
     );
 }
diff --git a/src/finiteVolume/fvMesh/extendedStencil/cellToFace/extendedCellToFaceStencil.C b/src/finiteVolume/fvMesh/extendedStencil/cellToFace/extendedCellToFaceStencil.C
index 5b1cb12e342a15f38eaa1caa5f9b3da4787197c9..8a7224288ce94f4b0fd49b515340855c31a9f7cb 100644
--- a/src/finiteVolume/fvMesh/extendedStencil/cellToFace/extendedCellToFaceStencil.C
+++ b/src/finiteVolume/fvMesh/extendedStencil/cellToFace/extendedCellToFaceStencil.C
@@ -280,9 +280,8 @@ Foam::extendedCellToFaceStencil::calcDistributeMap
         new mapDistribute
         (
             nCompact,
-            sendCompact,
-            recvCompact,
-            true            // reuse send/recv maps.
+            sendCompact.xfer(),
+            recvCompact.xfer()
         )
     );
 
diff --git a/src/meshTools/searchableSurface/distributedTriSurfaceMesh.C b/src/meshTools/searchableSurface/distributedTriSurfaceMesh.C
index 7f86c0f6581fcd94504b9cb7d39fdc67284a4506..33b6b6f1f55e71a87e4a213db2253556f3f740a2 100644
--- a/src/meshTools/searchableSurface/distributedTriSurfaceMesh.C
+++ b/src/meshTools/searchableSurface/distributedTriSurfaceMesh.C
@@ -340,9 +340,8 @@ Foam::distributedTriSurfaceMesh::distributeSegments
         new mapDistribute
         (
             segmentI,       // size after construction
-            sendMap,
-            constructMap,
-            true            // reuse storage
+            sendMap.xfer(),
+            constructMap.xfer()
         )
     );
 }
@@ -642,9 +641,8 @@ Foam::distributedTriSurfaceMesh::calcLocalQueries
         new mapDistribute
         (
             segmentI,       // size after construction
-            sendMap,
-            constructMap,
-            true            // reuse storage
+            sendMap.xfer(),
+            constructMap.xfer()
         )
     );
     const mapDistribute& map = mapPtr();
@@ -806,9 +804,8 @@ Foam::distributedTriSurfaceMesh::calcLocalQueries
         new mapDistribute
         (
             segmentI,       // size after construction
-            sendMap,
-            constructMap,
-            true            // reuse storage
+            sendMap.xfer(),
+            constructMap.xfer()
         )
     );
     return mapPtr;
@@ -2399,9 +2396,8 @@ void Foam::distributedTriSurfaceMesh::distribute
         new mapDistribute
         (
             allTris.size(),
-            faceSendMap,
-            faceConstructMap,
-            true
+            faceSendMap.xfer(),
+            faceConstructMap.xfer()
         )
     );
     pointMap.reset
@@ -2409,9 +2405,8 @@ void Foam::distributedTriSurfaceMesh::distribute
         new mapDistribute
         (
             allPoints.size(),
-            pointSendMap,
-            pointConstructMap,
-            true
+            pointSendMap.xfer(),
+            pointConstructMap.xfer()
         )
     );