diff --git a/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C b/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C
new file mode 100644
index 0000000000000000000000000000000000000000..9e68e1f726e9883f5b0a2ae9fbb6f2cbde127d34
--- /dev/null
+++ b/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C
@@ -0,0 +1,323 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  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 "loadOrCreateMesh.H"
+#include "processorPolyPatch.H"
+#include "Time.H"
+
+// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
+
+// Read mesh if available. Otherwise create empty mesh with same non-proc
+// patches as proc0 mesh. Requires all processors to have all patches
+// (and in same order).
+Foam::autoPtr<Foam::fvMesh> Foam::loadOrCreateMesh
+(
+    const IOobject& io
+)
+{
+    fileName meshSubDir;
+
+    if (io.name() == polyMesh::defaultRegion)
+    {
+        meshSubDir = polyMesh::meshSubDir;
+    }
+    else
+    {
+        meshSubDir = io.name()/polyMesh::meshSubDir;
+    }
+
+    // Check who has a mesh
+    const bool haveMesh = isDir(io.time().path()/io.instance()/meshSubDir);
+
+Pout<< "meshpath:" << io.time().path()/io.instance()/meshSubDir << endl;
+Pout<< "haveMesh:" << haveMesh << endl;
+
+    if (!haveMesh)
+    {
+        // Create dummy mesh. Only used on procs that don't have mesh.
+        IOobject noReadIO(io);
+        noReadIO.readOpt() = IOobject::NO_READ;
+        fvMesh dummyMesh
+        (
+            noReadIO,
+            xferCopy(pointField()),
+            xferCopy(faceList()),
+            xferCopy(labelList()),
+            xferCopy(labelList()),
+            false
+        );
+        // Add some dummy zones so upon reading it does not read them
+        // from the undecomposed case. Should be done as extra argument to
+        // regIOobject::readStream?
+        List<pointZone*> pz
+        (
+            1,
+            new pointZone
+            (
+                "dummyPointZone",
+                labelList(0),
+                0,
+                dummyMesh.pointZones()
+            )
+        );
+        List<faceZone*> fz
+        (
+            1,
+            new faceZone
+            (
+                "dummyFaceZone",
+                labelList(0),
+                boolList(0),
+                0,
+                dummyMesh.faceZones()
+            )
+        );
+        List<cellZone*> cz
+        (
+            1,
+            new cellZone
+            (
+                "dummyCellZone",
+                labelList(0),
+                0,
+                dummyMesh.cellZones()
+            )
+        );
+        dummyMesh.addZones(pz, fz, cz);
+        //Pout<< "Writing dummy mesh to " << dummyMesh.polyMesh::objectPath()
+        //    << endl;
+        dummyMesh.write();
+    }
+
+    //Pout<< "Reading mesh from " << io.objectPath() << endl;
+    autoPtr<fvMesh> meshPtr(new fvMesh(io));
+    fvMesh& mesh = meshPtr();
+
+
+    // Sync patches
+    // ~~~~~~~~~~~~
+
+    if (Pstream::master())
+    {
+        // Send patches
+        for
+        (
+            int slave=Pstream::firstSlave();
+            slave<=Pstream::lastSlave();
+            slave++
+        )
+        {
+            OPstream toSlave(Pstream::scheduled, slave);
+            toSlave << mesh.boundaryMesh();
+        }
+    }
+    else
+    {
+        // Receive patches
+        IPstream fromMaster(Pstream::scheduled, Pstream::masterNo());
+        PtrList<entry> patchEntries(fromMaster);
+
+        if (haveMesh)
+        {
+            // Check master names against mine
+
+            const polyBoundaryMesh& patches = mesh.boundaryMesh();
+
+            forAll(patchEntries, patchI)
+            {
+                const entry& e = patchEntries[patchI];
+                const word type(e.dict().lookup("type"));
+                const word& name = e.keyword();
+
+                if (type == processorPolyPatch::typeName)
+                {
+                    break;
+                }
+
+                if (patchI >= patches.size())
+                {
+                    FatalErrorIn
+                    (
+                        "createMesh(const Time&, const fileName&, const bool)"
+                    )   << "Non-processor patches not synchronised."
+                        << endl
+                        << "Processor " << Pstream::myProcNo()
+                        << " has only " << patches.size()
+                        << " patches, master has "
+                        << patchI
+                        << exit(FatalError);
+                }
+
+                if
+                (
+                    type != patches[patchI].type()
+                 || name != patches[patchI].name()
+                )
+                {
+                    FatalErrorIn
+                    (
+                        "createMesh(const Time&, const fileName&, const bool)"
+                    )   << "Non-processor patches not synchronised."
+                        << endl
+                        << "Master patch " << patchI
+                        << " name:" << type
+                        << " type:" << type << endl
+                        << "Processor " << Pstream::myProcNo()
+                        << " patch " << patchI
+                        << " has name:" << patches[patchI].name()
+                        << " type:" << patches[patchI].type()
+                        << exit(FatalError);
+                }
+            }
+        }
+        else
+        {
+            // Add patch
+            List<polyPatch*> patches(patchEntries.size());
+            label nPatches = 0;
+
+            forAll(patchEntries, patchI)
+            {
+                const entry& e = patchEntries[patchI];
+                const word type(e.dict().lookup("type"));
+                const word& name = e.keyword();
+
+                if (type == processorPolyPatch::typeName)
+                {
+                    break;
+                }
+
+                //Pout<< "Adding patch:" << nPatches
+                //    << " name:" << name << " type:" << type << endl;
+
+                dictionary patchDict(e.dict());
+                patchDict.remove("nFaces");
+                patchDict.add("nFaces", 0);
+                patchDict.remove("startFace");
+                patchDict.add("startFace", 0);
+
+                patches[patchI] = polyPatch::New
+                (
+                    name,
+                    patchDict,
+                    nPatches++,
+                    mesh.boundaryMesh()
+                ).ptr();
+            }
+            patches.setSize(nPatches);
+            mesh.addFvPatches(patches, false);  // no parallel comms
+
+            //// Write empty mesh now we have correct patches
+            //meshPtr().write();
+        }
+    }
+
+
+    // Determine zones
+    // ~~~~~~~~~~~~~~~
+
+    wordList pointZoneNames(mesh.pointZones().names());
+    Pstream::scatter(pointZoneNames);
+    wordList faceZoneNames(mesh.faceZones().names());
+    Pstream::scatter(faceZoneNames);
+    wordList cellZoneNames(mesh.cellZones().names());
+    Pstream::scatter(cellZoneNames);
+
+    if (!haveMesh)
+    {
+        // Add the zones. Make sure to remove the old dummy ones first
+        mesh.pointZones().clear();
+        mesh.faceZones().clear();
+        mesh.cellZones().clear();
+
+        List<pointZone*> pz(pointZoneNames.size());
+        forAll(pointZoneNames, i)
+        {
+            pz[i] = new pointZone
+            (
+                pointZoneNames[i],
+                labelList(0),
+                i,
+                mesh.pointZones()
+            );
+        }
+        List<faceZone*> fz(faceZoneNames.size());
+        forAll(faceZoneNames, i)
+        {
+            fz[i] = new faceZone
+            (
+                faceZoneNames[i],
+                labelList(0),
+                boolList(0),
+                i,
+                mesh.faceZones()
+            );
+        }
+        List<cellZone*> cz(cellZoneNames.size());
+        forAll(cellZoneNames, i)
+        {
+            cz[i] = new cellZone
+            (
+                cellZoneNames[i],
+                labelList(0),
+                i,
+                mesh.cellZones()
+            );
+        }
+        mesh.addZones(pz, fz, cz);
+    }
+
+
+    if (!haveMesh)
+    {
+        // We created a dummy mesh file above. Delete it.
+        //Pout<< "Removing dummy mesh " << io.objectPath() << endl;
+        rmDir(io.objectPath());
+    }
+
+    // Force recreation of globalMeshData.
+    mesh.clearOut();
+    mesh.globalData();
+
+
+    // Do some checks.
+
+    // Check if the boundary definition is unique
+    mesh.boundaryMesh().checkDefinition(true);
+    // Check if the boundary processor patches are correct
+    mesh.boundaryMesh().checkParallelSync(true);
+    // Check names of zones are equal
+    mesh.cellZones().checkDefinition(true);
+    mesh.cellZones().checkParallelSync(true);
+    mesh.faceZones().checkDefinition(true);
+    mesh.faceZones().checkParallelSync(true);
+    mesh.pointZones().checkDefinition(true);
+    mesh.pointZones().checkParallelSync(true);
+
+    return meshPtr;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.H b/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.H
new file mode 100644
index 0000000000000000000000000000000000000000..73d6dfd1c77da43399e69cdc561ca5331c4304d0
--- /dev/null
+++ b/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.H
@@ -0,0 +1,58 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  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/>.
+
+InNamespace
+    Foam
+
+Description
+    Load or create (0 size) a mesh. Used in distributing meshes to a
+    larger number of processors
+
+SourceFiles
+    loadOrCreateMesh.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef loadOrCreateMesh_H
+#define loadOrCreateMesh_H
+
+#include "fvMesh.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+//- Load (if it exists) or create zero cell mesh given an IOobject:
+//      name     : regionName
+//      instance : exact directory where to find mesh (i.e. does not
+//                 do a findInstance
+autoPtr<fvMesh> loadOrCreateMesh(const IOobject& io);
+
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //