diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files
index 392fa459985a2410f403700c3bb4e6cccea53187..4abc57669ebf212139abd71a21710d3b9fcbfc00 100644
--- a/src/meshTools/Make/files
+++ b/src/meshTools/Make/files
@@ -111,6 +111,7 @@ $(faceSources)/boundaryToFace/boundaryToFace.C
 $(faceSources)/zoneToFace/zoneToFace.C
 $(faceSources)/boxToFace/boxToFace.C
 $(faceSources)/regionToFace/regionToFace.C
+$(faceSources)/regionToFace/patchEdgeFaceRegion.C
 
 pointSources = sets/pointSources
 $(pointSources)/labelToPoint/labelToPoint.C
diff --git a/src/meshTools/sets/faceSources/regionToFace/patchEdgeFaceRegion.C b/src/meshTools/sets/faceSources/regionToFace/patchEdgeFaceRegion.C
new file mode 100644
index 0000000000000000000000000000000000000000..91e9b4c331919fd0c0a6e6e4097d0801c828aacd
--- /dev/null
+++ b/src/meshTools/sets/faceSources/regionToFace/patchEdgeFaceRegion.C
@@ -0,0 +1,50 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM 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 General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "patchEdgeFaceRegion.H"
+
+// * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
+
+Foam::Ostream& Foam::operator<<
+(
+    Foam::Ostream& os,
+    const Foam::patchEdgeFaceRegion& wDist
+)
+{
+    return os << wDist.region_;
+}
+
+
+Foam::Istream& Foam::operator>>
+(
+    Foam::Istream& is,
+    Foam::patchEdgeFaceRegion& wDist
+)
+{
+    return is >> wDist.region_;
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/sets/faceSources/regionToFace/patchEdgeFaceRegion.H b/src/meshTools/sets/faceSources/regionToFace/patchEdgeFaceRegion.H
new file mode 100644
index 0000000000000000000000000000000000000000..6c0b65f2d7525a2c6cdeb490978dac48dd88c824
--- /dev/null
+++ b/src/meshTools/sets/faceSources/regionToFace/patchEdgeFaceRegion.H
@@ -0,0 +1,193 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM 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 General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::patchEdgeFaceRegion
+
+Description
+    Transport of region for use in PatchEdgeFaceWave.
+
+    Set element to -2 to denote blocked.
+
+SourceFiles
+    patchEdgeFaceRegionI.H
+    patchEdgeFaceRegion.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef patchEdgeFaceRegion_H
+#define patchEdgeFaceRegion_H
+
+#include "point.H"
+#include "label.H"
+#include "scalar.H"
+#include "tensor.H"
+#include "indirectPrimitivePatch.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declaration of classes
+class polyPatch;
+class polyMesh;
+
+/*---------------------------------------------------------------------------*\
+                           Class patchEdgeFaceRegion Declaration
+\*---------------------------------------------------------------------------*/
+
+class patchEdgeFaceRegion
+{
+    // Private data
+
+        //- region
+        label region_;
+
+    // Private Member Functions
+
+        //- Combine current with w2. Update region_ if w2 has smaller
+        //  quantities and returns true.
+        template<class TrackingData>
+        inline bool update
+        (
+            const patchEdgeFaceRegion& w2,
+            const scalar tol,
+            TrackingData& td
+        );
+
+
+public:
+
+    // Constructors
+
+        //- Construct null
+        inline patchEdgeFaceRegion();
+
+        //- Construct from origin, distance
+        inline patchEdgeFaceRegion(const label);
+
+
+    // Member Functions
+
+        // Access
+
+            inline label region() const;
+
+
+        // Needed by meshWave
+
+            //- Check whether origin has been changed at all or
+            //  still contains original (invalid) value.
+            template<class TrackingData>
+            inline bool valid(TrackingData& td) const;
+
+            //- Apply rotation matrix
+            template<class TrackingData>
+            inline void transform
+            (
+                const polyMesh& mesh,
+                const indirectPrimitivePatch& patch,
+                const tensor& rotTensor,
+                const scalar tol,
+                TrackingData& td
+            );
+
+            //- Influence of face on edge
+            template<class TrackingData>
+            inline bool updateEdge
+            (
+                const polyMesh& mesh,
+                const indirectPrimitivePatch& patch,
+                const label edgeI,
+                const label faceI,
+                const patchEdgeFaceRegion& faceInfo,
+                const scalar tol,
+                TrackingData& td
+            );
+
+            //- New information for edge (from e.g. coupled edge)
+            template<class TrackingData>
+            inline bool updateEdge
+            (
+                const polyMesh& mesh,
+                const indirectPrimitivePatch& patch,
+                const patchEdgeFaceRegion& edgeInfo,
+                const bool sameOrientation,
+                const scalar tol,
+                TrackingData& td
+            );
+
+            //- Influence of edge on face.
+            template<class TrackingData>
+            inline bool updateFace
+            (
+                const polyMesh& mesh,
+                const indirectPrimitivePatch& patch,
+                const label faceI,
+                const label edgeI,
+                const patchEdgeFaceRegion& edgeInfo,
+                const scalar tol,
+                TrackingData& td
+            );
+
+            //- Same (like operator==)
+            template<class TrackingData>
+            inline bool equal(const patchEdgeFaceRegion&, TrackingData&) const;
+
+
+    // Member Operators
+
+        // Needed for List IO
+        inline bool operator==(const patchEdgeFaceRegion&) const;
+        inline bool operator!=(const patchEdgeFaceRegion&) const;
+
+
+    // IOstream Operators
+
+        friend Ostream& operator<<(Ostream&, const patchEdgeFaceRegion&);
+        friend Istream& operator>>(Istream&, patchEdgeFaceRegion&);
+};
+
+
+//- Data associated with patchEdgeFaceRegion type are contiguous
+template<>
+inline bool contiguous<patchEdgeFaceRegion>()
+{
+    return true;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "patchEdgeFaceRegionI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/meshTools/sets/faceSources/regionToFace/patchEdgeFaceRegionI.H b/src/meshTools/sets/faceSources/regionToFace/patchEdgeFaceRegionI.H
new file mode 100644
index 0000000000000000000000000000000000000000..60a6d13eb3f2797a2884162008f6841f697f4093
--- /dev/null
+++ b/src/meshTools/sets/faceSources/regionToFace/patchEdgeFaceRegionI.H
@@ -0,0 +1,209 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM 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 General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "polyMesh.H"
+#include "transform.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+// Update this with w2 if w2 nearer to pt.
+template<class TrackingData>
+inline bool Foam::patchEdgeFaceRegion::update
+(
+    const patchEdgeFaceRegion& w2,
+    const scalar tol,
+    TrackingData& td
+)
+{
+    if (!w2.valid(td))
+    {
+        FatalErrorIn("patchEdgeFaceRegion::update(..)")
+            << "problem." << abort(FatalError);
+    }
+
+    if (w2.region_ == -2 || region_ == -2)
+    {
+
+Pout<< "update : " << *this << "   w2:" << w2 << " return FALSE" << endl;
+
+        // Blocked edge/face
+        return false;
+    }
+
+    if (!valid(td))
+    {
+        // current not yet set so use any value
+        label oldRegion = region_;
+        operator=(w2);
+Pout<< "update : " << *this << " was:" << oldRegion
+    << "   w2:" << w2 << " return TRUE" << endl;
+        return true;
+    }
+    else
+    {
+        if (w2.region_ < region_)
+        {
+            label oldRegion = region_;
+            operator=(w2);
+Pout<< "update : " << *this << " was:" << oldRegion
+    << "   w2:" << w2 << " return TRUE" << endl;
+        return true;
+            return true;
+        }
+        else
+        {
+Pout<< "update : " << *this
+    << "   w2:" << w2 << " return FALSE" << endl;
+            return false;
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+// Null constructor
+inline Foam::patchEdgeFaceRegion::patchEdgeFaceRegion()
+:
+    region_(-1)
+{}
+
+
+// Construct from origin, distance
+inline Foam::patchEdgeFaceRegion::patchEdgeFaceRegion
+(
+    const label region
+)
+:
+    region_(region)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+inline Foam::label Foam::patchEdgeFaceRegion::region() const
+{
+    return region_;
+}
+
+
+template<class TrackingData>
+inline bool Foam::patchEdgeFaceRegion::valid(TrackingData& td) const
+{
+    return region_ != -1;
+}
+
+
+template<class TrackingData>
+inline void Foam::patchEdgeFaceRegion::transform
+(
+    const polyMesh& mesh,
+    const indirectPrimitivePatch& patch,
+    const tensor& rotTensor,
+    const scalar tol,
+    TrackingData& td
+)
+{}
+
+
+template<class TrackingData>
+inline bool Foam::patchEdgeFaceRegion::updateEdge
+(
+    const polyMesh& mesh,
+    const indirectPrimitivePatch& patch,
+    const label edgeI,
+    const label faceI,
+    const patchEdgeFaceRegion& faceInfo,
+    const scalar tol,
+    TrackingData& td
+)
+{
+    return update(faceInfo, tol, td);
+}
+
+
+template<class TrackingData>
+inline bool Foam::patchEdgeFaceRegion::updateEdge
+(
+    const polyMesh& mesh,
+    const indirectPrimitivePatch& patch,
+    const patchEdgeFaceRegion& edgeInfo,
+    const bool sameOrientation,
+    const scalar tol,
+    TrackingData& td
+)
+{
+    return update(edgeInfo, tol, td);
+}
+
+
+template<class TrackingData>
+inline bool Foam::patchEdgeFaceRegion::updateFace
+(
+    const polyMesh& mesh,
+    const indirectPrimitivePatch& patch,
+    const label faceI,
+    const label edgeI,
+    const patchEdgeFaceRegion& edgeInfo,
+    const scalar tol,
+    TrackingData& td
+)
+{
+    return update(edgeInfo, tol, td);
+}
+
+
+template <class TrackingData>
+inline bool Foam::patchEdgeFaceRegion::equal
+(
+    const patchEdgeFaceRegion& rhs,
+    TrackingData& td
+) const
+{
+    return operator==(rhs);
+}
+
+
+// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
+
+inline bool Foam::patchEdgeFaceRegion::operator==
+(
+    const Foam::patchEdgeFaceRegion& rhs
+) const
+{
+    return region() == rhs.region();
+}
+
+
+inline bool Foam::patchEdgeFaceRegion::operator!=
+(
+    const Foam::patchEdgeFaceRegion& rhs
+) const
+{
+    return !(*this == rhs);
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/sets/faceSources/regionToFace/regionToFace.C b/src/meshTools/sets/faceSources/regionToFace/regionToFace.C
index 20182eb7f5c2120ea6ffa6ae33c1704c96a7dec5..5c5f538876becc47012933bfb83376e11eb1d45f 100644
--- a/src/meshTools/sets/faceSources/regionToFace/regionToFace.C
+++ b/src/meshTools/sets/faceSources/regionToFace/regionToFace.C
@@ -30,6 +30,8 @@ License
 #include "indirectPrimitivePatch.H"
 #include "PatchTools.H"
 #include "addToRunTimeSelectionTable.H"
+#include "PatchEdgeFaceWave.H"
+#include "patchEdgeFaceRegion.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -56,69 +58,6 @@ Foam::topoSetSource::addToUsageTable Foam::regionToFace::usage_
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-// Synchronise edges
-void Foam::regionToFace::syncEdges
-(
-    const labelList& patchEdges,
-    const labelList& coupledEdges,
-    const bool syncNonCollocated,
-
-    PackedBoolList& isChangedEdge,
-    DynamicList<label>& changedEdges,
-    labelList& allEdgeData
-) const
-{
-    const globalMeshData& globalData = mesh_.globalData();
-    const mapDistribute& map = globalData.globalEdgeSlavesMap();
-
-    // Convert patch-edge data into cpp-edge data
-    labelList cppEdgeData(map.constructSize(), labelMax);
-
-    forAll(patchEdges, i)
-    {
-        label patchEdgeI = patchEdges[i];
-        label coupledEdgeI = coupledEdges[i];
-
-        if (isChangedEdge[patchEdgeI])
-        {
-            cppEdgeData[coupledEdgeI] = allEdgeData[patchEdgeI];
-        }
-    }
-
-    // Synchronise
-    globalData.syncData
-    (
-        cppEdgeData,
-        globalData.globalEdgeSlaves(),
-        (
-            syncNonCollocated
-          ? globalData.globalEdgeTransformedSlaves()    // transformed elems
-          : labelListList(globalData.globalEdgeSlaves().size()) //no transformed
-        ),
-        map,
-        minEqOp<label>()
-    );
-
-    // Back from cpp-edge to patch-edge data
-    forAll(patchEdges, i)
-    {
-        label patchEdgeI = patchEdges[i];
-        label coupledEdgeI = coupledEdges[i];
-
-        if (cppEdgeData[coupledEdgeI] != labelMax)
-        {
-            allEdgeData[patchEdgeI] = cppEdgeData[coupledEdgeI];
-
-            if (!isChangedEdge[patchEdgeI])
-            {
-                changedEdges.append(patchEdgeI);
-                isChangedEdge[patchEdgeI] = true;
-            }
-        }
-    }
-}
-
-
 void Foam::regionToFace::markZone
 (
     const indirectPrimitivePatch& patch,
@@ -128,130 +67,44 @@ void Foam::regionToFace::markZone
     labelList& faceZone
 ) const
 {
-    // Calculate correspondence between patch and globalData.coupledPatch.
-    labelList patchEdges;
-    labelList coupledEdges;
-    PackedBoolList sameEdgeOrientation;
-    PatchTools::matchEdges
-    (
-        mesh_.globalData().coupledPatch(),
-        patch,
-
-        coupledEdges,
-        patchEdges,
-        sameEdgeOrientation
-    );
-
-
-    DynamicList<label> changedEdges(patch.nEdges());
-    labelList allEdgeData(patch.nEdges(), -1);
-    PackedBoolList isChangedEdge(patch.nEdges());
+    // Data on all edges and faces
+    List<patchEdgeFaceRegion> allEdgeInfo(patch.nEdges());
+    List<patchEdgeFaceRegion> allFaceInfo(patch.size());
 
-
-    // Fill initial seed
-    // ~~~~~~~~~~~~~~~~~
+    DynamicList<label> changedEdges;
+    DynamicList<patchEdgeFaceRegion> changedInfo;
 
     if (Pstream::myProcNo() == procI)
     {
         const labelList& fEdges = patch.faceEdges()[faceI];
         forAll(fEdges, i)
         {
-            label edgeI = fEdges[i];
-            if (!isChangedEdge[edgeI])
-            {
-                allEdgeData[edgeI] = zoneI;
-                changedEdges.append(edgeI);
-                isChangedEdge[edgeI] = true;
-            }
+            changedEdges.append(fEdges[i]);
+            changedInfo.append(zoneI);
         }
     }
 
-    syncEdges
+    // Walk
+    PatchEdgeFaceWave
+    <
+        indirectPrimitivePatch,
+        patchEdgeFaceRegion
+    > calc
     (
-        patchEdges,
-        coupledEdges,
-        true,               //syncNonCollocated,
-
-        isChangedEdge,
+        mesh_,
+        patch,
         changedEdges,
-        allEdgeData
+        changedInfo,
+        allEdgeInfo,
+        allFaceInfo,
+        returnReduce(patch.nEdges(), sumOp<label>())
     );
 
-
-    // Edge-Face-Edge walk across patch
-    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    while (true)
+    forAll(allFaceInfo, faceI)
     {
-        // From edge to face
-        // ~~~~~~~~~~~~~~~~~
-
-        DynamicList<label> changedFaces(patch.size());
-
-        forAll(changedEdges, changedI)
-        {
-            label edgeI = changedEdges[changedI];
-            const labelList& eFaces = patch.edgeFaces()[edgeI];
-
-            forAll(eFaces, i)
-            {
-                label faceI = eFaces[i];
-
-                if (faceZone[faceI] == -1)
-                {
-                    faceZone[faceI] = zoneI;
-                    changedFaces.append(faceI);
-                }
-            }
-        }
-
-
-        label nChangedFaces = returnReduce(changedFaces.size(), sumOp<label>());
-        if (nChangedFaces == 0)
-        {
-            break;
-        }
-
-
-        // From face to edge
-        // ~~~~~~~~~~~~~~~~~
-
-        isChangedEdge = false;
-        changedEdges.clear();
-
-        forAll(changedFaces, i)
-        {
-            label faceI = changedFaces[i];
-            const labelList& fEdges = patch.faceEdges()[faceI];
-
-            forAll(fEdges, fp)
-            {
-                label edgeI = fEdges[fp];
-
-                if (!isChangedEdge[edgeI])
-                {
-                    allEdgeData[edgeI] = zoneI;
-                    changedEdges.append(edgeI);
-                    isChangedEdge[edgeI] = true;
-                }
-            }
-        }
-
-        syncEdges
-        (
-            patchEdges,
-            coupledEdges,
-            true,               //syncNonCollocated,
-
-            isChangedEdge,
-            changedEdges,
-            allEdgeData
-        );
-
-        label nChangedEdges = returnReduce(changedEdges.size(), sumOp<label>());
-        if (nChangedEdges == 0)
+        if (allFaceInfo[faceI].region() == zoneI)
         {
-            break;
+            faceZone[faceI] = zoneI;
         }
     }
 }
diff --git a/src/meshTools/sets/faceSources/regionToFace/regionToFace.H b/src/meshTools/sets/faceSources/regionToFace/regionToFace.H
index e4352792bb8e0849a15f12cc07398c15952e2fb4..1dc1d48069ff74a2311ed47de996498a5f971c7f 100644
--- a/src/meshTools/sets/faceSources/regionToFace/regionToFace.H
+++ b/src/meshTools/sets/faceSources/regionToFace/regionToFace.H
@@ -66,18 +66,6 @@ class regionToFace
 
     // Private Member Functions
 
-        //- Sync patch edges
-        void syncEdges
-        (
-            const labelList& patchEdges,
-            const labelList& coupledEdges,
-            const bool syncNonCollocated,
-
-            PackedBoolList& isChangedEdge,
-            DynamicList<label>& changedEdges,
-            labelList& allEdgeData
-        ) const;
-
         //- Walk edge-face-edge
         void markZone
         (