diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.C b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.C
index 52ccc834ff8e25592e170e4ae0008b495277e742..ce054e9e9e6f346ee824a92e7053f6e1fdb9daff 100644
--- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.C
+++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.C
@@ -525,7 +525,6 @@ void Foam::globalMeshData::calcGlobalPointSlaves() const
 
     // Calculate connected points for master points.
     globalPoints globalData(mesh_, coupledPatch(), true, true);
-    globalPointNumberingPtr_.reset(new globalIndex(globalData.globalIndices()));
 
     globalPointSlavesPtr_.reset
     (
@@ -1564,6 +1563,42 @@ void Foam::globalMeshData::calcGlobalPointBoundaryCells() const
 }
 
 
+void Foam::globalMeshData::calcGlobalCoPointSlaves() const
+{
+    if (debug)
+    {
+        Pout<< "globalMeshData::calcGlobalCoPointSlaves() :"
+            << " calculating coupled master to collocated"
+            << " slave point addressing." << endl;
+    }
+
+    // Calculate connected points for master points.
+    globalPoints globalData(mesh_, coupledPatch(), true, false);
+
+    globalCoPointSlavesPtr_.reset
+    (
+        new labelListList
+        (
+            globalData.pointPoints().xfer()
+        )
+    );
+    globalCoPointSlavesMapPtr_.reset
+    (
+        new mapDistribute
+        (
+            globalData.map().xfer()
+        )
+    );
+
+    if (debug)
+    {
+        Pout<< "globalMeshData::calcGlobalCoPointSlaves() :"
+            << " finished calculating coupled master to collocated"
+            << " slave point addressing." << endl;
+    }
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 // Construct from polyMesh
@@ -1639,6 +1674,10 @@ void Foam::globalMeshData::clearOut()
     globalPointBoundaryCellsPtr_.clear();
     globalPointTransformedBoundaryCellsPtr_.clear();
     globalPointBoundaryCellsMapPtr_.clear();
+
+    // Other: collocated points
+    globalCoPointSlavesPtr_.clear();
+    globalCoPointSlavesMapPtr_.clear();
 }
 
 
@@ -1971,7 +2010,10 @@ const Foam::globalIndex& Foam::globalMeshData::globalPointNumbering() const
 {
     if (!globalPointNumberingPtr_.valid())
     {
-        calcGlobalPointSlaves();
+        globalPointNumberingPtr_.reset
+        (
+            new globalIndex(coupledPatch().nPoints())
+        );
     }
     return globalPointNumberingPtr_();
 }
@@ -2161,6 +2203,26 @@ const
 }
 
 
+const Foam::labelListList& Foam::globalMeshData::globalCoPointSlaves() const
+{
+    if (!globalCoPointSlavesPtr_.valid())
+    {
+        calcGlobalCoPointSlaves();
+    }
+    return globalCoPointSlavesPtr_();
+}
+
+
+const Foam::mapDistribute& Foam::globalMeshData::globalCoPointSlavesMap() const
+{
+    if (!globalCoPointSlavesMapPtr_.valid())
+    {
+        calcGlobalCoPointSlaves();
+    }
+    return globalCoPointSlavesMapPtr_();
+}
+
+
 Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
 (
     labelList& pointToGlobal,
@@ -2168,33 +2230,70 @@ Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
 ) const
 {
     const indirectPrimitivePatch& cpp = coupledPatch();
-    const labelListList& pointSlaves = globalPointSlaves();
-    const mapDistribute& pointSlavesMap = globalPointSlavesMap();
+    const globalIndex& globalCoupledPoints = globalPointNumbering();
+    // Use collocated only
+    const labelListList& pointSlaves = globalCoPointSlaves();
+    const mapDistribute& pointSlavesMap = globalCoPointSlavesMap();
+
+
+    // Points are either
+    // - master with slaves
+    // - slave with a master
+    // - other (since e.g. non-collocated cyclics not connected)
+
+    labelList masterGlobalPoint(cpp.nPoints(), -1);
+    forAll(masterGlobalPoint, pointI)
+    {
+        const labelList& slavePoints = pointSlaves[pointI];
+        if (slavePoints.size() > 0)
+        {
+            masterGlobalPoint[pointI] = globalCoupledPoints.toGlobal(pointI);
+        }
+    }
+
+    // Sync by taking max
+    syncData
+    (
+        masterGlobalPoint,
+        pointSlaves,
+        labelListList(cpp.nPoints()),   // no transforms
+        pointSlavesMap,
+        maxEqOp<label>()
+    );
 
 
     // 1. Count number of masters on my processor.
-    label nCoupledMaster = 0;
+    label nMaster = 0;
     PackedBoolList isMaster(mesh_.nPoints(), 1);
     forAll(pointSlaves, pointI)
     {
-        const labelList& slavePoints = pointSlaves[pointI];
-
-        if (slavePoints.size() > 0)
+        if (masterGlobalPoint[pointI] == -1)
         {
-            nCoupledMaster++;
+            // unconnected point (e.g. from separated cyclic)
+            nMaster++;
+        }
+        else if
+        (
+            masterGlobalPoint[pointI]
+         == globalCoupledPoints.toGlobal(pointI)
+        )
+        {
+            // connected master
+            nMaster++;
         }
         else
         {
+            // connected slave point
             isMaster[cpp.meshPoints()[pointI]] = 0;
         }
     }
 
-    label myUniquePoints = mesh_.nPoints() - cpp.nPoints() + nCoupledMaster;
+    label myUniquePoints = mesh_.nPoints() - cpp.nPoints() + nMaster;
 
     //Pout<< "Points :" << nl
     //    << "    mesh             : " << mesh_.nPoints() << nl
     //    << "    of which coupled : " << cpp.nPoints() << nl
-    //    << "    of which master  : " << nCoupledMaster << nl
+    //    << "    of which master  : " << nMaster << nl
     //    << endl;
 
 
@@ -2206,7 +2305,7 @@ Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
     pointToGlobal.setSize(mesh_.nPoints());
     pointToGlobal = -1;
     uniquePoints.setSize(myUniquePoints);
-    label nMaster = 0;
+    nMaster = 0;
 
     forAll(isMaster, meshPointI)
     {
@@ -2245,11 +2344,10 @@ Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
         // On slave copy master index into overal map.
         forAll(pointSlaves, pointI)
         {
-            const labelList& slaves = pointSlaves[pointI];
+            label meshPointI = cpp.meshPoints()[pointI];
 
-            if (slaves.size() == 0)
+            if (!isMaster[meshPointI])
             {
-                label meshPointI = cpp.meshPoints()[pointI];
                 pointToGlobal[meshPointI] = masterToGlobal[pointI];
             }
         }
@@ -2268,8 +2366,8 @@ Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
 ) const
 {
     const indirectPrimitivePatch& cpp = coupledPatch();
-    const labelListList& pointSlaves = globalPointSlaves();
-    const mapDistribute& pointSlavesMap = globalPointSlavesMap();
+    const labelListList& pointSlaves = globalCoPointSlaves();
+    const mapDistribute& pointSlavesMap = globalCoPointSlavesMap();
 
 
     // The patch points come in two variants:
@@ -2280,19 +2378,18 @@ Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
     // coupled points to be the master but this master point is not
     // necessarily on the patch itself! (it might just be connected to the
     // patch point via coupled patches).
-    // So this means that all master point loops should be over the
-    // master-slave structure, not over the patch points and that the unique
-    // point returned is a mesh point.
-    // (unless we want to do the whole master-slave analysis again for the
-    //  current patch only).
 
 
-    // Determine mapping from coupled point to patch point and vice versa
-    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    // Determine mapping:
+    // - from patch point to coupled point (or -1)
+    // - from coupled point to global patch point
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    globalIndex globalPPoints(meshPoints.size());
 
     labelList patchToCoupled(meshPoints.size(), -1);
     label nCoupled = 0;
-    labelList coupledToPatch(pointSlavesMap.constructSize(), -1);
+    labelList coupledToGlobalPatch(pointSlavesMap.constructSize(), -1);
 
     // Note: loop over patch since usually smaller
     forAll(meshPoints, patchPointI)
@@ -2304,7 +2401,7 @@ Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
         if (iter != cpp.meshPointMap().end())
         {
             patchToCoupled[patchPointI] = iter();
-            coupledToPatch[iter()] = patchPointI;
+            coupledToGlobalPatch[iter()] = globalPPoints.toGlobal(patchPointI);
             nCoupled++;
         }
     }
@@ -2314,133 +2411,163 @@ Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
     //    << "    of which on coupled patch:" << nCoupled << endl;
 
 
-    // Pull coupled-to-patch information to master
-    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    pointSlavesMap.distribute(coupledToPatch);
-
-
-    // Check on master whether point is anywhere on patch
-    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    // List of master points that are on the patch
-    DynamicList<label> masterPoints(pointSlaves.size());
+    // Determine master of connected points
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    // Problem is that the coupled master might not be on the patch. So
+    // work out the best patch-point master from all connected points.
+    // - if the coupled master is on the patch it becomes the patch-point master
+    // - else the slave with the lowest numbered patch point label
 
+    // Get all data on master
+    pointSlavesMap.distribute(coupledToGlobalPatch);
     forAll(pointSlaves, coupledPointI)
     {
         const labelList& slaves = pointSlaves[coupledPointI];
 
         if (slaves.size() > 0)
         {
-            // I am master. Is this point on the patch on myself or on any
-            // any slave?
-            if (coupledToPatch[coupledPointI] != -1)
+            // I am master. What is the best candidate for patch-point master
+            label masterI = labelMax;
+            if (coupledToGlobalPatch[coupledPointI] != -1)
             {
-                masterPoints.append(coupledPointI);
+                // I am master and on the coupled patch. Use me.
+                masterI = coupledToGlobalPatch[coupledPointI];
             }
             else
             {
+                // Get min of slaves as master.
                 forAll(slaves, i)
                 {
-                    if (coupledToPatch[slaves[i]] != -1)
+                    label slavePp = coupledToGlobalPatch[slaves[i]];
+                    if (slavePp != -1 && slavePp < masterI)
                     {
-                        masterPoints.append(coupledPointI);
-                        break;
+                        masterI = slavePp;
                     }
                 }
             }
+
+            if (masterI != labelMax)
+            {
+                // Push back
+                coupledToGlobalPatch[coupledPointI] = masterI;
+                forAll(slaves, i)
+                {
+                    coupledToGlobalPatch[slaves[i]] = masterI;
+                }
+            }
         }
     }
+    pointSlavesMap.reverseDistribute(cpp.nPoints(), coupledToGlobalPatch);
 
 
-    // Create global indexing
-    // ~~~~~~~~~~~~~~~~~~~~~~
-    // 1. patch points that are not on coupled patch:
-    //      meshPoints.size()-nCoupled
-    // 2. master points that are on patch:
-    //      masterPoints.size()
-    label myUniquePoints = meshPoints.size()-nCoupled+masterPoints.size();
-    autoPtr<globalIndex> globalPointsPtr(new globalIndex(myUniquePoints));
-
-    //Pout<< "CoupledPatch:" << nl
-    //    << "    points:" << cpp.nPoints() << nl
-    //    << "    of which on patch:" << masterPoints.size() << endl;
-
-
-    // Allocate unique points
-    // ~~~~~~~~~~~~~~~~~~~~~~
+    // Generate compact numbering for master points
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    // Now coupledToGlobalPatch is the globalIndex of the master point.
+    // Now every processor can check whether they hold it and generate a
+    // compact numbering.
 
-    pointToGlobal.setSize(meshPoints.size());
-    pointToGlobal = -1;
-    uniqueMeshPoints.setSize(myUniquePoints);
-
-    // Allocate globals for uncoupled patch points
-    label nMaster = 0;
-    forAll(patchToCoupled, patchPointI)
+    label nMasters = 0;
+    forAll(meshPoints, patchPointI)
     {
         if (patchToCoupled[patchPointI] == -1)
         {
-            // Allocate global point
-            label globalI = globalPointsPtr().toGlobal(nMaster);
-            pointToGlobal[patchPointI] = globalI;
-            uniqueMeshPoints[nMaster] = meshPoints[patchPointI];
-            nMaster++;
+            nMasters++;
+        }
+        else
+        {
+            label coupledPointI = patchToCoupled[patchPointI];
+            if
+            (
+                globalPPoints.toGlobal(patchPointI)
+             == coupledToGlobalPatch[coupledPointI]
+            )
+            {
+                // I am the master
+                nMasters++;
+            }
         }
     }
 
-    // Allocate globals for master
-    labelList masterToGlobal(pointSlavesMap.constructSize(), -456);
+    autoPtr<globalIndex> globalPointsPtr(new globalIndex(nMasters));
 
-    forAll(masterPoints, i)
-    {
-        label coupledPointI = masterPoints[i];
+    //Pout<< "Patch:" << nl
+    //    << "    points:" << meshPoints.size() << nl
+    //    << "    of which on coupled patch:" << nCoupled << nl
+    //    << "    of which master:" << nMasters << endl;
 
-        // Allocate global point
-        label globalI = globalPointsPtr().toGlobal(nMaster);
-        if (coupledToPatch[coupledPointI] != -1)
+
+
+    // Push back compact numbering for master point onto slaves
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    pointToGlobal.setSize(meshPoints.size());
+    pointToGlobal = -1;
+    uniqueMeshPoints.setSize(nMasters);
+
+    // Sync master in global point numbering so all know the master point.
+    // Initialise globalMaster to be -1 except at a globalMaster.
+    labelList globalMaster(cpp.nPoints(), -1);
+
+    nMasters = 0;
+    forAll(meshPoints, patchPointI)
+    {
+        if (patchToCoupled[patchPointI] == -1)
         {
-            pointToGlobal[coupledToPatch[coupledPointI]] = globalI;
+            uniqueMeshPoints[nMasters++] = meshPoints[patchPointI];
         }
-        uniqueMeshPoints[nMaster] = cpp.meshPoints()[coupledPointI];
-        nMaster++;
-
-        // Put global into slave slots
-        const labelList& slaves = pointSlaves[coupledPointI];
-        masterToGlobal[coupledPointI] = globalI;    // not really necessary
-        forAll(slaves, i)
+        else
         {
-            masterToGlobal[slaves[i]] = globalI;
+            label coupledPointI = patchToCoupled[patchPointI];
+            if
+            (
+                globalPPoints.toGlobal(patchPointI)
+             == coupledToGlobalPatch[coupledPointI]
+            )
+            {
+                globalMaster[coupledPointI] =
+                    globalPointsPtr().toGlobal(nMasters);
+                uniqueMeshPoints[nMasters++] = meshPoints[patchPointI];
+            }
         }
     }
 
 
-    if (nMaster != myUniquePoints)
-    {
-        FatalErrorIn("globalMeshData::mergePoints(..)")
-            << "problem." << abort(FatalError);
-    }
-
+    // Sync by taking max
+    syncData
+    (
+        globalMaster,
+        pointSlaves,
+        labelListList(cpp.nPoints()),   // no transforms
+        pointSlavesMap,
+        maxEqOp<label>()
+    );
 
-    // Send back (from slave slots) to originating processor
-    pointSlavesMap.reverseDistribute(cpp.nPoints(), masterToGlobal);
 
-    // On slaves take over global number
-    forAll(patchToCoupled, patchPointI)
+    // Now everyone has the master point in globalPointsPtr numbering. Fill
+    // in the pointToGlobal map.
+    nMasters = 0;
+    forAll(meshPoints, patchPointI)
     {
-        label coupledPointI = patchToCoupled[patchPointI];
-
-        if (coupledPointI != -1)
+        if (patchToCoupled[patchPointI] == -1)
+        {
+            pointToGlobal[patchPointI] = globalPointsPtr().toGlobal(nMasters++);
+        }
+        else
         {
-            const labelList& slaves = pointSlaves[coupledPointI];
+            label coupledPointI = patchToCoupled[patchPointI];
+            pointToGlobal[patchPointI] = globalMaster[coupledPointI];
 
-            if (slaves.size() == 0)
+            if
+            (
+                globalPPoints.toGlobal(patchPointI)
+             == coupledToGlobalPatch[coupledPointI]
+            )
             {
-                pointToGlobal[patchPointI] = masterToGlobal[coupledPointI];
+                nMasters++;
             }
         }
     }
 
-
     return globalPointsPtr;
 }
 
diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.H b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.H
index 2a58bbbb2159d909e0303b954e5720cf7a14640a..8e9ab332143756ba8f63b551e029c35bc090bb97 100644
--- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.H
+++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.H
@@ -202,7 +202,7 @@ class globalMeshData
                 globalPointTransformedBoundaryFacesPtr_;
             mutable autoPtr<mapDistribute> globalPointBoundaryFacesMapPtr_;
 
-            // Coupled point to collocated boundary cells
+            // Coupled point to boundary cells
 
             mutable autoPtr<labelList> boundaryCellsPtr_;
             mutable autoPtr<globalIndex> globalBoundaryCellNumberingPtr_;
@@ -212,6 +212,12 @@ class globalMeshData
             mutable autoPtr<mapDistribute> globalPointBoundaryCellsMapPtr_;
 
 
+            // Other: coupled point to coupled COLLOCATED points
+            mutable autoPtr<labelListList> globalCoPointSlavesPtr_;
+            mutable autoPtr<mapDistribute> globalCoPointSlavesMapPtr_;
+
+
+
         // Globally shared point addressing
 
             //- Total number of global points
@@ -303,6 +309,18 @@ class globalMeshData
             //- Calculate global point to global boundary cell addressing.
             void calcGlobalPointBoundaryCells() const;
 
+        // Other
+
+            // Point to collocated points. Note that not all points on
+            // coupled patches now have a master! (since points on either
+            // side of a cyclic are not connected). So check whether the map
+            // reaches all points and decide who is master, slave and who is
+            // its own master. Maybe store as well?
+
+            void calcGlobalCoPointSlaves() const;
+            const labelListList& globalCoPointSlaves() const;
+            const mapDistribute& globalCoPointSlavesMap() const;
+
 
         //- Disallow default bitwise copy construct
         globalMeshData(const globalMeshData&);
@@ -547,7 +565,7 @@ public:
 
             // Other
 
-                //- Helper for merging mesh point data.
+                //- Helper for merging (collocated!) mesh point data.
                 //  Determines:
                 //  - my unique indices
                 //  - global numbering over all unique indices
@@ -559,11 +577,11 @@ public:
                     labelList& uniquePoints
                 ) const;
 
-                //- Helper for merging patch point data.
+                //- Helper for merging (collocated!) patch point data.
                 //  Takes maps from:
                 //  local points to/from mesh. Determines
-                //  - my unique points. These are mesh points, not patch points
-                //    since the master might not be on the patch.
+                //  - my unique points. These are mesh point indices, not patch
+                //    point indices.
                 //  - global numbering over all unique indices.
                 //  - the global number for all local points.
                 autoPtr<globalIndex> mergePoints
diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalPoints.C b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalPoints.C
index 96895ff92d1f9e30e521f4210bb933bd745af3a5..cb5f86144ccc1d5a042cb4f94c97a9c76a3d7211 100644
--- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalPoints.C
+++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalPoints.C
@@ -533,7 +533,7 @@ void Foam::globalPoints::sendPatchPoints
             // Send to neighbour
             if (debug)
             {
-                Pout<< " Sending to "
+                Pout<< " Sending from " << pp.name() << " to "
                     << procPatch.neighbProcNo() << "   point information:"
                     << patchFaces.size() << endl;
             }
@@ -589,7 +589,8 @@ void Foam::globalPoints::receivePatchPoints
 
             if (debug)
             {
-                Pout<< " Received from "
+                Pout<< " On " << pp.name()
+                    << " Received from "
                     << procPatch.neighbProcNo() << "   point information:"
                     << patchFaces.size() << endl;
             }