diff --git a/applications/solvers/compressible/rhoPimpleFoam/rhoPimpleFoam.C b/applications/solvers/compressible/rhoPimpleFoam/rhoPimpleFoam.C
index 9b09d73bbe9bc53c4394e24a7d99abb6812ad4dc..858d83749e9a93f70bb6c6fd554483ae1e8123f4 100644
--- a/applications/solvers/compressible/rhoPimpleFoam/rhoPimpleFoam.C
+++ b/applications/solvers/compressible/rhoPimpleFoam/rhoPimpleFoam.C
@@ -23,7 +23,7 @@ License
     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
 Application
-    rhoSimpleFoam
+    rhoPimpleFoam
 
 Description
     Transient solver for turbulent flow of compressible fluids for
diff --git a/applications/solvers/incompressible/pimpleFoam/Make/files b/applications/solvers/incompressible/pimpleFoam/Make/files
index 92943d3370c977025c7cdfee1e8681f06631655b..f4ec4391dfc36960fa2c8d2657ce63cddc6eac7f 100644
--- a/applications/solvers/incompressible/pimpleFoam/Make/files
+++ b/applications/solvers/incompressible/pimpleFoam/Make/files
@@ -1,3 +1,3 @@
 pimpleFoam.C
 
-EXE = $(FOAM_USER_APPBIN)/pimpleFoam
+EXE = $(FOAM_APPBIN)/pimpleFoam
diff --git a/applications/test/speed/Make/options b/applications/test/speed/Make/options
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e68056198750cebb50fea02c6fffbf8db9220261 100644
--- a/applications/test/speed/Make/options
+++ b/applications/test/speed/Make/options
@@ -0,0 +1 @@
+EXE_INC = /* -ffast-math -mtune=core2 */
diff --git a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
index 1df11e06da1770d31a921d349cf9a0d863297d1c..4737f38e53891198aff84081b08d7ab963f80c1d 100644
--- a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
+++ b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
@@ -370,7 +370,7 @@ int main(int argc, char *argv[])
         // Refinement parameters
         refinementParameters refineParams(refineDict);
 
-        refineDriver.doRefine(refineDict, refineParams, wantSnap);
+        refineDriver.doRefine(refineDict, refineParams, wantSnap, motionDict);
 
         writeMesh
         (
diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C
index 48f52d7880cebe3c905afc26e752479af6991fd9..c07b950d0a6344fbd2e37b1c19bb16695efceb37 100644
--- a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C
+++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C
@@ -491,6 +491,8 @@ void Foam::autoHexMeshDriver::doMesh()
 
     if (wantRefine)
     {
+        const dictionary& motionDict = dict_.subDict("motionDict");
+
         autoRefineDriver refineDriver
         (
             meshRefinerPtr_(),
@@ -502,7 +504,7 @@ void Foam::autoHexMeshDriver::doMesh()
         // Get all the refinement specific params
         refinementParameters refineParams(dict_, 1);
 
-        refineDriver.doRefine(dict_, refineParams, wantSnap);
+        refineDriver.doRefine(dict_, refineParams, wantSnap, motionDict);
 
         // Write mesh
         writeMesh("Refined mesh");
diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.C b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.C
index 7bbe58ff8f9d5575fbb1a341e11e455056d29272..ca0c0cbddc8c7704d675e3e77af2f2fd3966da43 100644
--- a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.C
+++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.C
@@ -497,7 +497,8 @@ Foam::label Foam::autoRefineDriver::shellRefine
 void Foam::autoRefineDriver::baffleAndSplitMesh
 (
     const refinementParameters& refineParams,
-    const bool handleSnapProblems
+    const bool handleSnapProblems,
+    const dictionary& motionDict
 )
 {
     Info<< nl
@@ -514,6 +515,7 @@ void Foam::autoRefineDriver::baffleAndSplitMesh
     (
         handleSnapProblems,
         !handleSnapProblems,            // merge free standing baffles?
+        motionDict,
         const_cast<Time&>(mesh.time()),
         globalToPatch_,
         refineParams.keepPoints()[0]
@@ -568,7 +570,8 @@ void Foam::autoRefineDriver::zonify
 void Foam::autoRefineDriver::splitAndMergeBaffles
 (
     const refinementParameters& refineParams,
-    const bool handleSnapProblems
+    const bool handleSnapProblems,
+    const dictionary& motionDict
 )
 {
     Info<< nl
@@ -588,6 +591,7 @@ void Foam::autoRefineDriver::splitAndMergeBaffles
     (
         handleSnapProblems,
         false,                  // merge free standing baffles?
+        motionDict,
         const_cast<Time&>(mesh.time()),
         globalToPatch_,
         refineParams.keepPoints()[0]
@@ -685,7 +689,8 @@ void Foam::autoRefineDriver::doRefine
 (
     const dictionary& refineDict,
     const refinementParameters& refineParams,
-    const bool prepareForSnapping
+    const bool prepareForSnapping,
+    const dictionary& motionDict
 )
 {
     Info<< nl
@@ -734,13 +739,13 @@ void Foam::autoRefineDriver::doRefine
     );
 
     // Introduce baffles at surface intersections
-    baffleAndSplitMesh(refineParams, prepareForSnapping);
+    baffleAndSplitMesh(refineParams, prepareForSnapping, motionDict);
 
     // Mesh is at its finest. Do optional zoning.
     zonify(refineParams);
 
     // Pull baffles apart
-    splitAndMergeBaffles(refineParams, prepareForSnapping);
+    splitAndMergeBaffles(refineParams, prepareForSnapping, motionDict);
 
     // Do something about cells with refined faces on the boundary
     if (prepareForSnapping)
diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.H b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.H
index 8aa33855def83c7c8cade6f4fa9abbaf202b0ba5..f1747a29be73c02ef6754edb2638eb7d6b0d256d 100644
--- a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.H
+++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.H
@@ -46,7 +46,6 @@ namespace Foam
 class featureEdgeMesh;
 class refinementParameters;
 
-
 /*---------------------------------------------------------------------------*\
                            Class autoRefineDriver Declaration
 \*---------------------------------------------------------------------------*/
@@ -112,7 +111,8 @@ class autoRefineDriver
         void baffleAndSplitMesh
         (
             const refinementParameters& refineParams,
-            const bool handleSnapProblems
+            const bool handleSnapProblems,
+            const dictionary& motionDict
         );
 
         //- Add zones
@@ -121,7 +121,8 @@ class autoRefineDriver
         void splitAndMergeBaffles
         (
             const refinementParameters& refineParams,
-            const bool handleSnapProblems
+            const bool handleSnapProblems,
+            const dictionary& motionDict
         );
 
         //- Merge refined boundary faces (from exposing coarser cell)
@@ -163,7 +164,8 @@ public:
         (
             const dictionary& refineDict,
             const refinementParameters& refineParams,
-            const bool prepareForSnapping
+            const bool prepareForSnapping,
+            const dictionary& motionDict
         );
 };
 
diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.C b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.C
index cc866d13ca4df0e004c8caae0e2642dcae1d25b6..520e6f69efc28dfc174b2a52e86b6773dfe75b1e 100644
--- a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.C
+++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.C
@@ -1294,6 +1294,169 @@ void Foam::autoSnapDriver::scaleMesh
 }
 
 
+// After snapping: correct patching according to nearest surface.
+// Code is very similar to calcNearestSurface.
+// - calculate face-wise snap distance as max of point-wise
+// - calculate face-wise nearest surface point
+// - repatch face according to patch for surface point.
+Foam::autoPtr<Foam::mapPolyMesh> Foam::autoSnapDriver::repatchToSurface
+(
+    const snapParameters& snapParams,
+    const labelList& adaptPatchIDs
+)
+{
+    const fvMesh& mesh = meshRefiner_.mesh();
+    const refinementSurfaces& surfaces = meshRefiner_.surfaces();
+
+    Info<< "Repatching faces according to nearest surface ..." << endl;
+
+    // Get the labels of added patches.
+    autoPtr<indirectPrimitivePatch> ppPtr
+    (
+        meshRefinement::makePatch
+        (
+            mesh,
+            adaptPatchIDs
+        )
+    );
+    indirectPrimitivePatch& pp = ppPtr();
+
+    // Divide surfaces into zoned and unzoned
+    labelList zonedSurfaces;
+    labelList unzonedSurfaces;
+    getZonedSurfaces(zonedSurfaces, unzonedSurfaces);
+
+
+    // Faces that do not move
+    PackedList<1> isZonedFace(mesh.nFaces(), 0);
+    {
+        // 1. All faces on zoned surfaces
+        const wordList& faceZoneNames = surfaces.faceZoneNames();
+        const faceZoneMesh& fZones = mesh.faceZones();
+
+        forAll(zonedSurfaces, i)
+        {
+            label zoneSurfI = zonedSurfaces[i];
+
+            label zoneI = fZones.findZoneID(faceZoneNames[zoneSurfI]);
+
+            const faceZone& fZone = fZones[zoneI];
+
+            forAll(fZone, i)
+            {
+                isZonedFace.set(fZone[i], 1);
+            }  
+        }
+    }
+
+
+    // Determine per pp face which patch it should be in
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    // Patch that face should be in
+    labelList closestPatch(pp.size(), -1);
+    {
+        // face snap distance as max of point snap distance
+        scalarField faceSnapDist(pp.size(), -GREAT);
+        {
+            // Distance to attract to nearest feature on surface
+            const scalarField snapDist(calcSnapDistance(snapParams, pp));
+
+            const faceList& localFaces = pp.localFaces();
+
+            forAll(localFaces, faceI)
+            {
+                const face& f = localFaces[faceI];
+
+                forAll(f, fp)
+                {
+                    faceSnapDist[faceI] = max
+                    (
+                        faceSnapDist[faceI],
+                        snapDist[f[fp]]
+                    );
+                }
+            }
+        }
+
+        pointField localFaceCentres(pp.size());
+        forAll(pp, i)
+        {
+            localFaceCentres[i] = mesh.faceCentres()[pp.addressing()[i]];
+        }
+
+        // Get nearest surface and region
+        labelList hitSurface;
+        labelList hitRegion;
+        surfaces.findNearestRegion
+        (
+            unzonedSurfaces,
+            localFaceCentres,
+            sqr(4*faceSnapDist),    // sqr of attract distance
+            hitSurface,
+            hitRegion
+        );
+
+        // Get patch
+        forAll(pp, i)
+        {
+            label faceI = pp.addressing()[i];
+
+            if (hitSurface[i] != -1 && (isZonedFace.get(faceI) == 0))
+            {
+                closestPatch[i] = globalToPatch_
+                [
+                    surfaces.globalRegion
+                    (
+                        hitSurface[i],
+                        hitRegion[i]
+                    )
+                ];
+            }
+        }
+    }
+
+
+    // Change those faces for which there is a different closest patch
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    labelList ownPatch(mesh.nFaces(), -1);
+    labelList neiPatch(mesh.nFaces(), -1);
+
+    const polyBoundaryMesh& patches = mesh.boundaryMesh();
+
+    forAll(patches, patchI)
+    {
+        const polyPatch& pp = patches[patchI];
+
+        forAll(pp, i)
+        {
+            ownPatch[pp.start()+i] = patchI;
+            neiPatch[pp.start()+i] = patchI;
+        }
+    }
+
+    label nChanged = 0;
+    forAll(closestPatch, i)
+    {
+        label faceI = pp.addressing()[i];
+
+        if (closestPatch[i] != -1 && closestPatch[i] != ownPatch[faceI])
+        {
+            ownPatch[faceI] = closestPatch[i];
+            neiPatch[faceI] = closestPatch[i];
+            nChanged++;
+        }
+    }
+
+    Info<< "Repatched " << returnReduce(nChanged, sumOp<label>())
+        << " faces in = " << mesh.time().cpuTimeIncrement() << " s\n" << nl
+        << endl;
+
+    return meshRefiner_.createBaffles(ownPatch, neiPatch);
+}
+
+
 void Foam::autoSnapDriver::doSnap
 (
     const dictionary& snapDict,
@@ -1329,7 +1492,7 @@ void Foam::autoSnapDriver::doSnap
         );
         indirectPrimitivePatch& pp = ppPtr();
 
-        // Distance to attact to nearest feature on surface
+        // Distance to attract to nearest feature on surface
         const scalarField snapDist(calcSnapDistance(snapParams, pp));
 
 
@@ -1383,6 +1546,9 @@ void Foam::autoSnapDriver::doSnap
 
     // Merge any introduced baffles.
     mergeZoneBaffles(baffles);
+
+    // Repatch faces according to nearest.
+    repatchToSurface(snapParams, adaptPatchIDs);
 }
 
 
diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.H b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.H
index 82cf448b98ae6b506fea1bf81bc16f2bd17e5dd7..1604e358593d6bab3969820c9a5af5ee2b8b36f0 100644
--- a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.H
+++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.H
@@ -215,6 +215,14 @@ public:
                 motionSmoother&
             );
 
+            //- Repatch faces according to surface nearest the face centre
+            autoPtr<mapPolyMesh> repatchToSurface
+            (
+                const snapParameters& snapParams,
+                const labelList& adaptPatchIDs
+            );
+
+
             void doSnap
             (
                 const dictionary& snapDict,
diff --git a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.C b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.C
index 4fe3005766f4f224c2fd219d7f27451d6a4fa290..7f5bc29a796e40d24048ae89155c0edfec971f24 100644
--- a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.C
+++ b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.C
@@ -50,6 +50,7 @@ License
 #include "globalIndex.H"
 #include "meshTools.H"
 #include "OFstream.H"
+#include "geomDecomp.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -426,15 +427,14 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::doRemoveCells
 
 // Determine for multi-processor regions the lowest numbered cell on the lowest
 // numbered processor.
-void Foam::meshRefinement::getRegionMaster
+void Foam::meshRefinement::getCoupledRegionMaster
 (
+    const globalIndex& globalCells,
     const boolList& blockedFace,
     const regionSplit& globalRegion,
     Map<label>& regionToMaster
 ) const
 {
-    globalIndex globalCells(mesh_.nCells());
-
     const polyBoundaryMesh& patches = mesh_.boundaryMesh();
 
     forAll(patches, patchI)
@@ -483,6 +483,274 @@ void Foam::meshRefinement::getRegionMaster
 }
 
 
+void Foam::meshRefinement::calcLocalRegions
+(
+    const globalIndex& globalCells,
+    const labelList& globalRegion,
+    const Map<label>& coupledRegionToMaster,
+
+    Map<label>& globalToLocalRegion,
+    pointField& localPoints
+) const
+{
+    globalToLocalRegion.resize(globalRegion.size());
+    DynamicList<point> localCc(globalRegion.size()/2);
+
+    forAll(globalRegion, cellI)
+    {
+        Map<label>::const_iterator fndMaster =
+            coupledRegionToMaster.find(globalRegion[cellI]);
+
+        if (fndMaster != coupledRegionToMaster.end())
+        {
+            // Multi-processor region.
+            if (globalCells.toGlobal(cellI) == fndMaster())
+            {
+                // I am master. Allocate region for me.
+                globalToLocalRegion.insert(globalRegion[cellI], localCc.size());
+                localCc.append(mesh_.cellCentres()[cellI]);
+            }
+        }
+        else
+        {
+            // Single processor region.
+            if (globalToLocalRegion.insert(globalRegion[cellI], localCc.size()))
+            {
+                localCc.append(mesh_.cellCentres()[cellI]);
+            }
+        }
+    }
+    localCc.shrink();
+    localPoints.transfer(localCc);
+
+    if (localPoints.size() != globalToLocalRegion.size())
+    {
+        FatalErrorIn("calcLocalRegions(..)")
+            << "localPoints:" << localPoints.size()
+            << " globalToLocalRegion:" << globalToLocalRegion.size()
+            << exit(FatalError);
+    }
+}
+
+
+Foam::label Foam::meshRefinement::getShiftedRegion
+(
+    const globalIndex& indexer,
+    const Map<label>& globalToLocalRegion,
+    const Map<label>& coupledRegionToShifted,
+    const label globalRegion
+)
+{
+    Map<label>::const_iterator iter =
+        globalToLocalRegion.find(globalRegion);
+
+    if (iter != globalToLocalRegion.end())
+    {
+        // Region is 'owned' locally. Convert local region index into global.
+        return indexer.toGlobal(iter());
+    }
+    else
+    {
+        return coupledRegionToShifted[globalRegion];
+    }
+}
+
+
+// Add if not yet present
+void Foam::meshRefinement::addUnique(const label elem, labelList& lst)
+{
+    if (findIndex(lst, elem) == -1)
+    {
+        label sz = lst.size();
+        lst.setSize(sz+1);
+        lst[sz] = elem;
+    }
+}
+
+
+void Foam::meshRefinement::calcRegionRegions
+(
+    const labelList& globalRegion,
+    const Map<label>& globalToLocalRegion,
+    const Map<label>& coupledRegionToMaster,
+    labelListList& regionRegions
+) const
+{
+    // Global region indexing since we now know the shifted regions.
+    globalIndex shiftIndexer(globalToLocalRegion.size());
+
+    // Redo the coupledRegionToMaster to be in shifted region indexing.
+    Map<label> coupledRegionToShifted(coupledRegionToMaster.size());
+    forAllConstIter(Map<label>, coupledRegionToMaster, iter)
+    {
+        label region = iter.key();
+
+        Map<label>::const_iterator fndRegion = globalToLocalRegion.find(region);
+
+        if (fndRegion != globalToLocalRegion.end())
+        {
+            // A local cell is master of this region. Get its shifted region.
+            coupledRegionToShifted.insert
+            (
+                region,
+                shiftIndexer.toGlobal(fndRegion())
+            );
+        }
+        Pstream::mapCombineGather(coupledRegionToShifted, minEqOp<label>());
+        Pstream::mapCombineScatter(coupledRegionToShifted);
+    }
+
+
+    // Determine region-region connectivity.
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    // This is for all my regions (so my local ones or the ones I am master
+    // of) the neighbouring region indices.
+
+
+    // Transfer lists.
+    PtrList<HashSet<edge, Hash<edge> > > regionConnectivity(Pstream::nProcs());
+    forAll(regionConnectivity, procI)
+    {
+        if (procI != Pstream::myProcNo())
+        {
+            regionConnectivity.set
+            (
+                procI,
+                new HashSet<edge, Hash<edge> >
+                (
+                    coupledRegionToShifted.size()
+                  / Pstream::nProcs()
+                )
+            );
+        }
+    }
+
+
+    // Connectivity. For all my local regions the connected regions.
+    regionRegions.setSize(globalToLocalRegion.size());
+
+    // Add all local connectivity to regionRegions; add all non-local
+    // to the transferlists.
+    for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
+    {
+        label ownRegion = globalRegion[mesh_.faceOwner()[faceI]];
+        label neiRegion = globalRegion[mesh_.faceNeighbour()[faceI]];
+
+        if (ownRegion != neiRegion)
+        {
+            label shiftOwnRegion = getShiftedRegion
+            (
+                shiftIndexer,
+                globalToLocalRegion,
+                coupledRegionToShifted,
+                ownRegion
+            );
+            label shiftNeiRegion = getShiftedRegion
+            (
+                shiftIndexer,
+                globalToLocalRegion,
+                coupledRegionToShifted,
+                neiRegion
+            );
+
+
+            // Connection between two regions. Send to owner of region.
+            // - is ownRegion 'owned' by me
+            // - is neiRegion 'owned' by me
+
+            if (shiftIndexer.isLocal(shiftOwnRegion))
+            {
+                label localI = shiftIndexer.toLocal(shiftOwnRegion);
+                addUnique(shiftNeiRegion, regionRegions[localI]);
+            }
+            else
+            {
+                label masterProc = shiftIndexer.whichProcID(shiftOwnRegion);
+                regionConnectivity[masterProc].insert
+                (
+                    edge(shiftOwnRegion, shiftNeiRegion)
+                );
+            }
+
+            if (shiftIndexer.isLocal(shiftNeiRegion))
+            {
+                label localI = shiftIndexer.toLocal(shiftNeiRegion);
+                addUnique(shiftOwnRegion, regionRegions[localI]);
+            }
+            else
+            {
+                label masterProc = shiftIndexer.whichProcID(shiftNeiRegion);
+                regionConnectivity[masterProc].insert
+                (
+                    edge(shiftOwnRegion, shiftNeiRegion)
+                );
+            }
+        }
+    }
+
+
+    // Send
+    forAll(regionConnectivity, procI)
+    {
+        if (procI != Pstream::myProcNo())
+        {
+            OPstream str(Pstream::blocking, procI);
+            str << regionConnectivity[procI];
+        }
+    }
+    // Receive
+    forAll(regionConnectivity, procI)
+    {
+        if (procI != Pstream::myProcNo())
+        {
+            IPstream str(Pstream::blocking, procI);
+            str >> regionConnectivity[procI];
+        }
+    }
+
+    // Add to addressing.
+    forAll(regionConnectivity, procI)
+    {
+        if (procI != Pstream::myProcNo())
+        {
+            for
+            (
+                HashSet<edge, Hash<edge> >::const_iterator iter =
+                    regionConnectivity[procI].begin();
+                iter != regionConnectivity[procI].end();
+                ++iter
+            )
+            {
+                const edge& e = iter.key();
+
+                bool someLocal = false;
+                if (shiftIndexer.isLocal(e[0]))
+                {
+                    label localI = shiftIndexer.toLocal(e[0]);
+                    addUnique(e[1], regionRegions[localI]);
+                    someLocal = true;
+                }
+                if (shiftIndexer.isLocal(e[1]))
+                {
+                    label localI = shiftIndexer.toLocal(e[1]);
+                    addUnique(e[0], regionRegions[localI]);
+                    someLocal = true;
+                }
+
+                if (!someLocal)
+                {
+                    FatalErrorIn("calcRegionRegions(..)")
+                        << "Received from processor " << procI
+                        << " connection " << e
+                        << " where none of the elements is local to me."
+                        << abort(FatalError);
+                }
+            }
+        }
+    }
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 // Construct from components
@@ -598,88 +866,88 @@ Foam::labelList Foam::meshRefinement::decomposeCombineRegions
     // the region might span multiple domains so we want to get
     // a "region master" per domain. Note that multi-processor
     // regions can only occur on cells on coupled patches.
+    // Note: since the number of regions does not change by this the
+    // process can be seen as just a shift of a region onto a single
+    // processor.
+
+
+    // Global cell numbering engine
+    globalIndex globalCells(mesh_.nCells());
 
 
     // Determine per coupled region the master cell (lowest numbered cell
     // on lowest numbered processor)
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    // (does not determine master for non-coupled=fully-local regions)
 
-    Map<label> regionToMaster(mesh_.nFaces()-mesh_.nInternalFaces());
-    getRegionMaster(blockedFace, globalRegion, regionToMaster);
+    Map<label> coupledRegionToMaster(mesh_.nFaces()-mesh_.nInternalFaces());
+    getCoupledRegionMaster
+    (
+        globalCells,
+        blockedFace,
+        globalRegion,
+        coupledRegionToMaster
+    );
 
+    // Determine my regions
+    // ~~~~~~~~~~~~~~~~~~~~
+    // These are the fully local ones or the coupled ones of which I am master.
 
-    // Global cell numbering engine
-    globalIndex globalCells(mesh_.nCells());
+    Map<label> globalToLocalRegion;
+    pointField localPoints;
+    calcLocalRegions
+    (
+        globalCells,
+        globalRegion,
+        coupledRegionToMaster,
 
+        globalToLocalRegion,
+        localPoints
+    );
 
-    // Determine cell centre per region
-    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-    // Now we can divide regions into
-    // - single-processor regions (almost all)
-    //   - allocate local region + coordinate for it
-    // - multi-processor for which I am master
-    //   - allocate local region + coordinate for it
-    // - multi-processor for which I am not master
-    //   - do not allocate region.
-    //   - but inherit new distribution from master.
 
-    Map<label> globalToLocalRegion(mesh_.nCells());
-    DynamicList<point> localCc(mesh_.nCells()/10);
 
-    forAll(globalRegion, cellI)
-    {
-        Map<label>::const_iterator fndMaster =
-            regionToMaster.find(globalRegion[cellI]);
+    // Find distribution for regions
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-        if (fndMaster != regionToMaster.end())
-        {
-            // Multi-processor region.
-            if (globalCells.toGlobal(cellI) == fndMaster())
-            {
-                // I am master. Allocate region for me.
-                globalToLocalRegion.insert(globalRegion[cellI], localCc.size());
-                localCc.append(mesh_.cellCentres()[cellI]);
-            }
-        }
-        else
-        {
-            // Single processor region.
-            Map<label>::iterator iter =
-                globalToLocalRegion.find(globalRegion[cellI]);
+    labelList regionDistribution;
 
-            if (iter == globalToLocalRegion.end())
-            {
-                globalToLocalRegion.insert(globalRegion[cellI], localCc.size());
-                localCc.append(mesh_.cellCentres()[cellI]);
-            }
-        }
+    if (isA<geomDecomp>(decomposer))
+    {
+        regionDistribution = decomposer.decompose(localPoints);
     }
-    localCc.shrink();
-    pointField localPoints;
-    localPoints.transfer(localCc);
-
+    else
+    {
+        labelListList regionRegions;
+        calcRegionRegions
+        (
+            globalRegion,
+            globalToLocalRegion,
+            coupledRegionToMaster,
 
-    // Call decomposer on localCc
-    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+            regionRegions
+        );
 
-    labelList localDistribution = decomposer.decompose(localPoints);
+        regionDistribution = decomposer.decompose(regionRegions, localPoints);
+    }
 
 
-    // Distribute the destination processor for coupled regions
-    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    Map<label> regionToDist(regionToMaster.size());
+    // Convert region-based decomposition back to cell-based one
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    forAllConstIter(Map<label>, regionToMaster, iter)
+    // Transfer destination processor back to all. Use global reduce for now.
+    Map<label> regionToDist(coupledRegionToMaster.size());
+    forAllConstIter(Map<label>, coupledRegionToMaster, iter)
     {
-        if (globalCells.isLocal(iter()))
+        label region = iter.key();
+
+        Map<label>::const_iterator regionFnd = globalToLocalRegion.find(region);
+
+        if (regionFnd != globalToLocalRegion.end())
         {
-            // Master cell is local.
-            regionToDist.insert
-            (
-                iter.key(),
-                localDistribution[globalToLocalRegion[iter.key()]]
-            );
+            // Master cell is local. Store my distribution.
+            regionToDist.insert(iter.key(), regionDistribution[regionFnd()]);
         }
         else
         {
@@ -691,29 +959,27 @@ Foam::labelList Foam::meshRefinement::decomposeCombineRegions
     Pstream::mapCombineScatter(regionToDist);
 
 
-    // Convert region-based decomposition back to cell-based one
-    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
+    // Determine destination for all cells
     labelList distribution(mesh_.nCells());
 
     forAll(globalRegion, cellI)
     {
-        Map<label>::const_iterator fndMaster =
+        Map<label>::const_iterator fndRegion =
             regionToDist.find(globalRegion[cellI]);
 
-        if (fndMaster != regionToDist.end())
+        if (fndRegion != regionToDist.end())
         {
-            // Special handling
-            distribution[cellI] = fndMaster();
+            distribution[cellI] = fndRegion();
         }
         else
         {
             // region is local to the processor.
             label localRegionI = globalToLocalRegion[globalRegion[cellI]];
 
-            distribution[cellI] = localDistribution[localRegionI];
+            distribution[cellI] = regionDistribution[localRegionI];
         }
     }
+
     return distribution;
 }
 
@@ -839,9 +1105,18 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::meshRefinement::balance
 
         if (debug)
         {
-            Pout<< "Wanted distribution:"
-                << distributor.countCells(distribution)
-                << endl;
+            labelList nProcCells(distributor.countCells(distribution));
+            Pout<< "Wanted distribution:" << nProcCells << endl;
+
+            Pstream::listCombineGather(nProcCells, plusEqOp<label>());
+            Pstream::listCombineScatter(nProcCells);
+
+            Pout<< "Wanted resulting decomposition:" << endl;
+            forAll(nProcCells, procI)
+            {
+                Pout<< "    " << procI << '\t' << nProcCells[procI] << endl;
+            }
+            Pout<< endl;
         }
         // Do actual sending/receiving of mesh
         map = distributor.distribute(distribution);
diff --git a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.H b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.H
index 012ef08d00691d25ab9b73d29b07306fe6e226f0..d3eb52b7c42d0ce699d1d8b189fe976456468e3a 100644
--- a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.H
+++ b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.H
@@ -68,6 +68,7 @@ class featureEdgeMesh;
 class fvMeshDistribute;
 class searchableSurface;
 class regionSplit;
+class globalIndex;
 
 /*---------------------------------------------------------------------------*\
                            Class meshRefinement Declaration
@@ -157,15 +158,6 @@ private:
             labelList& neiLevel,
             pointField& neiCc
         ) const;
-        ////- Calculate coupled boundary end vector and refinement level. Sort
-        ////  so both sides of coupled face have data in same order.
-        //void calcCanonicalBoundaryData
-        //(
-        //    labelList& leftLevel,
-        //    pointField& leftCc,
-        //    labelList& rightLevel,
-        //    pointField& rightCc
-        //)  const;
 
         //- Find any intersection of surface. Store in surfaceIndex_.
         void updateIntersections(const labelList& changedFaces);
@@ -194,15 +186,51 @@ private:
             const label exposedPatchI
         );
 
-        //- Used in decomposeCombineRegions. Given global region per cell
-        //  determines master processor/cell for regions straddling
-        //  procboundaries.
-        void getRegionMaster
-        (
-            const boolList& blockedFace,
-            const regionSplit& globalRegion,
-            Map<label>& regionToMaster
-        ) const;
+        // For decomposeCombineRegions
+
+            //- Used in decomposeCombineRegions. Given global region per cell
+            //  determines master processor/cell for regions straddling
+            //  procboundaries.
+            void getCoupledRegionMaster
+            (
+                const globalIndex& globalCells,
+                const boolList& blockedFace,
+                const regionSplit& globalRegion,
+                Map<label>& regionToMaster
+            ) const;
+
+            //- Determine regions that are local to me or coupled ones that
+            //  are owned by me. Determine representative location.
+            void calcLocalRegions
+            (
+                const globalIndex& globalCells,
+                const labelList& globalRegion,
+                const Map<label>& coupledRegionToMaster,
+
+                Map<label>& globalToLocalRegion,
+                pointField& localPoints
+            ) const;
+
+            //- Convert region into global index.
+            static label getShiftedRegion
+            (
+                const globalIndex& indexer,
+                const Map<label>& globalToLocalRegion,
+                const Map<label>& coupledRegionToShifted,
+                const label globalRegion
+            );
+
+            //- helper: add element if not in list. Linear search.
+            static void addUnique(const label, labelList&);
+
+            //- Calculate region connectivity. Major communication.
+            void calcRegionRegions
+            (
+                const labelList& globalRegion,
+                const Map<label>& globalToLocalRegion,
+                const Map<label>& coupledRegionToMaster,
+                labelListList& regionRegions
+            ) const;
 
 
         // Refinement candidate selection
@@ -334,6 +362,14 @@ private:
                 const labelList& globalToPatch
             ) const;
 
+            //- Returns list with for every internal face -1 or the patch
+            //  they should be baffled into.
+            labelList markFacesOnProblemCellsGeometric
+            (
+                const dictionary& motionDict,
+                const labelList& globalToPatch
+            ) const;
+
 
         // Baffle merging
 
@@ -552,6 +588,7 @@ public:
             (
                 const bool handleSnapProblems,
                 const bool mergeFreeStanding,
+                const dictionary& motionDict,
                 Time& runTime,
                 const labelList& globalToPatch,
                 const point& keepPoint
diff --git a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementBaffles.C b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementBaffles.C
index 8b0236a7e2e055a9e877efabc5e9626c6b0b4282..e6bd37f6709484919c1c94cc99257168ad12de9f 100644
--- a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementBaffles.C
+++ b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementBaffles.C
@@ -44,9 +44,9 @@ License
 #include "OFstream.H"
 #include "regionSplit.H"
 #include "removeCells.H"
-
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+#include "motionSmoother.H"
+#include "polyMeshGeometry.H"
+#include "IOmanip.H"
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
@@ -555,28 +555,28 @@ Foam::labelList Foam::meshRefinement::markFacesOnProblemCells
     boolList isBoundaryFace(mesh_.nFaces(), false);
 
     // Fill boundary data. All elements on meshed patches get marked.
-    forAll(globalToPatch, i)
+    // Get the labels of added patches.
+    labelList adaptPatchIDs(meshRefinement::addedPatches(globalToPatch));
+
+    forAll(adaptPatchIDs, i)
     {
-        label patchI = globalToPatch[i];
+        label patchI = adaptPatchIDs[i];
 
-        if (patchI != -1)
-        {
-            const polyPatch& pp = patches[patchI];
+        const polyPatch& pp = patches[patchI];
 
-            label faceI = pp.start();
+        label faceI = pp.start();
 
-            forAll(pp, j)
-            {
-                markBoundaryFace
-                (
-                    faceI,
-                    isBoundaryFace,
-                    isBoundaryEdge,
-                    isBoundaryPoint
-                );
+        forAll(pp, j)
+        {
+            markBoundaryFace
+            (
+                faceI,
+                isBoundaryFace,
+                isBoundaryEdge,
+                isBoundaryPoint
+            );
 
-                faceI++;
-            }
+            faceI++;
         }
     }
 
@@ -872,6 +872,264 @@ Foam::labelList Foam::meshRefinement::markFacesOnProblemCells
 
     return facePatch;
 }
+//XXXXXXXXXXXXXX
+// Mark faces to be baffled to prevent snapping problems. Does
+// test to find nearest surface and checks which faces would get squashed.
+Foam::labelList Foam::meshRefinement::markFacesOnProblemCellsGeometric
+(
+    const dictionary& motionDict,
+    const labelList& globalToPatch
+) const
+{
+    // Get the labels of added patches.
+    labelList adaptPatchIDs(meshRefinement::addedPatches(globalToPatch));
+
+    // Construct addressing engine.
+    autoPtr<indirectPrimitivePatch> ppPtr
+    (
+        meshRefinement::makePatch
+        (
+            mesh_,
+            adaptPatchIDs
+        )
+    );
+    const indirectPrimitivePatch& pp = ppPtr();
+    const pointField& localPoints = pp.localPoints();
+    const labelList& meshPoints = pp.meshPoints();
+
+    // Find nearest (non-baffle) surface
+    pointField newPoints(mesh_.points());
+    {
+        List<pointIndexHit> hitInfo;
+        labelList hitSurface;
+        surfaces_.findNearest
+        (
+            surfaces_.getUnnamedSurfaces(),
+            localPoints,
+            scalarField(localPoints.size(), sqr(GREAT)),    // sqr of attraction
+            hitSurface,
+            hitInfo
+        );
+    
+        forAll(hitInfo, i)
+        {
+            if (hitInfo[i].hit())
+            {
+                //label pointI = meshPoints[i];
+                //Pout<< "   " << pointI << " moved from "
+                //    << mesh_.points()[pointI] << " by "
+                //    << mag(hitInfo[i].hitPoint()-mesh_.points()[pointI])
+                //    << endl;
+                newPoints[meshPoints[i]] = hitInfo[i].hitPoint();
+            }
+        }
+    }
+
+    // Per face (internal or coupled!) the patch that the
+    // baffle should get (or -1).
+    labelList facePatch(mesh_.nFaces(), -1);
+    // Count of baffled faces
+    label nBaffleFaces = 0;
+
+
+//    // Sync position? Or not since same face on both side so just sync
+//    // result of baffle.
+//
+//    const scalar minArea(readScalar(motionDict.lookup("minArea")));
+//
+//    Pout<< "markFacesOnProblemCellsGeometric : Comparing to minArea:"
+//        << minArea << endl;
+//
+//    pointField facePoints;
+//    for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
+//    {
+//        const face& f = mesh_.faces()[faceI];
+//
+//        bool usesPatchPoint = false;
+//
+//        facePoints.setSize(f.size());
+//        forAll(f, fp)
+//        {
+//            Map<label>::const_iterator iter = pp.meshPointMap().find(f[fp]);
+//
+//            if (iter != pp.meshPointMap().end())
+//            {
+//                facePoints[fp] = newPosition[iter()];
+//                usesPatchPoint = true;
+//            }
+//            else
+//            {
+//                facePoints[fp] = mesh_.points()[f[fp]];
+//            }
+//        }
+//
+//        if (usesPatchPoint)
+//        {
+//            // Check area of face wrt original area
+//            face identFace(identity(f.size()));
+//
+//            if (identFace.mag(facePoints) < minArea)
+//            {
+//                facePatch[faceI] = getBafflePatch(facePatch, faceI);
+//                nBaffleFaces++;
+//            }
+//        }
+//    }
+//
+//
+//    const polyBoundaryMesh& patches = mesh_.boundaryMesh();
+//    forAll(patches, patchI)
+//    {
+//        const polyPatch& pp = patches[patchI];
+//
+//        if (pp.coupled())
+//        {
+//            forAll(pp, i)
+//            {
+//                label faceI = pp.start()+i;
+//
+//                const face& f = mesh_.faces()[faceI];
+//
+//                bool usesPatchPoint = false;
+//
+//                facePoints.setSize(f.size());
+//                forAll(f, fp)
+//                {
+//                    Map<label>::const_iterator iter =
+//                        pp.meshPointMap().find(f[fp]);
+//
+//                    if (iter != pp.meshPointMap().end())
+//                    {
+//                        facePoints[fp] = newPosition[iter()];
+//                        usesPatchPoint = true;
+//                    }
+//                    else
+//                    {
+//                        facePoints[fp] = mesh_.points()[f[fp]];
+//                    }
+//                }
+//
+//                if (usesPatchPoint)
+//                {
+//                    // Check area of face wrt original area
+//                    face identFace(identity(f.size()));
+//
+//                    if (identFace.mag(facePoints) < minArea)
+//                    {
+//                        facePatch[faceI] = getBafflePatch(facePatch, faceI);
+//                        nBaffleFaces++;
+//                    }
+//                }
+//            }
+//        }
+//    }
+
+    {
+        pointField oldPoints(mesh_.points());
+        mesh_.movePoints(newPoints);
+        faceSet wrongFaces(mesh_, "wrongFaces", 100);
+        {
+            //motionSmoother::checkMesh(false, mesh_, motionDict, wrongFaces);
+
+            // Just check the errors from squashing
+            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+            const labelList allFaces(identity(mesh_.nFaces()));
+            label nWrongFaces = 0;
+
+            scalar minArea(readScalar(motionDict.lookup("minArea")));
+            if (minArea > -SMALL)
+            {
+                polyMeshGeometry::checkFaceArea
+                (
+                    false,
+                    minArea,
+                    mesh_,
+                    mesh_.faceAreas(),
+                    allFaces,
+                    &wrongFaces
+                );
+
+                label nNewWrongFaces = returnReduce
+                (
+                    wrongFaces.size(),
+                    sumOp<label>()
+                );
+
+                Info<< "    faces with area < "
+                    << setw(5) << minArea
+                    << " m^2                            : "
+                    << nNewWrongFaces-nWrongFaces << endl;
+
+                nWrongFaces = nNewWrongFaces;
+            }
+
+//            scalar minDet(readScalar(motionDict.lookup("minDeterminant")));
+            scalar minDet = 0.01;
+            if (minDet > -1)
+            {
+                polyMeshGeometry::checkCellDeterminant
+                (
+                    false,
+                    minDet,
+                    mesh_,
+                    mesh_.faceAreas(),
+                    allFaces,
+                    polyMeshGeometry::affectedCells(mesh_, allFaces),
+                    &wrongFaces
+                );
+
+                label nNewWrongFaces = returnReduce
+                (
+                    wrongFaces.size(),
+                    sumOp<label>()
+                );
+
+                Info<< "    faces on cells with determinant < "
+                    << setw(5) << minDet << "                : "
+                    << nNewWrongFaces-nWrongFaces << endl;
+
+                nWrongFaces = nNewWrongFaces;
+            }
+        }
+
+
+        forAllConstIter(faceSet, wrongFaces, iter)
+        {
+            label patchI = mesh_.boundaryMesh().whichPatch(iter.key());
+
+            if (patchI == -1 || mesh_.boundaryMesh()[patchI].coupled())
+            {
+                facePatch[iter.key()] = getBafflePatch(facePatch, iter.key());
+                nBaffleFaces++;
+
+                //Pout<< "    " << iter.key()
+                //    //<< " on patch " << mesh_.boundaryMesh()[patchI].name()
+                //    << " is destined for patch " << facePatch[iter.key()]
+                //    << endl;
+            }
+        }
+        // Restore points.
+        mesh_.movePoints(oldPoints);
+    }
+
+
+    Info<< "markFacesOnProblemCellsGeometric : marked "
+        << returnReduce(nBaffleFaces, sumOp<label>())
+        << " additional internal and coupled faces"
+        << " to be converted into baffles." << endl;
+
+    syncTools::syncFaceList
+    (
+        mesh_,
+        facePatch,
+        maxEqOp<label>(),
+        false               // no separation
+    );
+
+    return facePatch;
+}
+//XXXXXXXX
 
 
 // Return a list of coupled face pairs, i.e. faces that use the same vertices.
@@ -1554,6 +1812,7 @@ void Foam::meshRefinement::baffleAndSplitMesh
 (
     const bool handleSnapProblems,
     const bool mergeFreeStanding,
+    const dictionary& motionDict,
     Time& runTime,
     const labelList& globalToPatch,
     const point& keepPoint
@@ -1584,6 +1843,12 @@ void Foam::meshRefinement::baffleAndSplitMesh
         ownPatch,
         neiPatch
     );
+
+    if (debug)
+    {
+        runTime++;
+    }
+
     createBaffles(ownPatch, neiPatch);
 
     if (debug)
@@ -1621,14 +1886,65 @@ void Foam::meshRefinement::baffleAndSplitMesh
 
         labelList facePatch
         (
-            markFacesOnProblemCells
+            //markFacesOnProblemCells
+            //(
+            //    globalToPatch
+            //)
+            markFacesOnProblemCellsGeometric
             (
+                motionDict,
                 globalToPatch
             )
         );
         Info<< "Analyzed problem cells in = "
             << runTime.cpuTimeIncrement() << " s\n" << nl << endl;
 
+        if (debug)
+        {
+            // Dump all these faces to a faceSet.
+            faceSet problemGeom(mesh_, "problemFacesGeom", 100);
+
+            const labelList facePatchGeom
+            (
+                markFacesOnProblemCellsGeometric
+                (
+                    motionDict,
+                    globalToPatch
+                )
+            );
+            forAll(facePatchGeom, faceI)
+            {
+                if (facePatchGeom[faceI] != -1)
+                {
+                    problemGeom.insert(faceI);
+                }
+            }
+            Pout<< "Dumping " << problemGeom.size()
+                << " problem faces to " << problemGeom.objectPath() << endl;
+            problemGeom.write();
+
+
+            faceSet problemTopo(mesh_, "problemFacesTopo", 100);
+
+            const labelList facePatchTopo
+            (    
+                markFacesOnProblemCells
+                (
+                    globalToPatch
+                )
+            );
+            forAll(facePatchTopo, faceI)
+            {
+                if (facePatchTopo[faceI] != -1)
+                {
+                    problemTopo.insert(faceI);
+                }
+            }
+            Pout<< "Dumping " << problemTopo.size()
+                << " problem faces to " << problemTopo.objectPath() << endl;
+            problemTopo.write();
+        }
+
         Info<< "Introducing baffles to delete problem cells." << nl << endl;
 
         if (debug)
diff --git a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C
index b8ee73b8cec7d2fbc22a9bb80ca91efce5536547..e9eb2cb44594008297c317e9994e6b52cbea1d28 100644
--- a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C
+++ b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C
@@ -1277,22 +1277,13 @@ Foam::autoPtr<Foam::mapDistributePolyMesh>
 
     if (Pstream::nProcs() > 1)
     {
-        labelList distribution(decomposer.decompose(mesh_.cellCentres()));
-        // Get distribution such that baffle faces stay internal to the
-        // processor.
-        //labelList distribution(decomposePreserveBaffles(decomposer));
-
-        if (debug)
-        {
-            Pout<< "Wanted distribution:"
-                << distributor.countCells(distribution)
-                << endl;
-        }
-        // Do actual sending/receiving of mesh
-        distMap = distributor.distribute(distribution);
-
-        // Update numbering of meshRefiner
-        distribute(distMap);
+        distMap = balance
+        (
+            false,  //keepZoneFaces
+            false,  //keepBaffles
+            decomposer,
+            distributor
+        );
 
         Info<< "Balanced mesh in = "
             << mesh_.time().cpuTimeIncrement() << " s" << endl;
@@ -1302,7 +1293,7 @@ Foam::autoPtr<Foam::mapDistributePolyMesh>
 
         if (debug)
         {
-            Pout<< "Writing " << msg
+            Pout<< "Writing balanced " << msg
                 << " mesh to time " << mesh_.time().timeName() << endl;
             write
             (
diff --git a/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.C b/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.C
index ce09e597e2480c80f1583778639ff7899aac5b57..1654e3cd7fcae7de1e9a73d4186d304952d3598e 100644
--- a/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.C
+++ b/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.C
@@ -377,15 +377,34 @@ Foam::refinementSurfaces::refinementSurfaces
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-// Get indices of named surfaces (surfaces with cellZoneName)
+// Get indices of unnamed surfaces (surfaces without faceZoneName)
+Foam::labelList Foam::refinementSurfaces::getUnnamedSurfaces() const
+{
+   labelList anonymousSurfaces(faceZoneNames_.size());
+
+    label i = 0;
+    forAll(faceZoneNames_, surfI)
+    {
+        if (faceZoneNames_[surfI].size() == 0)
+        {
+            anonymousSurfaces[i++] = surfI;
+        }
+    }
+    anonymousSurfaces.setSize(i);
+
+    return anonymousSurfaces;
+}
+
+
+// Get indices of named surfaces (surfaces with faceZoneName)
 Foam::labelList Foam::refinementSurfaces::getNamedSurfaces() const
 {
-   labelList namedSurfaces(cellZoneNames_.size());
+   labelList namedSurfaces(faceZoneNames_.size());
 
     label namedI = 0;
-    forAll(cellZoneNames_, surfI)
+    forAll(faceZoneNames_, surfI)
     {
-        if (cellZoneNames_[surfI].size() > 0)
+        if (faceZoneNames_[surfI].size() > 0)
         {
             namedSurfaces[namedI++] = surfI;
         }
@@ -846,6 +865,69 @@ void Foam::refinementSurfaces::findNearest
 }
 
 
+void Foam::refinementSurfaces::findNearestRegion
+(
+    const labelList& surfacesToTest,
+    const pointField& samples,
+    const  scalarField& nearestDistSqr,
+    labelList& hitSurface,
+    labelList& hitRegion
+) const
+{
+    labelList geometries(IndirectList<label>(surfaces_, surfacesToTest));
+
+    // Do the tests. Note that findNearest returns index in geometries.
+    List<pointIndexHit> hitInfo;
+    searchableSurfacesQueries::findNearest
+    (
+        allGeometry_,
+        geometries,
+        samples,
+        nearestDistSqr,
+        hitSurface,
+        hitInfo
+    );
+
+    // Rework the hitSurface to be surface (i.e. index into surfaces_)
+    forAll(hitSurface, pointI)
+    {
+        if (hitSurface[pointI] != -1)
+        {
+            hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
+        }
+    }
+
+    // Collect the region
+    hitRegion.setSize(hitSurface.size());
+    hitRegion = -1;
+
+    forAll(surfacesToTest, i)
+    {
+        label surfI = surfacesToTest[i];
+
+        // Collect hits for surfI
+        const labelList localIndices(findIndices(hitSurface, surfI));
+
+        List<pointIndexHit> localHits
+        (
+            IndirectList<pointIndexHit> 
+            (
+                hitInfo,
+                localIndices
+            )
+        );
+
+        labelList localRegion;
+        allGeometry_[surfaces_[surfI]].getRegion(localHits, localRegion);
+
+        forAll(localIndices, i)
+        {
+            hitRegion[localIndices[i]] = localRegion[i];
+        }
+    }
+}
+
+
 //// Find intersection with max of edge. Return -1 or the surface
 //// with the highest maxLevel above currentLevel
 //Foam::label Foam::refinementSurfaces::findHighestIntersection
diff --git a/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.H b/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.H
index edb613d966f11b8b62ab55de4c83765b9ab55bd9..ee5dd219a540cc5139e1d0ec0df11bc6dbf113ae 100644
--- a/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.H
+++ b/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.H
@@ -154,7 +154,10 @@ public:
                 return cellZoneNames_;
             }
 
-            //- Get indices of named surfaces (surfaces with cellZoneName)
+            //- Get indices of named surfaces (surfaces with faceZoneName)
+            labelList getUnnamedSurfaces() const;
+
+            //- Get indices of named surfaces (surfaces with faceZoneName)
             labelList getNamedSurfaces() const;
 
             //- Get indices of closed named surfaces
@@ -249,6 +252,8 @@ public:
 
             //- Find intersection nearest to the endpoints. surface1,2 are
             //  not indices into surfacesToTest but refinement surface indices.
+            //  Returns surface, region on surface (so not global surface)
+            //  and position on surface.
             void findNearestIntersection
             (
                 const labelList& surfacesToTest,
@@ -282,6 +287,17 @@ public:
                 List<pointIndexHit>&
             ) const;
 
+            //- Find nearest point on surfaces. Return surface and region on
+            //  surface (so not global surface)
+            void findNearestRegion
+            (
+                const labelList& surfacesToTest,
+                const pointField& samples,
+                const  scalarField& nearestDistSqr,
+                labelList& hitSurface,
+                labelList& hitRegion
+            ) const;
+
             //- Detect if a point is 'inside' (closed) surfaces.
             //  Returns -1 if not, returns first surface it is.
             void findInside
diff --git a/src/dynamicMesh/layerAdditionRemoval/removeCellLayer.C b/src/dynamicMesh/layerAdditionRemoval/removeCellLayer.C
index c5927a61289dc3394d1ddc07b9550eba9eda0d94..907eb097f1ce767d1934b35846f917a51da90662 100644
--- a/src/dynamicMesh/layerAdditionRemoval/removeCellLayer.C
+++ b/src/dynamicMesh/layerAdditionRemoval/removeCellLayer.C
@@ -301,7 +301,7 @@ void Foam::layerAdditionRemoval::removeCellLayer
 
         // Is any of the faces a boundary face?  If so, grab the patch
         // A boundary-to-boundary collapse is checked for in validCollapse()
-        // and cannnot happen here.  
+        // and cannot happen here.  
 
         if (!mesh.isInternalFace(mf[faceI]))
         {
diff --git a/src/meshTools/searchableSurface/searchableBox.C b/src/meshTools/searchableSurface/searchableBox.C
index b1776b3c9e79323f32177cb13a6983325ceb2a0a..1858905d49b77759a9375bf3bf79e8597771bdc4 100644
--- a/src/meshTools/searchableSurface/searchableBox.C
+++ b/src/meshTools/searchableSurface/searchableBox.C
@@ -436,7 +436,6 @@ void Foam::searchableBox::findLineAll
     // Work array
     DynamicList<pointIndexHit, 1, 1> hits;
 
-//XXX
     // Tolerances:
     // To find all intersections we add a small vector to the last intersection
     // This is chosen such that
diff --git a/tutorials/pimpleFoam/t-junction/0/U b/tutorials/pimpleFoam/t-junction/0/U
new file mode 100644
index 0000000000000000000000000000000000000000..8851e66583e7cfb1de3ec1aa63fdc95278a4c66c
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/0/U
@@ -0,0 +1,50 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  1.5                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volVectorField;
+    object      U;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 -1 0 0 0 0];
+
+internalField   uniform (0 0 0);
+
+boundaryField
+{
+    inlet      
+    {
+        type            pressureInletOutletVelocity;
+        value           uniform (0 0 0);
+    }
+
+    outlet1    
+    {
+        type            inletOutlet;
+        inletValue      uniform (0 0 0);
+        value           uniform (0 0 0);
+    }
+
+    outlet2   
+    {
+        type            inletOutlet;
+        inletValue      uniform (0 0 0);
+        value           uniform (0 0 0);
+    }
+
+    defaultFaces      
+    {
+        type            fixedValue;
+        value           uniform (0 0 0);
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/pimpleFoam/t-junction/0/epsilon b/tutorials/pimpleFoam/t-junction/0/epsilon
new file mode 100644
index 0000000000000000000000000000000000000000..8e5b3e553d196c92fbfd8148146609c1e9b254ca
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/0/epsilon
@@ -0,0 +1,49 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  1.5                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      epsilon;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -3 0 0 0 0];
+
+internalField   uniform 1;
+
+boundaryField
+{
+    inlet
+    {
+        type            turbulentMixingLengthDissipationRateInlet;
+        mixingLength    0.01;         // 1cm - half channel height
+        value           uniform 1;
+    }
+
+    outlet1
+    {
+        type            inletOutlet;
+        inletValue      uniform 1;
+    }
+
+    outlet2
+    {
+        type            inletOutlet;
+        inletValue      uniform 1;
+    }
+
+    defaultFaces
+    {
+        type            zeroGradient;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/pimpleFoam/t-junction/0/k b/tutorials/pimpleFoam/t-junction/0/k
new file mode 100644
index 0000000000000000000000000000000000000000..35b2bd3ff9a83789500a9b5d2488c086f274ae0b
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/0/k
@@ -0,0 +1,48 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  1.5                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      k;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -2 0 0 0 0];
+
+internalField   uniform 1;
+
+boundaryField
+{
+    inlet
+    {
+        type            turbulentIntensityKineticEnergyInlet;
+        intensity       0.05;           // 5% turbulence
+        value           uniform 1;
+    }
+
+    outlet1
+    {
+        type            inletOutlet;
+        inletValue      uniform 1;
+    }
+
+    outlet2
+    {
+        type            inletOutlet;
+        inletValue      uniform 1;
+    }
+
+    defaultFaces
+    {
+        type            zeroGradient;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/pimpleFoam/t-junction/0/nuTilda b/tutorials/pimpleFoam/t-junction/0/nuTilda
new file mode 100644
index 0000000000000000000000000000000000000000..6ea76a6b637460e79b57d09daedf5360e5595044
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/0/nuTilda
@@ -0,0 +1,44 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  1.5                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      nuTilda;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -1 0 0 0 0];
+
+internalField   uniform 0;
+
+boundaryField
+{
+    inlet
+    {
+        type            zeroGradient;
+    }
+
+    outlet1
+    {
+        type            zeroGradient;
+    }
+
+    outlet2
+    {
+        type            zeroGradient;
+    }
+
+    defaultFaces
+    {
+        type            zeroGradient;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/pimpleFoam/t-junction/0/p b/tutorials/pimpleFoam/t-junction/0/p
new file mode 100644
index 0000000000000000000000000000000000000000..b3d464605830159b73ceec6b1d2c199c5cf6eab4
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/0/p
@@ -0,0 +1,53 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  1.5                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       volScalarField;
+    object      p;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 2 -2 0 0 0 0];
+
+internalField   uniform 100000;
+
+boundaryField
+{
+    inlet      
+    {
+        type            totalPressure;
+        p0              uniform 100040;
+        U               U;
+        phi             phi;
+        rho             none;
+        psi             none;
+        gamma           1;
+        value           uniform 100040;
+    }
+
+    outlet1     
+    {
+        type            fixedValue;
+        value           uniform 100010;
+    }
+
+    outlet2    
+    {
+        type            fixedValue;
+        value           uniform 100000;
+    }
+
+    defaultFaces
+    {
+        type            zeroGradient;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/pimpleFoam/t-junction/README.txt b/tutorials/pimpleFoam/t-junction/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0905f8784d3f59c9372dcbf858c093d8c4477ee7
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/README.txt
@@ -0,0 +1,2 @@
+15/8/8 Simple T-junction. Inlet on left, one outlet at bottom, one at top.
+To test multiple outlets.
diff --git a/tutorials/pimpleFoam/t-junction/constant/RASProperties b/tutorials/pimpleFoam/t-junction/constant/RASProperties
new file mode 100644
index 0000000000000000000000000000000000000000..e46e0a858b12c777bb11bc364b144cd6feb2b1da
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/constant/RASProperties
@@ -0,0 +1,200 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  1.5                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      RASProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+RASModel            kEpsilon;
+
+turbulence          on;
+
+printCoeffs         on;
+
+laminarCoeffs
+{
+}
+
+kEpsilonCoeffs
+{
+    Cmu              0.09;
+    C1               1.44;
+    C2               1.92;
+    alphaEps         0.76923;
+}
+
+RNGkEpsilonCoeffs
+{
+    Cmu              0.0845;
+    C1               1.42;
+    C2               1.68;
+    alphak           1.39;
+    alphaEps         1.39;
+    eta0             4.38;
+    beta             0.012;
+}
+
+realizableKECoeffs
+{
+    Cmu              0.09;
+    A0               4.0;
+    C2               1.9;
+    alphak           1;
+    alphaEps         0.833333;
+}
+
+kOmegaSSTCoeffs
+{
+    alphaK1          0.85034;
+    alphaK2          1.0;
+    alphaOmega1      0.5;
+    alphaOmega2      0.85616;
+    gamma1           0.5532;
+    gamma2           0.4403;
+    beta1            0.0750;
+    beta2            0.0828;
+    betaStar         0.09;
+    a1               0.31;
+    c1               10;
+
+    Cmu              0.09;
+}
+
+NonlinearKEShihCoeffs
+{
+    Cmu              0.09;
+    C1               1.44;
+    C2               1.92;
+    alphak           1;
+    alphaEps         0.76932;
+    A1               1.25;
+    A2               1000;
+    Ctau1            -4;
+    Ctau2            13;
+    Ctau3            -2;
+    alphaKsi         0.9;
+}
+
+LienCubicKECoeffs
+{
+    C1               1.44;
+    C2               1.92;
+    alphak           1;
+    alphaEps         0.76923;
+    A1               1.25;
+    A2               1000;
+    Ctau1            -4;
+    Ctau2            13;
+    Ctau3            -2;
+    alphaKsi         0.9;
+}
+
+QZetaCoeffs
+{
+    Cmu              0.09;
+    C1               1.44;
+    C2               1.92;
+    alphaZeta        0.76923;
+    anisotropic     no;
+}
+
+LaunderSharmaKECoeffs
+{
+    Cmu              0.09;
+    C1               1.44;
+    C2               1.92;
+    alphaEps         0.76923;
+}
+
+LamBremhorstKECoeffs
+{
+    Cmu              0.09;
+    C1               1.44;
+    C2               1.92;
+    alphaEps         0.76923;
+}
+
+LienCubicKELowReCoeffs
+{
+    Cmu              0.09;
+    C1               1.44;
+    C2               1.92;
+    alphak           1;
+    alphaEps         0.76923;
+    A1               1.25;
+    A2               1000;
+    Ctau1            -4;
+    Ctau2            13;
+    Ctau3            -2;
+    alphaKsi         0.9;
+    Am               0.016;
+    Aepsilon         0.263;
+    Amu              0.00222;
+}
+
+LienLeschzinerLowReCoeffs
+{
+    Cmu              0.09;
+    C1               1.44;
+    C2               1.92;
+    alphak           1;
+    alphaEps         0.76923;
+    Am               0.016;
+    Aepsilon         0.263;
+    Amu              0.00222;
+}
+
+LRRCoeffs
+{
+    Cmu              0.09;
+    Clrr1            1.8;
+    Clrr2            0.6;
+    C1               1.44;
+    C2               1.92;
+    Cs               0.25;
+    Ceps             0.15;
+    alphaEps         0.76923;
+}
+
+LaunderGibsonRSTMCoeffs
+{
+    Cmu              0.09;
+    Clg1             1.8;
+    Clg2             0.6;
+    C1               1.44;
+    C2               1.92;
+    C1Ref            0.5;
+    C2Ref            0.3;
+    Cs               0.25;
+    Ceps             0.15;
+    alphaEps         0.76923;
+    alphaR           1.22;
+}
+
+SpalartAllmarasCoeffs
+{
+    alphaNut         1.5;
+    Cb1              0.1355;
+    Cb2              0.622;
+    Cw2              0.3;
+    Cw3              2;
+    Cv1              7.1;
+    Cv2              5.0;
+}
+
+wallFunctionCoeffs
+{
+    kappa            0.4187;
+    E                9;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/pimpleFoam/t-junction/constant/polyMesh/blockMeshDict b/tutorials/pimpleFoam/t-junction/constant/polyMesh/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..d8f6e3bb6ef8c12a381ef57d1033f8c091703f2a
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/constant/polyMesh/blockMeshDict
@@ -0,0 +1,109 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  1.5                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//           outlet1
+//             +-+
+//             | |
+//             | |
+//             | |
+//             | |
+// +-----------+ |
+// |inlet        |
+// +-----------+ |
+//             | |
+//             | |
+//             | |
+//             | |
+//             +-+
+//           outlet2
+
+convertToMeters 1;
+
+vertices        
+(
+    (0.0  -0.01 0)   //0
+    (0.2  -0.01 0)
+    (0.2   0.01 0)   //2
+    (0.0   0.01 0)
+
+    (0.22 -0.01 0)  //4
+    (0.22  0.01 0)
+
+    (0.2  -0.21 0)  //6
+    (0.22 -0.21 0)
+
+    (0.2   0.21 0)  //8
+    (0.22  0.21 0)
+
+    // Z
+    (0.0  -0.01 0.02)   //0
+    (0.2  -0.01 0.02)
+    (0.2   0.01 0.02)   //2
+    (0.0   0.01 0.02)
+
+    (0.22 -0.01 0.02)  //4
+    (0.22  0.01 0.02)
+
+    (0.2  -0.21 0.02)  //6
+    (0.22 -0.21 0.02)
+
+    (0.2   0.21 0.02)  //8
+    (0.22  0.21 0.02)
+
+);
+
+blocks          
+(
+    // inlet block
+    hex (0 1 2 3  10 11 12 13) (50 5 5) simpleGrading (1 1 1)
+
+    // central block
+    hex (1 4 5 2  11 14 15 12) (5 5 5) simpleGrading (1 1 1)
+
+    // bottom block
+    hex (6 7 4 1  16 17 14 11) (5 50 5) simpleGrading (1 1 1)
+
+    // top block
+    hex (2 5 9 8  12 15 19 18) (5 50 5) simpleGrading (1 1 1)
+);
+
+edges           
+(
+);
+
+patches         
+(
+    patch inlet
+    (
+        (0 10 13 3)
+    )
+
+    patch outlet1
+    (
+        (6 7 17 16)
+    )
+
+    patch outlet2
+    (
+        (8 18 19 9)
+    )
+);
+
+mergePatchPairs
+(
+);
+
+// ************************************************************************* //
diff --git a/tutorials/pimpleFoam/t-junction/constant/polyMesh/boundary b/tutorials/pimpleFoam/t-junction/constant/polyMesh/boundary
new file mode 100644
index 0000000000000000000000000000000000000000..4ea7f95a3e9c35ac60edb879d026c17c690eddce
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/constant/polyMesh/boundary
@@ -0,0 +1,46 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       polyBoundaryMesh;
+    location    "constant/polyMesh";
+    object      boundary;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+4
+(
+    inlet
+    {
+        type            patch;
+        nFaces          25;
+        startFace       10050;
+    }
+    outlet1
+    {
+        type            patch;
+        nFaces          25;
+        startFace       10075;
+    }
+    outlet2
+    {
+        type            patch;
+        nFaces          25;
+        startFace       10100;
+    }
+    defaultFaces
+    {
+        type            wall;
+        nFaces          3075;
+        startFace       10125;
+    }
+)
+
+// ************************************************************************* //
diff --git a/tutorials/pimpleFoam/t-junction/constant/transportProperties b/tutorials/pimpleFoam/t-junction/constant/transportProperties
new file mode 100644
index 0000000000000000000000000000000000000000..fd5fc94660c15bb124be01fc5bfb49f4e27dde73
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/constant/transportProperties
@@ -0,0 +1,37 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  1.5                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      transportProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+transportModel  Newtonian;
+
+nu              nu [0 2 -1 0 0 0 0] 1e-05;
+
+CrossPowerLawCoeffs
+{
+    nu0             nu0 [0 2 -1 0 0 0 0] 1e-06;
+    nuInf           nuInf [0 2 -1 0 0 0 0] 1e-06;
+    m               m [0 0 1 0 0 0 0] 1;
+    n               n [0 0 0 0 0 0 0] 1;
+}
+
+BirdCarreauCoeffs
+{
+    nu0             nu0 [0 2 -1 0 0 0 0] 1e-06;
+    nuInf           nuInf [0 2 -1 0 0 0 0] 1e-06;
+    k               k [0 0 1 0 0 0 0] 0;
+    n               n [0 0 0 0 0 0 0] 1;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/pimpleFoam/t-junction/system/controlDict b/tutorials/pimpleFoam/t-junction/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..b5f0d20f7e2cd66501bd7b248f537d0db8804fb9
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/system/controlDict
@@ -0,0 +1,82 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  1.5                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+application turbFoam;
+
+startFrom       startTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         1;
+
+deltaT          0.001;
+
+writeControl    adjustableRunTime;
+
+writeInterval   0.1;
+
+purgeWrite      0;
+
+writeFormat     ascii;
+
+writePrecision  6;
+
+writeCompression uncompressed;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable yes;
+
+adjustTimeStep  yes;
+maxCo           5;
+
+functions
+(
+    probes
+    {
+        // Type of functionObject
+        type probes;
+
+        // Where to load it from (if not already in solver)
+        functionObjectLibs ("libsampling.so");
+
+        // Name of the directory for the probe data
+        name probes;
+
+        // Locations to be probed. runTime modifiable!
+        probeLocations
+        (
+            (1E-6 0 0.01)           // at inlet
+            (0.21 -0.20999 0.01)    // at outlet1
+            (0.21  0.20999 0.01)    // at outlet2
+            (0.21 0 0.01)           // at central block
+        );
+
+        // Fields to be probed. runTime modifiable!
+        fields
+        (
+            p
+            U
+        );
+    }
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/pimpleFoam/t-junction/system/fvSchemes b/tutorials/pimpleFoam/t-junction/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..bbe7fab0d2e1553b63c1695352cb9fe538ecd597
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/system/fvSchemes
@@ -0,0 +1,69 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  1.5                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default Euler;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+    grad(p)         Gauss linear;
+    grad(U)         Gauss linear;
+}
+
+divSchemes
+{
+    default         none;
+    div(phi,U)      Gauss limitedLinearV 1;
+    div(phi,k)      Gauss limitedLinear 1;
+    div(phi,epsilon) Gauss limitedLinear 1;
+    div(phi,R)      Gauss limitedLinear 1;
+    div(R)          Gauss linear;
+    div(phi,nuTilda) Gauss limitedLinear 1;
+    div((nuEff*dev(grad(U).T()))) Gauss linear;
+}
+
+laplacianSchemes
+{
+    default         none;
+    laplacian(nuEff,U) Gauss linear corrected;
+    laplacian((1|A(U)),p) Gauss linear corrected;
+    laplacian(DkEff,k) Gauss linear corrected;
+    laplacian(DepsilonEff,epsilon) Gauss linear corrected;
+    laplacian(DREff,R) Gauss linear corrected;
+    laplacian(DnuTildaEff,nuTilda) Gauss linear corrected;
+}
+
+interpolationSchemes
+{
+    default         linear;
+    interpolate(U)  linear;
+}
+
+snGradSchemes
+{
+    default         corrected;
+}
+
+fluxRequired
+{
+    default         no;
+    p;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/pimpleFoam/t-junction/system/fvSolution b/tutorials/pimpleFoam/t-junction/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..995edf623c2b4a9ff14788cf5b6202105c66d15b
--- /dev/null
+++ b/tutorials/pimpleFoam/t-junction/system/fvSolution
@@ -0,0 +1,88 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  1.5                                   |
+|   \\  /    A nd           | Web:      http://www.OpenFOAM.org               |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    p GAMG
+    {
+        tolerance        1e-6;
+        relTol           0.01;
+
+        smoother         GaussSeidel;
+
+        cacheAgglomeration true;
+        nCellsInCoarsestLevel 10;
+        agglomerator     faceAreaPair;
+        mergeLevels      1;
+    };
+    pFinal GAMG
+    {
+        tolerance        1e-6;
+        relTol           0.0;
+
+        smoother         GaussSeidel;
+
+        cacheAgglomeration true;
+        nCellsInCoarsestLevel 10;
+        agglomerator     faceAreaPair;
+        mergeLevels      1;
+    };
+
+    U PBiCG
+    {
+        preconditioner   DILU;
+        tolerance        1e-05;
+        relTol           0.1;
+    };
+    UFinal PBiCG
+    {
+        preconditioner   DILU;
+        tolerance        1e-05;
+        relTol           0;
+    };
+    k PBiCG
+    {
+        preconditioner   DILU;
+        tolerance        1e-05;
+        relTol           0;
+    };
+    epsilon PBiCG
+    {
+        preconditioner   DILU;
+        tolerance        1e-05;
+        relTol           0;
+    };
+}
+
+PIMPLE
+{
+    nOuterCorrectors 2;
+    nCorrectors     2;
+    nNonOrthogonalCorrectors 0;
+    pRefCell        0;
+    pRefValue       0;
+}
+
+relaxationFactors
+{
+    //p               0.3;
+    U               1.0;
+    k               1.0;
+    epsilon         1.0;
+}
+
+
+// ************************************************************************* //