diff --git a/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C b/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C
new file mode 100644
index 0000000000..9e68e1f726
--- /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 .
+
+\*---------------------------------------------------------------------------*/
+
+#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::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 pz
+ (
+ 1,
+ new pointZone
+ (
+ "dummyPointZone",
+ labelList(0),
+ 0,
+ dummyMesh.pointZones()
+ )
+ );
+ List fz
+ (
+ 1,
+ new faceZone
+ (
+ "dummyFaceZone",
+ labelList(0),
+ boolList(0),
+ 0,
+ dummyMesh.faceZones()
+ )
+ );
+ List 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 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 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 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 pz(pointZoneNames.size());
+ forAll(pointZoneNames, i)
+ {
+ pz[i] = new pointZone
+ (
+ pointZoneNames[i],
+ labelList(0),
+ i,
+ mesh.pointZones()
+ );
+ }
+ List fz(faceZoneNames.size());
+ forAll(faceZoneNames, i)
+ {
+ fz[i] = new faceZone
+ (
+ faceZoneNames[i],
+ labelList(0),
+ boolList(0),
+ i,
+ mesh.faceZones()
+ );
+ }
+ List 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 0000000000..73d6dfd1c7
--- /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 .
+
+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 loadOrCreateMesh(const IOobject& io);
+
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //