diff --git a/applications/solvers/electromagnetics/mhdFoam/createPhiB.H b/applications/solvers/electromagnetics/mhdFoam/createPhiB.H
index 21076a51a5914c8fed9cd94a6a946e2a37f9222d..02b48f8d2809352fba68bb274bed8aa0e8f181ac 100644
--- a/applications/solvers/electromagnetics/mhdFoam/createPhiB.H
+++ b/applications/solvers/electromagnetics/mhdFoam/createPhiB.H
@@ -9,7 +9,7 @@ IOobject phiBHeader
 
 surfaceScalarField* phiBPtr = nullptr;
 
-    if (phiBHeader.typeHeaderOk<surfaceScalarField>(true))
+if (phiBHeader.typeHeaderOk<surfaceScalarField>(true))
 {
     Info<< "Reading face flux ";
 
diff --git a/applications/solvers/heatTransfer/thermoFoam/setAlphaEff.H b/applications/solvers/heatTransfer/thermoFoam/setAlphaEff.H
index c760349a6eb0efa409467f47e21c735a82a7d3af..e7da9c6af68050ba26abf6891cc6075340e860c1 100644
--- a/applications/solvers/heatTransfer/thermoFoam/setAlphaEff.H
+++ b/applications/solvers/heatTransfer/thermoFoam/setAlphaEff.H
@@ -11,7 +11,7 @@ IOobject turbulencePropertiesHeader
     false
 );
 
-if (turbulencePropertiesHeader.typeHeaderOk<IOdictionary>(false))
+if (turbulencePropertiesHeader.typeHeaderOk<IOdictionary>(true))
 {
     autoPtr<compressible::turbulenceModel> turbulence
     (
diff --git a/applications/test/CompactIOList/Test-CompactIOList.C b/applications/test/CompactIOList/Test-CompactIOList.C
index 12d64c6bde9eea6cb050a83f4734e37453830b05..2024e663e094f4d535b970ed87e334eab6ccea44 100644
--- a/applications/test/CompactIOList/Test-CompactIOList.C
+++ b/applications/test/CompactIOList/Test-CompactIOList.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -87,7 +87,8 @@ int main(int argc, char *argv[])
         (
             format,
             IOstream::currentVersion,
-            IOstream::UNCOMPRESSED
+            IOstream::UNCOMPRESSED,
+            true
         );
 
         Info<< "Written old format faceList in = "
@@ -149,7 +150,8 @@ int main(int argc, char *argv[])
         (
             format,
             IOstream::currentVersion,
-            IOstream::UNCOMPRESSED
+            IOstream::UNCOMPRESSED,
+            true
         );
 
         Info<< "Written new format faceList in = "
diff --git a/applications/test/IOField/Make/files b/applications/test/IOField/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..74e614deae50fd2db849cc673414cb8b1e651153
--- /dev/null
+++ b/applications/test/IOField/Make/files
@@ -0,0 +1,3 @@
+Test-IOField.C
+
+EXE = $(FOAM_USER_APPBIN)/Test-IOField
diff --git a/applications/test/IOField/Make/options b/applications/test/IOField/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..6a9e9810b3d5ce6684bdaf03143933480ff45e42
--- /dev/null
+++ b/applications/test/IOField/Make/options
@@ -0,0 +1,2 @@
+/* EXE_INC = -I$(LIB_SRC)/cfdTools/include */
+/* EXE_LIBS = -lfiniteVolume */
diff --git a/applications/test/IOField/Test-IOField.C b/applications/test/IOField/Test-IOField.C
new file mode 100644
index 0000000000000000000000000000000000000000..d49acaf8f570a2b52c6366282a7f12edbb2bb6ee
--- /dev/null
+++ b/applications/test/IOField/Test-IOField.C
@@ -0,0 +1,189 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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/>.
+
+Application
+    Test-IOField
+
+Description
+    Test the processor-local reading of IOField (used in the lagrangian libs)
+
+\*---------------------------------------------------------------------------*/
+
+#include "IOField.H"
+#include "argList.H"
+#include "polyMesh.H"
+#include "Time.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+void write(const IOobject& io, const label sz)
+{
+    IOField<label> fld(io, sz);
+    forAll(fld, i)
+    {
+        fld[i] = i+1000;
+    }
+    Pout<< "writing:" << fld << endl;
+    fld.write(sz > 0);
+}
+
+
+void read(const IOobject& io, const label sz)
+{
+    bool valid = (sz > 0);
+    Pout<< "    valid:" << valid << endl;
+    IOField<label> fld(io, valid);
+    Pout<< "    wanted:" << sz << " actually read:" << fld.size() << endl;
+
+    if (fld.size() != sz)
+    {
+        FatalErrorInFunction<< "io:" << io.objectPath() << exit(FatalError);
+    }
+}
+
+
+void writeAndRead
+(
+    const IOobject& io,
+    const label sz,
+    const word& writeType,
+    const IOobject::readOption readOpt,
+    const word& readType
+)
+{
+    Pout<< "** Writing:" << writeType
+        << " Reading:" << readType << endl;
+
+    autoPtr<fileOperation> writeHandler(fileOperation::New(writeType));
+    fileHandler(writeHandler);
+
+    // Delete
+    Pout<< "Deleting:" << fileHandler().filePath(io.objectPath()) << endl;
+    fileHandler().rm(fileHandler().filePath(io.objectPath()));
+
+    // Write
+    Pout<< "Writing:" << fileHandler().objectPath(io) << endl;
+    write(io, sz);
+
+    autoPtr<fileOperation> readHandler(fileOperation::New(readType));
+    fileHandler(readHandler);
+
+    // Read
+    IOobject readIO(io);
+    readIO.readOpt() = readOpt;
+    Pout<< "Reading:" << fileHandler().filePath(readIO.objectPath()) << endl;
+    read(readIO, sz);
+
+    Pout<< "** Done writing:" << writeType
+        << " Reading:" << readType << endl << endl << endl;
+}
+
+
+void readIfPresent
+(
+    IOobject& io,
+    const label sz,
+    const word& readType
+)
+{
+    autoPtr<fileOperation> readHandler(fileOperation::New(readType));
+    fileHandler(readHandler);
+
+    // Read
+    Pout<< "Reading:" << fileHandler().filePath(io.objectPath()) << endl;
+    io.readOpt() = IOobject::READ_IF_PRESENT;
+    read(io, sz);
+}
+
+
+// Main program:
+
+int main(int argc, char *argv[])
+{
+    #include "addTimeOptions.H"
+    #include "setRootCase.H"
+    #include "createTime.H"
+    #include "createPolyMesh.H"
+
+    label sz = 0;
+    if (Pstream::myProcNo() % 2)
+    {
+        sz = 1;
+    }
+
+    IOobject io
+    (
+        "bla",
+        runTime.timeName(),
+        mesh,
+        IOobject::NO_READ,
+        IOobject::NO_WRITE
+    );
+
+    wordList handlers
+    (
+        Foam::fileOperation::wordConstructorTablePtr_->sortedToc()
+    );
+
+    Info<< "Found handlers:" << handlers << endl;
+
+
+/*
+    forAll(handlers, readi)
+    {
+        const word& readHandler = handlers[readi];
+
+        readIfPresent(io, sz, readHandler);
+    }
+*/
+
+
+    forAll(handlers, writei)
+    {
+        const word& writeHandler = handlers[writei];
+
+        forAll(handlers, readi)
+        {
+            const word& readHandler = handlers[readi];
+
+            writeAndRead
+            (
+                io,
+                sz,
+                writeHandler,
+                IOobject::READ_IF_PRESENT,
+                readHandler
+            );
+        }
+    }
+
+
+    Pout<< "End\n" << endl;
+
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/test/decomposedBlockData/Make/files b/applications/test/decomposedBlockData/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..3d33e10b6167317a1329d07ba5ad66af68b60a36
--- /dev/null
+++ b/applications/test/decomposedBlockData/Make/files
@@ -0,0 +1,3 @@
+Test-decomposedBlockData.C
+
+EXE = $(FOAM_USER_APPBIN)/Test-decomposedBlockData
diff --git a/applications/test/decomposedBlockData/Make/options b/applications/test/decomposedBlockData/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/applications/test/decomposedBlockData/Test-decomposedBlockData.C b/applications/test/decomposedBlockData/Test-decomposedBlockData.C
new file mode 100644
index 0000000000000000000000000000000000000000..1c8676549762acbef5b69ce1049f16a02dc68040
--- /dev/null
+++ b/applications/test/decomposedBlockData/Test-decomposedBlockData.C
@@ -0,0 +1,98 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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/>.
+
+Application
+    Test-decomposedBlockData
+
+Description
+    Convert decomposedBlockData into its components.
+
+\*---------------------------------------------------------------------------*/
+
+#include "argList.H"
+#include "Time.H"
+#include "decomposedBlockData.H"
+#include "OFstream.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+//  Main program:
+
+int main(int argc, char *argv[])
+{
+    argList::validArgs.append("file");
+    #include "setRootCase.H"
+
+    if (!Pstream::parRun())
+    {
+        FatalErrorInFunction
+            << "Run in parallel" << exit(FatalError);
+    }
+
+    #include "createTime.H"
+
+    const fileName file(args[1]);
+
+    Info<< "Reading " << file << nl << endl;
+    decomposedBlockData data
+    (
+        Pstream::worldComm,
+        IOobject
+        (
+            file,
+            runTime,
+            IOobject::MUST_READ,
+            IOobject::NO_WRITE,
+            false
+        )
+    );
+
+    data.rename(data.name() + "Data");
+    fileName objPath(data.objectPath());
+    mkDir(objPath.path());
+    Info<< "Opening output file " << objPath << nl << endl;
+    OFstream os
+    (
+        objPath,
+        IOstream::BINARY,
+        IOstream::currentVersion,
+        runTime.writeCompression()
+    );
+    if (!os.good())
+    {
+        FatalErrorInFunction
+            << "Failed opening " << objPath << exit(FatalError);
+    }
+
+    if (!data.writeData(os))
+    {
+        FatalErrorInFunction
+            << "Failed writing " << objPath << exit(FatalError);
+    }
+
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/test/surfaceMeshConvert/Test-surfaceMeshConvert.C b/applications/test/surfaceMeshConvert/Test-surfaceMeshConvert.C
index 39cc729ba3a8b203ae62e9c26c84aa84202c1f17..c74dcf96af701db8b72b90d1942179d2eee45a7d 100644
--- a/applications/test/surfaceMeshConvert/Test-surfaceMeshConvert.C
+++ b/applications/test/surfaceMeshConvert/Test-surfaceMeshConvert.C
@@ -498,7 +498,9 @@ int main(int argc, char *argv[])
             Info<< "surfIn = " << surfIn.size() << endl;
 
             Info<< "writing surfMesh as obj = oldSurfIn.obj" << endl;
-            surfIn.write("oldSurfIn.obj");
+
+            using Foam::surfMesh;
+            surfIn.write(fileName("oldSurfIn.obj"));
 
             Info<< "runTime.instance() = " << runTime.instance() << endl;
 
@@ -550,7 +552,7 @@ int main(int argc, char *argv[])
             surfOut.write();
 
             // write directly
-            surfOut.write("someName.ofs");
+            surfOut.surfMesh::write(fileName("someName.ofs"));
 
 #if 1
             const surfZoneList& zones = surfOut.surfZones();
diff --git a/applications/utilities/mesh/advanced/modifyMesh/modifyMesh.C b/applications/utilities/mesh/advanced/modifyMesh/modifyMesh.C
index 8996c8afdc528e09f886fac477134c7f23f24aa9..4ac6cf6017367cdd0c488ef27e1189a1865b7830 100644
--- a/applications/utilities/mesh/advanced/modifyMesh/modifyMesh.C
+++ b/applications/utilities/mesh/advanced/modifyMesh/modifyMesh.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -64,6 +64,7 @@ Description
 #include "globalIndex.H"
 #include "topoSet.H"
 #include "processorMeshes.H"
+#include "IOdictionary.H"
 
 using namespace Foam;
 
diff --git a/applications/utilities/mesh/advanced/selectCells/edgeStats.C b/applications/utilities/mesh/advanced/selectCells/edgeStats.C
index 980219c970fa195d12c90c399997b85204c44765..907bb665f103bd1cc4d7af6e24beeef67df9c3a8 100644
--- a/applications/utilities/mesh/advanced/selectCells/edgeStats.C
+++ b/applications/utilities/mesh/advanced/selectCells/edgeStats.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2014 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -28,6 +28,7 @@ License
 #include "polyMesh.H"
 #include "Ostream.H"
 #include "twoDPointCorrector.H"
+#include "IOdictionary.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -143,10 +144,8 @@ Foam::scalar Foam::edgeStats::minLen(Ostream& os) const
 
     const edgeList& edges = mesh_.edges();
 
-    forAll(edges, edgeI)
+    forAll(const edge& e : edges)
     {
-        const edge& e = edges[edgeI];
-
         vector eVec(e.vec(mesh_.points()));
 
         scalar eMag = mag(eVec);
@@ -209,13 +208,5 @@ Foam::scalar Foam::edgeStats::minLen(Ostream& os) const
 }
 
 
-// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
-
-
-// * * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * //
-
-
-// * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
-
 
 // ************************************************************************* //
diff --git a/applications/utilities/mesh/conversion/foamToStarMesh/foamToStarMesh.C b/applications/utilities/mesh/conversion/foamToStarMesh/foamToStarMesh.C
index f8fe44f19fc05c81ff81eaa76bf2032e73a89d76..047e48be44319f39d63f35cb9f1e8f7ad2250617 100644
--- a/applications/utilities/mesh/conversion/foamToStarMesh/foamToStarMesh.C
+++ b/applications/utilities/mesh/conversion/foamToStarMesh/foamToStarMesh.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -57,6 +57,7 @@ See also
 #include "Time.H"
 #include "polyMesh.H"
 #include "STARCDMeshWriter.H"
+#include "IOdictionary.H"
 
 using namespace Foam;
 
@@ -134,4 +135,5 @@ int main(int argc, char *argv[])
     return 0;
 }
 
+
 // ************************************************************************* //
diff --git a/applications/utilities/mesh/conversion/foamToSurface/foamToSurface.C b/applications/utilities/mesh/conversion/foamToSurface/foamToSurface.C
index 404b5b7e65a27f367615ae6c6914316017b173a2..7da047ad5ca778a780eed4c131f467ed675b6039 100644
--- a/applications/utilities/mesh/conversion/foamToSurface/foamToSurface.C
+++ b/applications/utilities/mesh/conversion/foamToSurface/foamToSurface.C
@@ -47,7 +47,7 @@ Usage
 #include "timeSelector.H"
 #include "Time.H"
 #include "polyMesh.H"
-
+#include "IOdictionary.H"
 #include "MeshedSurfaces.H"
 
 using namespace Foam;
diff --git a/applications/utilities/mesh/generation/foamyMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMeshIO.C b/applications/utilities/mesh/generation/foamyMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMeshIO.C
index 5d6232510b6fda478a9cca6f90094950ee759080..5a4b0bafde9ac8607d9995dd19c0a0ede68a8b8a 100644
--- a/applications/utilities/mesh/generation/foamyMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMeshIO.C
+++ b/applications/utilities/mesh/generation/foamyMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMeshIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2012-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -387,7 +387,7 @@ Foam::DelaunayMesh<Triangulation>::createMesh
             IOobject::NO_READ,
             IOobject::AUTO_WRITE
         ),
-        Triangulation::number_of_vertices()
+        label(Triangulation::number_of_vertices())
     );
 
     labelIOField processorIndices
@@ -401,7 +401,7 @@ Foam::DelaunayMesh<Triangulation>::createMesh
             IOobject::NO_READ,
             IOobject::AUTO_WRITE
         ),
-        Triangulation::number_of_vertices()
+        label(Triangulation::number_of_vertices())
     );
 
     for
diff --git a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
index 00f2c7d05d9ab3c67536afe45156a81db16ee9ea..619d84eca5aeaccdeac9c4de48dc820d21d97149 100644
--- a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
+++ b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
@@ -531,6 +531,7 @@ void extractSurface
           ? runTime.path()/".."/outFileName
           : runTime.path()/outFileName
         );
+        globalCasePath.clean();
 
         Info<< "Writing merged surface to " << globalCasePath << endl;
 
diff --git a/applications/utilities/mesh/manipulation/checkMesh/checkMesh.C b/applications/utilities/mesh/manipulation/checkMesh/checkMesh.C
index a8905b30a93ab8cd65ae6cd79abf68b13dfb0c10..6d1cee15ad621ab255ed030b6003648a9d34b265 100644
--- a/applications/utilities/mesh/manipulation/checkMesh/checkMesh.C
+++ b/applications/utilities/mesh/manipulation/checkMesh/checkMesh.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2015-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -67,6 +67,7 @@ Usage
 #include "globalMeshData.H"
 #include "surfaceWriter.H"
 #include "vtkSetWriter.H"
+#include "IOdictionary.H"
 
 #include "checkTools.H"
 #include "checkTopology.H"
diff --git a/applications/utilities/mesh/manipulation/checkMesh/checkTools.C b/applications/utilities/mesh/manipulation/checkMesh/checkTools.C
index 456ce03b8e878de0d19b44e1aa2dc53a7171c19e..b68047b11db0f425641cf7d2d73387096f6bee0d 100644
--- a/applications/utilities/mesh/manipulation/checkMesh/checkTools.C
+++ b/applications/utilities/mesh/manipulation/checkMesh/checkTools.C
@@ -281,7 +281,7 @@ void Foam::mergeAndWrite
         mesh.points()
     );
 
-    const fileName outputDir
+    fileName outputDir
     (
         set.time().path()
       / (Pstream::parRun() ? ".." : "")
@@ -289,6 +289,7 @@ void Foam::mergeAndWrite
       / mesh.pointsInstance()
       / set.name()
     );
+    outputDir.clean();
 
     mergeAndWrite(mesh, writer, set.name(), setPatch, outputDir);
 }
@@ -374,7 +375,7 @@ void Foam::mergeAndWrite
         mesh.points()
     );
 
-    const fileName outputDir
+    fileName outputDir
     (
         set.time().path()
       / (Pstream::parRun() ? ".." : "")
@@ -382,6 +383,7 @@ void Foam::mergeAndWrite
       / mesh.pointsInstance()
       / set.name()
     );
+    outputDir.clean();
 
     mergeAndWrite(mesh, writer, set.name(), setPatch, outputDir);
 }
@@ -477,7 +479,7 @@ void Foam::mergeAndWrite
 
         // Output e.g. pointSet p0 to
         // postProcessing/<time>/p0.vtk
-        const fileName outputDir
+        fileName outputDir
         (
             set.time().path()
           / (Pstream::parRun() ? ".." : "")
@@ -485,6 +487,7 @@ void Foam::mergeAndWrite
           / mesh.pointsInstance()
           // set.name()
         );
+        outputDir.clean();
         mkDir(outputDir);
 
         fileName outputFile(outputDir/writer.getFileName(points, wordList()));
diff --git a/applications/utilities/mesh/manipulation/createPatch/createPatch.C b/applications/utilities/mesh/manipulation/createPatch/createPatch.C
index 55060ae39898b9e65eca1ec7c5bad75c10c0deac..251f7641e64e833d107d4a1b17b1500ad5da3d39 100644
--- a/applications/utilities/mesh/manipulation/createPatch/createPatch.C
+++ b/applications/utilities/mesh/manipulation/createPatch/createPatch.C
@@ -53,6 +53,7 @@ Description
 #include "polyModifyFace.H"
 #include "wordReList.H"
 #include "processorMeshes.H"
+#include "IOdictionary.H"
 
 using namespace Foam;
 
diff --git a/applications/utilities/mesh/manipulation/refineMesh/refineMesh.C b/applications/utilities/mesh/manipulation/refineMesh/refineMesh.C
index 219513850fdf4852c7702b6a8a63e082cabc596a..ecd1d89e077ddcf0f97525ff70c242c226238039 100644
--- a/applications/utilities/mesh/manipulation/refineMesh/refineMesh.C
+++ b/applications/utilities/mesh/manipulation/refineMesh/refineMesh.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -54,6 +54,7 @@ Description
 #include "wedgePolyPatch.H"
 #include "plane.H"
 #include "SubField.H"
+#include "IOdictionary.H"
 
 using namespace Foam;
 
diff --git a/applications/utilities/mesh/manipulation/setSet/setSet.C b/applications/utilities/mesh/manipulation/setSet/setSet.C
index df20caa2fffe1a40cfea529922ebdd403eb6cec1..3a7b554ee282256a46613bddcb73dccf03a5c05f 100644
--- a/applications/utilities/mesh/manipulation/setSet/setSet.C
+++ b/applications/utilities/mesh/manipulation/setSet/setSet.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -52,6 +52,7 @@ Description
 #include "faceZoneSet.H"
 #include "pointZoneSet.H"
 #include "timeSelector.H"
+#include "collatedFileOperation.H"
 
 #include <stdio.h>
 
@@ -743,6 +744,11 @@ commandStatus parseAction(const word& actionName)
 
 int main(int argc, char *argv[])
 {
+    // Specific to topoSet/setSet: quite often we want to block upon writing
+    // a set so we can immediately re-read it. So avoid use of threading
+    // for set writing.
+    fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0;
+
     timeSelector::addOptions(true, false);
     #include "addRegionOption.H"
     argList::addBoolOption("noVTK", "do not write VTK files");
diff --git a/applications/utilities/mesh/manipulation/stitchMesh/stitchMesh.C b/applications/utilities/mesh/manipulation/stitchMesh/stitchMesh.C
index c056932f3c0ee39f192a2a4178396ca913da6f87..1fa978d1259c95e8f8e92591cab8fc110045973c 100644
--- a/applications/utilities/mesh/manipulation/stitchMesh/stitchMesh.C
+++ b/applications/utilities/mesh/manipulation/stitchMesh/stitchMesh.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -487,7 +487,8 @@ int main(int argc, char *argv[])
         (
             runTime.writeFormat(),
             IOstream::currentVersion,
-            runTime.writeCompression()
+            runTime.writeCompression(),
+            true
         )
     )
     {
diff --git a/applications/utilities/mesh/manipulation/topoSet/topoSet.C b/applications/utilities/mesh/manipulation/topoSet/topoSet.C
index eb03d855f1682c2e4fb7a311fb45ea845a9f8cce..e3df780cabed43a682d05015ec92e4c1a4feddaf 100644
--- a/applications/utilities/mesh/manipulation/topoSet/topoSet.C
+++ b/applications/utilities/mesh/manipulation/topoSet/topoSet.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -42,6 +42,8 @@ Description
 #include "cellZoneSet.H"
 #include "faceZoneSet.H"
 #include "pointZoneSet.H"
+#include "IOdictionary.H"
+#include "collatedFileOperation.H"
 
 using namespace Foam;
 
@@ -194,6 +196,11 @@ polyMesh::readUpdateState meshReadUpdate(polyMesh& mesh)
 
 int main(int argc, char *argv[])
 {
+    // Specific to topoSet/setSet: quite often we want to block upon writing
+    // a set so we can immediately re-read it. So avoid use of threading
+    // for set writing.
+    fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0;
+
     timeSelector::addOptions(true, false);
     #include "addDictOption.H"
     #include "addRegionOption.H"
diff --git a/applications/utilities/miscellaneous/foamFormatConvert/foamFormatConvert.C b/applications/utilities/miscellaneous/foamFormatConvert/foamFormatConvert.C
index b024745f42a79c95989af936e582ce7d79be65c8..c68438c0e484762f4be499ef1ad95f95e97c2edd 100644
--- a/applications/utilities/miscellaneous/foamFormatConvert/foamFormatConvert.C
+++ b/applications/utilities/miscellaneous/foamFormatConvert/foamFormatConvert.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -62,9 +62,19 @@ Usage
 #include "cellIOList.H"
 #include "IOobjectList.H"
 #include "IOPtrList.H"
+#include "cloud.H"
+#include "labelIOField.H"
+#include "scalarIOField.H"
+#include "sphericalTensorIOField.H"
+#include "symmTensorIOField.H"
+#include "tensorIOField.H"
+#include "labelFieldIOField.H"
+#include "vectorFieldIOField.H"
+#include "Cloud.H"
+#include "passiveParticle.H"
+#include "fieldDictionary.H"
 
 #include "writeMeshObject.H"
-#include "fieldDictionary.H"
 
 using namespace Foam;
 
@@ -143,7 +153,8 @@ bool writeZones(const word& name, const fileName& meshDir, Time& runTime)
         (
             IOstream::ASCII,
             IOstream::currentVersion,
-            runTime.writeCompression()
+            runTime.writeCompression(),
+            true
         );
     }
 
@@ -151,6 +162,75 @@ bool writeZones(const word& name, const fileName& meshDir, Time& runTime)
 }
 
 
+// Reduction for non-empty strings
+class uniqueEqOp
+{
+    public:
+    void operator()(stringList& x, const stringList& y) const
+    {
+        stringList newX(x.size()+y.size());
+        label n = 0;
+        forAll(x, i)
+        {
+            if (!x[i].empty())
+            {
+                newX[n++] = x[i];
+            }
+        }
+        forAll(y, i)
+        {
+            if (!y[i].empty() && findIndex(x, y[i]) == -1)
+            {
+                newX[n++] = y[i];
+            }
+        }
+        newX.setSize(n);
+        x.transfer(newX);
+    }
+};
+
+
+template<class T>
+bool writeOptionalMeshObject
+(
+    const word& name,
+    const fileName& meshDir,
+    Time& runTime,
+    const bool valid
+)
+{
+    IOobject io
+    (
+        name,
+        runTime.timeName(),
+        meshDir,
+        runTime,
+        IOobject::MUST_READ,
+        IOobject::NO_WRITE,
+        false
+    );
+
+    bool writeOk = false;
+
+    bool haveFile = io.typeHeaderOk<IOField<label>>(false);
+
+    // Make sure all know if there is a valid class name
+    stringList classNames(1, io.headerClassName());
+    combineReduce(classNames, uniqueEqOp());
+
+    // Check for correct type
+    if (classNames[0] == T::typeName)
+    {
+        Info<< "        Reading " << classNames[0]
+            << " : " << name << endl;
+        T meshObject(io, valid && haveFile);
+
+        Info<< "        Writing " << name << endl;
+        writeOk = meshObject.regIOobject::write(valid && haveFile);
+    }
+
+    return writeOk;
+}
 
 
 int main(int argc, char *argv[])
@@ -183,6 +263,8 @@ int main(int argc, char *argv[])
 
 
     #include "createTime.H"
+    // Optional mesh (used to read Clouds)
+    autoPtr<polyMesh> meshPtr;
 
     const bool enableEntries = args.optionFound("enableFunctionEntries");
     if (enableEntries)
@@ -221,11 +303,24 @@ int main(int argc, char *argv[])
         Info<< "Time = " << runTime.timeName() << endl;
 
         // Convert all the standard mesh files
-        writeMeshObject<cellCompactIOList>("cells", meshDir, runTime);
+        writeMeshObject<cellCompactIOList, cellIOList>
+        (
+            "cells",
+            meshDir,
+            runTime
+        );
         writeMeshObject<labelIOList>("owner", meshDir, runTime);
         writeMeshObject<labelIOList>("neighbour", meshDir, runTime);
-        writeMeshObject<faceCompactIOList>("faces", meshDir, runTime);
+        writeMeshObject<faceCompactIOList, faceIOList>
+        (
+            "faces",
+            meshDir,
+            runTime
+        );
         writeMeshObject<pointIOField>("points", meshDir, runTime);
+        // Write boundary in ascii. This is only needed for fileHandler to
+        // kick in. Should not give problems since always writing ascii.
+        writeZones("boundary", meshDir, runTime);
         writeMeshObject<labelIOList>("pointProcAddressing", meshDir, runTime);
         writeMeshObject<labelIOList>("faceProcAddressing", meshDir, runTime);
         writeMeshObject<labelIOList>("cellProcAddressing", meshDir, runTime);
@@ -279,22 +374,196 @@ int main(int argc, char *argv[])
              || headerClassName == pointSphericalTensorField::typeName
              || headerClassName == pointSymmTensorField::typeName
              || headerClassName == pointTensorField::typeName
+
+             || headerClassName == volScalarField::Internal::typeName
+             || headerClassName == volVectorField::Internal::typeName
+             || headerClassName == volSphericalTensorField::Internal::typeName
+             || headerClassName == volSymmTensorField::Internal::typeName
+             || headerClassName == volTensorField::Internal::typeName
             )
             {
                 Info<< "        Reading " << headerClassName
                     << " : " << iter()->name() << endl;
 
-                fieldDictionary fDict
-                (
-                    *iter(),
-                    headerClassName
-                );
+                fieldDictionary fDict(*iter(), headerClassName);
 
                 Info<< "        Writing " << iter()->name() << endl;
                 fDict.regIOobject::write();
             }
         }
 
+
+
+        // Check for lagrangian
+        stringList lagrangianDirs
+        (
+            1,
+            fileHandler().filePath
+            (
+                runTime.timePath()
+              / regionPrefix
+              / cloud::prefix
+            )
+        );
+
+        combineReduce(lagrangianDirs, uniqueEqOp());
+
+        if (!lagrangianDirs.empty())
+        {
+            if (meshPtr.valid())
+            {
+                meshPtr().readUpdate();
+            }
+            else
+            {
+                Info<< "        Create polyMesh for time = "
+                    << runTime.timeName() << endl;
+
+                meshPtr.reset
+                (
+                    new polyMesh
+                    (
+                        IOobject
+                        (
+                            polyMesh::defaultRegion,
+                            runTime.timeName(),
+                            runTime,
+                            Foam::IOobject::MUST_READ
+                        )
+                    )
+                );
+            }
+
+            stringList cloudDirs
+            (
+                fileHandler().readDir
+                (
+                    lagrangianDirs[0],
+                    fileName::DIRECTORY
+                )
+            );
+
+            combineReduce(cloudDirs, uniqueEqOp());
+
+            forAll(cloudDirs, i)
+            {
+                fileName dir(cloud::prefix/cloudDirs[i]);
+
+                Cloud<passiveParticle> parcels(meshPtr(), cloudDirs[i], false);
+
+                parcels.writeObject
+                (
+                    runTime.writeFormat(),
+                    IOstream::currentVersion,
+                    runTime.writeCompression(),
+                    parcels.size()
+                );
+
+
+                // Do local scan for valid cloud objects
+                IOobjectList sprayObjs(runTime, runTime.timeName(), dir);
+
+                // Combine with all other cloud objects
+                stringList sprayFields(sprayObjs.sortedToc());
+                combineReduce(sprayFields, uniqueEqOp());
+
+                forAll(sprayFields, fieldi)
+                {
+                    const word& name = sprayFields[fieldi];
+
+                    // Note: try the various field types. Make sure to
+                    //       exit once sucessful conversion to avoid re-read
+                    //       converted file.
+
+                    if
+                    (
+                        name == "positions"
+                     || name == "origProcId"
+                     || name == "origId"
+                    )
+                    {
+                        continue;
+                    }
+
+                    bool writeOk = writeOptionalMeshObject<labelIOField>
+                    (
+                        name,
+                        dir,
+                        runTime,
+                        parcels.size() > 0
+                    );
+                    if (writeOk) continue;
+
+                    writeOk = writeOptionalMeshObject<scalarIOField>
+                    (
+                        name,
+                        dir,
+                        runTime,
+                        parcels.size() > 0
+                    );
+                    if (writeOk) continue;
+
+                    writeOk = writeOptionalMeshObject<vectorIOField>
+                    (
+                        name,
+                        dir,
+                        runTime,
+                        parcels.size() > 0
+                    );
+                    if (writeOk) continue;
+
+                    writeOk = writeOptionalMeshObject<sphericalTensorIOField>
+                    (
+                        name,
+                        dir,
+                        runTime,
+                        parcels.size() > 0
+                    );
+                    if (writeOk) continue;
+
+                    writeOk = writeOptionalMeshObject<symmTensorIOField>
+                    (
+                        name,
+                        dir,
+                        runTime,
+                        parcels.size() > 0
+                    );
+                    if (writeOk) continue;
+
+                    writeOk = writeOptionalMeshObject<tensorIOField>
+                    (
+                        name,
+                        dir,
+                        runTime,
+                        parcels.size() > 0
+                    );
+                    if (writeOk) continue;
+
+                    writeOk = writeOptionalMeshObject<labelFieldIOField>
+                    (
+                        name,
+                        dir,
+                        runTime,
+                        parcels.size() > 0
+                    );
+                    if (writeOk) continue;
+
+                    writeOk = writeOptionalMeshObject<vectorFieldIOField>
+                    (
+                        name,
+                        dir,
+                        runTime,
+                        parcels.size() > 0
+                    );
+
+                    if (!writeOk)
+                    {
+                        Info<< "        Failed converting " << name << endl;
+                    }
+                }
+            }
+        }
+
         Info<< endl;
     }
 
diff --git a/applications/utilities/miscellaneous/foamFormatConvert/writeMeshObject.H b/applications/utilities/miscellaneous/foamFormatConvert/writeMeshObject.H
index 06c064e077a0f409a437833e24d754da0774e8e4..87afd6cf424196b549dbd7ac4ac2a6215a792c2e 100644
--- a/applications/utilities/miscellaneous/foamFormatConvert/writeMeshObject.H
+++ b/applications/utilities/miscellaneous/foamFormatConvert/writeMeshObject.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -39,7 +39,7 @@ namespace Foam
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-template<class T>
+template<class Type, class CheckType = Type>
 inline bool writeMeshObject
 (
     const word& name,
@@ -61,7 +61,7 @@ inline bool writeMeshObject
 
     bool writeOk = false;
 
-    if (io.typeHeaderOk<T>(false))
+    if (io.typeHeaderOk<T>(true, true, false))
     {
         Info<< "        Reading " << io.headerClassName()
             << " : " << name << endl;
@@ -71,15 +71,15 @@ inline bool writeMeshObject
         word oldTypeName;
         if (disableHeaderChecking)
         {
-            oldTypeName = T::typeName;
-            const_cast<word&>(T::typeName) = word::null;
+            oldTypeName = Type::typeName;
+            const_cast<word&>(Type::typeName) = word::null;
         }
 
-        T meshObject(io);
+        Type meshObject(io);
 
         if (disableHeaderChecking)
         {
-            const_cast<word&>(T::typeName) = oldTypeName;
+            const_cast<word&>(Type::typeName) = oldTypeName;
             // Fake type back to what was in field
             const_cast<word&>(meshObject.type()) = io.headerClassName();
         }
diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
index e245698752642fcbdeec87d550de60893698a08d..2ccf7cf4bbb5433074080df81194c15047892bf0 100644
--- a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
+++ b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
@@ -104,6 +104,7 @@ Usage
 #include "pointFieldDecomposer.H"
 #include "lagrangianFieldDecomposer.H"
 #include "decompositionModel.H"
+#include "collatedFileOperation.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -157,13 +158,14 @@ void decomposeUniform
     // Any uniform data to copy/link?
     const fileName uniformDir(regionDir/"uniform");
 
-    if (isDir(runTime.timePath()/uniformDir))
+    if (fileHandler().isDir(runTime.timePath()/uniformDir))
     {
         Info<< "Detected additional non-decomposed files in "
             << runTime.timePath()/uniformDir
             << endl;
 
-        const fileName timePath = processorDb.timePath();
+        const fileName timePath =
+            fileHandler().filePath(processorDb.timePath());
 
         // If no fields have been decomposed the destination
         // directory will not have been created so make sure.
@@ -171,11 +173,14 @@ void decomposeUniform
 
         if (copyUniform || mesh.distributed())
         {
-            cp
-            (
-                runTime.timePath()/uniformDir,
-                timePath/uniformDir
-            );
+            if (!fileHandler().exists(timePath/uniformDir))
+            {
+                fileHandler().cp
+                (
+                    runTime.timePath()/uniformDir,
+                    timePath/uniformDir
+                );
+            }
         }
         else
         {
@@ -189,11 +194,15 @@ void decomposeUniform
 
             fileName currentDir(cwd());
             chDir(timePath);
-            ln
-            (
-                parentPath/runTime.timeName()/uniformDir,
-                uniformDir
-            );
+
+            if (!fileHandler().exists(uniformDir))
+            {
+                fileHandler().ln
+                (
+                    parentPath/runTime.timeName()/uniformDir,
+                    uniformDir
+                );
+            }
             chDir(currentDir);
         }
     }
@@ -329,24 +338,10 @@ int main(int argc, char *argv[])
         Info<< "\n\nDecomposing mesh " << regionName << nl << endl;
 
 
-        // determine the existing processor count directly
-        label nProcs = 0;
-        while
-        (
-            isDir
-            (
-                runTime.path()
-              / (word("processor") + name(nProcs))
-              / runTime.constant()
-              / regionDir
-              / polyMesh::meshSubDir
-            )
-        )
-        {
-            ++nProcs;
-        }
+        // Determine the existing processor count directly
+        label nProcs = fileHandler().nProcs(runTime.path(), regionDir);
 
-        // get requested numberOfSubdomains. Note: have no mesh yet so
+        // Get requested numberOfSubdomains. Note: have no mesh yet so
         // cannot use decompositionModel::New
         const label nDomains = readLabel
         (
@@ -402,6 +397,8 @@ int main(int argc, char *argv[])
                 Info<< "Removing " << nProcs
                     << " existing processor directories" << endl;
 
+                fileHandler().rmDir(runTime.path()/word("processors"));
+
                 // remove existing processor dirs
                 // reverse order to avoid gaps if someone interrupts the process
                 for (label proci = nProcs-1; proci >= 0; --proci)
@@ -411,7 +408,7 @@ int main(int argc, char *argv[])
                         runTime.path()/(word("processor") + name(proci))
                     );
 
-                    rmDir(procDir);
+                    fileHandler().rmDir(procDir);
                 }
 
                 procDirsProblem = false;
@@ -448,7 +445,11 @@ int main(int argc, char *argv[])
         // Decompose the mesh
         if (!decomposeFieldsOnly)
         {
-            mesh.decomposeMesh();
+            // Disable buffering when writing mesh since we need to read
+            // it later on when decomposing the fields
+            float bufSz =
+                fileOperations::collatedFileOperation::maxThreadFileBufferSize;
+            fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0;
 
             mesh.writeDecomposition(decomposeSets);
 
@@ -505,12 +506,16 @@ int main(int argc, char *argv[])
                     << cellDist.name() << " for use in postprocessing."
                     << endl;
             }
+
+            fileOperations::collatedFileOperation::maxThreadFileBufferSize =
+                bufSz;
         }
 
 
         if (copyZero)
         {
-            // Link the 0 directory into each of the processor directories
+            // Copy the 0 directory into each of the processor directories
+            fileName prevTimePath;
             for (label proci = 0; proci < mesh.nProcs(); proci++)
             {
                 Time processorDb
@@ -521,14 +526,32 @@ int main(int argc, char *argv[])
                 );
                 processorDb.setTime(runTime);
 
-                if (isDir(runTime.timePath()))
+                if (fileHandler().isDir(runTime.timePath()))
                 {
-                    const fileName timePath = processorDb.timePath();
+                    // Get corresponding directory name (to handle processors/)
+                    const fileName timePath
+                    (
+                        fileHandler().objectPath
+                        (
+                            IOobject
+                            (
+                                "",
+                                processorDb.timeName(),
+                                processorDb
+                            ),
+                            word::null
+                        )
+                    );
 
-                    Info<< "Processor " << proci
-                        << ": linking " << runTime.timePath() << nl
-                        << " to " << processorDb.timePath() << endl;
-                    cp(runTime.timePath(), processorDb.timePath());
+                    if (timePath != prevTimePath)
+                    {
+                        Info<< "Processor " << proci
+                            << ": copying " << runTime.timePath() << nl
+                            << " to " << timePath << endl;
+                        fileHandler().cp(runTime.timePath(), timePath);
+
+                        prevTimePath = timePath;
+                    }
                 }
             }
         }
@@ -629,9 +652,10 @@ int main(int argc, char *argv[])
 
                 fileNameList cloudDirs
                 (
-                    readDir
+                    fileHandler().readDir
                     (
-                        runTime.timePath()/cloud::prefix, fileName::DIRECTORY
+                        runTime.timePath()/cloud::prefix,
+                        fileName::DIRECTORY
                     )
                 );
 
diff --git a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C
index 047c68b21a5ad885820067c71433609ecffe6b54..b2a14692578501d8aa02aafa234abc3f9e7aa484 100644
--- a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C
+++ b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C
@@ -317,9 +317,6 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
             time().caseName()/fileName(word("processor") + Foam::name(proci))
         );
 
-        // make the processor directory
-        mkDir(time().rootPath()/processorCasePath);
-
         // create a database
         Time processorDb
         (
diff --git a/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposerDecomposeFields.C b/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposerDecomposeFields.C
index 79754c1c0552ad6bd51c71314b521f46bb6ceadc..3528dfd5d3496599532d79a9a6b5255be1d75f53 100644
--- a/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposerDecomposeFields.C
+++ b/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposerDecomposeFields.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -188,11 +188,12 @@ void Foam::lagrangianFieldDecomposer::decomposeFields
     const PtrList<GeoField>& fields
 ) const
 {
-    if (particleIndices_.size())
+    //if (particleIndices_.size())
     {
+        bool valid = particleIndices_.size() > 0;
         forAll(fields, fieldi)
         {
-            decomposeField(cloudName, fields[fieldi])().write();
+            decomposeField(cloudName, fields[fieldi])().write(valid);
         }
     }
 }
@@ -205,11 +206,12 @@ void Foam::lagrangianFieldDecomposer::decomposeFieldFields
     const PtrList<GeoField>& fields
 ) const
 {
-    if (particleIndices_.size())
+    //if (particleIndices_.size())
     {
+        bool valid = particleIndices_.size() > 0;
         forAll(fields, fieldi)
         {
-            decomposeFieldField(cloudName, fields[fieldi])().write();
+            decomposeFieldField(cloudName, fields[fieldi])().write(valid);
         }
     }
 }
diff --git a/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C b/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C
index 4be4abb392dcac6907fd207cb85e69c2b7f6e934..716f8522abfe89ee94642a458114f442ec332663 100644
--- a/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C
+++ b/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2015 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -177,13 +177,44 @@ int main(int argc, char *argv[])
     const bool allRegions = args.optionFound("allRegions");
 
 
-    // determine the processor count directly
-    label nProcs = 0;
-    while (isDir(args.path()/(word("processor") + name(nProcs))))
+    wordList regionNames;
+    wordList regionDirs;
+    if (allRegions)
+    {
+        Info<< "Reconstructing for all regions in regionProperties" << nl
+            << endl;
+        regionProperties rp(runTime);
+        forAllConstIter(HashTable<wordList>, rp, iter)
+        {
+            const wordList& regions = iter();
+            forAll(regions, i)
+            {
+                if (findIndex(regionNames, regions[i]) == -1)
+                {
+                    regionNames.append(regions[i]);
+                }
+            }
+        }
+        regionDirs = regionNames;
+    }
+    else
     {
-        ++nProcs;
+        word regionName;
+        if (args.optionReadIfPresent("region", regionName))
+        {
+            regionNames = wordList(1, regionName);
+            regionDirs = regionNames;
+        }
+        else
+        {
+            regionNames = wordList(1, fvMesh::defaultRegion);
+            regionDirs = wordList(1, word::null);
+        }
     }
 
+    // Determine the processor count
+    label nProcs = fileHandler().nProcs(args.path(), regionDirs[0]);
+
     if (!nProcs)
     {
         FatalErrorInFunction
@@ -225,9 +256,8 @@ int main(int argc, char *argv[])
 
     if (timeDirs.empty())
     {
-        FatalErrorInFunction
-            << "No times selected"
-            << exit(FatalError);
+        WarningInFunction << "No times selected";
+        exit(1);
     }
 
 
@@ -251,42 +281,6 @@ int main(int argc, char *argv[])
     }
 
 
-    wordList regionNames;
-    wordList regionDirs;
-    if (allRegions)
-    {
-        Info<< "Reconstructing for all regions in regionProperties" << nl
-            << endl;
-        regionProperties rp(runTime);
-        forAllConstIter(HashTable<wordList>, rp, iter)
-        {
-            const wordList& regions = iter();
-            forAll(regions, i)
-            {
-                if (findIndex(regionNames, regions[i]) == -1)
-                {
-                    regionNames.append(regions[i]);
-                }
-            }
-        }
-        regionDirs = regionNames;
-    }
-    else
-    {
-        word regionName;
-        if (args.optionReadIfPresent("region", regionName))
-        {
-            regionNames = wordList(1, regionName);
-            regionDirs = regionNames;
-        }
-        else
-        {
-            regionNames = wordList(1, fvMesh::defaultRegion);
-            regionDirs = wordList(1, word::null);
-        }
-    }
-
-
     forAll(regionNames, regioni)
     {
         const word& regionName = regionNames[regioni];
@@ -553,17 +547,26 @@ int main(int argc, char *argv[])
 
                 forAll(databases, proci)
                 {
-                    fileNameList cloudDirs
+                    fileName lagrangianDir
                     (
-                        readDir
+                        fileHandler().filePath
                         (
                             databases[proci].timePath()
                           / regionDir
-                          / cloud::prefix,
-                            fileName::DIRECTORY
+                          / cloud::prefix
                         )
                     );
 
+                    fileNameList cloudDirs;
+                    if (!lagrangianDir.empty())
+                    {
+                        cloudDirs = fileHandler().readDir
+                        (
+                            lagrangianDir,
+                            fileName::DIRECTORY
+                        );
+                    }
+
                     forAll(cloudDirs, i)
                     {
                         // Check if we already have cloud objects for this
@@ -1067,12 +1070,15 @@ int main(int argc, char *argv[])
             {
                 fileName uniformDir0
                 (
-                    databases[0].timePath()/regionDir/"uniform"
+                    fileHandler().filePath
+                    (
+                        databases[0].timePath()/regionDir/"uniform"
+                    )
                 );
 
-                if (isDir(uniformDir0))
+                if (!uniformDir0.empty() && fileHandler().isDir(uniformDir0))
                 {
-                    cp(uniformDir0, runTime.timePath()/regionDir);
+                    fileHandler().cp(uniformDir0, runTime.timePath()/regionDir);
                 }
             }
 
@@ -1082,12 +1088,15 @@ int main(int argc, char *argv[])
             {
                 fileName uniformDir0
                 (
-                    databases[0].timePath()/"uniform"
+                    fileHandler().filePath
+                    (
+                        databases[0].timePath()/"uniform"
+                    )
                 );
 
-                if (isDir(uniformDir0))
+                if (!uniformDir0.empty() && fileHandler().isDir(uniformDir0))
                 {
-                    cp(uniformDir0, runTime.timePath());
+                    fileHandler().cp(uniformDir0, runTime.timePath());
                 }
             }
         }
diff --git a/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C b/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C
index b1fa2872af2ea9ad5684b94d1e5b48293046988f..476954964688492510f3fa34b118956ac5bf8d2c 100644
--- a/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C
+++ b/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C
@@ -549,20 +549,7 @@ int main(int argc, char *argv[])
     bool writeCellDist = args.optionFound("cellDist");
 
 
-    int nProcs = 0;
-
-    while
-    (
-        isDir
-        (
-            args.rootPath()
-          / args.caseName()
-          / fileName(word("processor") + name(nProcs))
-        )
-    )
-    {
-        nProcs++;
-    }
+    label nProcs = fileHandler().nProcs(args.path());
 
     Info<< "Found " << nProcs << " processor directories" << nl << endl;
 
@@ -610,13 +597,21 @@ int main(int argc, char *argv[])
             databases[proci].setTime(timeDirs[timeI], timeI);
         }
 
-        const fileName meshPath =
-            databases[0].path()
-           /databases[0].timeName()
-           /regionDir
-           /polyMesh::meshSubDir;
+        IOobject facesIO
+        (
+            "faces",
+            databases[0].timeName(),
+            regionDir/polyMesh::meshSubDir,
+            databases[0],
+            IOobject::NO_READ,
+            IOobject::NO_WRITE
+        );
+
 
-        if (!isFile(meshPath/"faces"))
+        // Problem: faceCompactIOList recognises both 'faceList' and
+        //          'faceCompactList' so we should be lenient when doing
+        //          typeHeaderOk
+        if (!facesIO.typeHeaderOk<faceCompactIOList>(false))
         {
             Info<< "No mesh." << nl << endl;
             continue;
diff --git a/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C b/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C
index e8a082a271e9fb11aac1f170d5b48e09d168f4d6..b219c65bcbe0067475ce40a6573529b659570ea4 100644
--- a/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C
+++ b/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C
@@ -145,13 +145,14 @@ Foam::autoPtr<Foam::fvMesh> Foam::loadOrCreateMesh
     // ~~~~~~~~~~~~
 
     // Check who has a mesh
-    //const bool haveMesh = isDir(io.time().path()/io.instance()/meshSubDir);
-    const bool haveMesh = isFile
+    const bool haveMesh = fileHandler().isFile
     (
-        io.time().path()/io.instance()/meshSubDir/"faces"
+        fileHandler().filePath
+        (
+            io.time().path()/io.instance()/meshSubDir/"faces"
+        )
     );
 
-
     if (!haveMesh)
     {
         bool oldParRun = Pstream::parRun();
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H
index 9c0c612ed7fc5fe68233c257509dec635e45d517..7da98b7351bc11e0a6af421f36776293111a58c7 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H
@@ -1,4 +1,4 @@
-// check for "points" in any of the result directories
+// Check for "points" in any of the result directories
 
 bool meshMoving = false;
 
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/getTimeIndex.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/getTimeIndex.H
index 70964a667d9986f8fbb997cc6965dd72d19ddbbd..91c718994f16c21fe2d336039b046049852551dc 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/getTimeIndex.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/getTimeIndex.H
@@ -40,4 +40,4 @@
 
     Info<< nl << "Time [" << timeIndex << "] = " << runTime.timeName() << nl;
 
-// end-of-file
\ No newline at end of file
+// end-of-file
diff --git a/applications/utilities/postProcessing/noise/noise.C b/applications/utilities/postProcessing/noise/noise.C
index 089efeefac8724dc3fd5c7e3a2f17e89680f6aea..97f2cb775f3f9ddb4a29f3d2a97ac97629e0f3e1 100644
--- a/applications/utilities/postProcessing/noise/noise.C
+++ b/applications/utilities/postProcessing/noise/noise.C
@@ -64,7 +64,8 @@ Usage
         // Surface writer
         writer      ensight;
 
-        // Collate times for ensight output - ensures geometry is only written once
+        // Collate times for ensight output
+        // - ensures geometry is only written once
         writeOptions
         {
             ensight
diff --git a/applications/utilities/preProcessing/changeDictionary/changeDictionary.C b/applications/utilities/preProcessing/changeDictionary/changeDictionary.C
index f9be71c75fa5f9da247288b48b70dfb4f5aea0cd..62442c9ca39a87418442d2f7edd4e1f64b97422b 100644
--- a/applications/utilities/preProcessing/changeDictionary/changeDictionary.C
+++ b/applications/utilities/preProcessing/changeDictionary/changeDictionary.C
@@ -443,255 +443,274 @@ int main(int argc, char *argv[])
         FatalErrorInFunction
             << "No times selected." << exit(FatalError);
     }
-    runTime.setTime(times[0], 0);
-    word instance = args.optionLookupOrDefault("instance", runTime.timeName());
+    forAll(times, timei)
+    {
+        word instance;
+        if (args.optionFound("instance"))
+        {
+            if (times.size() > 1)
+            {
+                FatalErrorInFunction
+                    << "Multiple times selected with 'instance' option"
+                    << exit(FatalError);
+            }
 
-    #include "createNamedMesh.H"
+            args.optionLookup("instance")() >> instance;
+        }
+        else
+        {
+            runTime.setTime(times[timei], timei);
+            instance = runTime.timeName();
+        }
 
-    const bool literalRE = args.optionFound("literalRE");
-    if (literalRE)
-    {
-        Info<< "Not interpreting any regular expressions (RE)"
-            << " in the changeDictionaryDict." << endl
-            << "Instead they are handled as any other entry, i.e. added if"
-            << " not present." << endl;
-    }
+        #include "createNamedMesh.H"
 
-    const bool enableEntries = args.optionFound("enableFunctionEntries");
-    if (enableEntries)
-    {
-        Info<< "Allowing dictionary preprocessing ('#include', '#codeStream')."
-            << endl;
-    }
+        const bool literalRE = args.optionFound("literalRE");
+        if (literalRE)
+        {
+            Info<< "Not interpreting any regular expressions (RE)"
+                << " in the changeDictionaryDict." << endl
+                << "Instead they are handled as any other entry, i.e. added if"
+                << " not present." << endl;
+        }
 
-    const int oldFlag = entry::disableFunctionEntries;
-    if (!enableEntries)
-    {
-        // By default disable dictionary expansion for fields
-        entry::disableFunctionEntries = 1;
-    }
+        const bool enableEntries = args.optionFound("enableFunctionEntries");
+        if (enableEntries)
+        {
+            Info<< "Allowing dictionary preprocessing ('#include', '#codeStream')."
+                << endl;
+        }
 
+        const int oldFlag = entry::disableFunctionEntries;
+        if (!enableEntries)
+        {
+            // By default disable dictionary expansion for fields
+            entry::disableFunctionEntries = 1;
+        }
 
-    const bool disablePatchGroups = args.optionFound("disablePatchGroups");
-    if (disablePatchGroups)
-    {
-        Info<< "Not interpreting any keys in the changeDictionary"
-            << " as patchGroups"
-            << endl;
-    }
 
+        const bool disablePatchGroups = args.optionFound("disablePatchGroups");
+        if (disablePatchGroups)
+        {
+            Info<< "Not interpreting any keys in the changeDictionary"
+                << " as patchGroups"
+                << endl;
+        }
 
-    fileName regionPrefix = "";
-    if (regionName != fvMesh::defaultRegion)
-    {
-        regionPrefix = regionName;
-    }
 
+        fileName regionPrefix = "";
+        if (regionName != fvMesh::defaultRegion)
+        {
+            regionPrefix = regionName;
+        }
 
-    // Make sure we do not use the master-only reading since we read
-    // fields (different per processor) as dictionaries.
-    regIOobject::fileModificationChecking = regIOobject::timeStamp;
 
+        // Make sure we do not use the master-only reading since we read
+        // fields (different per processor) as dictionaries.
+        regIOobject::fileModificationChecking = regIOobject::timeStamp;
 
-    // Get the replacement rules from a dictionary
 
-    const word dictName("changeDictionaryDict");
-    #include "setSystemMeshDictionaryIO.H"
-    IOdictionary dict(dictIO);
+        // Get the replacement rules from a dictionary
 
-    const dictionary* replaceDictsPtr = &dict;
+        const word dictName("changeDictionaryDict");
+        #include "setSystemMeshDictionaryIO.H"
+        IOdictionary dict(dictIO);
 
-    if (args.optionFound("subDict"))
-    {
-        word subDictName(args.optionLookup("subDict")());
-        replaceDictsPtr = &dict.subDict(subDictName);
-    }
+        const dictionary* replaceDictsPtr = &dict;
 
-    const dictionary& replaceDicts = *replaceDictsPtr;
+        if (args.optionFound("subDict"))
+        {
+            word subDictName(args.optionLookup("subDict")());
+            replaceDictsPtr = &dict.subDict(subDictName);
+        }
 
-    Info<< "Read dictionary " << dict.name()
-        << " with replacements for dictionaries "
-        << replaceDicts.toc() << endl;
+        const dictionary& replaceDicts = *replaceDictsPtr;
 
+        Info<< "Read dictionary " << dict.name()
+            << " with replacements for dictionaries "
+            << replaceDicts.toc() << endl;
 
 
-    // Always read boundary to get patch groups
-    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    Info<< "Reading polyMesh/boundary file to extract patch names"
-        << endl;
+        // Always read boundary to get patch groups
+        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    // Read PtrList of dictionary as dictionary.
-    const word oldTypeName = IOPtrList<entry>::typeName;
-    const_cast<word&>(IOPtrList<entry>::typeName) = word::null;
-    IOPtrList<entry> dictList
-    (
-        IOobject
+        Info<< "Reading polyMesh/boundary file to extract patch names"
+            << endl;
+
+        // Read PtrList of dictionary as dictionary.
+        const word oldTypeName = IOPtrList<entry>::typeName;
+        const_cast<word&>(IOPtrList<entry>::typeName) = word::null;
+        IOPtrList<entry> dictList
         (
-            "boundary",
-            runTime.findInstance
+            IOobject
             (
-                regionPrefix/polyMesh::meshSubDir,
                 "boundary",
-                IOobject::READ_IF_PRESENT
-            ),
-            polyMesh::meshSubDir,
-            mesh,
-            IOobject::READ_IF_PRESENT,
-            IOobject::NO_WRITE,
-            false
-        )
-    );
-    const_cast<word&>(IOPtrList<entry>::typeName) = oldTypeName;
+                runTime.findInstance
+                (
+                    regionPrefix/polyMesh::meshSubDir,
+                    "boundary",
+                    IOobject::READ_IF_PRESENT
+                ),
+                polyMesh::meshSubDir,
+                mesh,
+                IOobject::READ_IF_PRESENT,
+                IOobject::NO_WRITE,
+                false
+            )
+        );
+        const_cast<word&>(IOPtrList<entry>::typeName) = oldTypeName;
 
-    // Fake type back to what was in field
-    const_cast<word&>(dictList.type()) = dictList.headerClassName();
+        // Fake type back to what was in field
+        const_cast<word&>(dictList.type()) = dictList.headerClassName();
 
-    // Temporary convert to dictionary
-    dictionary fieldDict;
-    forAll(dictList, i)
-    {
-        fieldDict.add(dictList[i].keyword(), dictList[i].dict());
-    }
+        // Temporary convert to dictionary
+        dictionary fieldDict;
+        forAll(dictList, i)
+        {
+            fieldDict.add(dictList[i].keyword(), dictList[i].dict());
+        }
 
-    if (dictList.size())
-    {
-        Info<< "Loaded dictionary " << dictList.name()
-            << " with entries " << fieldDict.toc() << endl;
-    }
+        if (dictList.size())
+        {
+            Info<< "Loaded dictionary " << dictList.name()
+                << " with entries " << fieldDict.toc() << endl;
+        }
 
-    // Extract any patchGroups information (= shortcut for set of
-    // patches)
-    HashTable<wordList, word> patchGroups;
-    if (!disablePatchGroups)
-    {
-        patchGroups = extractPatchGroups(fieldDict);
-        if (patchGroups.size())
+        // Extract any patchGroups information (= shortcut for set of
+        // patches)
+        HashTable<wordList, word> patchGroups;
+        if (!disablePatchGroups)
         {
-            Info<< "Extracted patch groups:" << endl;
-            wordList groups(patchGroups.sortedToc());
-            forAll(groups, i)
+            patchGroups = extractPatchGroups(fieldDict);
+            if (patchGroups.size())
             {
-                Info<< "    group " << groups[i] << " with patches "
-                    << patchGroups[groups[i]] << endl;
+                Info<< "Extracted patch groups:" << endl;
+                wordList groups(patchGroups.sortedToc());
+                forAll(groups, i)
+                {
+                    Info<< "    group " << groups[i] << " with patches "
+                        << patchGroups[groups[i]] << endl;
+                }
             }
         }
-    }
 
 
-    // Every replacement is a dictionary name and a keyword in this
+        // Every replacement is a dictionary name and a keyword in this
 
-    forAllConstIter(dictionary, replaceDicts, fieldIter)
-    {
-        const word& fieldName = fieldIter().keyword();
-        Info<< "Replacing entries in dictionary " << fieldName << endl;
-
-        // Handle 'boundary' specially:
-        // - is PtrList of dictionaries
-        // - is in polyMesh/
-        if (fieldName == "boundary")
+        forAllConstIter(dictionary, replaceDicts, fieldIter)
         {
-            Info<< "Special handling of " << fieldName
-                << " as polyMesh/boundary file." << endl;
+            const word& fieldName = fieldIter().keyword();
+            Info<< "Replacing entries in dictionary " << fieldName << endl;
 
-            // Get the replacement dictionary for the field
-            const dictionary& replaceDict = fieldIter().dict();
-            Info<< "Merging entries from " << replaceDict.toc() << endl;
+            // Handle 'boundary' specially:
+            // - is PtrList of dictionaries
+            // - is in polyMesh/
+            if (fieldName == "boundary")
+            {
+                Info<< "Special handling of " << fieldName
+                    << " as polyMesh/boundary file." << endl;
 
-            // Merge the replacements in. Do not add non-existing entries.
-            merge(false, fieldDict, replaceDict, literalRE, patchGroups);
+                // Get the replacement dictionary for the field
+                const dictionary& replaceDict = fieldIter().dict();
+                Info<< "Merging entries from " << replaceDict.toc() << endl;
 
-            Info<< "fieldDict:" << fieldDict << endl;
+                // Merge the replacements in. Do not add non-existing entries.
+                merge(false, fieldDict, replaceDict, literalRE, patchGroups);
 
-            // Convert back into dictList
-            wordList doneKeys(dictList.size());
+                Info<< "fieldDict:" << fieldDict << endl;
 
-            label nEntries = fieldDict.size();
+                // Convert back into dictList
+                wordList doneKeys(dictList.size());
 
-            forAll(dictList, i)
-            {
-                doneKeys[i] = dictList[i].keyword();
-                dictList.set
-                (
-                    i,
-                    fieldDict.lookupEntry
+                label nEntries = fieldDict.size();
+
+                forAll(dictList, i)
+                {
+                    doneKeys[i] = dictList[i].keyword();
+                    dictList.set
                     (
-                        doneKeys[i],
-                        false,
-                        true
-                    ).clone()
+                        i,
+                        fieldDict.lookupEntry
+                        (
+                            doneKeys[i],
+                            false,
+                            true
+                        ).clone()
+                    );
+                    fieldDict.remove(doneKeys[i]);
+                }
+
+                // Add remaining entries
+                label sz = dictList.size();
+                dictList.setSize(nEntries);
+                forAllConstIter(dictionary, fieldDict, iter)
+                {
+                    dictList.set(sz++, iter().clone());
+                }
+
+                Info<< "Writing modified " << fieldName << endl;
+                dictList.writeObject
+                (
+                    runTime.writeFormat(),
+                    runTime.writeFormat(),
+                    IOstream::UNCOMPRESSED,
+                    true
                 );
-                fieldDict.remove(doneKeys[i]);
             }
-
-            // Add remaining entries
-            label sz = dictList.size();
-            dictList.setSize(nEntries);
-            forAllConstIter(dictionary, fieldDict, iter)
+            else
             {
-                dictList.set(sz++, iter().clone());
-            }
-
-            Info<< "Writing modified " << fieldName << endl;
-            dictList.writeObject
-            (
-                runTime.writeFormat(),
-                runTime.writeFormat(),
-                IOstream::UNCOMPRESSED
-            );
-        }
-        else
-        {
-            // Read dictionary
-            // Note: disable class type checking so we can load field
-            Info<< "Loading dictionary " << fieldName << endl;
-            const word oldTypeName = IOdictionary::typeName;
-            const_cast<word&>(IOdictionary::typeName) = word::null;
+                // Read dictionary
+                // Note: disable class type checking so we can load field
+                Info<< "Loading dictionary " << fieldName << endl;
+                const word oldTypeName = IOdictionary::typeName;
+                const_cast<word&>(IOdictionary::typeName) = word::null;
 
-            IOobject fieldHeader
-            (
-                fieldName,
-                instance,
-                mesh,
-                IOobject::MUST_READ_IF_MODIFIED,
-                IOobject::NO_WRITE,
-                false
-            );
+                IOobject fieldHeader
+                (
+                    fieldName,
+                    instance,
+                    mesh,
+                    IOobject::MUST_READ_IF_MODIFIED,
+                    IOobject::NO_WRITE,
+                    false
+                );
 
-            if (fieldHeader.typeHeaderOk<IOdictionary>(false))
-            {
-                IOdictionary fieldDict(fieldHeader);
+                if (fieldHeader.typeHeaderOk<IOdictionary>(false))
+                {
+                    IOdictionary fieldDict(fieldHeader);
 
-                const_cast<word&>(IOdictionary::typeName) = oldTypeName;
+                    const_cast<word&>(IOdictionary::typeName) = oldTypeName;
 
-                // Fake type back to what was in field
-                const_cast<word&>(fieldDict.type()) =
-                    fieldDict.headerClassName();
+                    // Fake type back to what was in field
+                    const_cast<word&>(fieldDict.type()) =
+                        fieldDict.headerClassName();
 
-                Info<< "Loaded dictionary " << fieldName
-                    << " with entries " << fieldDict.toc() << endl;
+                    Info<< "Loaded dictionary " << fieldName
+                        << " with entries " << fieldDict.toc() << endl;
 
-                // Get the replacement dictionary for the field
-                const dictionary& replaceDict = fieldIter().dict();
-                Info<< "Merging entries from " << replaceDict.toc() << endl;
+                    // Get the replacement dictionary for the field
+                    const dictionary& replaceDict = fieldIter().dict();
+                    Info<< "Merging entries from " << replaceDict.toc() << endl;
 
-                // Merge the replacements in (allow adding)
-                merge(true, fieldDict, replaceDict, literalRE, patchGroups);
+                    // Merge the replacements in (allow adding)
+                    merge(true, fieldDict, replaceDict, literalRE, patchGroups);
 
-                Info<< "Writing modified fieldDict " << fieldName << endl;
-                fieldDict.regIOobject::write();
-            }
-            else
-            {
-                WarningInFunction
-                    << "Requested field to change " << fieldName
-                    << " does not exist in " << fieldHeader.path() << endl;
+                    Info<< "Writing modified fieldDict " << fieldName << endl;
+                    fieldDict.regIOobject::write();
+                }
+                else
+                {
+                    WarningInFunction
+                        << "Requested field to change " << fieldName
+                        << " does not exist in " << fieldHeader.path() << endl;
+                }
             }
+
+            entry::disableFunctionEntries = oldFlag;
         }
     }
 
-    entry::disableFunctionEntries = oldFlag;
-
     Info<< "\nEnd\n" << endl;
 
     return 0;
diff --git a/applications/utilities/preProcessing/mapFields/MapConsistentVolFields.H b/applications/utilities/preProcessing/mapFields/MapConsistentVolFields.H
index 14f682751564b8bbbce21356b557509c64336f85..9fda2c5705b391063eb0f3de0f45c3df746c07e3 100644
--- a/applications/utilities/preProcessing/mapFields/MapConsistentVolFields.H
+++ b/applications/utilities/preProcessing/mapFields/MapConsistentVolFields.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -49,9 +49,7 @@ void MapConsistentVolFields
     const fvMesh& meshSource = meshToMesh0Interp.fromMesh();
     const fvMesh& meshTarget = meshToMesh0Interp.toMesh();
 
-    word fieldClassName(fieldType::typeName);
-
-    IOobjectList fields = objects.lookupClass(fieldClassName);
+    IOobjectList fields = objects.lookupClass(fieldType::typeName);
 
     forAllIter(IOobjectList, fields, fieldIter)
     {
diff --git a/applications/utilities/preProcessing/mapFields/MapVolFields.H b/applications/utilities/preProcessing/mapFields/MapVolFields.H
index f5be235de18809bb94552f4eef5b004875b097c2..97aff73fff0c728d5414f558f60f82361c14f0ae 100644
--- a/applications/utilities/preProcessing/mapFields/MapVolFields.H
+++ b/applications/utilities/preProcessing/mapFields/MapVolFields.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -49,9 +49,7 @@ void MapVolFields
     const fvMesh& meshSource = meshToMesh0Interp.fromMesh();
     const fvMesh& meshTarget = meshToMesh0Interp.toMesh();
 
-    word fieldClassName(fieldType::typeName);
-
-    IOobjectList fields = objects.lookupClass(fieldClassName);
+    IOobjectList fields = objects.lookupClass(fieldType::typeName);
 
     forAllIter(IOobjectList, fields, fieldIter)
     {
@@ -66,15 +64,10 @@ void MapVolFields
 
         if (fieldTargetIOobject.typeHeaderOk<fieldType>(true))
         {
-            Info<< "    interpolating " << fieldIter()->name()
-                << endl;
+            Info<< "    interpolating " << fieldIter()->name() << endl;
 
             // Read field fieldSource
-            fieldType fieldSource
-            (
-                *fieldIter(),
-                meshSource
-            );
+            fieldType fieldSource(*fieldIter(), meshSource);
 
             // Read fieldTarget
             fieldType fieldTarget
diff --git a/applications/utilities/surface/surfaceHookUp/surfaceHookUp.C b/applications/utilities/surface/surfaceHookUp/surfaceHookUp.C
index 9cf697d8b4d6528d7467c8d1d2e513a47b088597..57351df046e2787a90705d27b310eb2860f714e3 100644
--- a/applications/utilities/surface/surfaceHookUp/surfaceHookUp.C
+++ b/applications/utilities/surface/surfaceHookUp/surfaceHookUp.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2014-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2014-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -44,6 +44,7 @@ Usage
 #include "PackedBoolList.H"
 #include "unitConversion.H"
 #include "searchableSurfaces.H"
+#include "IOdictionary.H"
 
 using namespace Foam;
 
diff --git a/applications/utilities/surface/surfaceMeshTriangulate/surfaceMeshTriangulate.C b/applications/utilities/surface/surfaceMeshTriangulate/surfaceMeshTriangulate.C
index e97ab8154913440b60202339a7dcdee406bbe523..8637ebd9f544dbd44b81890a28fab2327970cdf6 100644
--- a/applications/utilities/surface/surfaceMeshTriangulate/surfaceMeshTriangulate.C
+++ b/applications/utilities/surface/surfaceMeshTriangulate/surfaceMeshTriangulate.C
@@ -431,6 +431,7 @@ int main(int argc, char *argv[])
             sortedFace.write(globalCasePath);
         }
     }
+
     Info<< "End\n" << endl;
 
     return 0;
diff --git a/applications/utilities/thermophysical/equilibriumCO/equilibriumCO.C b/applications/utilities/thermophysical/equilibriumCO/equilibriumCO.C
index bbc5029e6aec7f4fb68daf2f1a99b13907cf85c1..8b3eeb33d89ddde640f479790fbe8502cf3069b7 100644
--- a/applications/utilities/thermophysical/equilibriumCO/equilibriumCO.C
+++ b/applications/utilities/thermophysical/equilibriumCO/equilibriumCO.C
@@ -46,6 +46,7 @@ Description
 #include "absoluteEnthalpy.H"
 
 #include "SLPtrList.H"
+#include "IOdictionary.H"
 
 using namespace Foam;
 
diff --git a/etc/controlDict b/etc/controlDict
index 4b53bf4c368476fdd9a558d9a21833c343007e69..037737875884da4fd4075e5a755875ba69d04218 100644
--- a/etc/controlDict
+++ b/etc/controlDict
@@ -71,6 +71,20 @@ OptimisationSwitches
     //  - inotifyMaster     : do inotify (and file reading) only on master.
     fileModificationChecking timeStampMaster;
 
+    //- Parallel IO file handler
+    //  uncollated (default), collated or masterUncollated
+    fileHandler uncollated;
+
+    //- collated: thread buffer size for queued file writes.
+    //  If set to 0 or not sufficient for the file size threading is not used.
+    //  Default: 2e9
+    maxThreadFileBufferSize 2e9;
+
+    //- masterUncollated: non-blocking buffer size.
+    //  If the file exceeds this buffer size scheduled transfer is used.
+    //  Default: 2e9
+    maxMasterFileBufferSize 2e9;
+
     commsType       nonBlocking; //scheduled; //blocking;
     floatTransfer   0;
     nProcsSimpleSum 0;
diff --git a/src/OSspecific/POSIX/POSIX.C b/src/OSspecific/POSIX/POSIX.C
index 3a922ed016c5fe9420d575ee6ab68a9dc10cd440..9fa15a2e524a92ff70183d6b81a756bece1f5b9a 100644
--- a/src/OSspecific/POSIX/POSIX.C
+++ b/src/OSspecific/POSIX/POSIX.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -40,6 +40,8 @@ Description
 #include "DynamicList.H"
 #include "CStringList.H"
 #include "SubList.H"
+#include "IOstreams.H"
+#include "Pstream.H"
 
 #include <fstream>
 #include <cstdlib>
@@ -323,7 +325,17 @@ bool Foam::chDir(const fileName& dir)
 
 bool Foam::mkDir(const fileName& pathName, mode_t mode)
 {
-    // Ignore an empty pathName => always false
+    if (POSIX::debug)
+    {
+        Pout<< FUNCTION_NAME << " : pathName:" << pathName << " mode:" << mode
+            << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
+    }
+
+    // empty names are meaningless
     if (pathName.empty())
     {
         return false;
@@ -469,6 +481,15 @@ bool Foam::mkDir(const fileName& pathName, mode_t mode)
 
 bool Foam::chMod(const fileName& name, const mode_t m)
 {
+    if (POSIX::debug)
+    {
+        Pout<< FUNCTION_NAME << " : name:" << name << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
+    }
+
     // Ignore an empty name => always false
     return !name.empty() && ::chmod(name.c_str(), m) == 0;
 }
@@ -476,6 +497,11 @@ bool Foam::chMod(const fileName& name, const mode_t m)
 
 mode_t Foam::mode(const fileName& name, const bool followLink)
 {
+    if (POSIX::debug)
+    {
+        Pout<< FUNCTION_NAME << " : name:" << name << endl;
+    }
+
     // Ignore an empty name => always 0
     if (!name.empty())
     {
@@ -498,6 +524,15 @@ Foam::fileName::Type Foam::type(const fileName& name, const bool followLink)
         return fileName::UNDEFINED;
     }
 
+    if (POSIX::debug)
+    {
+        Pout<< FUNCTION_NAME << " : name:" << name << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
+    }
+
     mode_t m = mode(name, followLink);
 
     if (S_ISREG(m))
@@ -524,6 +559,16 @@ bool Foam::exists
     const bool followLink
 )
 {
+    if (POSIX::debug)
+    {
+        Pout<< FUNCTION_NAME << " : name:" << name << " checkGzip:" << checkGzip
+            << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
+    }
+
     // Ignore an empty name => always false
     return
     (
@@ -535,6 +580,15 @@ bool Foam::exists
 
 bool Foam::isDir(const fileName& name, const bool followLink)
 {
+    if (POSIX::debug)
+    {
+        Pout<< FUNCTION_NAME << " : name:" << name << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
+    }
+
     // Ignore an empty name => always false
     return !name.empty() && S_ISDIR(mode(name, followLink));
 }
@@ -547,6 +601,16 @@ bool Foam::isFile
     const bool followLink
 )
 {
+    if (POSIX::debug)
+    {
+        Pout<< FUNCTION_NAME << " : name:" << name << " checkGzip:" << checkGzip
+            << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
+    }
+
     // Ignore an empty name => always false
     return
     (
@@ -561,6 +625,15 @@ bool Foam::isFile
 
 off_t Foam::fileSize(const fileName& name, const bool followLink)
 {
+    if (POSIX::debug)
+    {
+        Pout<< FUNCTION_NAME << " : name:" << name << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
+    }
+
     // Ignore an empty name
     if (!name.empty())
     {
@@ -577,6 +650,15 @@ off_t Foam::fileSize(const fileName& name, const bool followLink)
 
 time_t Foam::lastModified(const fileName& name, const bool followLink)
 {
+    if (POSIX::debug)
+    {
+        Pout<< FUNCTION_NAME << " : name:" << name << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
+    }
+
     // Ignore an empty name
     if (!name.empty())
     {
@@ -591,8 +673,17 @@ time_t Foam::lastModified(const fileName& name, const bool followLink)
 }
 
 
-double Foam::highResLastModified(const fileName& name)
+double Foam::highResLastModified(const fileName& name, const bool followLink)
 {
+    if (POSIX::debug)
+    {
+        Pout<< FUNCTION_NAME << " : name:" << name << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
+    }
+
     // Ignore an empty name
     if (!name.empty())
     {
@@ -645,8 +736,12 @@ Foam::fileNameList Foam::readDir
 
     if (POSIX::debug)
     {
-        InfoInFunction
-            << "reading directory " << directory << endl;
+        //InfoInFunction
+        Pout<< FUNCTION_NAME << " : reading directory " << directory << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
     }
 
     label nEntries = 0;
@@ -699,16 +794,26 @@ Foam::fileNameList Foam::readDir
 
 bool Foam::cp(const fileName& src, const fileName& dest, const bool followLink)
 {
+    if (POSIX::debug)
+    {
+        Pout<< FUNCTION_NAME << " : src:" << src << " dest:" << dest << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
+    }
+
     // Make sure source exists - this also handles an empty source name
     if (!exists(src))
     {
         return false;
     }
 
+    const fileName::Type srcType = src.type(followLink);
+
     fileName destFile(dest);
 
     // Check type of source file.
-    const fileName::Type srcType = src.type(followLink);
     if (srcType == fileName::FILE)
     {
         // If dest is a directory, create the destination file name.
@@ -802,6 +907,7 @@ bool Foam::cp(const fileName& src, const fileName& dest, const bool followLink)
             false,
             followLink
         );
+
         forAll(subdirs, i)
         {
             if (POSIX::debug)
@@ -828,9 +934,13 @@ bool Foam::ln(const fileName& src, const fileName& dst)
 {
     if (POSIX::debug)
     {
-        InfoInFunction
-            << "Create softlink from : " << src << " to " << dst
-            << endl;
+        //InfoInFunction
+        Pout<< FUNCTION_NAME
+            << " : Create softlink from : " << src << " to " << dst << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
     }
 
     if (src.empty())
@@ -879,8 +989,12 @@ bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink)
 {
     if (POSIX::debug)
     {
-        InfoInFunction
-            << "Move : " << src << " to " << dst << endl;
+        //InfoInFunction
+        Pout<< FUNCTION_NAME << " : Move : " << src << " to " << dst << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
     }
 
     // Ignore an empty names => always false
@@ -910,8 +1024,13 @@ bool Foam::mvBak(const fileName& src, const std::string& ext)
 {
     if (POSIX::debug)
     {
-        InfoInFunction
-            << "mvBak : " << src << " to extension " << ext << endl;
+        //InfoInFunction
+        Pout<< FUNCTION_NAME
+            << " : moving : " << src << " to extension " << ext << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
     }
 
     // Ignore an empty name or extension => always false
@@ -952,8 +1071,12 @@ bool Foam::rm(const fileName& file)
 {
     if (POSIX::debug)
     {
-        InfoInFunction
-            << "Removing : " << file << endl;
+        //InfoInFunction
+        Pout<< FUNCTION_NAME << " : Removing : " << file << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
     }
 
     // Ignore an empty name => always false
@@ -996,8 +1119,12 @@ bool Foam::rmDir(const fileName& directory, const bool silent)
 
     if (POSIX::debug)
     {
-        InfoInFunction
-            << "removing directory " << directory << endl;
+        //InfoInFunction
+        Pout<< FUNCTION_NAME << " : removing directory " << directory << endl;
+        if ((POSIX::debug & 2) && !Pstream::master())
+        {
+            error::printStack(Pout);
+        }
     }
 
     // Process each directory entry, counting any errors encountered
@@ -1504,6 +1631,145 @@ Foam::scalar Foam::osRandomDouble(List<char>& buffer)
     drand48_r(reinterpret_cast<drand48_data*>(buffer.begin()), &result);
     return result;
     #endif
+
+}
+
+
+static Foam::DynamicList<Foam::autoPtr<pthread_t>> threads_;
+static Foam::DynamicList<Foam::autoPtr<pthread_mutex_t>> mutexes_;
+
+Foam::label Foam::allocateThread()
+{
+    forAll(threads_, i)
+    {
+        if (!threads_[i].valid())
+        {
+            if (POSIX::debug)
+            {
+                Pout<< "allocateThread : reusing index:" << i << endl;
+            }
+            // Reuse entry
+            threads_[i].reset(new pthread_t());
+            return i;
+        }
+    }
+
+    label index = threads_.size();
+    if (POSIX::debug)
+    {
+        Pout<< "allocateThread : new index:" << index << endl;
+    }
+    threads_.append(autoPtr<pthread_t>(new pthread_t()));
+
+    return index;
+}
+
+
+void Foam::createThread
+(
+    const label index,
+    void *(*start_routine) (void *),
+    void *arg
+)
+{
+    if (POSIX::debug)
+    {
+        Pout<< "createThread : index:" << index << endl;
+    }
+    if (pthread_create(&threads_[index](), nullptr, start_routine, arg))
+    {
+        FatalErrorInFunction
+            << "Failed starting thread " << index << exit(FatalError);
+    }
+}
+
+
+void Foam::joinThread(const label index)
+{
+    if (POSIX::debug)
+    {
+        Pout<< "freeThread : join:" << index << endl;
+    }
+    if (pthread_join(threads_[index](), nullptr))
+    {
+        FatalErrorInFunction << "Failed freeing thread " << index
+            << exit(FatalError);
+    }
+}
+
+
+void Foam::freeThread(const label index)
+{
+    if (POSIX::debug)
+    {
+        Pout<< "freeThread : index:" << index << endl;
+    }
+    threads_[index].clear();
+}
+
+
+Foam::label Foam::allocateMutex()
+{
+    forAll(mutexes_, i)
+    {
+        if (!mutexes_[i].valid())
+        {
+            if (POSIX::debug)
+            {
+                Pout<< "allocateMutex : reusing index:" << i << endl;
+            }
+            // Reuse entry
+            mutexes_[i].reset(new pthread_mutex_t());
+            return i;
+        }
+    }
+
+    label index = mutexes_.size();
+
+    if (POSIX::debug)
+    {
+        Pout<< "allocateMutex : new index:" << index << endl;
+    }
+    mutexes_.append(autoPtr<pthread_mutex_t>(new pthread_mutex_t()));
+    return index;
+}
+
+
+void Foam::lockMutex(const label index)
+{
+    if (POSIX::debug)
+    {
+        Pout<< "lockMutex : index:" << index << endl;
+    }
+    if (pthread_mutex_lock(&mutexes_[index]()))
+    {
+        FatalErrorInFunction << "Failed locking mutex " << index
+            << exit(FatalError);
+    }
+}
+
+
+void Foam::unlockMutex(const label index)
+{
+    if (POSIX::debug)
+    {
+        Pout<< "unlockMutex : index:" << index << endl;
+    }
+    if (pthread_mutex_unlock(&mutexes_[index]()))
+    {
+        FatalErrorInFunction << "Failed unlocking mutex " << index
+            << exit(FatalError);
+    }
+}
+
+
+void Foam::freeMutex(const label index)
+{
+    if (POSIX::debug)
+    {
+        Pout<< "freeMutex : index:" << index << endl;
+    }
+    mutexes_[index].clear();
 }
 
 
diff --git a/src/OSspecific/POSIX/regExp.H b/src/OSspecific/POSIX/regExp.H
index 1f82552d07fb177946ed575a953fefc3a52f72b4..6a03192cf27e7607e971f66e9749da252ec0d9ac 100644
--- a/src/OSspecific/POSIX/regExp.H
+++ b/src/OSspecific/POSIX/regExp.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index 0dd52536e95fe460712f2b713ea008c3724d4c54..46a3c7db22d0980f0c6951e134b089d87a4af5cd 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -9,6 +9,14 @@ global/profiling/profilingSysInfo.C
 global/profiling/profilingTrigger.C
 global/etcFiles/etcFiles.C
 
+fileOps = global/fileOperations
+$(fileOps)/fileOperation/fileOperation.C
+$(fileOps)/uncollatedFileOperation/uncollatedFileOperation.C
+$(fileOps)/masterUncollatedFileOperation/masterUncollatedFileOperation.C
+$(fileOps)/collatedFileOperation/collatedFileOperation.C
+$(fileOps)/collatedFileOperation/threadedCollatedOFstream.C
+$(fileOps)/collatedFileOperation/OFstreamCollator.C
+
 bools = primitives/bools
 $(bools)/bool/bool.C
 $(bools)/bool/boolIO.C
@@ -169,6 +177,7 @@ $(gzstream)/gzstream.C
 Fstreams = $(Streams)/Fstreams
 $(Fstreams)/IFstream.C
 $(Fstreams)/OFstream.C
+$(Fstreams)/masterOFstream.C
 
 Tstreams = $(Streams)/Tstreams
 $(Tstreams)/ITstream.C
@@ -225,6 +234,9 @@ $(IOdictionary)/localIOdictionary.C
 $(IOdictionary)/unwatchedIOdictionary.C
 
 db/IOobjects/IOMap/IOMapName.C
+db/IOobjects/decomposedBlockData/decomposedBlockData.C
+db/IOobjects/GlobalIOField/GlobalIOFields.C
+
 
 db/IOobjects/GlobalIOList/globalIOLists.C
 
@@ -639,8 +651,6 @@ $(Fields)/quaternionField/quaternionIOField.C
 $(Fields)/triadField/triadIOField.C
 $(Fields)/transformField/transformField.C
 
-$(Fields)/globalFields/globalIOFields.C
-
 
 pointPatchFields = fields/pointPatchFields
 $(pointPatchFields)/pointPatchField/pointPatchFields.C
diff --git a/src/OpenFOAM/db/IOobject/IOobject.C b/src/OpenFOAM/db/IOobject/IOobject.C
index 1dfeac42536108a40b887f3be44eb6d05153b858..563eb9c5426514de9ee0288dfc7a2508d77794aa 100644
--- a/src/OpenFOAM/db/IOobject/IOobject.C
+++ b/src/OpenFOAM/db/IOobject/IOobject.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -426,182 +426,25 @@ Foam::fileName Foam::IOobject::path
 }
 
 
-Foam::fileName Foam::IOobject::localFilePath(const bool search) const
+Foam::fileName Foam::IOobject::localFilePath
+(
+    const word& typeName,
+    const bool search
+) const
 {
-    if (isOutsideOfCase(instance()))
-    {
-        const fileName objectPath = instance()/name();
-
-        if (isFile(objectPath))
-        {
-            return objectPath;
-        }
-        else
-        {
-            return fileName::null;
-        }
-    }
-    else
-    {
-        const fileName path = this->path();
-        const fileName objectPath = path/name();
-
-        if (isFile(objectPath))
-        {
-            return objectPath;
-        }
-        else
-        {
-            if (!isDir(path) && search)
-            {
-                const word newInstancePath = time().findInstancePath
-                (
-                    instant(instance())
-                );
-
-                if (newInstancePath.size())
-                {
-                    const fileName fName
-                    (
-                        rootPath()/caseName()
-                       /newInstancePath/db_.dbDir()/local()/name()
-                    );
-
-                    if (isFile(fName))
-                    {
-                        return fName;
-                    }
-                }
-            }
-        }
-
-        return fileName::null;
-    }
+    // Do not check for undecomposed files
+    return fileHandler().filePath(false, *this, typeName, search);
 }
 
 
-Foam::fileName Foam::IOobject::globalFilePath(const bool search) const
-{
-    if (isOutsideOfCase(instance()))
-    {
-        const fileName objectPath = instance()/name();
-        if (isFile(objectPath))
-        {
-            if (objectRegistry::debug)
-            {
-                Pout<< "globalFilePath : returning absolute:" << objectPath
-                    << endl;
-            }
-            return objectPath;
-        }
-        else
-        {
-            if (objectRegistry::debug)
-            {
-                Pout<< "globalFilePath : absolute not found:" << objectPath
-                    << endl;
-            }
-            return fileName::null;
-        }
-    }
-    else
-    {
-        const fileName path = this->path();
-        const fileName objectPath = path/name();
-
-        if (isFile(objectPath))
-        {
-            if (objectRegistry::debug)
-            {
-                Pout<< "globalFilePath : returning time:" << objectPath << endl;
-            }
-            return objectPath;
-        }
-        else
-        {
-            if
-            (
-                time().processorCase()
-             && (
-                    instance() == time().system()
-                 || instance() == time().constant()
-                )
-            )
-            {
-                // Constant & system can come from global case
-
-                const fileName parentObjectPath =
-                    rootPath()/time().globalCaseName()
-                   /instance()/db().dbDir()/local()/name();
-
-                if (isFile(parentObjectPath))
-                {
-                    if (objectRegistry::debug)
-                    {
-                        Pout<< "globalFilePath : returning parent:"
-                            << parentObjectPath << endl;
-                    }
-                    return parentObjectPath;
-                }
-            }
-
-            // Check for approximately same (local) time
-            if (!isDir(path) && search)
-            {
-                const word newInstancePath = time().findInstancePath
-                (
-                    instant(instance())
-                );
-
-                if (newInstancePath.size())
-                {
-                    const fileName fName
-                    (
-                        rootPath()/caseName()
-                       /newInstancePath/db().dbDir()/local()/name()
-                    );
-
-                    if (isFile(fName))
-                    {
-                        if (objectRegistry::debug)
-                        {
-                            Pout<< "globalFilePath : returning similar time:"
-                                << fName << endl;
-                        }
-
-                        return fName;
-                    }
-                }
-            }
-        }
-
-        if (objectRegistry::debug)
-        {
-            Pout<< "globalFilePath : time not found:" << objectPath << endl;
-        }
-        return fileName::null;
-    }
-}
-
-
-Foam::Istream* Foam::IOobject::objectStream(const fileName& fName)
+Foam::fileName Foam::IOobject::globalFilePath
+(
+    const word& typeName,
+    const bool search
+) const
 {
-    if (fName.size())
-    {
-        IFstream* isPtr = new IFstream(fName);
-
-        if (isPtr->good())
-        {
-            return isPtr;
-        }
-        else
-        {
-            delete isPtr;
-            return nullptr;
-        }
-    }
-
-    return nullptr;
+    // Check for undecomposed files
+    return fileHandler().filePath(true, *this, typeName, search);
 }
 
 
diff --git a/src/OpenFOAM/db/IOobject/IOobject.H b/src/OpenFOAM/db/IOobject/IOobject.H
index 7b89997c8a53dafeb31fafdeca090400f3b1f258..c520fbd890917ceb590e64c15a1fdc651a2f4c98 100644
--- a/src/OpenFOAM/db/IOobject/IOobject.H
+++ b/src/OpenFOAM/db/IOobject/IOobject.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -131,6 +131,7 @@ public:
 
         static const Enum<fileCheckTypes> fileCheckTypesNames;
 
+
 private:
 
     // Private data
@@ -173,14 +174,6 @@ protected:
 
     // Protected Member Functions
 
-        //- Construct and return an IFstream for the object.
-        // \return nullptr if the stream construction failed
-        Istream* objectStream();
-
-        //- Return an IFstream for the object given the exact file.
-        // \return nullptr if the stream construction failed
-        Istream* objectStream(const fileName& fName);
-
         //- Set the object state to bad
         void setBad(const string& s);
 
@@ -393,12 +386,20 @@ public:
         //- Helper for filePath that searches locally.
         //  When search is false, simply use the current instance,
         //  otherwise search previous instances.
-        fileName localFilePath(const bool search=true) const;
+        fileName localFilePath
+        (
+            const word& typeName,
+            const bool search=true
+        ) const;
 
         //- Helper for filePath that searches up if in parallel
         //  When search is false, simply use the current instance,
         //  otherwise search previous instances.
-        fileName globalFilePath(const bool search=true) const;
+        fileName globalFilePath
+        (
+            const word& typeName,
+            const bool search=true
+        ) const;
 
 
       // Reading
@@ -414,7 +415,8 @@ public:
         bool typeHeaderOk
         (
             const bool checkType = true,
-            const bool search = true
+            const bool search = true,
+            const bool verbose = true
         );
 
         //- Helper: warn that type does not support re-reading
@@ -475,15 +477,16 @@ inline bool typeGlobal()
     return false;
 }
 
+
 //- Template function for obtaining local or global filePath
 template<class T>
-inline fileName typeFilePath(const IOobject& io, const bool search=true)
+inline fileName typeFilePath(const IOobject& io, const bool search = true)
 {
     return
     (
         typeGlobal<T>()
-      ? io.globalFilePath(search)
-      : io.localFilePath(search)
+      ? io.globalFilePath(T::typeName, search)
+      : io.localFilePath(T::typeName, search)
     );
 }
 
diff --git a/src/OpenFOAM/db/IOobject/IOobjectTemplates.C b/src/OpenFOAM/db/IOobject/IOobjectTemplates.C
index 58757394db789d24e0bc910de6f66c35f20b7cc4..c1eec9abea5fd6423617cfbc9c0d4cf3a6c16f1e 100644
--- a/src/OpenFOAM/db/IOobject/IOobjectTemplates.C
+++ b/src/OpenFOAM/db/IOobject/IOobjectTemplates.C
@@ -2,8 +2,8 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2015-2017 OpenFOAM Foundation
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -24,8 +24,8 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "IOobject.H"
+#include "fileOperation.H"
 #include "Istream.H"
-
 #include "IOstreams.H"
 #include "Pstream.H"
 
@@ -35,7 +35,8 @@ template<class Type>
 bool Foam::IOobject::typeHeaderOk
 (
     const bool checkType,
-    const bool search
+    const bool search,
+    const bool verbose
 )
 {
     bool ok = true;
@@ -48,55 +49,26 @@ bool Foam::IOobject::typeHeaderOk
          || IOobject::fileModificationChecking == inotifyMaster
         );
 
+    const fileOperation& fp = Foam::fileHandler();
 
     // Determine local status
     if (!masterOnly || Pstream::master())
     {
-        Istream* isPtr = objectStream(typeFilePath<Type>(*this, search));
+        fileName fName(typeFilePath<Type>(*this, search));
 
-        // If the stream has failed return
-        if (!isPtr)
+        ok = fp.readHeader(*this, fName, Type::typeName);
+        if (ok && checkType && headerClassName_ != Type::typeName)
         {
-            if (IOobject::debug)
+            if (verbose)
             {
-                InfoInFunction
-                    << "file " << objectPath() << " could not be opened"
-                    << endl;
+                WarningInFunction
+                    << "unexpected class name " << headerClassName_
+                    << " expected " << Type::typeName
+                    << " when reading " << fName << endl;
             }
 
             ok = false;
         }
-        else
-        {
-            // Try reading header
-            if (readHeader(*isPtr))
-            {
-                if (checkType && headerClassName_ != Type::typeName)
-                {
-                    if (debug)
-                    {
-                        IOWarningInFunction(*isPtr)
-                            << "unexpected class name " << headerClassName_
-                            << " expected " << Type::typeName << endl;
-                    }
-
-                    ok = false;
-                }
-            }
-            else
-            {
-                if (IOobject::debug)
-                {
-                    IOWarningInFunction(*isPtr)
-                        << "failed to read header of file " << objectPath()
-                        << endl;
-                }
-
-                ok = false;
-            }
-        }
-
-        delete isPtr;
     }
 
     // If masterOnly make sure all processors know about it
diff --git a/src/OpenFOAM/db/IOobject/IOobjectWriteHeader.C b/src/OpenFOAM/db/IOobject/IOobjectWriteHeader.C
index 4e01787843e6d09e17cbcba0cdaaccc884dc006c..96f47f61a65db8881e82f0c238f2e444f000f2cc 100644
--- a/src/OpenFOAM/db/IOobject/IOobjectWriteHeader.C
+++ b/src/OpenFOAM/db/IOobject/IOobjectWriteHeader.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -146,7 +146,7 @@ bool Foam::IOobject::writeHeader(Ostream& os, const word& type) const
         << "    object      " << name() << ";\n"
         << "}" << nl;
 
-    writeDivider(os) << endl;
+    writeDivider(os) << nl;
 
     return true;
 }
diff --git a/src/OpenFOAM/db/IOobjectList/IOobjectList.C b/src/OpenFOAM/db/IOobjectList/IOobjectList.C
index f70f3e7ebfcffc107a5d63d45f43488ffcf6606e..a91134d91c389462d989d6872fcb77e61ab26a83 100644
--- a/src/OpenFOAM/db/IOobjectList/IOobjectList.C
+++ b/src/OpenFOAM/db/IOobjectList/IOobjectList.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -141,23 +141,16 @@ Foam::IOobjectList::IOobjectList
 :
     HashPtrTable<IOobject>()
 {
-    word newInstance = instance;
-
-    if (!isDir(db.path(instance)))
-    {
-        newInstance = db.time().findInstancePath(instant(instance));
-
-        if (newInstance.empty())
-        {
-            return;
-        }
-    }
-
-    // Create a list of file names in this directory
-    const auto objNames =
-        readDir(db.path(newInstance, db.dbDir()/local), fileName::FILE);
+    word newInstance;
+    fileNameList ObjectNames = fileHandler().readObjects
+    (
+        db,
+        instance,
+        local,
+        newInstance
+    );
 
-    for (const auto& objName : objNames)
+    for (const auto& objName : ObjectNames)
     {
         IOobject* objectPtr = new IOobject
         (
diff --git a/src/OpenFOAM/db/IOobjects/CompactIOField/CompactIOField.C b/src/OpenFOAM/db/IOobjects/CompactIOField/CompactIOField.C
index c5e369b1cf2446dea1953117fa350d5aa6ed67f7..ef8e34185aab6d15798893b0559881ae212509c0 100644
--- a/src/OpenFOAM/db/IOobjects/CompactIOField/CompactIOField.C
+++ b/src/OpenFOAM/db/IOobjects/CompactIOField/CompactIOField.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -29,30 +29,33 @@ License
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
 template<class T, class BaseType>
-void Foam::CompactIOField<T, BaseType>::readFromStream()
+void Foam::CompactIOField<T, BaseType>::readFromStream(const bool valid)
 {
-    Istream& is = readStream(word::null);
+    Istream& is = readStream(word::null, valid);
 
-    if (headerClassName() == IOField<T>::typeName)
+    if (valid)
     {
-        is >> static_cast<Field<T>&>(*this);
-        close();
-    }
-    else if (headerClassName() == typeName)
-    {
-        is >> *this;
-        close();
-    }
-    else
-    {
-        FatalIOErrorInFunction
-        (
-            is
-        )   << "unexpected class name " << headerClassName()
-            << " expected " << typeName << " or " << IOField<T>::typeName
-            << endl
-            << "    while reading object " << name()
-            << exit(FatalIOError);
+        if (headerClassName() == IOField<T>::typeName)
+        {
+            is >> static_cast<Field<T>&>(*this);
+            close();
+        }
+        else if (headerClassName() == typeName)
+        {
+            is >> *this;
+            close();
+        }
+        else
+        {
+            FatalIOErrorInFunction
+            (
+                is
+            )   << "unexpected class name " << headerClassName()
+                << " expected " << typeName << " or " << IOField<T>::typeName
+                << endl
+                << "    while reading object " << name()
+                << exit(FatalIOError);
+        }
     }
 }
 
@@ -75,6 +78,27 @@ Foam::CompactIOField<T, BaseType>::CompactIOField(const IOobject& io)
 }
 
 
+template<class T, class BaseType>
+Foam::CompactIOField<T, BaseType>::CompactIOField
+(
+    const IOobject& io,
+    const bool valid
+)
+:
+    regIOobject(io)
+{
+    if (io.readOpt() == IOobject::MUST_READ)
+    {
+        readFromStream(valid);
+    }
+    else if (io.readOpt() == IOobject::READ_IF_PRESENT)
+    {
+        bool haveFile = headerOk();
+        readFromStream(valid && haveFile);
+    }
+}
+
+
 template<class T, class BaseType>
 Foam::CompactIOField<T, BaseType>::CompactIOField
 (
@@ -160,7 +184,8 @@ bool Foam::CompactIOField<T, BaseType>::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     if (fmt == IOstream::ASCII)
@@ -170,7 +195,7 @@ bool Foam::CompactIOField<T, BaseType>::writeObject
 
         const_cast<word&>(typeName) = IOField<T>::typeName;
 
-        bool good = regIOobject::writeObject(fmt, ver, cmp);
+        bool good = regIOobject::writeObject(fmt, ver, cmp, valid);
 
         // Change type back
         const_cast<word&>(typeName) = oldTypeName;
@@ -179,7 +204,7 @@ bool Foam::CompactIOField<T, BaseType>::writeObject
     }
     else
     {
-        return regIOobject::writeObject(fmt, ver, cmp);
+        return regIOobject::writeObject(fmt, ver, cmp, valid);
     }
 }
 
diff --git a/src/OpenFOAM/db/IOobjects/CompactIOField/CompactIOField.H b/src/OpenFOAM/db/IOobjects/CompactIOField/CompactIOField.H
index 231119e6a003dacb1d337fceee29387fd0615893..02fbedacc7ff7aa4a1303c0d4127de8ec85b0503 100644
--- a/src/OpenFOAM/db/IOobjects/CompactIOField/CompactIOField.H
+++ b/src/OpenFOAM/db/IOobjects/CompactIOField/CompactIOField.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -75,7 +75,7 @@ class CompactIOField
     // Private Member Functions
 
         //- Read according to header type
-        void readFromStream();
+        void readFromStream(const bool valid = true);
 
 public:
 
@@ -88,6 +88,9 @@ public:
         //- Construct from IOobject
         CompactIOField(const IOobject&);
 
+        //- Construct from IOobject; does local processor require reading?
+        CompactIOField(const IOobject&, const bool valid);
+
         //- Construct from IOobject and size
         CompactIOField(const IOobject&, const label);
 
@@ -109,7 +112,8 @@ public:
         (
             IOstream::streamFormat,
             IOstream::versionNumber,
-            IOstream::compressionType
+            IOstream::compressionType,
+            const bool valid
         ) const;
 
         virtual bool writeData(Ostream&) const;
diff --git a/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.C b/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.C
index 8bb3aa009b3e886908b0adc469b47bd9c505d375..887f03bacb49596ccc0b870b7ea4d52201ce552a 100644
--- a/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.C
+++ b/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2015 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -175,7 +175,8 @@ bool Foam::CompactIOList<T, BaseType>::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     if (fmt == IOstream::ASCII)
@@ -185,7 +186,26 @@ bool Foam::CompactIOList<T, BaseType>::writeObject
 
         const_cast<word&>(typeName) = IOList<T>::typeName;
 
-        bool good = regIOobject::writeObject(fmt, ver, cmp);
+        bool good = regIOobject::writeObject(fmt, ver, cmp, valid);
+
+        // Change type back
+        const_cast<word&>(typeName) = oldTypeName;
+
+        return good;
+    }
+    else if (overflows())
+    {
+        WarningInFunction
+            << "Overall number of elements of CompactIOList of size "
+            << this->size() << " overflows the representation of a label"
+            << endl << "    Switching to ascii writing" << endl;
+
+        // Change type to be non-compact format type
+        const word oldTypeName = typeName;
+
+        const_cast<word&>(typeName) = IOList<T>::typeName;
+
+        bool good = regIOobject::writeObject(IOstream::ASCII, ver, cmp, valid);
 
         // Change type back
         const_cast<word&>(typeName) = oldTypeName;
@@ -213,7 +233,7 @@ bool Foam::CompactIOList<T, BaseType>::writeObject
     }
     else
     {
-        return regIOobject::writeObject(fmt, ver, cmp);
+        return regIOobject::writeObject(fmt, ver, cmp, valid);
     }
 }
 
diff --git a/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.H b/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.H
index 80c902c73bf24765ab39170fdf6eb63edc1484fd..78434784513c1ee0bcf2b70d195a2a9a936030ec 100644
--- a/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.H
+++ b/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -114,7 +114,8 @@ public:
         (
             IOstream::streamFormat,
             IOstream::versionNumber,
-            IOstream::compressionType
+            IOstream::compressionType,
+            const bool valid
         ) const;
 
         virtual bool writeData(Ostream&) const;
diff --git a/src/OpenFOAM/db/IOobjects/GlobalIOField/GlobalIOField.H b/src/OpenFOAM/db/IOobjects/GlobalIOField/GlobalIOField.H
index ee2dcbf79a534e33bc0b9fb8a883c0c3ea0af955..f4b4124f871dafc99881c4285f13287daf931fcd 100644
--- a/src/OpenFOAM/db/IOobjects/GlobalIOField/GlobalIOField.H
+++ b/src/OpenFOAM/db/IOobjects/GlobalIOField/GlobalIOField.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2015-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -90,7 +90,7 @@ public:
         //  either in the case/processor or case otherwise null
         virtual fileName filePath() const
         {
-            return globalFilePath();
+            return globalFilePath(type());
         }
 
         //- ReadData function required for regIOobject read operation
diff --git a/src/OpenFOAM/fields/Fields/globalFields/globalIOFields.C b/src/OpenFOAM/db/IOobjects/GlobalIOField/GlobalIOFields.C
similarity index 64%
rename from src/OpenFOAM/fields/Fields/globalFields/globalIOFields.C
rename to src/OpenFOAM/db/IOobjects/GlobalIOField/GlobalIOFields.C
index e7d926afa3916631e296df05f1624861a3ec931a..51080e07eed1ebd07bd5d01f19616a81d9d0e0ae 100644
--- a/src/OpenFOAM/fields/Fields/globalFields/globalIOFields.C
+++ b/src/OpenFOAM/db/IOobjects/GlobalIOField/GlobalIOFields.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -23,22 +23,43 @@ License
 
 \*---------------------------------------------------------------------------*/
 
-#include "globalIOFields.H"
+#include "GlobalIOField.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
 {
-    defineTemplateTypeNameWithName(labelGlobalIOField, "labelField");
-    defineTemplateTypeNameWithName(scalarGlobalIOField, "scalarField");
-    defineTemplateTypeNameWithName(vectorGlobalIOField, "vectorField");
-    defineTemplateTypeNameWithName
+    defineTemplateTypeNameAndDebugWithName
     (
-        sphericalTensorGlobalIOField,
-        "sphericalTensorField"
+        GlobalIOField<scalar>,
+        "scalarField",
+        0
+    );
+    defineTemplateTypeNameAndDebugWithName
+    (
+        GlobalIOField<vector>,
+        "vectorField",
+        0
+    );
+    defineTemplateTypeNameAndDebugWithName
+    (
+        GlobalIOField<sphericalTensor>,
+        "sphericalTensorField",
+        0
+    );
+    defineTemplateTypeNameAndDebugWithName
+    (
+        GlobalIOField<symmTensor>,
+        "symmTensorField",
+        0
+    );
+    defineTemplateTypeNameAndDebugWithName
+    (
+        GlobalIOField<tensor>,
+        "tensorField",
+        0
     );
-    defineTemplateTypeNameWithName(symmTensorGlobalIOField, "symmTensorField");
-    defineTemplateTypeNameWithName(tensorGlobalIOField, "tensorField");
 }
 
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOobjects/GlobalIOList/GlobalIOList.H b/src/OpenFOAM/db/IOobjects/GlobalIOList/GlobalIOList.H
index 7230fd6c7d20c561a3a413527951031c25eb6d74..1f7cb9c4662c55b079ffa51244debe7371722276 100644
--- a/src/OpenFOAM/db/IOobjects/GlobalIOList/GlobalIOList.H
+++ b/src/OpenFOAM/db/IOobjects/GlobalIOList/GlobalIOList.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2015-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -90,7 +90,7 @@ public:
         //  either in the case/processor or case otherwise null
         virtual fileName filePath() const
         {
-            return globalFilePath();
+            return globalFilePath(type());
         }
 
         //- ReadData function required for regIOobject read operation
diff --git a/src/OpenFOAM/db/IOobjects/GlobalIOList/globalIOLists.C b/src/OpenFOAM/db/IOobjects/GlobalIOList/globalIOLists.C
index d7e1214fb5a01e1529a34ab7379de676f5f122f9..143b5e7cd65cc36ef3473fd2f51ce5dcda3a4587 100644
--- a/src/OpenFOAM/db/IOobjects/GlobalIOList/globalIOLists.C
+++ b/src/OpenFOAM/db/IOobjects/GlobalIOList/globalIOLists.C
@@ -41,4 +41,5 @@ namespace Foam
     defineTemplateTypeNameWithName(tensorGlobalIOList, "tensorList");
 }
 
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOobjects/GlobalIOList/globalIOLists.H b/src/OpenFOAM/db/IOobjects/GlobalIOList/globalIOLists.H
index c65a5619c628891f2e8769a9ad98143c6c51eeca..9780a451a52537dca54cc891f6ff4f423e725102 100644
--- a/src/OpenFOAM/db/IOobjects/GlobalIOList/globalIOLists.H
+++ b/src/OpenFOAM/db/IOobjects/GlobalIOList/globalIOLists.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2015-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -53,34 +53,39 @@ namespace Foam
     {
         return true;
     }
+
     template<>
     inline bool typeGlobal<scalarGlobalIOList>()
     {
         return true;
     }
+
     template<>
     inline bool typeGlobal<vectorGlobalIOList>()
     {
         return true;
     }
+
     template<>
     inline bool typeGlobal<sphericalTensorGlobalIOList>()
     {
         return true;
     }
+
     template<>
     inline bool typeGlobal<symmTensorGlobalIOList>()
     {
         return true;
     }
+
     template<>
     inline bool typeGlobal<tensorGlobalIOList>()
     {
         return true;
     }
-
 }
 
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 #endif
diff --git a/src/OpenFOAM/db/IOobjects/IOField/IOField.C b/src/OpenFOAM/db/IOobjects/IOField/IOField.C
index ce115c36f7be69b5d4199835fa5204e9460d3a7a..41d386e2d50b6ebc1b46f828139d1754362f7940 100644
--- a/src/OpenFOAM/db/IOobjects/IOField/IOField.C
+++ b/src/OpenFOAM/db/IOobjects/IOField/IOField.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -50,6 +50,43 @@ Foam::IOField<Type>::IOField(const IOobject& io)
 }
 
 
+template<class Type>
+Foam::IOField<Type>::IOField(const IOobject& io, const bool valid)
+:
+    regIOobject(io)
+{
+    // Check for MUST_READ_IF_MODIFIED
+    warnNoRereading<IOField<Type>>();
+
+    if
+    (
+        io.readOpt() == IOobject::MUST_READ
+     || io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
+    )
+    {
+        Istream& is = readStream(typeName, valid);
+
+        if (valid)
+        {
+            is >> *this;
+        }
+        close();
+    }
+    else if (io.readOpt() == IOobject::READ_IF_PRESENT)
+    {
+        bool haveFile = headerOk();
+
+        Istream& is = readStream(typeName, haveFile && valid);
+
+        if (valid && haveFile)
+        {
+            is >> *this;
+        }
+        close();
+    }
+}
+
+
 template<class Type>
 Foam::IOField<Type>::IOField(const IOobject& io, const label size)
 :
diff --git a/src/OpenFOAM/db/IOobjects/IOField/IOField.H b/src/OpenFOAM/db/IOobjects/IOField/IOField.H
index c5029307db6099041028cdf1d1bc8a29222dafd2..768c8b05ea8df5f3b9ea475da8104e9ca2651a8c 100644
--- a/src/OpenFOAM/db/IOobjects/IOField/IOField.H
+++ b/src/OpenFOAM/db/IOobjects/IOField/IOField.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -64,6 +64,9 @@ public:
         //- Construct from IOobject
         IOField(const IOobject&);
 
+        //- Construct from IOobject; does local processor require reading?
+        IOField(const IOobject&, const bool valid);
+
         //- Construct from IOobject and size (does not set values)
         IOField(const IOobject&, const label size);
 
diff --git a/src/OpenFOAM/db/IOobjects/IOMap/IOMap.C b/src/OpenFOAM/db/IOobjects/IOMap/IOMap.C
index 39bf6c994f01343d2eb26b772fe91936ca8b2f73..3e1cea8c958cd98a69e4ac5c3fdb6d4ab87d0978 100644
--- a/src/OpenFOAM/db/IOobjects/IOMap/IOMap.C
+++ b/src/OpenFOAM/db/IOobjects/IOMap/IOMap.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/OpenFOAM/db/IOobjects/IOMap/IOMap.H b/src/OpenFOAM/db/IOobjects/IOMap/IOMap.H
index 1d79af3ec54b1eb8ee9f27759e3dd7e5796ef9d6..5dce64772f52478d3523acbdcb0e553dbebe5f5c 100644
--- a/src/OpenFOAM/db/IOobjects/IOMap/IOMap.H
+++ b/src/OpenFOAM/db/IOobjects/IOMap/IOMap.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -94,7 +94,7 @@ public:
         //  either in the case/processor or case otherwise null
         virtual fileName filePath() const
         {
-            return globalFilePath();
+            return globalFilePath(type());
         }
 
     // Member operators
diff --git a/src/OpenFOAM/db/IOobjects/IOMap/IOMapName.C b/src/OpenFOAM/db/IOobjects/IOMap/IOMapName.C
index 9ee8cb061ae9279d025f522925a0e955ae2741f5..40f655d1b29505879dba427213936e80401c68ca 100644
--- a/src/OpenFOAM/db/IOobjects/IOMap/IOMapName.C
+++ b/src/OpenFOAM/db/IOobjects/IOMap/IOMapName.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2014 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -36,6 +36,14 @@ namespace Foam
     {
         return true;
     }
+
+    //- Template specialisation for obtaining filePath
+    template<>
+    fileName typeFilePath<IOMap<dictionary>>(const IOobject& io)
+    {
+        return io.globalFilePath(IOMap<dictionary>::typeName);
+    }
 }
 
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOobjects/IOPtrList/IOPtrList.C b/src/OpenFOAM/db/IOobjects/IOPtrList/IOPtrList.C
index 2c7e436faaf7f0615f8809473070a7a49d380ef2..9e39ab5150399f1561f1bbdb41499e21765c0667 100644
--- a/src/OpenFOAM/db/IOobjects/IOPtrList/IOPtrList.C
+++ b/src/OpenFOAM/db/IOobjects/IOPtrList/IOPtrList.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/OpenFOAM/db/IOobjects/IOdictionary/IOdictionary.C b/src/OpenFOAM/db/IOobjects/IOdictionary/IOdictionary.C
index e4302967c886b72fe94778c448df7e3889f9f41f..ae894d55f49a8b6d2df91947b266a97093b34b12 100644
--- a/src/OpenFOAM/db/IOobjects/IOdictionary/IOdictionary.C
+++ b/src/OpenFOAM/db/IOobjects/IOdictionary/IOdictionary.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/OpenFOAM/db/IOobjects/IOdictionary/IOdictionary.H b/src/OpenFOAM/db/IOobjects/IOdictionary/IOdictionary.H
index 6fbf3a10b28fe944f7af76e53c7c85c2194efae3..1422ecea5ba84762425c2d157e9f3c957d03e47f 100644
--- a/src/OpenFOAM/db/IOobjects/IOdictionary/IOdictionary.H
+++ b/src/OpenFOAM/db/IOobjects/IOdictionary/IOdictionary.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -85,9 +85,8 @@ public:
         //  either in the case/processor or case otherwise null
         virtual fileName filePath() const
         {
-            return globalFilePath();
+            return globalFilePath(type());
         }
-
 };
 
 
diff --git a/src/OpenFOAM/db/IOobjects/IOdictionary/baseIOdictionary.H b/src/OpenFOAM/db/IOobjects/IOdictionary/baseIOdictionary.H
index abe9592abb03c58013c881f60d45c6d6491ddd3e..5aeb311d6fff2353c297db919ad36e5b5d95d7b3 100644
--- a/src/OpenFOAM/db/IOobjects/IOdictionary/baseIOdictionary.H
+++ b/src/OpenFOAM/db/IOobjects/IOdictionary/baseIOdictionary.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2014 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -27,9 +27,9 @@ Class
 Description
     baseIOdictionary is derived from dictionary and IOobject to give the
     dictionary automatic IO functionality via the objectRegistry.
-    To facilitate IO,
-    baseIOdictionary is provided with a constructor from IOobject and with
-    readData/writeData functions.
+
+    To facilitate IO, baseIOdictionary is provided with a constructor from
+    IOobject and with readData/writeData functions.
 
 SourceFiles
     baseIOdictionary.C
diff --git a/src/OpenFOAM/db/IOobjects/IOdictionary/localIOdictionary.C b/src/OpenFOAM/db/IOobjects/IOdictionary/localIOdictionary.C
index efb05d8afa5e57942b34ca981a6b39ebb9189306..e431cd5bdb5ea6646a1a281f42328e8d94312895 100644
--- a/src/OpenFOAM/db/IOobjects/IOdictionary/localIOdictionary.C
+++ b/src/OpenFOAM/db/IOobjects/IOdictionary/localIOdictionary.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2015-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -38,6 +38,21 @@ Foam::localIOdictionary::localIOdictionary(const IOobject& io)
 }
 
 
+Foam::localIOdictionary::localIOdictionary
+(
+    const IOobject& io,
+    const word& wantedType
+)
+:
+    baseIOdictionary(io)
+{
+    readHeaderOk(IOstream::ASCII, wantedType);
+
+    // For if MUST_READ_IF_MODIFIED
+    addWatch();
+}
+
+
 Foam::localIOdictionary::localIOdictionary
 (
     const IOobject& io,
diff --git a/src/OpenFOAM/db/IOobjects/IOdictionary/localIOdictionary.H b/src/OpenFOAM/db/IOobjects/IOdictionary/localIOdictionary.H
index e7a753beb4c777e89f36d2466e8cfd981a40eb66..b8c7142f211a3e1ce9f1137ec791a952ce73c576 100644
--- a/src/OpenFOAM/db/IOobjects/IOdictionary/localIOdictionary.H
+++ b/src/OpenFOAM/db/IOobjects/IOdictionary/localIOdictionary.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2015-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -44,7 +44,7 @@ namespace Foam
 {
 
 /*---------------------------------------------------------------------------*\
-                           Class localIOdictionary Declaration
+                      Class localIOdictionary Declaration
 \*---------------------------------------------------------------------------*/
 
 class localIOdictionary
@@ -65,6 +65,10 @@ public:
         //- Construct given an IOobject and Istream
         localIOdictionary(const IOobject& io, Istream& is);
 
+        //- Construct given an IOobject, supply wanted typeName
+        localIOdictionary(const IOobject& io, const word& wantedType);
+
+
     //- Destructor
     virtual ~localIOdictionary();
 
@@ -82,7 +86,7 @@ public:
         virtual fileName filePath() const
         {
             // Use default (local only) search strategy
-            return localFilePath();
+            return localFilePath(type());
         }
 
 };
diff --git a/src/OpenFOAM/db/IOobjects/IOdictionary/unwatchedIOdictionary.H b/src/OpenFOAM/db/IOobjects/IOdictionary/unwatchedIOdictionary.H
index 66e064350ca0ede830286f0fc18a65a243792cec..8431aa835973cd9363c3c8bdf21d59e5920a215f 100644
--- a/src/OpenFOAM/db/IOobjects/IOdictionary/unwatchedIOdictionary.H
+++ b/src/OpenFOAM/db/IOobjects/IOdictionary/unwatchedIOdictionary.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2015-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -85,7 +85,7 @@ public:
         //  either in the case/processor or case otherwise null
         virtual fileName filePath() const
         {
-            return globalFilePath();
+            return globalFilePath(type());
         }
 
         //- Add file watch on object (READ_IF_MODIFIED)
diff --git a/src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.C b/src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.C
new file mode 100644
index 0000000000000000000000000000000000000000..7afbd2fb82c2f67e48944c0585841635742bfe62
--- /dev/null
+++ b/src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.C
@@ -0,0 +1,921 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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 "decomposedBlockData.H"
+#include "OPstream.H"
+#include "IPstream.H"
+#include "PstreamBuffers.H"
+#include "OFstream.H"
+#include "IFstream.H"
+#include "IStringStream.H"
+#include "dictionary.H"
+#include <sys/time.h>
+#include "objectRegistry.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(decomposedBlockData, 0);
+}
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::decomposedBlockData::decomposedBlockData
+(
+    const label comm,
+    const IOobject& io,
+    const UPstream::commsTypes commsType
+)
+:
+    regIOobject(io),
+    commsType_(commsType),
+    comm_(comm)
+{
+    // Temporary warning
+    if (io.readOpt() == IOobject::MUST_READ_IF_MODIFIED)
+    {
+        WarningInFunction
+            << "decomposedBlockData " << name()
+            << " constructed with IOobject::MUST_READ_IF_MODIFIED"
+            " but decomposedBlockData does not support automatic rereading."
+            << endl;
+    }
+    if
+    (
+        (
+            io.readOpt() == IOobject::MUST_READ
+         || io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
+        )
+     || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
+    )
+    {
+        read();
+    }
+}
+
+
+Foam::decomposedBlockData::decomposedBlockData
+(
+    const label comm,
+    const IOobject& io,
+    const UList<char>& list,
+    const UPstream::commsTypes commsType
+)
+:
+    regIOobject(io),
+    commsType_(commsType),
+    comm_(comm)
+{
+    // Temporary warning
+    if (io.readOpt() == IOobject::MUST_READ_IF_MODIFIED)
+    {
+        WarningInFunction
+            << "decomposedBlockData " << name()
+            << " constructed with IOobject::MUST_READ_IF_MODIFIED"
+            " but decomposedBlockData does not support automatic rereading."
+            << endl;
+    }
+
+    if
+    (
+        (
+            io.readOpt() == IOobject::MUST_READ
+         || io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
+        )
+     || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
+    )
+    {
+        read();
+    }
+    else
+    {
+        List<char>::operator=(list);
+    }
+}
+
+
+Foam::decomposedBlockData::decomposedBlockData
+(
+    const label comm,
+    const IOobject& io,
+    const Xfer<List<char>>& list,
+    const UPstream::commsTypes commsType
+)
+:
+    regIOobject(io),
+    commsType_(commsType),
+    comm_(comm)
+{
+    // Temporary warning
+    if (io.readOpt() == IOobject::MUST_READ_IF_MODIFIED)
+    {
+        WarningInFunction
+            << "decomposedBlockData " << name()
+            << " constructed with IOobject::MUST_READ_IF_MODIFIED"
+            " but decomposedBlockData does not support automatic rereading."
+            << endl;
+    }
+
+    List<char>::transfer(list());
+
+    if
+    (
+        (
+            io.readOpt() == IOobject::MUST_READ
+         || io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
+        )
+     || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
+    )
+    {
+        read();
+    }
+}
+
+
+// * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * * //
+
+Foam::decomposedBlockData::~decomposedBlockData()
+{}
+
+
+// * * * * * * * * * * * * * * * Members Functions * * * * * * * * * * * * * //
+
+bool Foam::decomposedBlockData::readMasterHeader(IOobject& io, Istream& is)
+{
+    if (debug)
+    {
+        Pout<< "decomposedBlockData::readMasterHeader:"
+            << " stream:" << is.name() << endl;
+    }
+
+    // Master-only reading of header
+    is.fatalCheck("read(Istream&)");
+
+    List<char> data(is);
+    is.fatalCheck("read(Istream&) : reading entry");
+    string buf(data.begin(), data.size());
+    IStringStream str(is.name(), buf);
+
+    return io.readHeader(str);
+}
+
+
+void Foam::decomposedBlockData::writeHeader
+(
+    Ostream& os,
+    const IOstream::versionNumber version,
+    const IOstream::streamFormat format,
+    const word& type,
+    const string& note,
+    const fileName& location,
+    const word& name
+)
+{
+    IOobject::writeBanner(os)
+        << "FoamFile\n{\n"
+        << "    version     " << version << ";\n"
+        << "    format      " << format << ";\n"
+        << "    class       " << type << ";\n";
+    if (note.size())
+    {
+        os  << "    note        " << note << ";\n";
+    }
+
+    if (location.size())
+    {
+        os  << "    location    " << location << ";\n";
+    }
+
+    os  << "    object      " << name << ";\n"
+        << "}" << nl;
+
+    IOobject::writeDivider(os) << nl;
+}
+
+
+Foam::autoPtr<Foam::ISstream> Foam::decomposedBlockData::readBlock
+(
+    const label blocki,
+    Istream& is,
+    IOobject& headerIO
+)
+{
+    if (debug)
+    {
+        Pout<< "decomposedBlockData::readBlock:"
+            << " stream:" << is.name() << " attempt to read block " << blocki
+            << endl;
+    }
+
+    is.fatalCheck("read(Istream&)");
+
+    List<char> data;
+    autoPtr<ISstream> realIsPtr;
+
+    if (blocki == 0)
+    {
+        is >> data;
+        is.fatalCheck("read(Istream&) : reading entry");
+
+        string buf(data.begin(), data.size());
+        realIsPtr = new IStringStream(is.name(), buf);
+
+        // Read header
+        if (!headerIO.readHeader(realIsPtr()))
+        {
+            FatalIOErrorInFunction(realIsPtr())
+                << "problem while reading header for object "
+                << is.name() << exit(FatalIOError);
+        }
+    }
+    else
+    {
+        // Read master for header
+        is >> data;
+        is.fatalCheck("read(Istream&) : reading entry");
+
+        IOstream::versionNumber ver(IOstream::currentVersion);
+        IOstream::streamFormat fmt;
+        {
+            string buf(data.begin(), data.size());
+            IStringStream headerStream(is.name(), buf);
+
+            // Read header
+            if (!headerIO.readHeader(headerStream))
+            {
+                FatalIOErrorInFunction(headerStream)
+                    << "problem while reading header for object "
+                    << is.name() << exit(FatalIOError);
+            }
+            ver = headerStream.version();
+            fmt = headerStream.format();
+        }
+
+        for (label i = 1; i < blocki+1; i++)
+        {
+            // Read data, override old data
+            is >> data;
+            is.fatalCheck("read(Istream&) : reading entry");
+        }
+        string buf(data.begin(), data.size());
+        realIsPtr = new IStringStream(is.name(), buf);
+
+        // Apply master stream settings to realIsPtr
+        realIsPtr().format(fmt);
+        realIsPtr().version(ver);
+    }
+    return realIsPtr;
+}
+
+
+bool Foam::decomposedBlockData::readBlocks
+(
+    const label comm,
+    autoPtr<ISstream>& isPtr,
+    List<char>& data,
+    const UPstream::commsTypes commsType
+)
+{
+    if (debug)
+    {
+        Pout<< "decomposedBlockData::readBlocks:"
+            << " stream:" << (isPtr.valid() ? isPtr().name() : "invalid")
+            << " commsType:" << Pstream::commsTypeNames[commsType]
+            << " comm:" << comm << endl;
+    }
+
+    bool ok = false;
+
+    if (commsType == UPstream::commsTypes::scheduled)
+    {
+        if (UPstream::master(comm))
+        {
+            Istream& is = isPtr();
+            is.fatalCheck("read(Istream&)");
+
+            // Read master data
+            {
+                is >> data;
+                is.fatalCheck("read(Istream&) : reading entry");
+            }
+
+            // Read slave data
+            for
+            (
+                label proci = 1;
+                proci < UPstream::nProcs(comm);
+                proci++
+            )
+            {
+                List<char> elems(is);
+                is.fatalCheck("read(Istream&) : reading entry");
+
+                OPstream os
+                (
+                    UPstream::commsTypes::scheduled,
+                    proci,
+                    0,
+                    UPstream::msgType(),
+                    comm
+                );
+                os << elems;
+            }
+
+            ok = is.good();
+        }
+        else
+        {
+            IPstream is
+            (
+                UPstream::commsTypes::scheduled,
+                UPstream::masterNo(),
+                0,
+                UPstream::msgType(),
+                comm
+            );
+            is >> data;
+        }
+    }
+    else
+    {
+        PstreamBuffers pBufs
+        (
+            UPstream::commsTypes::nonBlocking,
+            UPstream::msgType(),
+            comm
+        );
+
+        if (UPstream::master(comm))
+        {
+            Istream& is = isPtr();
+            is.fatalCheck("read(Istream&)");
+
+            // Read master data
+            {
+                is >> data;
+                is.fatalCheck("read(Istream&) : reading entry");
+            }
+
+            // Read slave data
+            for
+            (
+                label proci = 1;
+                proci < UPstream::nProcs(comm);
+                proci++
+            )
+            {
+                List<char> elems(is);
+                is.fatalCheck("read(Istream&) : reading entry");
+
+                UOPstream os(proci, pBufs);
+                os << elems;
+            }
+        }
+
+        labelList recvSizes;
+        pBufs.finishedSends(recvSizes);
+
+        if (!UPstream::master(comm))
+        {
+            UIPstream is(UPstream::masterNo(), pBufs);
+            is >> data;
+        }
+    }
+
+    Pstream::scatter(ok, Pstream::msgType(), comm);
+
+    return ok;
+}
+
+
+Foam::autoPtr<Foam::ISstream> Foam::decomposedBlockData::readBlocks
+(
+    const label comm,
+    const fileName& fName,
+    autoPtr<ISstream>& isPtr,
+    IOobject& headerIO,
+    const UPstream::commsTypes commsType
+)
+{
+    if (debug)
+    {
+        Pout<< "decomposedBlockData::readBlocks:"
+            << " stream:" << (isPtr.valid() ? isPtr().name() : "invalid")
+            << " commsType:" << Pstream::commsTypeNames[commsType] << endl;
+    }
+
+    bool ok = false;
+
+    List<char> data;
+    autoPtr<ISstream> realIsPtr;
+
+    if (commsType == UPstream::commsTypes::scheduled)
+    {
+        if (UPstream::master(comm))
+        {
+            Istream& is = isPtr();
+            is.fatalCheck("read(Istream&)");
+
+            // Read master data
+            {
+                is >> data;
+                is.fatalCheck("read(Istream&) : reading entry");
+
+                string buf(data.begin(), data.size());
+                realIsPtr = new IStringStream(fName, buf);
+
+                // Read header
+                if (!headerIO.readHeader(realIsPtr()))
+                {
+                    FatalIOErrorInFunction(realIsPtr())
+                        << "problem while reading header for object "
+                        << is.name() << exit(FatalIOError);
+                }
+            }
+
+            // Read slave data
+            for
+            (
+                label proci = 1;
+                proci < UPstream::nProcs(comm);
+                proci++
+            )
+            {
+                is >> data;
+                is.fatalCheck("read(Istream&) : reading entry");
+
+                OPstream os
+                (
+                    UPstream::commsTypes::scheduled,
+                    proci,
+                    0,
+                    UPstream::msgType(),
+                    comm
+                );
+                os << data;
+            }
+
+            ok = is.good();
+        }
+        else
+        {
+            IPstream is
+            (
+                UPstream::commsTypes::scheduled,
+                UPstream::masterNo(),
+                0,
+                UPstream::msgType(),
+                comm
+            );
+            is >> data;
+
+            string buf(data.begin(), data.size());
+            realIsPtr = new IStringStream(fName, buf);
+        }
+    }
+    else
+    {
+        PstreamBuffers pBufs
+        (
+            UPstream::commsTypes::nonBlocking,
+            UPstream::msgType(),
+            comm
+        );
+
+        if (UPstream::master(comm))
+        {
+            Istream& is = isPtr();
+            is.fatalCheck("read(Istream&)");
+
+            // Read master data
+            {
+                is >> data;
+                is.fatalCheck("read(Istream&) : reading entry");
+
+                string buf(data.begin(), data.size());
+                realIsPtr = new IStringStream(fName, buf);
+
+                // Read header
+                if (!headerIO.readHeader(realIsPtr()))
+                {
+                    FatalIOErrorInFunction(realIsPtr())
+                        << "problem while reading header for object "
+                        << is.name() << exit(FatalIOError);
+                }
+            }
+
+            // Read slave data
+            for
+            (
+                label proci = 1;
+                proci < UPstream::nProcs(comm);
+                proci++
+            )
+            {
+                List<char> elems(is);
+                is.fatalCheck("read(Istream&) : reading entry");
+
+                UOPstream os(proci, pBufs);
+                os << elems;
+            }
+
+            ok = is.good();
+        }
+
+        labelList recvSizes;
+        pBufs.finishedSends(recvSizes);
+
+        if (!UPstream::master(comm))
+        {
+            UIPstream is(UPstream::masterNo(), pBufs);
+            is >> data;
+
+            string buf(data.begin(), data.size());
+            realIsPtr = new IStringStream(fName, buf);
+        }
+    }
+
+    Pstream::scatter(ok, Pstream::msgType(), comm);
+
+    // version
+    string versionString(realIsPtr().version().str());
+    Pstream::scatter(versionString,  Pstream::msgType(), comm);
+    realIsPtr().version(IStringStream(versionString)());
+
+    // stream
+    {
+        OStringStream os;
+        os << realIsPtr().format();
+        string formatString(os.str());
+        Pstream::scatter(formatString,  Pstream::msgType(), comm);
+        realIsPtr().format(formatString);
+    }
+
+    word name(headerIO.name());
+    Pstream::scatter(name, Pstream::msgType(), comm);
+    headerIO.rename(name);
+    Pstream::scatter(headerIO.headerClassName(), Pstream::msgType(), comm);
+    Pstream::scatter(headerIO.note(), Pstream::msgType(), comm);
+    //Pstream::scatter(headerIO.instance(), Pstream::msgType(), comm);
+    //Pstream::scatter(headerIO.local(), Pstream::msgType(), comm);
+
+    return realIsPtr;
+}
+
+
+bool Foam::decomposedBlockData::writeBlocks
+(
+    const label comm,
+    autoPtr<OSstream>& osPtr,
+    List<std::streamoff>& start,
+    const UList<char>& data,
+    const UPstream::commsTypes commsType,
+    const bool syncReturnState
+)
+{
+    if (debug)
+    {
+        Pout<< "decomposedBlockData::writeBlocks:"
+            << " stream:" << (osPtr.valid() ? osPtr().name() : "invalid")
+            << " data:" << data.size()
+            << " commsType:" << Pstream::commsTypeNames[commsType] << endl;
+    }
+
+    bool ok = true;
+
+    labelList recvSizes(Pstream::nProcs(comm));
+    recvSizes[Pstream::myProcNo(comm)] = data.byteSize();
+    Pstream::gatherList(recvSizes, Pstream::msgType(), comm);
+
+    if (commsType == UPstream::commsTypes::scheduled)
+    {
+        if (UPstream::master(comm))
+        {
+            start.setSize(UPstream::nProcs(comm));
+
+            OSstream& os = osPtr();
+
+            // Write master data
+            {
+                os << nl << "// Processor" << UPstream::masterNo() << nl;
+                start[UPstream::masterNo()] = os.stdStream().tellp();
+                os << data;
+            }
+            // Write slaves
+            List<char> elems;
+            for (label proci = 1; proci < UPstream::nProcs(comm); proci++)
+            {
+                elems.setSize(recvSizes[proci]);
+                IPstream::read
+                (
+                    UPstream::commsTypes::scheduled,
+                    proci,
+                    elems.begin(),
+                    elems.size(),
+                    Pstream::msgType(),
+                    comm
+                );
+
+                os << nl << nl << "// Processor" << proci << nl;
+                start[proci] = os.stdStream().tellp();
+                os << elems;
+            }
+
+            ok = os.good();
+        }
+        else
+        {
+            UOPstream::write
+            (
+                UPstream::commsTypes::scheduled,
+                UPstream::masterNo(),
+                data.begin(),
+                data.byteSize(),
+                Pstream::msgType(),
+                comm
+            );
+        }
+    }
+    else
+    {
+        if (debug)
+        {
+            struct timeval tv;
+            gettimeofday(&tv, nullptr);
+            Pout<< "Starting sending at:"
+                << 1.0*tv.tv_sec+tv.tv_usec/1e6 << " s"
+                << Foam::endl;
+        }
+
+
+        label startOfRequests = Pstream::nRequests();
+
+        if (!UPstream::master(comm))
+        {
+            UOPstream::write
+            (
+                UPstream::commsTypes::nonBlocking,
+                UPstream::masterNo(),
+                data.begin(),
+                data.byteSize(),
+                Pstream::msgType(),
+                comm
+            );
+            Pstream::waitRequests(startOfRequests);
+        }
+        else
+        {
+            List<List<char>> recvBufs(Pstream::nProcs(comm));
+            for (label proci = 1; proci < UPstream::nProcs(comm); proci++)
+            {
+                recvBufs[proci].setSize(recvSizes[proci]);
+                UIPstream::read
+                (
+                    UPstream::commsTypes::nonBlocking,
+                    proci,
+                    recvBufs[proci].begin(),
+                    recvSizes[proci],
+                    Pstream::msgType(),
+                    comm
+                );
+            }
+
+            if (debug)
+            {
+                struct timeval tv;
+                gettimeofday(&tv, nullptr);
+                Pout<< "Starting master-only writing at:"
+                    << 1.0*tv.tv_sec+tv.tv_usec/1e6 << " s"
+                    << Foam::endl;
+            }
+
+            start.setSize(UPstream::nProcs(comm));
+
+            OSstream& os = osPtr();
+
+            // Write master data
+            {
+                os << nl << "// Processor" << UPstream::masterNo() << nl;
+                start[UPstream::masterNo()] = os.stdStream().tellp();
+                os << data;
+            }
+
+            if (debug)
+            {
+                struct timeval tv;
+                gettimeofday(&tv, nullptr);
+                Pout<< "Starting slave writing at:"
+                    << 1.0*tv.tv_sec+tv.tv_usec/1e6 << " s"
+                    << Foam::endl;
+            }
+
+            // Write slaves
+            for (label proci = 1; proci < UPstream::nProcs(comm); proci++)
+            {
+                os << nl << nl << "// Processor" << proci << nl;
+                start[proci] = os.stdStream().tellp();
+
+                if (Pstream::finishedRequest(startOfRequests+proci-1))
+                {
+                    os << recvBufs[proci];
+                }
+            }
+
+            Pstream::resetRequests(startOfRequests);
+
+            ok = os.good();
+        }
+    }
+    if (debug)
+    {
+        struct timeval tv;
+        gettimeofday(&tv, nullptr);
+        Pout<< "Finished master-only writing at:"
+            << 1.0*tv.tv_sec+tv.tv_usec/1e6 << " s"
+            << Foam::endl;
+    }
+
+    if (syncReturnState)
+    {
+        //- Enable to get synchronised error checking. Is the one that keeps
+        //  slaves as slow as the master (which does all the writing)
+        Pstream::scatter(ok, Pstream::msgType(), comm);
+    }
+
+    return ok;
+}
+
+
+bool Foam::decomposedBlockData::read()
+{
+    autoPtr<ISstream> isPtr;
+    fileName objPath(fileHandler().filePath(false, *this, word::null));
+    if (UPstream::master(comm_))
+    {
+        isPtr.reset(new IFstream(objPath));
+        IOobject::readHeader(isPtr());
+    }
+
+    List<char>& data = *this;
+    return readBlocks(comm_, isPtr, data, commsType_);
+}
+
+
+bool Foam::decomposedBlockData::writeData(Ostream& os) const
+{
+    const List<char>& data = *this;
+
+    string str
+    (
+        reinterpret_cast<const char*>(data.cbegin()),
+        data.byteSize()
+    );
+
+    IOobject io(*this);
+    if (Pstream::master())
+    {
+        IStringStream is(name(), str);
+        io.readHeader(is);
+    }
+
+    // Scatter header information
+
+    // version
+    string versionString(os.version().str());
+    Pstream::scatter(versionString);
+
+    // stream
+    string formatString;
+    {
+        OStringStream os;
+        os << os.format();
+        formatString  = os.str();
+        Pstream::scatter(formatString);
+    }
+
+    //word masterName(name());
+    //Pstream::scatter(masterName);
+
+    Pstream::scatter(io.headerClassName());
+    Pstream::scatter(io.note());
+    //Pstream::scatter(io.instance(), Pstream::msgType(), comm);
+    //Pstream::scatter(io.local(), Pstream::msgType(), comm);
+
+    fileName masterLocation(instance()/db().dbDir()/local());
+    Pstream::scatter(masterLocation);
+
+    if (!Pstream::master())
+    {
+        writeHeader
+        (
+            os,
+            IOstream::versionNumber(IStringStream(versionString)()),
+            IOstream::formatEnum(formatString),
+            io.headerClassName(),
+            io.note(),
+            masterLocation,
+            name()
+        );
+    }
+
+    os.writeQuoted(str, false);
+
+    if (!Pstream::master())
+    {
+        IOobject::writeEndDivider(os);
+    }
+
+    return os.good();
+}
+
+
+bool Foam::decomposedBlockData::writeObject
+(
+    IOstream::streamFormat fmt,
+    IOstream::versionNumber ver,
+    IOstream::compressionType cmp,
+    const bool valid
+) const
+{
+    autoPtr<OSstream> osPtr;
+    if (UPstream::master(comm_))
+    {
+        // Note: always write binary. These are strings so readable
+        //       anyway. They have already be tokenised on the sending side.
+        osPtr.reset(new OFstream(objectPath(), IOstream::BINARY, ver, cmp));
+        IOobject::writeHeader(osPtr());
+    }
+    List<std::streamoff> start;
+    return writeBlocks(comm_, osPtr, start, *this, commsType_);
+}
+
+
+Foam::label Foam::decomposedBlockData::numBlocks(const fileName& fName)
+{
+    label nBlocks = 0;
+
+    IFstream is(fName);
+    is.fatalCheck("decomposedBlockData::numBlocks(const fileName&)");
+
+    if (!is.good())
+    {
+        return nBlocks;
+    }
+
+    // Skip header
+    token firstToken(is);
+
+    if
+    (
+        is.good()
+     && firstToken.isWord()
+     && firstToken.wordToken() == "FoamFile"
+    )
+    {
+        dictionary headerDict(is);
+        is.version(headerDict.lookup("version"));
+        is.format(headerDict.lookup("format"));
+    }
+
+    List<char> data;
+    while (is.good())
+    {
+        token sizeToken(is);
+        if (!sizeToken.isLabel())
+        {
+            return nBlocks;
+        }
+        is.putBack(sizeToken);
+
+        is >> data;
+        nBlocks++;
+    }
+
+    return nBlocks;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.H b/src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.H
new file mode 100644
index 0000000000000000000000000000000000000000..dc4e3d70f2a2f5b036267772d7742a1dbd779569
--- /dev/null
+++ b/src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.H
@@ -0,0 +1,197 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::decomposedBlockData
+
+Description
+    decomposedBlockData is a List<char> with IO on the master processor only.
+
+SourceFiles
+    decomposedBlockData.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef decomposedBlockData_H
+#define decomposedBlockData_H
+
+#include "IOList.H"
+#include "regIOobject.H"
+#include "UPstream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class decomposedBlockData Declaration
+\*---------------------------------------------------------------------------*/
+
+class decomposedBlockData
+:
+    public regIOobject,
+    public List<char>
+{
+protected:
+
+    // Protected data
+
+        //- Type to use for gather
+        const UPstream::commsTypes commsType_;
+
+        //- Communicator for all parallel comms
+        const label comm_;
+
+
+    // Protected member functions
+
+        //- Read data into *this. ISstream is only valid on master.
+        static bool readBlocks
+        (
+            const label comm,
+            autoPtr<ISstream>& isPtr,
+            List<char>& data,
+            const UPstream::commsTypes commsType
+        );
+
+
+public:
+
+    TypeName("decomposedBlockData");
+
+
+    // Constructors
+
+        //- Construct given an IOobject
+        decomposedBlockData
+        (
+            const label comm,
+            const IOobject&,
+            const UPstream::commsTypes = UPstream::commsTypes::scheduled
+        );
+
+        //- Construct given an IOobject and for READ_IF_MODIFIED a List<char>
+        decomposedBlockData
+        (
+            const label comm,
+            const IOobject&,
+            const UList<char>&,
+            const UPstream::commsTypes = UPstream::commsTypes::scheduled
+        );
+
+        //- Construct by transferring the IOList contents
+        decomposedBlockData
+        (
+            const label comm,
+            const IOobject&,
+            const Xfer<List<char>>&,
+            const UPstream::commsTypes = UPstream::commsTypes::scheduled
+        );
+
+
+    //- Destructor
+    virtual ~decomposedBlockData();
+
+
+    // Member functions
+
+        //- Read object
+        virtual bool read();
+
+        //- Write separated content. Assumes content is the serialised data
+        //  and that the master data contains a header
+        virtual bool writeData(Ostream&) const;
+
+        //- Write using given format, version and compression
+        virtual bool writeObject
+        (
+            IOstream::streamFormat,
+            IOstream::versionNumber,
+            IOstream::compressionType,
+            const bool valid
+        ) const;
+
+
+    // Helpers
+
+        //- Read header. Call only on master.
+        static bool readMasterHeader(IOobject&, Istream&);
+
+        //- Helper: write FoamFile IOobject header
+        static void writeHeader
+        (
+            Ostream& os,
+            const IOstream::versionNumber version,
+            const IOstream::streamFormat format,
+            const word& type,
+            const string& note,
+            const fileName& location,
+            const word& name
+        );
+
+        //- Read selected block (non-seeking) + header information
+        static autoPtr<ISstream> readBlock
+        (
+            const label blocki,
+            Istream& is,
+            IOobject& headerIO
+        );
+
+        //- Read master header information (into headerIO) and return
+        //  data in stream. Note: isPtr is only valid on master.
+        static autoPtr<ISstream> readBlocks
+        (
+            const label comm,
+            const fileName& fName,
+            autoPtr<ISstream>& isPtr,
+            IOobject& headerIO,
+            const UPstream::commsTypes commsType
+        );
+
+        //- Write *this. Ostream only valid on master. Returns starts of
+        //  processor blocks
+        static bool writeBlocks
+        (
+            const label comm,
+            autoPtr<OSstream>& osPtr,
+            List<std::streamoff>& start,
+            const UList<char>&,
+            const UPstream::commsTypes,
+            const bool syncReturnState = true
+        );
+
+        //- Detect number of blocks in a file
+        static label numBlocks(const fileName&);
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOstreams/Fstreams/OFstream.C b/src/OpenFOAM/db/IOstreams/Fstreams/OFstream.C
index aad480a105a2d038b80ded2733c1d06e05fd1588..17a2b7d1e427a8ecfa14f92c0978f0298d111fbb 100644
--- a/src/OpenFOAM/db/IOstreams/Fstreams/OFstream.C
+++ b/src/OpenFOAM/db/IOstreams/Fstreams/OFstream.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -40,7 +40,8 @@ namespace Foam
 Foam::OFstreamAllocator::OFstreamAllocator
 (
     const fileName& pathname,
-    IOstream::compressionType compression
+    IOstream::compressionType compression,
+    const bool append
 )
 :
     allocatedPtr_(nullptr)
@@ -52,26 +53,48 @@ Foam::OFstreamAllocator::OFstreamAllocator
             InfoInFunction << "Cannot open null file " << endl;
         }
     }
+    ofstream::openmode mode(ofstream::out);
+    if (append)
+    {
+        mode |= ofstream::app;
+    }
 
     if (compression == IOstream::COMPRESSED)
     {
         // Get identically named uncompressed version out of the way
-        if (isFile(pathname, false))
+        fileName::Type pathType = Foam::type(pathname, false);
+        if (pathType == fileName::FILE || pathType == fileName::LINK)
         {
             rm(pathname);
         }
+        fileName gzPathName(pathname + ".gz");
+
+        if (!append && Foam::type(gzPathName) == fileName::LINK)
+        {
+            // Disallow writing into softlink to avoid any problems with
+            // e.g. softlinked initial fields
+            rm(gzPathName);
+        }
 
-        allocatedPtr_ = new ogzstream((pathname + ".gz").c_str());
+        allocatedPtr_ = new ogzstream(gzPathName.c_str(), mode);
     }
     else
     {
-        // Get identically named compressed version out of the way
-        if (isFile(pathname + ".gz", false))
+        // get identically named compressed version out of the way
+        fileName gzPathName(pathname + ".gz");
+        fileName::Type gzType = Foam::type(gzPathName, false);
+        if (gzType == fileName::FILE || gzType == fileName::LINK)
+        {
+            rm(gzPathName);
+        }
+        if (!append && Foam::type(pathname, false) == fileName::LINK)
         {
-            rm(pathname + ".gz");
+            // Disallow writing into softlink to avoid any problems with
+            // e.g. softlinked initial fields
+            rm(pathname);
         }
 
-        allocatedPtr_ = new std::ofstream(pathname);
+        allocatedPtr_ = new std::ofstream(pathname, mode);
     }
 }
 
@@ -99,11 +122,19 @@ Foam::OFstream::OFstream
     const fileName& pathname,
     streamFormat format,
     versionNumber version,
-    compressionType compression
+    compressionType compression,
+    const bool append
 )
 :
-    OFstreamAllocator(pathname, compression),
-    OSstream(*allocatedPtr_, pathname, format, version, compression)
+    OFstreamAllocator(pathname, compression, append),
+    OSstream
+    (
+        *allocatedPtr_,
+        "OFstream.sinkFile_",
+        format,
+        version,
+        compression
+    )
 {
     setClosed();
     setState(allocatedPtr_->rdstate());
diff --git a/src/OpenFOAM/db/IOstreams/Fstreams/OFstream.H b/src/OpenFOAM/db/IOstreams/Fstreams/OFstream.H
index 84487809d25366c372f33b7b6dc6a7b038c09111..732fd6901012b8a6b02f346dedeea7ac4b3a2812 100644
--- a/src/OpenFOAM/db/IOstreams/Fstreams/OFstream.H
+++ b/src/OpenFOAM/db/IOstreams/Fstreams/OFstream.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -68,7 +68,8 @@ protected:
         OFstreamAllocator
         (
             const fileName& pathname,
-            IOstream::compressionType compression=IOstream::UNCOMPRESSED
+            IOstream::compressionType compression=IOstream::UNCOMPRESSED,
+            const bool append = false
         );
 
 
@@ -107,7 +108,8 @@ public:
             const fileName& pathname,
             streamFormat format=ASCII,
             versionNumber version=currentVersion,
-            compressionType compression=UNCOMPRESSED
+            compressionType compression=UNCOMPRESSED,
+            const bool append = false
         );
 
 
diff --git a/src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.C b/src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.C
new file mode 100644
index 0000000000000000000000000000000000000000..f25097a779ed40f6a838333ef0cb81f016f1a614
--- /dev/null
+++ b/src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.C
@@ -0,0 +1,168 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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 "masterOFstream.H"
+#include "OFstream.H"
+#include "OSspecific.H"
+#include "PstreamBuffers.H"
+#include "masterUncollatedFileOperation.H"
+#include "boolList.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::masterOFstream::checkWrite
+(
+    const fileName& fName,
+    const string& str
+)
+{
+    mkDir(fName.path());
+
+    OFstream os
+    (
+        fName,
+        IOstream::BINARY,   //format(),
+        version(),
+        compression_,
+        append_
+    );
+    if (!os.good())
+    {
+        FatalIOErrorInFunction(os)
+            << "Could not open file " << fName
+            << exit(FatalIOError);
+    }
+
+    os.writeQuoted(str, false);
+    if (!os.good())
+    {
+        FatalIOErrorInFunction(os)
+            << "Failed writing to " << fName
+            << exit(FatalIOError);
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::masterOFstream::masterOFstream
+(
+    const fileName& pathName,
+    streamFormat format,
+    versionNumber version,
+    compressionType compression,
+    const bool append,
+    const bool valid
+)
+:
+    OStringStream(format, version),
+    pathName_(pathName),
+    compression_(compression),
+    append_(append),
+    valid_(valid)
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::masterOFstream::~masterOFstream()
+{
+    if (Pstream::parRun())
+    {
+        List<fileName> filePaths(Pstream::nProcs());
+        filePaths[Pstream::myProcNo()] = pathName_;
+        Pstream::gatherList(filePaths);
+
+        bool uniform =
+            fileOperations::masterUncollatedFileOperation::uniformFile
+            (
+                filePaths
+            );
+
+        Pstream::scatter(uniform);
+
+        if (uniform)
+        {
+            if (Pstream::master() && valid_)
+            {
+                checkWrite(pathName_, str());
+            }
+            return;
+        }
+        boolList valid(Pstream::nProcs());
+        valid[Pstream::myProcNo()] = valid_;
+        Pstream::gatherList(valid);
+
+
+        // Different files
+        PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
+
+        // Send my buffer to master
+        if (!Pstream::master())
+        {
+            UOPstream os(Pstream::masterNo(), pBufs);
+            string s(this->str());
+            os.write(&s[0], s.size());
+        }
+
+        labelList recvSizes;
+        pBufs.finishedSends(recvSizes);
+
+        if (Pstream::master())
+        {
+            // Write my own data
+            {
+                if (valid[Pstream::myProcNo()])
+                {
+                    checkWrite(filePaths[Pstream::myProcNo()], str());
+                }
+            }
+
+            for (label proci = 1; proci < Pstream::nProcs(); proci++)
+            {
+                UIPstream is(proci, pBufs);
+                List<char> buf(recvSizes[proci]);
+
+                is.read(buf.begin(), buf.size());
+
+                if (valid[proci])
+                {
+                    checkWrite
+                    (
+                        filePaths[proci],
+                        string(buf.begin(), buf.size())
+                    );
+                }
+            }
+        }
+    }
+    else
+    {
+        checkWrite(pathName_, str());
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.H b/src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.H
new file mode 100644
index 0000000000000000000000000000000000000000..6bc595d692c55baa61323d370e821d76b23bcac8
--- /dev/null
+++ b/src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.H
@@ -0,0 +1,100 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::masterOFstream
+
+Description
+    Master-only drop-in replacement for OFstream.
+
+SourceFiles
+    masterOFstream.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef masterOFstream_H
+#define masterOFstream_H
+
+#include "OStringStream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                       Class masterOFstream Declaration
+\*---------------------------------------------------------------------------*/
+
+class masterOFstream
+:
+    public OStringStream
+{
+    // Private data
+
+        const fileName pathName_;
+
+        const IOstream::compressionType compression_;
+
+        const bool append_;
+
+        //- Should file be written
+        const bool valid_;
+
+
+    // Private Member Functions
+
+        //- Open file with checking
+        void checkWrite(const fileName& fName, const string& str);
+
+
+public:
+
+    // Constructors
+
+        //- Construct and set stream status
+        masterOFstream
+        (
+            const fileName& pathname,
+            streamFormat format=ASCII,
+            versionNumber version=currentVersion,
+            compressionType compression=UNCOMPRESSED,
+            const bool append = false,
+            const bool valid = true
+        );
+
+
+    //- Destructor
+    ~masterOFstream();
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOstreams/dummyISstream/dummyISstream.H b/src/OpenFOAM/db/IOstreams/dummyISstream/dummyISstream.H
new file mode 100644
index 0000000000000000000000000000000000000000..a774271a11ad77fa3cb7a689dd288906edafcaa7
--- /dev/null
+++ b/src/OpenFOAM/db/IOstreams/dummyISstream/dummyISstream.H
@@ -0,0 +1,160 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::dummyISstream
+
+Description
+    Dummy stream for input. Aborts at any attempt to read from it.
+
+SourceFiles
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef dummyISstream_H
+#define dummyISstream_H
+
+#include "IStringStream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                        Class dummyISstream Declaration
+\*---------------------------------------------------------------------------*/
+
+class dummyISstream
+:
+    public IStringStream
+{
+
+public:
+
+    // Constructors
+
+        //- Construct null
+        dummyISstream()
+        :
+            IStringStream(string::null)
+        {}
+
+
+    //- Destructor
+    virtual ~dummyISstream()
+    {}
+
+
+    // Member functions
+
+        // Read functions
+
+            //- Return next token from stream
+            virtual Istream& read(token&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read a character
+            virtual Istream& read(char&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read a word
+            virtual Istream& read(word&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            // Read a string (including enclosing double-quotes)
+            virtual Istream& read(string&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read a label
+            virtual Istream& read(label&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read a floatScalar
+            virtual Istream& read(floatScalar&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read a doubleScalar
+            virtual Istream& read(doubleScalar&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read binary block
+            virtual Istream& read(char*, std::streamsize)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Rewind and return the stream so that it may be read again
+            virtual Istream& rewind()
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Return flags of stream
+            virtual ios_base::fmtflags flags() const
+            {
+                NotImplemented;
+                return ios_base::fmtflags(0);
+            }
+
+            //- Set flags of stream
+            virtual ios_base::fmtflags flags(const ios_base::fmtflags f)
+            {
+                NotImplemented;
+                return f;
+            }
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOstreams/dummyIstream/dummyIstream.H b/src/OpenFOAM/db/IOstreams/dummyIstream/dummyIstream.H
new file mode 100644
index 0000000000000000000000000000000000000000..9e8549820db4869fff8b7a11347a90a97614ebd2
--- /dev/null
+++ b/src/OpenFOAM/db/IOstreams/dummyIstream/dummyIstream.H
@@ -0,0 +1,161 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::dummyIstream
+
+Description
+    Dummy stream for input. Aborts at any attempt to read from it.
+
+SourceFiles
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef dummyIstream_H
+#define dummyIstream_H
+
+#include "Istream.H"
+//#include <sstream>
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                        Class dummyIstream Declaration
+\*---------------------------------------------------------------------------*/
+
+class dummyIstream
+:
+    public Istream
+{
+
+public:
+
+    // Constructors
+
+        //- Construct null
+        dummyIstream()
+        :
+            Istream()
+        {}
+
+
+    //- Destructor
+    ~dummyIstream()
+    {}
+
+
+    // Member functions
+
+        // Read functions
+
+            //- Return next token from stream
+            virtual Istream& read(token&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read a character
+            virtual Istream& read(char&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read a word
+            virtual Istream& read(word&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            // Read a string (including enclosing double-quotes)
+            virtual Istream& read(string&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read a label
+            virtual Istream& read(label&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read a floatScalar
+            virtual Istream& read(floatScalar&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read a doubleScalar
+            virtual Istream& read(doubleScalar&)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Read binary block
+            virtual Istream& read(char*, std::streamsize)
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Rewind and return the stream so that it may be read again
+            virtual Istream& rewind()
+            {
+                NotImplemented;
+                return *this;
+            }
+
+            //- Return flags of stream
+            virtual ios_base::fmtflags flags() const
+            {
+                NotImplemented;
+                return ios_base::fmtflags(0);
+            }
+
+            //- Set flags of stream
+            virtual ios_base::fmtflags flags(const ios_base::fmtflags f)
+            {
+                NotImplemented;
+                return f;
+            }
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/Time/Time.C b/src/OpenFOAM/db/Time/Time.C
index 93d58ca42c3b52636e100f92fb814c3ec737f4b6..39ee01ede9b857a5829d20da029d07fa265abd74 100644
--- a/src/OpenFOAM/db/Time/Time.C
+++ b/src/OpenFOAM/db/Time/Time.C
@@ -29,6 +29,7 @@ License
 #include "HashSet.H"
 #include "profiling.H"
 #include "demandDrivenData.H"
+#include "IOdictionary.H"
 
 #include <sstream>
 
@@ -177,13 +178,12 @@ void Foam::Time::setControls()
 
     // Check if time directory exists
     // If not increase time precision to see if it is formatted differently.
-    if (!exists(timePath(), false))
+    if (!fileHandler().exists(timePath(), false))
     {
         int oldPrecision = precision_;
         int requiredPrecision = -1;
         bool found = false;
         word oldTime(timeName());
-
         for
         (
             precision_ = maxPrecision_;
@@ -194,7 +194,6 @@ void Foam::Time::setControls()
             // Update the time formatting
             setTime(startTime_, 0);
 
-            // Check that the time name has changed otherwise exit loop
             word newTime(timeName());
             if (newTime == oldTime)
             {
@@ -203,7 +202,7 @@ void Foam::Time::setControls()
             oldTime = newTime;
 
             // Check the existence of the time directory with the new format
-            found = exists(timePath(), false);
+            found = fileHandler().exists(timePath(), false);
 
             if (found)
             {
@@ -379,17 +378,8 @@ void Foam::Time::setMonitoring(const bool forceProfiling)
     // Time objects not registered so do like objectRegistry::checkIn ourselves.
     if (runTimeModifiable_)
     {
-        monitorPtr_.reset
-        (
-            new fileMonitor
-            (
-                regIOobject::fileModificationChecking == inotify
-             || regIOobject::fileModificationChecking == inotifyMaster
-            )
-        );
-
         // Monitor all files that controlDict depends on
-        addWatches(controlDict_, controlDict_.files());
+        fileHandler().addWatches(controlDict_, controlDict_.files());
     }
 
     // Clear dependent files - not needed now
@@ -685,7 +675,7 @@ Foam::Time::~Time()
 
     forAllReverse(controlDict_.watchIndices(), i)
     {
-        removeWatch(controlDict_.watchIndices()[i]);
+        fileHandler().removeWatch(controlDict_.watchIndices()[i]);
     }
 
     // Destroy function objects first
@@ -698,86 +688,6 @@ Foam::Time::~Time()
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-void Foam::Time::addWatches(regIOobject& rio, const fileNameList& files) const
-{
-    const labelList& watchIndices = rio.watchIndices();
-
-    DynamicList<label> newWatchIndices;
-    labelHashSet removedWatches(watchIndices);
-
-    forAll(files, i)
-    {
-        const fileName& f = files[i];
-        label index = findWatch(watchIndices, f);
-
-        if (index == -1)
-        {
-            newWatchIndices.append(addTimeWatch(f));
-        }
-        else
-        {
-            // Existing watch
-            newWatchIndices.append(watchIndices[index]);
-            removedWatches.erase(index);
-        }
-    }
-
-    // Remove any unused watches
-    forAllConstIter(labelHashSet, removedWatches, iter)
-    {
-        removeWatch(watchIndices[iter.key()]);
-    }
-
-    rio.watchIndices() = newWatchIndices;
-}
-
-
-Foam::label Foam::Time::findWatch
-(
-    const labelList& watchIndices,
-    const fileName& fName
-) const
-{
-    forAll(watchIndices, i)
-    {
-        if (getFile(watchIndices[i]) == fName)
-        {
-            return i;
-        }
-    }
-    return -1;
-}
-
-
-Foam::label Foam::Time::addTimeWatch(const fileName& fName) const
-{
-    return monitorPtr_().addWatch(fName);
-}
-
-
-bool Foam::Time::removeWatch(const label watchIndex) const
-{
-    return monitorPtr_().removeWatch(watchIndex);
-}
-
-const Foam::fileName& Foam::Time::getFile(const label watchIndex) const
-{
-    return monitorPtr_().getFile(watchIndex);
-}
-
-
-Foam::fileMonitor::fileState Foam::Time::getState(const label watchIndex) const
-{
-    return monitorPtr_().getState(watchIndex);
-}
-
-
-void Foam::Time::setUnmodified(const label watchIndex) const
-{
-    monitorPtr_().setUnmodified(watchIndex);
-}
-
-
 Foam::word Foam::Time::timeName(const scalar t, const int precision)
 {
     std::ostringstream buf;
@@ -806,26 +716,22 @@ Foam::word Foam::Time::findInstancePath
     const instant& t
 ) const
 {
-    // Read directory entries into a list
-    fileNameList dirEntries(readDir(directory, fileName::DIRECTORY));
+    // Simplified version: use findTimes (readDir + sort). The expensive
+    // bit is the readDir, not the sorting. Tbd: avoid calling findInstancePath
+    // from filePath.
 
-    forAll(dirEntries, i)
-    {
-        scalar timeValue;
-        if (readScalar(dirEntries[i].c_str(), timeValue) && t.equal(timeValue))
-        {
-            return dirEntries[i];
-        }
-    }
+    instantList timeDirs = findTimes(path(), constant());
+    // Note:
+    // - times will include constant (with value 0) as first element.
+    //   For backwards compatibility make sure to find 0 in preference
+    //   to constant.
+    // - list is sorted so could use binary search
 
-    if (t.equal(0.0))
+    forAllReverse(timeDirs, i)
     {
-        const word& constantName = constant();
-
-        // Looking for 0 or constant. 0 already checked above.
-        if (isDir(directory/constantName))
+        if (t.equal(timeDirs[i].value()))
         {
-            return constantName;
+            return timeDirs[i].name();
         }
     }
 
@@ -1030,6 +936,7 @@ void Foam::Time::setTime(const Time& t)
     value() = t.value();
     dimensionedScalar::name() = t.dimensionedScalar::name();
     timeIndex_ = t.timeIndex_;
+    fileHandler().setTime(*this);
 }
 
 
@@ -1056,6 +963,7 @@ void Foam::Time::setTime(const instant& inst, const label newIndex)
     timeDict.readIfPresent("deltaT", deltaT_);
     timeDict.readIfPresent("deltaT0", deltaT0_);
     timeDict.readIfPresent("index", timeIndex_);
+    fileHandler().setTime(*this);
 }
 
 
@@ -1070,6 +978,7 @@ void Foam::Time::setTime(const scalar newTime, const label newIndex)
     value() = newTime;
     dimensionedScalar::name() = timeName(timeToUserTime(newTime));
     timeIndex_ = newIndex;
+    fileHandler().setTime(*this);
 }
 
 
diff --git a/src/OpenFOAM/db/Time/Time.H b/src/OpenFOAM/db/Time/Time.H
index f43f74d360e15c97b4b51e63e995d9f771835cf0..aac5d71738ff1207bd1ffb0220b4a40f044790c9 100644
--- a/src/OpenFOAM/db/Time/Time.H
+++ b/src/OpenFOAM/db/Time/Time.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -51,7 +51,6 @@ SourceFiles
 #include "typeInfo.H"
 #include "dlLibraryTable.H"
 #include "functionObjectList.H"
-#include "fileMonitor.H"
 #include "sigWriteNow.H"
 #include "sigStopAtWriteNow.H"
 
@@ -78,9 +77,6 @@ class Time
 {
     // Private data
 
-        //- file-change monitor for all registered files
-        mutable autoPtr<fileMonitor> monitorPtr_;
-
         //- Profiling trigger for time-loop (for run, loop)
         mutable profilingTrigger* loopProfiling_;
 
@@ -182,6 +178,9 @@ protected:
         //- Read the control dictionary and set the write controls etc.
         virtual void readDict();
 
+        //- Find IOobject in the objectPath
+        static bool exists(IOobject&);
+
 
 private:
 
@@ -331,40 +330,8 @@ public:
             //- Read control dictionary, update controls and time
             virtual bool read();
 
-            // Automatic rereading
-
-                //- Read the objects that have been modified
-                void readModifiedObjects();
-
-                //- Helper: add watches for list of files
-                void addWatches
-                (
-                    regIOobject& rio,
-                    const fileNameList& files
-                ) const;
-
-                //- Find index (or -1) of file in list of handles
-                label findWatch
-                (
-                    const labelList& watchIndices,
-                    const fileName& fName
-                ) const;
-
-                //- Add watching of a file. Returns handle
-                label addTimeWatch(const fileName& fName) const;
-
-                //- Remove watch on a file (using handle)
-                bool removeWatch(const label watchIndex) const;
-
-                //- Get name of file being watched (using handle)
-                const fileName& getFile(const label watchIndex) const;
-
-                //- Get current state of file (using handle)
-                fileMonitor::fileState getState(const label watchIndex) const;
-
-                //- Set current state of file (using handle) to unmodified
-                void setUnmodified(const label watchIndex) const;
-
+            //- Read the objects that have been modified
+            void readModifiedObjects();
 
             //- Return the location of "dir" containing the file "name".
             //  (eg, used in reading mesh data)
@@ -410,9 +377,10 @@ public:
             //- Write using given format, version and compression
             virtual bool writeObject
             (
-                IOstream::streamFormat fmt,
-                IOstream::versionNumber ver,
-                IOstream::compressionType cmp
+                IOstream::streamFormat,
+                IOstream::versionNumber,
+                IOstream::compressionType,
+                const bool valid
             ) const;
 
             //- Write the objects now (not at end of iteration) and continue
diff --git a/src/OpenFOAM/db/Time/TimeIO.C b/src/OpenFOAM/db/Time/TimeIO.C
index 5c8c2c5c5ab39bad0d0a09e1919ab8711a9e054e..0659616f85c25e783880bed58ff0fb9a801d4b49 100644
--- a/src/OpenFOAM/db/Time/TimeIO.C
+++ b/src/OpenFOAM/db/Time/TimeIO.C
@@ -28,6 +28,8 @@ License
 #include "simpleObjectRegistry.H"
 #include "dimensionedConstants.H"
 #include "profiling.H"
+#include "IOdictionary.H"
+#include "fileOperation.H"
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
@@ -127,6 +129,43 @@ void Foam::Time::readDict()
                 }
             }
         }
+
+
+        // Handle fileHandler override explicitly since interacts with
+        // local dictionary monitoring.
+        word fileHandlerName;
+        if
+        (
+            localSettings.readIfPresent("fileHandler", fileHandlerName)
+         && fileHandler().type() != fileHandlerName
+        )
+        {
+            // Remove the old watches since destroying the file
+            fileNameList oldWatchedFiles(controlDict_.watchIndices());
+            forAllReverse(controlDict_.watchIndices(), i)
+            {
+                label watchi = controlDict_.watchIndices()[i];
+                oldWatchedFiles[i] = fileHandler().getFile(watchi);
+                fileHandler().removeWatch(watchi);
+            }
+            controlDict_.watchIndices().clear();
+
+            // Installing the new handler
+            Info<< "Overriding fileHandler to " << fileHandlerName << endl;
+
+            autoPtr<fileOperation> handler
+            (
+                fileOperation::New
+                (
+                    fileHandlerName,
+                    true
+                )
+            );
+            Foam::fileHandler(handler);
+
+            // Reinstall old watches
+            fileHandler().addWatches(controlDict_, oldWatchedFiles);
+        }
     }
 
 
@@ -368,11 +407,12 @@ void Foam::Time::readDict()
     controlDict_.readIfPresent("graphFormat", graphFormat_);
     controlDict_.readIfPresent("runTimeModifiable", runTimeModifiable_);
 
+
     if (!runTimeModifiable_ && controlDict_.watchIndices().size())
     {
         forAllReverse(controlDict_.watchIndices(), i)
         {
-            removeWatch(controlDict_.watchIndices()[i]);
+            fileHandler().removeWatch(controlDict_.watchIndices()[i]);
         }
         controlDict_.watchIndices().clear();
     }
@@ -393,7 +433,7 @@ bool Foam::Time::read()
             // already updated all the watchIndices via the addWatch but
             // controlDict_ is an unwatchedIOdictionary so will only have
             // stored the dependencies as files.
-             addWatches(controlDict_, controlDict_.files());
+            fileHandler().addWatches(controlDict_, controlDict_.files());
         }
         controlDict_.files().clear();
 
@@ -414,7 +454,7 @@ void Foam::Time::readModifiedObjects()
         // valid filePath).
         // Note: requires same ordering in objectRegistries on different
         // processors!
-        monitorPtr_().updateStates
+        fileHandler().updateStates
         (
             (
                 regIOobject::fileModificationChecking == inotifyMaster
@@ -437,7 +477,7 @@ void Foam::Time::readModifiedObjects()
                 // controlDict_ is an unwatchedIOdictionary so will only have
                 // stored the dependencies as files.
 
-                addWatches(controlDict_, controlDict_.files());
+                fileHandler().addWatches(controlDict_, controlDict_.files());
             }
             controlDict_.files().clear();
         }
@@ -482,7 +522,8 @@ bool Foam::Time::writeTimeDict() const
     (
         IOstream::ASCII,
         IOstream::currentVersion,
-        IOstream::UNCOMPRESSED
+        IOstream::UNCOMPRESSED,
+        true
     );
 }
 
@@ -491,7 +532,8 @@ bool Foam::Time::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     if (writeTime())
@@ -500,7 +542,7 @@ bool Foam::Time::writeObject
 
         if (writeOK)
         {
-            writeOK = objectRegistry::writeObject(fmt, ver, cmp);
+            writeOK = objectRegistry::writeObject(fmt, ver, cmp, valid);
         }
 
         if (writeOK)
diff --git a/src/OpenFOAM/db/Time/findInstance.C b/src/OpenFOAM/db/Time/findInstance.C
index ab24791b7fe4e6752f4087df02d63302b1b64eb4..f10fad0d384144cb77e808722673fc054da3cb7b 100644
--- a/src/OpenFOAM/db/Time/findInstance.C
+++ b/src/OpenFOAM/db/Time/findInstance.C
@@ -2,8 +2,8 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
+     \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -35,6 +35,49 @@ Description
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+bool Foam::Time::exists(IOobject& io)
+{
+    // Generate filename for object
+    fileName objPath(fileHandler().objectPath(io, word::null));
+
+    // Test for either directory or a (valid) file & IOobject
+    bool ok;
+    if (io.name().empty())
+    {
+        ok = fileHandler().isDir(objPath);
+    }
+    else
+    {
+        ok =
+            fileHandler().isFile(objPath)
+         && io.typeHeaderOk<IOList<label>>(false);// object with local scope
+    }
+
+    if (!ok)
+    {
+        // Re-test with raw objectPath. This is for backwards
+        // compatibility
+        fileName originalPath(io.objectPath());
+        if (originalPath != objPath)
+        {
+            // Test for either directory or a (valid) file & IOobject
+            if (io.name().empty())
+            {
+                ok = fileHandler().isDir(originalPath);
+            }
+            else
+            {
+                ok =
+                    fileHandler().isFile(originalPath)
+                 && io.typeHeaderOk<IOList<label>>(false);
+            }
+        }
+    }
+
+    return ok;
+}
+
+
 Foam::word Foam::Time::findInstance
 (
     const fileName& dir,
@@ -44,39 +87,32 @@ Foam::word Foam::Time::findInstance
 ) const
 {
     // Note: - if name is empty, just check the directory itself
+    //       - check both for isFile and headerOk since the latter does a
+    //         filePath so searches for the file.
     //       - check for an object with local file scope (so no looking up in
     //         parent directory in case of parallel)
 
-    const fileName tPath(path());
-    const fileName dirPath(tPath/timeName()/dir);
-
-    // check the current time directory
-    if
-    (
-        name.empty()
-      ? isDir(dirPath)
-      :
-        (
-            isFile(dirPath/name)
-         && IOobject
-            (
-                name,
-                timeName(),
-                dir,
-                *this
-            ).typeHeaderOk<IOList<label>>(false) // use object with local scope
-        )
-    )
     {
-        if (debug)
+        IOobject io
+        (
+            name,           // name might be empty!
+            timeName(),
+            dir,
+            *this
+        );
+
+        if (exists(io))
         {
-            InfoInFunction
-                << "Found \"" << name
-                << "\" in " << timeName()/dir
-                << endl;
-        }
+            if (debug)
+            {
+                InfoInFunction
+                    << "Found exact match for \"" << name
+                    << "\" in " << timeName()/dir
+                    << endl;
+            }
 
-        return timeName();
+            return timeName();
+        }
     }
 
     // Search back through the time directories to find the time
@@ -96,27 +132,20 @@ Foam::word Foam::Time::findInstance
     // continue searching from here
     for (; instanceI >= 0; --instanceI)
     {
-        if
+        IOobject io
         (
-            name.empty()
-          ? isDir(tPath/ts[instanceI].name()/dir)
-          :
-            (
-                isFile(tPath/ts[instanceI].name()/dir/name)
-             && IOobject
-                (
-                    name,
-                    ts[instanceI].name(),
-                    dir,
-                    *this
-                ).typeHeaderOk<IOList<label>>(false)
-            )
-        )
+            name,           // name might be empty!
+            ts[instanceI].name(),
+            dir,
+            *this
+        );
+
+        if (exists(io))
         {
             if (debug)
             {
                 InfoInFunction
-                    << "Found \"" << name
+                    << "Found instance match for \"" << name
                     << "\" in " << ts[instanceI].name()/dir
                     << endl;
             }
@@ -129,7 +158,8 @@ Foam::word Foam::Time::findInstance
         {
             if (debug)
             {
-                InfoInFunction
+                //InfoInFunction
+                Pout<< "findInstance : "
                     << "Hit stopInstance " << stopInstance
                     << endl;
             }
@@ -169,27 +199,20 @@ Foam::word Foam::Time::findInstance
     // constant function of the time, because the latter points to
     // the case constant directory in parallel cases
 
-    if
+    IOobject io
     (
-        name.empty()
-      ? isDir(tPath/constant()/dir)
-      :
-        (
-            isFile(tPath/constant()/dir/name)
-         && IOobject
-            (
-                name,
-                constant(),
-                dir,
-                *this
-            ).typeHeaderOk<IOList<label>>(false)
-        )
-    )
+        name,
+        constant(),
+        dir,
+        *this
+    );
+
+    if (exists(io))
     {
         if (debug)
         {
             InfoInFunction
-                << "Found \"" << name
+                << "Found constant match for \"" << name
                 << "\" in " << constant()/dir
                 << endl;
         }
diff --git a/src/OpenFOAM/db/Time/findTimes.C b/src/OpenFOAM/db/Time/findTimes.C
index 1046d82843ee06c9f8df4a7f5bee537213dfd57a..52dcf50dcc0c145daff82078cbcd4fc0b64a7e9f 100644
--- a/src/OpenFOAM/db/Time/findTimes.C
+++ b/src/OpenFOAM/db/Time/findTimes.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -40,62 +40,8 @@ Foam::instantList Foam::Time::findTimes
     const word& constantName
 )
 {
-    if (debug)
-    {
-        InfoInFunction << "Finding times in directory " << directory << endl;
-    }
-
-    // Read directory entries into a list
-    fileNameList dirEntries(readDir(directory, fileName::DIRECTORY));
-
-    // Initialise instant list
-    instantList Times(dirEntries.size() + 1);
-    label nTimes = 0;
-
-    // Check for "constant"
-    bool haveConstant = false;
-    forAll(dirEntries, i)
-    {
-        if (dirEntries[i] == constantName)
-        {
-            Times[nTimes].value() = 0;
-            Times[nTimes].name() = dirEntries[i];
-            nTimes++;
-            haveConstant = true;
-            break;
-        }
-    }
-
-    // Read and parse all the entries in the directory
-    forAll(dirEntries, i)
-    {
-        IStringStream timeStream(dirEntries[i]);
-        token timeToken(timeStream);
-
-        if (timeToken.isNumber() && timeStream.eof())
-        {
-            Times[nTimes].value() = timeToken.number();
-            Times[nTimes].name() = dirEntries[i];
-            nTimes++;
-        }
-    }
-
-    // Reset the length of the times list
-    Times.setSize(nTimes);
-
-    if (haveConstant)
-    {
-        if (nTimes > 2)
-        {
-            std::sort(&Times[1], Times.end(), instant::less());
-        }
-    }
-    else if (nTimes > 1)
-    {
-        std::sort(&Times[0], Times.end(), instant::less());
-    }
-
-    return Times;
+    return fileHandler().findTimes(directory, constantName);
 }
 
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/db/Time/instant/instant.C b/src/OpenFOAM/db/Time/instant/instant.C
index bcbe24e55db7705a76d1598a7ac9dcd7894621a9..eb1e9e56ffc1ffe9982922baa49fcfa8ed857611 100644
--- a/src/OpenFOAM/db/Time/instant/instant.C
+++ b/src/OpenFOAM/db/Time/instant/instant.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -76,6 +76,18 @@ bool Foam::operator!=(const instant& a, const instant& b)
 }
 
 
+bool Foam::operator<(const instant& a, const instant& b)
+{
+    return a.value_ < b.value_;
+}
+
+
+bool Foam::operator>(const instant& a, const instant& b)
+{
+    return a.value_ > b.value_;
+}
+
+
 // * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
 
 Foam::Istream& Foam::operator>>(Istream& is, instant& I)
diff --git a/src/OpenFOAM/db/Time/instant/instant.H b/src/OpenFOAM/db/Time/instant/instant.H
index be3ea4e011362b6cf8a4c7394f8398b871a63527..0eb4db8fcb420b437c419e895669407ccef482ee 100644
--- a/src/OpenFOAM/db/Time/instant/instant.H
+++ b/src/OpenFOAM/db/Time/instant/instant.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -51,6 +51,8 @@ class instant;
 
 bool operator==(const instant&, const instant&);
 bool operator!=(const instant&, const instant&);
+bool operator<(const instant&, const instant&);
+bool operator>(const instant&, const instant&);
 
 // IOstream Operators
 
@@ -141,6 +143,8 @@ public:
 
         friend bool operator==(const instant&, const instant&);
         friend bool operator!=(const instant&, const instant&);
+        friend bool operator<(const instant&, const instant&);
+        friend bool operator>(const instant&, const instant&);
 
 
     // IOstream Operators
diff --git a/src/OpenFOAM/db/Time/timeSelector.C b/src/OpenFOAM/db/Time/timeSelector.C
index 875064b2e87d8de7afb38a5371d4d075f1c22c5a..a6c7bc4b0bf9c0883eae68bf9b40858af895c378 100644
--- a/src/OpenFOAM/db/Time/timeSelector.C
+++ b/src/OpenFOAM/db/Time/timeSelector.C
@@ -325,7 +325,12 @@ Foam::instantList Foam::timeSelector::select
         forAll(timeDirs, timeI)
         {
             selectTimes[timeI] =
-                !exists(runTime.path()/timeDirs[timeI].name()/fName);
+               !fileHandler().exists
+                (
+                    runTime.path()
+                   /timeDirs[timeI].name()
+                   /fName
+                );
         }
 
         return subset(selectTimes, timeDirs);
diff --git a/src/OpenFOAM/db/dictionary/dictionaryIO.C b/src/OpenFOAM/db/dictionary/dictionaryIO.C
index 85e806ca470ce185698732fd6fb42da42c66b5ca..ddc505c661e8df646e8b50f21b98d19973156d97 100644
--- a/src/OpenFOAM/db/dictionary/dictionaryIO.C
+++ b/src/OpenFOAM/db/dictionary/dictionaryIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -25,6 +25,7 @@ License
 
 #include "dictionary.H"
 #include "IFstream.H"
+#include "regExp.H"
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
index 2afbb7183182ec1beaf3281a5692fa2e2e06fbd9..60d42062c758a4714ea7acae97268238094594e0 100644
--- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
+++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H
index 172e84519bca5748b6b2e3df9ea38b71752d60dc..c91f724a8798356e6c077d6450a4d90e53e126c8 100644
--- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H
+++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2014 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/OpenFOAM/db/dictionary/functionEntries/includeEntry/includeEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/includeEntry/includeEntry.C
index 9f25f28e0430e446f1d649ae8a576364c184fc8b..a9ddde6632d835adda3db4833e719b1d735b5b2b 100644
--- a/src/OpenFOAM/db/dictionary/functionEntries/includeEntry/includeEntry.C
+++ b/src/OpenFOAM/db/dictionary/functionEntries/includeEntry/includeEntry.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -28,6 +28,8 @@ License
 #include "addToMemberFunctionSelectionTable.H"
 #include "stringOps.H"
 #include "Time.H"
+#include "IOstreams.H"
+#include "fileOperation.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -113,10 +115,8 @@ bool Foam::functionEntries::includeEntry::execute
 {
     const fileName rawName(is);
     const fileName fName = resolveFile(is.name().path(), rawName, parentDict);
-
-
-    // Read contents of file into parentDict
-    IFstream ifs(fName);
+    autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
+    ISstream& ifs = ifsPtr();
 
     if (ifs)
     {
@@ -166,9 +166,8 @@ bool Foam::functionEntries::includeEntry::execute
 {
     const fileName rawName(is);
     const fileName fName = resolveFile(is.name().path(), rawName, parentDict);
-
-    // Read contents of file into parentDict
-    IFstream ifs(fName);
+    autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
+    ISstream& ifs = ifsPtr();
 
     if (ifs)
     {
diff --git a/src/OpenFOAM/db/dictionary/functionEntries/includeEtcEntry/includeEtcEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/includeEtcEntry/includeEtcEntry.C
index c9e12d0e12334974aac937fbaa27cca4622d9410..c77204a5dd56874c61592a07cb2cdae81c007912 100644
--- a/src/OpenFOAM/db/dictionary/functionEntries/includeEtcEntry/includeEtcEntry.C
+++ b/src/OpenFOAM/db/dictionary/functionEntries/includeEtcEntry/includeEtcEntry.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2015-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -25,9 +25,10 @@ License
 
 #include "includeEtcEntry.H"
 #include "etcFiles.H"
-#include "IFstream.H"
 #include "stringOps.H"
 #include "addToMemberFunctionSelectionTable.H"
+#include "IOstreams.H"
+#include "fileOperation.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -92,7 +93,10 @@ bool Foam::functionEntries::includeEtcEntry::execute
 {
     const fileName rawName(is);
     const fileName fName(resolveFile(rawName, parentDict));
-    IFstream ifs(fName);
+
+    //IFstream ifs(fName);
+    autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
+    ISstream& ifs = ifsPtr();
 
     if (ifs)
     {
@@ -127,7 +131,10 @@ bool Foam::functionEntries::includeEtcEntry::execute
 {
     const fileName rawName(is);
     const fileName fName(resolveFile(rawName, parentDict));
-    IFstream ifs(fName);
+
+    //IFstream ifs(fName);
+    autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
+    ISstream& ifs = ifsPtr();
 
     if (ifs)
     {
diff --git a/src/OpenFOAM/db/dictionary/functionEntries/includeIfPresentEntry/includeIfPresentEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/includeIfPresentEntry/includeIfPresentEntry.C
index 369e3b925b16f55656f91cdb32d9c1432194cebb..202e1408fe7c1ac7991eaf589f41d5c581874c9a 100644
--- a/src/OpenFOAM/db/dictionary/functionEntries/includeIfPresentEntry/includeIfPresentEntry.C
+++ b/src/OpenFOAM/db/dictionary/functionEntries/includeIfPresentEntry/includeIfPresentEntry.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -28,6 +28,7 @@ License
 #include "IFstream.H"
 #include "regIOobject.H"
 #include "addToMemberFunctionSelectionTable.H"
+#include "fileOperation.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -64,7 +65,8 @@ bool Foam::functionEntries::includeIfPresentEntry::execute
 )
 {
     const fileName fName(resolveFile(is, parentDict));
-    IFstream ifs(fName);
+    autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
+    ISstream& ifs = ifsPtr();
 
     if (ifs)
     {
@@ -99,7 +101,8 @@ bool Foam::functionEntries::includeIfPresentEntry::execute
 )
 {
     const fileName fName(resolveFile(is, parentDict));
-    IFstream ifs(fName);
+    autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
+    ISstream& ifs = ifsPtr();
 
     if (ifs)
     {
diff --git a/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.C b/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.C
index 5248d2309865801047a1fa837aff42528ca1d92e..641a051a41d59da9b35ec196c244d2320fd1679b 100644
--- a/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.C
+++ b/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -65,7 +65,11 @@ Foam::dlLibraryTable::~dlLibraryTable()
                     << "Closing " << libNames_[i]
                     << " with handle " << uintptr_t(libPtrs_[i]) << endl;
             }
-            dlClose(libPtrs_[i]);
+            if (!dlClose(libPtrs_[i]))
+            {
+                WarningInFunction<< "Failed closing " << libNames_[i]
+                    << " with handle " << uintptr_t(libPtrs_[i]) << endl;
+            }
         }
     }
 }
diff --git a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C
index 762bfb3bf936a568c8868a65951896d7a374170e..5f70e6fb5a1d53968956dfc0c7535767a7c115f0 100644
--- a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C
+++ b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2015-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -29,11 +29,12 @@ License
 #include "profiling.H"
 #include "argList.H"
 #include "timeControlFunctionObject.H"
-#include "IFstream.H"
+//#include "IFstream.H"
 #include "dictionaryEntry.H"
 #include "stringOps.H"
 #include "Tuple2.H"
 #include "etcFiles.H"
+#include "IOdictionary.H"
 
 /* * * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * * */
 
@@ -103,7 +104,7 @@ void Foam::functionObjectList::listDir
 {
     // Search specified directory for functionObject configuration files
     {
-        fileNameList foFiles(readDir(dir));
+        fileNameList foFiles(fileHandler().readDir(dir));
         forAll(foFiles, f)
         {
             if (foFiles[f].ext().empty())
@@ -115,7 +116,7 @@ void Foam::functionObjectList::listDir
 
     // Recurse into sub-directories
     {
-        fileNameList foDirs(readDir(dir, fileName::DIRECTORY));
+        fileNameList foDirs(fileHandler().readDir(dir, fileName::DIRECTORY));
         forAll(foDirs, fd)
         {
             listDir(dir/foDirs[fd], foMap);
@@ -278,7 +279,10 @@ bool Foam::functionObjectList::readFunctionObject
     }
 
     // Read the functionObject dictionary
-    IFstream fileStream(path);
+    //IFstream fileStream(path);
+    autoPtr<ISstream> fileStreamPtr(fileHandler().NewIFstream(path));
+    ISstream& fileStream = fileStreamPtr();
+
     dictionary funcsDict(fileStream);
     dictionary* funcDictPtr = &funcsDict;
 
diff --git a/src/OpenFOAM/db/functionObjects/writeFile/writeFile.C b/src/OpenFOAM/db/functionObjects/writeFile/writeFile.C
index 210114175ff37446822e8d7c6a0db64f87e4cc4f..3c71b2713d2e51b854038884e1ea6258963554c4 100644
--- a/src/OpenFOAM/db/functionObjects/writeFile/writeFile.C
+++ b/src/OpenFOAM/db/functionObjects/writeFile/writeFile.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2012-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2015-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -73,6 +73,9 @@ Foam::fileName Foam::functionObjects::writeFile::baseFileDir() const
         }
     }
 
+    // Remove any ".."
+    baseDir.clean();
+
     return baseDir;
 }
 
diff --git a/src/OpenFOAM/db/objectRegistry/objectRegistry.C b/src/OpenFOAM/db/objectRegistry/objectRegistry.C
index 4a6c60c612eb0e3f438107c87325930447e0c5db..c5f19d4c9da3cd17d6e204e613168783af92acbc 100644
--- a/src/OpenFOAM/db/objectRegistry/objectRegistry.C
+++ b/src/OpenFOAM/db/objectRegistry/objectRegistry.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2015-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -354,7 +354,8 @@ bool Foam::objectRegistry::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     bool ok = true;
@@ -374,7 +375,7 @@ bool Foam::objectRegistry::writeObject
 
         if (iter()->writeOpt() != NO_WRITE)
         {
-            ok = iter()->writeObject(fmt, ver, cmp) && ok;
+            ok = iter()->writeObject(fmt, ver, cmp, valid) && ok;
         }
     }
 
diff --git a/src/OpenFOAM/db/objectRegistry/objectRegistry.H b/src/OpenFOAM/db/objectRegistry/objectRegistry.H
index 77d390754f6aef1aa479644f8cc5dc7ebd06c9ad..b0471ef9ba499c13f9644c15d371896081089fdd 100644
--- a/src/OpenFOAM/db/objectRegistry/objectRegistry.H
+++ b/src/OpenFOAM/db/objectRegistry/objectRegistry.H
@@ -132,209 +132,210 @@ public:
 
     // Member functions
 
-      // Access
+        // Access
 
-        //- Return time
-        const Time& time() const
-        {
-            return time_;
-        }
+            //- Return time
+            const Time& time() const
+            {
+                return time_;
+            }
 
-        //- Return the parent objectRegistry
-        const objectRegistry& parent() const
-        {
-            return parent_;
-        }
+            //- Return the parent objectRegistry
+            const objectRegistry& parent() const
+            {
+                return parent_;
+            }
 
-        //- Local directory path of this objectRegistry relative to the time
-        virtual const fileName& dbDir() const
-        {
-            return dbDir_;
-        }
+            //- Local directory path of this objectRegistry relative to the time
+            virtual const fileName& dbDir() const
+            {
+                return dbDir_;
+            }
 
 
-      // Summary of classes
+        // Summary of classes
 
-        //- A summary hash of classes used and their associated object names.
-        //  Behaviour and usage as per IOobjectList::classes
-        HashTable<wordHashSet> classes() const;
+            //- A summary hash of classes used and their associated object names.
+            //  Behaviour and usage as per IOobjectList::classes
+            HashTable<wordHashSet> classes() const;
 
-        //- A summary hash of classes used and their associated object names
-        //  restricted to objects with names that satisfy the input matcher
-        HashTable<wordHashSet> classes(const wordRe& matcher) const;
+            //- A summary hash of classes used and their associated object names
+            //  restricted to objects with names that satisfy the input matcher
+            HashTable<wordHashSet> classes(const wordRe& matcher) const;
 
-        //- A summary hash of classes used and their associated object names
-        //  restricted to objects with names that satisfy the input matcher
-        HashTable<wordHashSet> classes(const wordRes& matcher) const;
+            //- A summary hash of classes used and their associated object names
+            //  restricted to objects with names that satisfy the input matcher
+            HashTable<wordHashSet> classes(const wordRes& matcher) const;
+
+
+        // Summary of names
+
+            //- A list of names of the objects
+            wordList names() const;
+
+            //- The names of objects with the given class name
+            wordList names(const word& clsName) const;
+
+            //- The names of objects with the given type
+            template<class Type>
+            wordList names() const;
+
+            //- The names of objects with the given type that also
+            //  have a name satisfying the input matcher
+            template<class Type>
+            wordList names(const wordRe& matcher) const;
+
+            //- The names of objects with the given type that also
+            //  have a name satisfying the input matcher
+            template<class Type>
+            wordList names(const wordRes& matcher) const;
+
+
+        // Summary of names (sorted)
+
+            //- A sorted list of names of the objects
+            wordList sortedNames() const;
+
+            //- The sorted names of objects with the given class name
+            wordList sortedNames(const word& clsName) const;
 
+            //- The sorted names of objects with the given type
+            template<class Type>
+            wordList sortedNames() const;
 
-      // Summary of names
+            //- The sorted names of objects with the given type that also
+            //  have a name satisfying the input matcher
+            template<class Type>
+            wordList sortedNames(const wordRe& matcher) const;
 
-        //- A list of names of the objects
-        wordList names() const;
+            //- The sorted names of objects with the given type that also
+            //  have a name satisfying the input matcher
+            template<class Type>
+            wordList sortedNames(const wordRes& matcher) const;
 
-        //- The names of objects with the given class name
-        wordList names(const word& clsName) const;
 
-        //- The names of objects with the given type
-        template<class Type>
-        wordList names() const;
+        // Lookup
 
-        //- The names of objects with the given type that also
-        //  have a name satisfying the input matcher
-        template<class Type>
-        wordList names(const wordRe& matcher) const;
+            //- Lookup and return a const sub-objectRegistry.
+            //  Optionally create it if it does not exist.
+            //  If recursive, search parent registries.
+            const objectRegistry& subRegistry
+            (
+                const word& name,
+                const bool forceCreate = false,
+                const bool recursive = false
+            ) const;
 
-        //- The names of objects with the given type that also
-        //  have a name satisfying the input matcher
-        template<class Type>
-        wordList names(const wordRes& matcher) const;
 
+            //- Lookup and return all objects of the given Type
+            template<class Type>
+            HashTable<const Type*> lookupClass(const bool strict = false) const;
 
-      // Summary of names (sorted)
+            //- Lookup and return all objects of the given Type
+            template<class Type>
+            HashTable<Type*> lookupClass(const bool strict = false);
 
-        //- A sorted list of names of the objects
-        wordList sortedNames() const;
+            //- Is the named Type found?
+            //  If recursive, search parent registries.
+            template<class Type>
+            bool foundObject
+            (
+                const word& name,
+                const bool recursive = false
+            ) const;
 
-        //- The sorted names of objects with the given class name
-        wordList sortedNames(const word& clsName) const;
+            //- Lookup and return the object of the given Type.
+            //  If recursive, search parent registries.
+            template<class Type>
+            const Type& lookupObject
+            (
+                const word& name,
+                const bool recursive = false
+            ) const;
 
-        //- The sorted names of objects with the given type
-        template<class Type>
-        wordList sortedNames() const;
+            //- Lookup and return the object of the given Type.
+            //  If recursive, search parent registries.
+            template<class Type>
+            Type& lookupObjectRef
+            (
+                const word& name,
+                const bool recursive = false
+            ) const;
 
-        //- The sorted names of objects with the given type that also
-        //  have a name satisfying the input matcher
-        template<class Type>
-        wordList sortedNames(const wordRe& matcher) const;
+            //- Lookup and return pointer to the object of the given Type,
+            //  otherwise nullptr if the object was not found,
+            //  or had the incorrect type.
+            //  If recursive, search parent registries.
+            template<class Type>
+            const Type* lookupObjectPtr
+            (
+                const word& name,
+                const bool recursive = false
+            ) const;
 
-        //- The sorted names of objects with the given type that also
-        //  have a name satisfying the input matcher
-        template<class Type>
-        wordList sortedNames(const wordRes& matcher) const;
 
+            //- Lookup and return non-const pointer to the object
+            //  of the given Type,
+            //  otherwise nullptr if the object was not found,
+            //  or had the incorrect type.
+            //  If recursive, search parent registries.
+            template<class Type>
+            Type* lookupObjectRefPtr
+            (
+                const word& name,
+                const bool recursive = false
+            ) const;
 
-      // Lookup
-
-        //- Lookup and return a const sub-objectRegistry.
-        //  Optionally create it if it does not exist.
-        //  If recursive, search parent registries.
-        const objectRegistry& subRegistry
-        (
-            const word& name,
-            const bool forceCreate = false,
-            const bool recursive = false
-        ) const;
-
-
-        //- Lookup and return all objects of the given Type
-        template<class Type>
-        HashTable<const Type*> lookupClass(const bool strict = false) const;
-
-        //- Lookup and return all objects of the given Type
-        template<class Type>
-        HashTable<Type*> lookupClass(const bool strict = false);
-
-        //- Is the named Type found?
-        //  If recursive, search parent registries.
-        template<class Type>
-        bool foundObject
-        (
-            const word& name,
-            const bool recursive = false
-        ) const;
-
-        //- Lookup and return the object of the given Type.
-        //  If recursive, search parent registries.
-        template<class Type>
-        const Type& lookupObject
-        (
-            const word& name,
-            const bool recursive = false
-        ) const;
-
-        //- Lookup and return the object of the given Type.
-        //  If recursive, search parent registries.
-        template<class Type>
-        Type& lookupObjectRef
-        (
-            const word& name,
-            const bool recursive = false
-        ) const;
-
-        //- Lookup and return pointer to the object of the given Type,
-        //  otherwise nullptr if the object was not found,
-        //  or had the incorrect type.
-        //  If recursive, search parent registries.
-        template<class Type>
-        const Type* lookupObjectPtr
-        (
-            const word& name,
-            const bool recursive = false
-        ) const;
-
-
-        //- Lookup and return non-const pointer to the object
-        //  of the given Type,
-        //  otherwise nullptr if the object was not found,
-        //  or had the incorrect type.
-        //  If recursive, search parent registries.
-        template<class Type>
-        Type* lookupObjectRefPtr
-        (
-            const word& name,
-            const bool recursive = false
-        ) const;
-
-
-      // Events
-
-        //- Return new event number.
-        label getEvent() const;
 
+        // Events
 
-      // Edit
-
-        //- Rename
-        virtual void rename(const word& newName);
-
-        //- Add an regIOobject to registry
-        bool checkIn(regIOobject& io) const;
-
-        //- Remove an regIOobject from registry
-        bool checkOut(regIOobject& io) const;
-
-
-      // Reading
-
-        //- Return true if any of the object's files have been modified
-        virtual bool modified() const;
-
-        //- Read the objects that have been modified
-        void readModifiedObjects();
-
-        //- Read object if modified
-        virtual bool readIfModified();
-
-
-      // Writing
-
-        //- writeData function required by regIOobject but not used
-        //  for this class, write is used instead
-        virtual bool writeData(Ostream&) const
-        {
-            NotImplemented;
-
-            return false;
-        }
-
-        //- Write the objects
-        virtual bool writeObject
-        (
-            IOstream::streamFormat fmt,
-            IOstream::versionNumber ver,
-            IOstream::compressionType cmp
-        ) const;
+            //- Return new event number.
+            label getEvent() const;
+
+
+        // Edit
+
+            //- Rename
+            virtual void rename(const word& newName);
+
+            //- Add an regIOobject to registry
+            bool checkIn(regIOobject& io) const;
+
+            //- Remove an regIOobject from registry
+            bool checkOut(regIOobject& io) const;
+
+
+        // Reading
+
+            //- Return true if any of the object's files have been modified
+            virtual bool modified() const;
+
+            //- Read the objects that have been modified
+            void readModifiedObjects();
+
+            //- Read object if modified
+            virtual bool readIfModified();
+
+
+        // Writing
+
+            //- writeData function required by regIOobject but not used
+            //  for this class, write is used instead
+            virtual bool writeData(Ostream&) const
+            {
+                NotImplemented;
+
+                return false;
+            }
+
+            //- Write the objects
+            virtual bool writeObject
+            (
+                IOstream::streamFormat fmt,
+                IOstream::versionNumber ver,
+                IOstream::compressionType cmp,
+                const bool valid
+            ) const;
 };
 
 
diff --git a/src/OpenFOAM/db/regIOobject/regIOobject.C b/src/OpenFOAM/db/regIOobject/regIOobject.C
index 5a6177c3914bc9a1f8ead582f840cfa6d6a6ed15..92216a1d63c4f2debcc6d3b251777890abefb36f 100644
--- a/src/OpenFOAM/db/regIOobject/regIOobject.C
+++ b/src/OpenFOAM/db/regIOobject/regIOobject.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -27,6 +27,7 @@ License
 #include "Time.H"
 #include "polyMesh.H"
 #include "registerSwitch.H"
+#include "fileOperation.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -46,6 +47,7 @@ registerOptSwitch
     Foam::regIOobject::fileModificationSkew
 );
 
+
 bool Foam::regIOobject::masterOnlyReading = false;
 
 
@@ -62,8 +64,7 @@ Foam::regIOobject::regIOobject(const IOobject& io, const bool isTime)
         isTime
       ? 0
       : db().getEvent()
-    ),
-    isPtr_(nullptr)
+    )
 {
     // Register with objectRegistry if requested
     if (registerObject())
@@ -156,12 +157,6 @@ Foam::regIOobject::~regIOobject()
             << endl;
     }
 
-    if (isPtr_)
-    {
-        delete isPtr_;
-        isPtr_ = nullptr;
-    }
-
     // Check out of objectRegistry if not owned by the registry
     if (!ownedByRegistry_)
     {
@@ -216,7 +211,7 @@ bool Foam::regIOobject::checkOut()
 
         forAllReverse(watchIndices_, i)
         {
-            time().removeWatch(watchIndices_[i]);
+            fileHandler().removeWatch(watchIndices_[i]);
         }
         watchIndices_.clear();
         return db().checkOut(*this);
@@ -237,12 +232,12 @@ Foam::label Foam::regIOobject::addWatch(const fileName& f)
      && time().runTimeModifiable()
     )
     {
-        index = time().findWatch(watchIndices_, f);
+        index = fileHandler().findWatch(watchIndices_, f);
 
         if (index == -1)
         {
             index = watchIndices_.size();
-            watchIndices_.append(time().addTimeWatch(f));
+            watchIndices_.append(fileHandler().addWatch(f));
         }
     }
     return index;
@@ -266,7 +261,7 @@ void Foam::regIOobject::addWatch()
             f = objectPath();
         }
 
-        label index = time().findWatch(watchIndices_, f);
+        label index = fileHandler().findWatch(watchIndices_, f);
         if (index != -1)
         {
             FatalErrorInFunction
@@ -293,7 +288,7 @@ void Foam::regIOobject::addWatch()
                 watchFiles.setSize(watchIndices_.size());
                 forAll(watchIndices_, i)
                 {
-                    watchFiles[i] = time().getFile(watchIndices_[i]);
+                    watchFiles[i] = fileHandler().getFile(watchIndices_[i]);
                 }
             }
             Pstream::scatter(watchFiles);
@@ -303,18 +298,18 @@ void Foam::regIOobject::addWatch()
                 // unregister current ones
                 forAllReverse(watchIndices_, i)
                 {
-                    time().removeWatch(watchIndices_[i]);
+                    fileHandler().removeWatch(watchIndices_[i]);
                 }
 
                 watchIndices_.clear();
                 forAll(watchFiles, i)
                 {
-                    watchIndices_.append(time().addTimeWatch(watchFiles[i]));
+                    watchIndices_.append(fileHandler().addWatch(watchFiles[i]));
                 }
             }
         }
 
-        addWatch(f);
+        watchIndices_.append(fileHandler().addWatch(f));
     }
 }
 
@@ -416,64 +411,35 @@ void Foam::regIOobject::rename(const word& newName)
 
 Foam::fileName Foam::regIOobject::filePath() const
 {
-    return localFilePath();
-}
-
-
-Foam::Istream* Foam::regIOobject::objectStream()
-{
-    return IOobject::objectStream(filePath());
+    return localFilePath(type());
 }
 
 
 bool Foam::regIOobject::headerOk()
 {
+    // Note: Should be consistent with IOobject::typeHeaderOk(false)
+
     bool ok = true;
 
-    Istream* isPtr = objectStream();
+    fileName fName(filePath());
 
-    // If the stream has failed return
-    if (!isPtr)
-    {
-        if (objectRegistry::debug)
-        {
-            Info
-                << "regIOobject::headerOk() : "
-                << "file " << objectPath() << " could not be opened"
-                << endl;
-        }
+    ok = Foam::fileHandler().readHeader(*this, fName, type());
 
-        ok = false;
-    }
-    else
+    if (!ok && IOobject::debug)
     {
-        // Try reading header
-        if (!readHeader(*isPtr))
-        {
-            if (objectRegistry::debug)
-            {
-                IOWarningInFunction(*isPtr)
-                    << "failed to read header of file " << objectPath()
-                    << endl;
-            }
-
-            ok = false;
-        }
+        IOWarningInFunction(fName)
+            << "failed to read header of file " << objectPath()
+            << endl;
     }
 
-    delete isPtr;
-
     return ok;
 }
 
 
 void Foam::regIOobject::operator=(const IOobject& io)
 {
-    if (isPtr_)
-    {
-        delete isPtr_;
-        isPtr_ = nullptr;
-    }
+    // Close any file
+    isPtr_.clear();
 
     // Check out of objectRegistry
     checkOut();
diff --git a/src/OpenFOAM/db/regIOobject/regIOobject.H b/src/OpenFOAM/db/regIOobject/regIOobject.H
index d345dc860244163eaa648ca14a7f7a58b0db66ee..2181b0c629fd5ecd7577ba8d98a3d11683d481b3 100644
--- a/src/OpenFOAM/db/regIOobject/regIOobject.H
+++ b/src/OpenFOAM/db/regIOobject/regIOobject.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -52,6 +52,11 @@ namespace functionEntries
 {
     class codeStream;
 }
+namespace fileOperations
+{
+    class uncollatedFileOperation;
+    class masterUncollatedFileOperation;
+}
 
 /*---------------------------------------------------------------------------*\
                          Class regIOobject Declaration
@@ -61,25 +66,14 @@ class regIOobject
 :
     public IOobject
 {
-
 protected:
 
-        //- Read everywhere or only on master and scatter
-        bool read
-        (
-            const bool masterOnly,
-            const IOstream::streamFormat PstreamFormat,
-            const word& typeName
-        );
-
-public:
-        //- Check readOpt flags and read if necessary. Uses above read
+        //- Helper: check readOpt flags and read if necessary
         bool readHeaderOk
         (
             const IOstream::streamFormat PstreamFormat,
             const word& typeName
         );
-protected:
 
         //- Construct and return an IFstream for the object.
         //  The results is NULL if the stream construction failed
@@ -106,13 +100,13 @@ private:
         label eventNo_;
 
         //- Istream for reading
-        Istream* isPtr_;
+        autoPtr<ISstream> isPtr_;
 
 
     // Private Member Functions
 
         //- Return Istream
-        Istream& readStream();
+        Istream& readStream(const bool valid = true);
 
         //- Dissallow assignment
         void operator=(const regIOobject&);
@@ -123,6 +117,8 @@ public:
         //- Declare friendship with any classes that need access to
         //  masterOnlyReading
         friend class functionEntries::codeStream;
+        friend class fileOperations::uncollatedFileOperation;
+        friend class fileOperations::masterUncollatedFileOperation;
 
 
     // Static data
@@ -252,7 +248,7 @@ public:
             bool headerOk();
 
             //- Return Istream and check object type against that given
-            Istream& readStream(const word&);
+            Istream& readStream(const word&, const bool valid = true);
 
             //- Close Istream
             void close();
@@ -294,11 +290,12 @@ public:
             (
                 IOstream::streamFormat,
                 IOstream::versionNumber,
-                IOstream::compressionType
+                IOstream::compressionType,
+                const bool valid
             ) const;
 
             //- Write using setting from DB
-            virtual bool write() const;
+            virtual bool write(const bool valid = true) const;
 
 
         // Other
diff --git a/src/OpenFOAM/db/regIOobject/regIOobjectRead.C b/src/OpenFOAM/db/regIOobject/regIOobjectRead.C
index 8fa856d357d2fe13b6b3efa21b3736204a2afa78..2bd29561b5120dcdb4cf309cd9d9fa59b7b6e93f 100644
--- a/src/OpenFOAM/db/regIOobject/regIOobjectRead.C
+++ b/src/OpenFOAM/db/regIOobject/regIOobjectRead.C
@@ -28,112 +28,10 @@ License
 #include "Time.H"
 #include "Pstream.H"
 #include "HashSet.H"
+#include "fileOperation.H"
 
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
-bool Foam::regIOobject::read
-(
-    const bool masterOnly,
-    const IOstream::streamFormat format,
-    const word& typeName
-)
-{
-    bool ok = true;
-    if (Pstream::master() || !masterOnly)
-    {
-        if (IFstream::debug)
-        {
-            Pout<< "regIOobject::read() : "
-                << "reading object " << name()
-                << " from file " << endl;
-        }
-
-        // Set flag for e.g. codeStream
-        const bool oldGlobal = globalObject();
-        globalObject() = masterOnly;
-        // If codeStream originates from dictionary which is
-        // not IOdictionary we have a problem so use global
-        const bool oldFlag = regIOobject::masterOnlyReading;
-        regIOobject::masterOnlyReading = masterOnly;
-
-        // Read file
-        ok = readData(readStream(typeName));
-        close();
-
-        // Restore flags
-        globalObject() = oldGlobal;
-        regIOobject::masterOnlyReading = oldFlag;
-    }
-
-    if (masterOnly && Pstream::parRun())
-    {
-        // Scatter master data using communication scheme
-
-        const List<Pstream::commsStruct>& comms =
-        (
-            (Pstream::nProcs() < Pstream::nProcsSimpleSum)
-          ? Pstream::linearCommunication()
-          : Pstream::treeCommunication()
-        );
-
-        // Master reads headerclassname from file. Make sure this gets
-        // transfered as well as contents.
-        Pstream::scatter
-        (
-            comms,
-            const_cast<word&>(headerClassName()),
-            Pstream::msgType(),
-            Pstream::worldComm
-        );
-        Pstream::scatter(comms, note(), Pstream::msgType(), Pstream::worldComm);
-
-
-        // Get my communication order
-        const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
-
-        // Reveive from up
-        if (myComm.above() != -1)
-        {
-            if (IFstream::debug)
-            {
-                Pout<< "regIOobject::read() : "
-                    << "reading object " << name()
-                    << " from processor " << myComm.above()
-                    << endl;
-            }
-
-            IPstream fromAbove
-            (
-                Pstream::commsTypes::scheduled,
-                myComm.above(),
-                0,
-                Pstream::msgType(),
-                Pstream::worldComm,
-                format
-            );
-            ok = readData(fromAbove);
-        }
-
-        // Send to my downstairs neighbours
-        forAllReverse(myComm.below(), belowI)
-        {
-            OPstream toBelow
-            (
-                Pstream::commsTypes::scheduled,
-                myComm.below()[belowI],
-                0,
-                Pstream::msgType(),
-                Pstream::worldComm,
-                format
-            );
-            bool okWrite = writeData(toBelow);
-            ok = ok && okWrite;
-        }
-    }
-    return ok;
-}
-
-
 bool Foam::regIOobject::readHeaderOk
 (
     const IOstream::streamFormat format,
@@ -176,7 +74,7 @@ bool Foam::regIOobject::readHeaderOk
      || isHeaderOk
     )
     {
-        return regIOobject::read(masterOnly, format, typeName);
+        return fileHandler().read(*this, masterOnly, format, typeName);
     }
     else
     {
@@ -184,9 +82,10 @@ bool Foam::regIOobject::readHeaderOk
     }
 }
 
+
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-Foam::Istream& Foam::regIOobject::readStream()
+Foam::Istream& Foam::regIOobject::readStream(const bool valid)
 {
     if (IFstream::debug)
     {
@@ -206,13 +105,13 @@ Foam::Istream& Foam::regIOobject::readStream()
     }
 
     // Construct object stream and read header if not already constructed
-    if (!isPtr_)
+    if (!isPtr_.valid())
     {
         fileName objPath;
         if (watchIndices_.size())
         {
             // File is being watched. Read exact file that is being watched.
-            objPath = time().getFile(watchIndices_.last());
+            objPath = fileHandler().getFile(watchIndices_.last());
         }
         else
         {
@@ -227,72 +126,47 @@ Foam::Istream& Foam::regIOobject::readStream()
                     << " in file " << objPath
                     << endl;
             }
-
-            if (!objPath.size())
-            {
-                FatalIOError
-                (
-                    "regIOobject::readStream()",
-                    __FILE__,
-                    __LINE__,
-                    objectPath(),
-                    0
-                )   << "cannot find file"
-                    << exit(FatalIOError);
-            }
         }
 
-        if (!(isPtr_ = IOobject::objectStream(objPath)))
-        {
-            FatalIOError
-            (
-                "regIOobject::readStream()",
-                __FILE__,
-                __LINE__,
-                objPath,
-                0
-            )   << "cannot open file"
-                << exit(FatalIOError);
-        }
-        else if (!readHeader(*isPtr_))
-        {
-            FatalIOErrorInFunction(*isPtr_)
-                << "problem while reading header for object " << name()
-                << exit(FatalIOError);
-        }
+        isPtr_ = fileHandler().readStream(*this, objPath, type(), valid);
     }
 
-    return *isPtr_;
+    return isPtr_();
 }
 
 
-Foam::Istream& Foam::regIOobject::readStream(const word& expectName)
+Foam::Istream& Foam::regIOobject::readStream
+(
+    const word& expectName,
+    const bool valid
+)
 {
     if (IFstream::debug)
     {
         Pout<< "regIOobject::readStream(const word&) : "
             << "reading object " << name()
             << " of type " << type()
-            << " from file " << objectPath()
+            << " from file " << filePath()
             << endl;
     }
 
     // Construct IFstream if not already constructed
-    if (!isPtr_)
+    if (!isPtr_.valid())
     {
-        readStream();
+        readStream(valid);
 
         // Check the className of the regIOobject
         // dictionary is an allowable name in case the actual class
         // instantiated is a dictionary
         if
         (
-            expectName.size()
+            valid
+         && expectName.size()
          && headerClassName() != expectName
          && headerClassName() != "dictionary"
         )
         {
-            FatalIOErrorInFunction(*isPtr_)
+            FatalIOErrorInFunction(isPtr_())
                 << "unexpected class name " << headerClassName()
                 << " expected " << expectName << endl
                 << "    while reading object " << name()
@@ -300,7 +174,7 @@ Foam::Istream& Foam::regIOobject::readStream(const word& expectName)
         }
     }
 
-    return *isPtr_;
+    return isPtr_();
 }
 
 
@@ -309,15 +183,11 @@ void Foam::regIOobject::close()
     if (IFstream::debug)
     {
         Pout<< "regIOobject::close() : "
-            << "finished reading " << filePath()
+            << "finished reading " << isPtr_().name()
             << endl;
     }
 
-    if (isPtr_)
-    {
-        delete isPtr_;
-        isPtr_ = nullptr;
-    }
+    isPtr_.clear();
 }
 
 
@@ -341,11 +211,11 @@ bool Foam::regIOobject::read()
         oldWatchFiles.setSize(watchIndices_.size());
         forAll(watchIndices_, i)
         {
-            oldWatchFiles[i] = time().getFile(watchIndices_[i]);
+            oldWatchFiles[i] = fileHandler().getFile(watchIndices_[i]);
         }
         forAllReverse(watchIndices_, i)
         {
-            time().removeWatch(watchIndices_[i]);
+            fileHandler().removeWatch(watchIndices_[i]);
         }
         watchIndices_.clear();
     }
@@ -359,7 +229,9 @@ bool Foam::regIOobject::read()
          || regIOobject::fileModificationChecking == inotifyMaster
         );
 
-    bool ok = read(masterOnly, IOstream::BINARY, type());
+    // Note: IOstream::binary flag is for all the processor comms. (Only for
+    //       dictionaries should it be ascii)
+    bool ok = fileHandler().read(*this, masterOnly, IOstream::BINARY, type());
 
     if (oldWatchFiles.size())
     {
@@ -375,7 +247,7 @@ bool Foam::regIOobject::modified() const
 {
     forAllReverse(watchIndices_, i)
     {
-        if (time().getState(watchIndices_[i]) != fileMonitor::UNMODIFIED)
+        if (fileHandler().getState(watchIndices_[i]) != fileMonitor::UNMODIFIED)
         {
             return true;
         }
@@ -392,7 +264,7 @@ bool Foam::regIOobject::readIfModified()
     label modified = -1;
     forAllReverse(watchIndices_, i)
     {
-        if (time().getState(watchIndices_[i]) != fileMonitor::UNMODIFIED)
+        if (fileHandler().getState(watchIndices_[i]) != fileMonitor::UNMODIFIED)
         {
             modified = watchIndices_[i];
             break;
@@ -401,7 +273,7 @@ bool Foam::regIOobject::readIfModified()
 
     if (modified != -1)
     {
-        const fileName& fName = time().getFile(watchIndices_.last());
+        const fileName fName = fileHandler().getFile(watchIndices_.last());
 
         if (modified == watchIndices_.last())
         {
@@ -414,7 +286,8 @@ bool Foam::regIOobject::readIfModified()
             InfoInFunction
                 << "    Re-reading object " << name()
                 << " from file " << fName
-                << " because of modified file " << time().getFile(modified)
+                << " because of modified file "
+                << fileHandler().getFile(modified)
                 << endl;
         }
 
diff --git a/src/OpenFOAM/db/regIOobject/regIOobjectWrite.C b/src/OpenFOAM/db/regIOobject/regIOobjectWrite.C
index 733bd47ccc0850eb8b419957e3e6de31e406fb16..1617b8a03052ba13c79bc0cf73e52c3098e19506 100644
--- a/src/OpenFOAM/db/regIOobject/regIOobjectWrite.C
+++ b/src/OpenFOAM/db/regIOobject/regIOobjectWrite.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -37,7 +37,8 @@ bool Foam::regIOobject::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     if (!good())
@@ -113,33 +114,34 @@ bool Foam::regIOobject::writeObject
 
     if (Pstream::master() || !masterOnly)
     {
-        if (mkDir(path()))
-        {
-            // Try opening an OFstream for object
-            OFstream os(objectPath(), fmt, ver, cmp);
-
-            // If any of these fail, return (leave error handling to Ostream
-            // class)
-            if (!os.good())
-            {
-                return false;
-            }
-
-            if (!writeHeader(os))
-            {
-                return false;
-            }
-
-            // Write the data to the Ostream
-            if (!writeData(os))
-            {
-                return false;
-            }
-
-            writeEndDivider(os);
-
-            osGood = os.good();
-        }
+        //if (mkDir(path()))
+        //{
+        //    // Try opening an OFstream for object
+        //    OFstream os(objectPath(), fmt, ver, cmp);
+        //
+        //    // If any of these fail, return (leave error handling to Ostream
+        //    // class)
+        //    if (!os.good())
+        //    {
+        //        return false;
+        //    }
+        //
+        //    if (!writeHeader(os))
+        //    {
+        //        return false;
+        //    }
+        //
+        //    // Write the data to the Ostream
+        //    if (!writeData(os))
+        //    {
+        //        return false;
+        //    }
+        //
+        //    writeEndDivider(os);
+        //
+        //    osGood = os.good();
+        //}
+        osGood = fileHandler().writeObject(*this, fmt, ver, cmp, valid);
     }
     else
     {
@@ -156,20 +158,21 @@ bool Foam::regIOobject::writeObject
     // i.e. lastModified_ is already set
     if (watchIndices_.size())
     {
-        time().setUnmodified(watchIndices_.last());
+        fileHandler().setUnmodified(watchIndices_.last());
     }
 
     return osGood;
 }
 
 
-bool Foam::regIOobject::write() const
+bool Foam::regIOobject::write(const bool valid) const
 {
     return writeObject
     (
         time().writeFormat(),
         IOstream::currentVersion,
-        time().writeCompression()
+        time().writeCompression(),
+        valid
     );
 }
 
diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C
index 61b8aa4c957bd4f507bbe396b7deafb36a76e778..cd0210b1ea22c20ce854802a2b4b52d53ae165bd 100644
--- a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C
+++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C
@@ -26,6 +26,7 @@ License
 #include "GeometricField.H"
 #include "Time.H"
 #include "demandDrivenData.H"
+#include "dictionary.H"
 #include "localIOdictionary.H"
 #include "data.H"
 
@@ -76,13 +77,14 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::readFields()
         IOobject
         (
             this->name(),
-            this->time().timeName(),
+            this->instance(),
+            this->local(),
             this->db(),
-            IOobject::NO_READ,
+            IOobject::MUST_READ,
             IOobject::NO_WRITE,
             false
         ),
-        this->readStream(typeName)
+        typeName
     );
 
     this->close();
diff --git a/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.H b/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.H
index f4223ec40a9ac96ceee9d200f571938bcd62abe4..dec729bf592155c06858726cbd1ffa4277ce56f0 100644
--- a/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.H
+++ b/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -105,7 +105,7 @@ public:
         //  either in the case/processor or case otherwise null
         virtual fileName filePath() const
         {
-            return globalFilePath();
+            return globalFilePath(type());
         }
 
 
diff --git a/src/OpenFOAM/fields/pointPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValuePointPatchField.C b/src/OpenFOAM/fields/pointPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValuePointPatchField.C
index 1f434f4f2a60f05f026d606be34c631c30821beb..dbd463810db99aed158b403e7afeec0a06b4bcdb 100644
--- a/src/OpenFOAM/fields/pointPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValuePointPatchField.C
+++ b/src/OpenFOAM/fields/pointPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValuePointPatchField.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2014 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -25,7 +25,6 @@ License
 
 #include "timeVaryingUniformFixedValuePointPatchField.H"
 #include "Time.H"
-#include "IFstream.H"
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C
index 87c8c30f03eba0aa22db99281531f8ebf4409f45..b88047a1ee381d16ac9707848c02586afb29bf7c 100644
--- a/src/OpenFOAM/global/argList/argList.C
+++ b/src/OpenFOAM/global/argList/argList.C
@@ -38,6 +38,8 @@ License
 #include "sigQuit.H"
 #include "sigSegv.H"
 #include "foamVersion.H"
+#include "uncollatedFileOperation.H"
+#include "masterUncollatedFileOperation.H"
 
 #include <cctype>
 
@@ -659,13 +661,43 @@ void Foam::argList::parse
         }
     }
 
+
+    // Set fileHandler. In increasing order of priority:
+    // 1. default = uncollated
+    // 2. environment var FOAM_FILEHANDLER
+    // 3. etc/controlDict optimisationSwitches 'fileHandler'
+    // 4. system/controlDict 'fileHandler' (not handled here; done in TimeIO.C)
+
+    {
+        word handlerType(getEnv("FOAM_FILEHANDLER"));
+        HashTable<string>::const_iterator iter = options_.find("fileHandler");
+        if (iter != options_.end())
+        {
+            handlerType = iter();
+        }
+
+        if (handlerType.empty())
+        {
+            handlerType = fileOperation::defaultFileHandler;
+        }
+
+        autoPtr<fileOperation> handler
+        (
+            fileOperation::New
+            (
+                handlerType,
+                bannerEnabled_
+            )
+        );
+        Foam::fileHandler(handler);
+    }
+
     // Case is a single processor run unless it is running parallel
     int nProcs = 1;
 
     // Roots if running distributed
     fileNameList roots;
 
-
     // If this actually is a parallel run
     if (parRunControl_.parRun())
     {
@@ -1046,6 +1078,10 @@ void Foam::argList::parse
 Foam::argList::~argList()
 {
     jobInfo.end();
+
+    // Delete file handler to flush any remaining IO
+    autoPtr<fileOperation> dummy(nullptr);
+    fileHandler(dummy);
 }
 
 
@@ -1339,7 +1375,7 @@ bool Foam::argList::check(bool checkArgs, bool checkOpts) const
 
 bool Foam::argList::checkRootCase() const
 {
-    if (!isDir(rootPath()))
+    if (!fileHandler().isDir(rootPath()))
     {
         FatalError
             << executable_
@@ -1349,18 +1385,18 @@ bool Foam::argList::checkRootCase() const
         return false;
     }
 
-    if (Pstream::parRun())
+    fileName pathDir(fileHandler().filePath(path()));
+
+    if ((checkProcessorDirectories_ && pathDir.empty()) && Pstream::master())
     {
-        if (Pstream::master() && (checkProcessorDirectories_ && !isDir(path())))
-        {
-            // Allow slaves on non-existing processor directories created later
-            FatalError
-                << executable_
-                << ": cannot open case directory " << path()
-                << endl;
+        // Allow slaves on non-existing processor directories, created later
+        // (e.g. redistributePar)
+        FatalError
+            << executable_
+            << ": cannot open case directory " << path()
+            << endl;
 
-            return false;
-        }
+        return false;
     }
     else
     {
diff --git a/src/OpenFOAM/global/fileOperations/collatedFileOperation/OFstreamCollator.C b/src/OpenFOAM/global/fileOperations/collatedFileOperation/OFstreamCollator.C
new file mode 100644
index 0000000000000000000000000000000000000000..b5c8ab4942235f901455d5f246d192ff024cbdc7
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/collatedFileOperation/OFstreamCollator.C
@@ -0,0 +1,335 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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 "OFstreamCollator.H"
+#include "OFstream.H"
+#include "OSspecific.H"
+#include "IOstreams.H"
+#include "Pstream.H"
+#include "decomposedBlockData.H"
+#include "PstreamReduceOps.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(OFstreamCollator, 0);
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+bool Foam::OFstreamCollator::writeFile
+(
+    const label comm,
+    const word& typeName,
+    const fileName& fName,
+    const string& s,
+    IOstream::streamFormat fmt,
+    IOstream::versionNumber ver,
+    IOstream::compressionType cmp,
+    const bool append
+)
+{
+    if (debug)
+    {
+        Pout<< "OFstreamCollator : Writing " << s.size()
+            << " bytes to " << fName
+            << " using comm " << comm << endl;
+    }
+
+    autoPtr<OSstream> osPtr;
+    if (UPstream::master(comm))
+    {
+        Foam::mkDir(fName.path());
+        osPtr.reset
+        (
+            new OFstream
+            (
+                fName,
+                fmt,
+                ver,
+                cmp,
+                append
+            )
+        );
+
+        // We don't have IOobject so cannot use IOobject::writeHeader
+        OSstream& os = osPtr();
+        decomposedBlockData::writeHeader
+        (
+            os,
+            ver,
+            fmt,
+            typeName,
+            "",
+            fName,
+            fName.name()
+        );
+    }
+
+    UList<char> slice(const_cast<char*>(s.data()), label(s.size()));
+
+    // Assuming threaded writing hides any slowness so we might
+    // as well use scheduled communication to send the data to
+    // the master processor in order.
+
+    List<std::streamoff> start;
+    decomposedBlockData::writeBlocks
+    (
+        comm,
+        osPtr,
+        start,
+        slice,
+        UPstream::commsTypes::scheduled,
+        false       // do not reduce return state
+    );
+
+    if (osPtr.valid() && !osPtr().good())
+    {
+        FatalIOErrorInFunction(osPtr())
+            << "Failed writing to " << fName << exit(FatalIOError);
+    }
+
+    if (debug)
+    {
+        Pout<< "OFstreamCollator : Finished writing " << s.size()
+            << " bytes to " << fName
+            << " using comm " << comm << endl;
+    }
+
+    return true;
+}
+
+
+void* Foam::OFstreamCollator::writeAll(void *threadarg)
+{
+    OFstreamCollator& handler = *static_cast<OFstreamCollator*>(threadarg);
+
+    // Consume stack
+    while (true)
+    {
+        writeData* ptr = nullptr;
+
+        //pthread_mutex_lock(&handler.mutex_);
+        lockMutex(handler.mutex_);
+
+        if (handler.objects_.size())
+        {
+            ptr = handler.objects_.pop();
+        }
+        //pthread_mutex_unlock(&handler.mutex_);
+        unlockMutex(handler.mutex_);
+
+        if (!ptr)
+        {
+            break;
+        }
+        else
+        {
+            bool ok = writeFile
+            (
+                handler.comm_,
+                ptr->typeName_,
+                ptr->pathName_,
+                ptr->data_,
+                ptr->format_,
+                ptr->version_,
+                ptr->compression_,
+                ptr->append_
+            );
+            if (!ok)
+            {
+                FatalIOErrorInFunction(ptr->pathName_)
+                    << "Failed writing " << ptr->pathName_
+                    << exit(FatalIOError);
+            }
+
+            delete ptr;
+        }
+        //sleep(1);
+    }
+
+    if (debug)
+    {
+        Pout<< "OFstreamCollator : Exiting write thread " << endl;
+    }
+
+    //pthread_mutex_lock(&handler.mutex_);
+    lockMutex(handler.mutex_);
+    handler.threadRunning_ = false;
+    //pthread_mutex_unlock(&handler.mutex_);
+    unlockMutex(handler.mutex_);
+
+    return nullptr;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::OFstreamCollator::OFstreamCollator(const off_t maxBufferSize)
+:
+    maxBufferSize_(maxBufferSize),
+    //mutex_(PTHREAD_MUTEX_INITIALIZER),
+    mutex_
+    (
+        maxBufferSize_ > 0
+      ? allocateMutex()
+      : -1
+    ),
+    thread_
+    (
+        maxBufferSize_ > 0
+      ? allocateThread()
+      : -1
+    ),
+    threadRunning_(false),
+    comm_
+    (
+        UPstream::allocateCommunicator
+        (
+            UPstream::worldComm,
+            identity(UPstream::nProcs(UPstream::worldComm))
+        )
+    )
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::OFstreamCollator::~OFstreamCollator()
+{
+    if (threadRunning_)
+    {
+        if (debug)
+        {
+            Pout<< "~OFstreamCollator : Waiting for write thread" << endl;
+        }
+
+        //pthread_join(thread_, nullptr);
+        joinThread(thread_);
+    }
+    if (thread_ != -1)
+    {
+        freeThread(thread_);
+    }
+    if (mutex_ != -1)
+    {
+        freeMutex(mutex_);
+    }
+    if (comm_ != -1)
+    {
+        UPstream::freeCommunicator(comm_);
+    }
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+bool Foam::OFstreamCollator::write
+(
+    const word& typeName,
+    const fileName& fName,
+    const string& data,
+    IOstream::streamFormat fmt,
+    IOstream::versionNumber ver,
+    IOstream::compressionType cmp,
+    const bool append
+)
+{
+    if (maxBufferSize_ > 0)
+    {
+        while (true)
+        {
+            // Count files to be written
+            off_t totalSize = 0;
+            //pthread_mutex_lock(&mutex_);
+            lockMutex(mutex_);
+            forAllConstIter(FIFOStack<writeData*>, objects_, iter)
+            {
+                totalSize += iter()->data_.size();
+            }
+            //pthread_mutex_unlock(&mutex_);
+            unlockMutex(mutex_);
+
+            if
+            (
+                totalSize == 0
+             || (totalSize+off_t(data.size()) < maxBufferSize_)
+            )
+            {
+                break;
+            }
+
+            if (debug)
+            {
+                Pout<< "OFstreamCollator : Waiting for buffer space."
+                    << " Currently in use:" << totalSize
+                    << " limit:" << maxBufferSize_
+                    << endl;
+            }
+
+            sleep(5);
+        }
+
+        if (debug)
+        {
+            Pout<< "OFstreamCollator : relaying write of " << fName
+                << " to thread " << endl;
+        }
+        //pthread_mutex_lock(&mutex_);
+        lockMutex(mutex_);
+        objects_.push
+        (
+            new writeData(typeName, fName, data, fmt, ver, cmp, append)
+        );
+        //pthread_mutex_unlock(&mutex_);
+        unlockMutex(mutex_);
+
+        //pthread_mutex_lock(&mutex_);
+        lockMutex(mutex_);
+        if (!threadRunning_)
+        {
+            createThread(thread_, writeAll, this);
+            if (debug)
+            {
+                Pout<< "OFstreamCollator : Started write thread " << endl;
+            }
+            threadRunning_ = true;
+        }
+        //pthread_mutex_unlock(&mutex_);
+        unlockMutex(mutex_);
+
+        return true;
+    }
+    else
+    {
+        // Immediate writing
+        return writeFile(comm_, typeName, fName, data, fmt, ver, cmp, append);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/collatedFileOperation/OFstreamCollator.H b/src/OpenFOAM/global/fileOperations/collatedFileOperation/OFstreamCollator.H
new file mode 100644
index 0000000000000000000000000000000000000000..17904fc386df51807c501f47b4f85b2468b9e10b
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/collatedFileOperation/OFstreamCollator.H
@@ -0,0 +1,167 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::OFstreamCollator
+
+Description
+    Threaded file writer.
+
+SourceFiles
+    OFstreamCollator.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef OFstreamCollator_H
+#define OFstreamCollator_H
+
+#include "IOstream.H"
+#include "List.H"
+#include "FIFOStack.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                        Class OFstreamCollator Declaration
+\*---------------------------------------------------------------------------*/
+
+class OFstreamCollator
+{
+    // Private class
+
+        class writeData
+        {
+        public:
+
+            const word typeName_;
+            const fileName pathName_;
+            const string data_;
+            const IOstream::streamFormat format_;
+            const IOstream::versionNumber version_;
+            const IOstream::compressionType compression_;
+            const bool append_;
+
+            writeData
+            (
+                const word& typeName,
+                const fileName& pathName,
+                const string& data,
+                IOstream::streamFormat format,
+                IOstream::versionNumber version,
+                IOstream::compressionType compression,
+                const bool append
+            )
+            :
+                typeName_(typeName),
+                pathName_(pathName),
+                data_(data),
+                format_(format),
+                version_(version),
+                compression_(compression),
+                append_(append)
+            {}
+        };
+
+
+    // Private data
+
+        const off_t maxBufferSize_;
+
+        //pthread_mutex_t mutex_;
+        label mutex_;
+
+        //pthread_t thread_;
+        label thread_;
+
+        FIFOStack<writeData*> objects_;
+
+        bool threadRunning_;
+
+        //- Communicator to use for all parallel ops
+        label comm_;
+
+
+    // Private Member Functions
+
+        //- Write actual file
+        static bool writeFile
+        (
+            const label comm,
+            const word& typeName,
+            const fileName& fName,
+            const string& data,
+            IOstream::streamFormat fmt,
+            IOstream::versionNumber ver,
+            IOstream::compressionType cmp,
+            const bool append
+        );
+
+        //- Write all files in stack
+        static void* writeAll(void *threadarg);
+
+
+public:
+
+    // Declare name of the class and its debug switch
+    TypeName("OFstreamCollator");
+
+
+    // Constructors
+
+        //- Construct from buffer size. 0 = do not use thread
+        OFstreamCollator(const off_t maxBufferSize);
+
+
+    //- Destructor
+    virtual ~OFstreamCollator();
+
+
+    // Member functions
+
+        //- Write file with contents. Blocks until writethread has space
+        //  available (total file sizes < maxBufferSize)
+        bool write
+        (
+            const word& typeName,
+            const fileName&,
+            const string& data,
+            IOstream::streamFormat,
+            IOstream::versionNumber,
+            IOstream::compressionType,
+            const bool append
+        );
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C
new file mode 100644
index 0000000000000000000000000000000000000000..b5dbb13517b9d583e279cf65abf343d026194206
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C
@@ -0,0 +1,415 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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 "collatedFileOperation.H"
+#include "addToRunTimeSelectionTable.H"
+#include "Pstream.H"
+#include "Time.H"
+#include "threadedCollatedOFstream.H"
+#include "decomposedBlockData.H"
+#include "registerSwitch.H"
+#include "masterOFstream.H"
+#include "OFstream.H"
+
+/* * * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * * */
+
+namespace Foam
+{
+namespace fileOperations
+{
+    defineTypeNameAndDebug(collatedFileOperation, 0);
+    addToRunTimeSelectionTable
+    (
+        fileOperation,
+        collatedFileOperation,
+        word
+    );
+
+    float collatedFileOperation::maxThreadFileBufferSize
+    (
+        debug::floatOptimisationSwitch("maxThreadFileBufferSize", 1e9)
+    );
+    registerOptSwitch
+    (
+        "maxThreadFileBufferSize",
+        float,
+        collatedFileOperation::maxThreadFileBufferSize
+    );
+}
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+bool Foam::fileOperations::collatedFileOperation::appendObject
+(
+    const regIOobject& io,
+    const fileName& pathName,
+    IOstream::streamFormat fmt,
+    IOstream::versionNumber ver,
+    IOstream::compressionType cmp
+) const
+{
+    // Append to processors/ file
+
+    fileName prefix;
+    fileName postfix;
+    label proci = splitProcessorPath(io.objectPath(), prefix, postfix);
+
+    if (debug)
+    {
+        Pout<< "writeObject:" << " : For local object : "
+            << io.name()
+            << " appending processor " << proci
+            << " data to " << pathName << endl;
+    }
+
+    if (proci == -1)
+    {
+        FatalErrorInFunction
+            << "Not a valid processor path " << pathName
+            << exit(FatalError);
+    }
+
+
+    // Create string from all data to write
+    string buf;
+    {
+        OStringStream os(fmt, ver);
+        if (proci == 0)
+        {
+            if (!io.writeHeader(os))
+            {
+                return false;
+            }
+        }
+
+        // Write the data to the Ostream
+        if (!io.writeData(os))
+        {
+            return false;
+        }
+
+        if (proci == 0)
+        {
+            IOobject::writeEndDivider(os);
+        }
+
+        buf = os.str();
+    }
+
+
+    bool append = (proci > 0);
+
+    // Note: cannot do append + compression. This is a limitation
+    // of ogzstream (or rather most compressed formats)
+
+    OFstream os
+    (
+        pathName,
+        IOstream::BINARY,
+        ver,
+        IOstream::UNCOMPRESSED, // no compression
+        append
+    );
+
+    if (!os.good())
+    {
+        FatalIOErrorInFunction(os)
+            << "Cannot open for appending"
+            << exit(FatalIOError);
+    }
+
+    if (proci == 0)
+    {
+        IOobject::writeBanner(os)
+            << "FoamFile\n{\n"
+            << "    version     " << os.version() << ";\n"
+            << "    format      " << os.format() << ";\n"
+            << "    class       " << decomposedBlockData::typeName
+            << ";\n"
+            << "    location    " << pathName << ";\n"
+            << "    object      " << pathName.name() << ";\n"
+            << "}" << nl;
+        IOobject::writeDivider(os) << nl;
+    }
+
+    // Write data
+    UList<char> slice
+    (
+        const_cast<char*>(buf.data()),
+        label(buf.size())
+    );
+    os << nl << "// Processor" << proci << nl << slice << nl;
+
+    return os.good();
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::fileOperations::collatedFileOperation::collatedFileOperation
+(
+    const bool verbose
+)
+:
+    masterUncollatedFileOperation(false),
+    writer_(maxThreadFileBufferSize)
+{
+    if (verbose)
+    {
+        Info<< "I/O    : " << typeName
+            << " (maxThreadFileBufferSize " << maxThreadFileBufferSize
+            << ')' << endl;
+
+        if (maxThreadFileBufferSize == 0)
+        {
+            Info<< "         Threading not activated "
+                   "since maxThreadFileBufferSize = 0." << nl
+                << "         Writing may run slowly for large file sizes."
+                << endl;
+        }
+        else
+        {
+            Info<< "         Threading activated "
+                   "since maxThreadFileBufferSize > 0." << nl
+                << "         Requires thread support enabled in MPI, "
+                   "otherwise the simulation" << nl
+                << "         may \"hang\".  If thread support cannot be "
+                   "enabled, deactivate threading" << nl
+                << "         by setting maxThreadFileBufferSize to 0 in "
+                   "$FOAM_ETC/controlDict"
+                << endl;
+        }
+
+        if
+        (
+            regIOobject::fileModificationChecking
+         == regIOobject::inotifyMaster
+        )
+        {
+            WarningInFunction
+                << "Resetting fileModificationChecking to inotify" << endl;
+        }
+
+        if
+        (
+            regIOobject::fileModificationChecking
+         == regIOobject::timeStampMaster
+        )
+        {
+            WarningInFunction
+                << "Resetting fileModificationChecking to timeStamp" << endl;
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::fileOperations::collatedFileOperation::~collatedFileOperation()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::fileName Foam::fileOperations::collatedFileOperation::objectPath
+(
+    const IOobject& io,
+    const word& typeName
+) const
+{
+    // Replacement for objectPath
+    if (io.time().processorCase())
+    {
+        return masterUncollatedFileOperation::objectPath
+        (
+            io,
+            fileOperation::PROCESSORSOBJECT,
+            io.instance()
+        );
+    }
+    else
+    {
+        return masterUncollatedFileOperation::objectPath
+        (
+            io,
+            fileOperation::OBJECT,
+            io.instance()
+        );
+    }
+}
+
+
+bool Foam::fileOperations::collatedFileOperation::writeObject
+(
+    const regIOobject& io,
+    IOstream::streamFormat fmt,
+    IOstream::versionNumber ver,
+    IOstream::compressionType cmp,
+    const bool valid
+) const
+{
+    const Time& tm = io.time();
+    const fileName& inst = io.instance();
+
+    if (inst.isAbsolute() || !tm.processorCase())
+    {
+        mkDir(io.path());
+        fileName pathName(io.objectPath());
+
+        if (debug)
+        {
+            Pout<< "writeObject:"
+                << " : For object : " << io.name()
+                << " falling back to master-only output to " << io.path()
+                << endl;
+        }
+
+        masterOFstream os
+        (
+            pathName,
+            fmt,
+            ver,
+            cmp,
+            false,
+            valid
+        );
+
+        // If any of these fail, return (leave error handling to Ostream class)
+        if (!os.good())
+        {
+            return false;
+        }
+        if (!io.writeHeader(os))
+        {
+            return false;
+        }
+        // Write the data to the Ostream
+        if (!io.writeData(os))
+        {
+            return false;
+        }
+        IOobject::writeEndDivider(os);
+
+        return true;
+    }
+    else
+    {
+        // Construct the equivalent processors/ directory
+        fileName path(processorsPath(io, inst));
+
+        mkDir(path);
+        fileName pathName(path/io.name());
+
+        if (io.global())
+        {
+            if (debug)
+            {
+                Pout<< "writeObject:" << " : For global object : " << io.name()
+                    << " falling back to master-only output to " << pathName
+                    << endl;
+            }
+
+            masterOFstream os
+            (
+                pathName,
+                fmt,
+                ver,
+                cmp,
+                false,
+                valid
+            );
+
+            // If any of these fail, return (leave error handling to Ostream
+            // class)
+            if (!os.good())
+            {
+                return false;
+            }
+            if (!io.writeHeader(os))
+            {
+                return false;
+            }
+            // Write the data to the Ostream
+            if (!io.writeData(os))
+            {
+                return false;
+            }
+            IOobject::writeEndDivider(os);
+
+            return true;
+        }
+        else if (!Pstream::parRun())
+        {
+            // Special path for e.g. decomposePar. Append to
+            // processors/ file
+            if (debug)
+            {
+                Pout<< "writeObject:"
+                    << " : For object : " << io.name()
+                    << " appending to " << pathName << endl;
+            }
+
+            return appendObject(io, pathName, fmt, ver, cmp);
+        }
+        else
+        {
+            if (debug)
+            {
+                Pout<< "writeObject:"
+                    << " : For object : " << io.name()
+                    << " starting collating output to " << pathName << endl;
+            }
+
+            threadedCollatedOFstream os(writer_, pathName, fmt, ver, cmp);
+
+            // If any of these fail, return (leave error handling to Ostream
+            // class)
+            if (!os.good())
+            {
+                return false;
+            }
+            if (Pstream::master() && !io.writeHeader(os))
+            {
+                return false;
+            }
+            // Write the data to the Ostream
+            if (!io.writeData(os))
+            {
+                return false;
+            }
+            if (Pstream::master())
+            {
+                IOobject::writeEndDivider(os);
+            }
+
+            return true;
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H
new file mode 100644
index 0000000000000000000000000000000000000000..49a19e6735fec7d27aa730849176cfa1c140a87e
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H
@@ -0,0 +1,138 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::fileOperations::collatedFileOperation
+
+Description
+    Version of masterUncollatedFileOperation that collates regIOobjects
+    into a container in the processors/ subdirectory.
+
+    Uses threading if maxThreadFileBufferSize > 0.
+
+See also
+    masterUncollatedFileOperation
+
+SourceFiles
+    collatedFileOperation.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef fileOperations_collatedFileOperation_H
+#define fileOperations_collatedFileOperation_H
+
+#include "masterUncollatedFileOperation.H"
+#include "OFstreamCollator.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace fileOperations
+{
+
+/*---------------------------------------------------------------------------*\
+                    Class collatedFileOperation Declaration
+\*---------------------------------------------------------------------------*/
+
+class collatedFileOperation
+:
+    public masterUncollatedFileOperation
+{
+    // Private data
+
+        //- Threaded writer
+        mutable OFstreamCollator writer_;
+
+
+   // Private Member Functions
+
+        //- Append to processors/ file
+        bool appendObject
+        (
+            const regIOobject& io,
+            const fileName& pathName,
+            IOstream::streamFormat fmt,
+            IOstream::versionNumber ver,
+            IOstream::compressionType cmp
+        ) const;
+
+
+public:
+
+        //- Runtime type information
+        TypeName("collated");
+
+
+    // Static data
+
+        //- Max size of thread buffer size. This is the overall size of
+        //  all files to be written. Starts blocking if not enough size.
+        //  Read as float to enable easy specificiation of large sizes.
+        static float maxThreadFileBufferSize;
+
+
+    // Constructors
+
+        //- Construct null
+        collatedFileOperation(const bool verbose);
+
+
+    //- Destructor
+    virtual ~collatedFileOperation();
+
+
+    // Member Functions
+
+        // (reg)IOobject functionality
+
+            //- Generate disk file name for object. Opposite of filePath.
+            virtual fileName objectPath
+            (
+                const IOobject& io,
+                const word& typeName
+            ) const;
+
+            //- Writes a regIOobject (so header, contents and divider).
+            //  Returns success state.
+            virtual bool writeObject
+            (
+                const regIOobject&,
+                IOstream::streamFormat format=IOstream::ASCII,
+                IOstream::versionNumber version=IOstream::currentVersion,
+                IOstream::compressionType compression=IOstream::UNCOMPRESSED,
+                const bool valid = true
+            ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace fileOperations
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/collatedFileOperation/threadedCollatedOFstream.C b/src/OpenFOAM/global/fileOperations/collatedFileOperation/threadedCollatedOFstream.C
new file mode 100644
index 0000000000000000000000000000000000000000..df919680fbd92c71163012ec84d5cc0305b59dd4
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/collatedFileOperation/threadedCollatedOFstream.C
@@ -0,0 +1,65 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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 "threadedCollatedOFstream.H"
+#include "decomposedBlockData.H"
+#include "OFstreamCollator.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::threadedCollatedOFstream::threadedCollatedOFstream
+(
+    OFstreamCollator& writer,
+    const fileName& pathName,
+    streamFormat format,
+    versionNumber version,
+    compressionType compression
+)
+:
+    OStringStream(format, version),
+    writer_(writer),
+    pathName_(pathName),
+    compression_(compression)
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::threadedCollatedOFstream::~threadedCollatedOFstream()
+{
+    writer_.write
+    (
+        decomposedBlockData::typeName,
+        pathName_,
+        str(),
+        IOstream::BINARY,
+        version(),
+        compression_,
+        false                   // append
+    );
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/collatedFileOperation/threadedCollatedOFstream.H b/src/OpenFOAM/global/fileOperations/collatedFileOperation/threadedCollatedOFstream.H
new file mode 100644
index 0000000000000000000000000000000000000000..e296e1132ca8ea99b6cd3097abe5d94378630449
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/collatedFileOperation/threadedCollatedOFstream.H
@@ -0,0 +1,92 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::threadedCollatedOFstream
+
+Description
+    Master-only drop-in replacement for OFstream.
+
+SourceFiles
+    threadedCollatedOFstream.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef threadedCollatedOFstream_H
+#define threadedCollatedOFstream_H
+
+#include "OStringStream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+class OFstreamCollator;
+
+/*---------------------------------------------------------------------------*\
+                  Class threadedCollatedOFstream Declaration
+\*---------------------------------------------------------------------------*/
+
+class threadedCollatedOFstream
+:
+    public OStringStream
+{
+    // Private data
+
+        OFstreamCollator& writer_;
+
+        const fileName pathName_;
+
+        const IOstream::compressionType compression_;
+
+
+public:
+
+    // Constructors
+
+        //- Construct and set stream status
+        threadedCollatedOFstream
+        (
+            OFstreamCollator&,
+            const fileName& pathname,
+            streamFormat format=ASCII,
+            versionNumber version=currentVersion,
+            compressionType compression=UNCOMPRESSED
+        );
+
+
+    //- Destructor
+    ~threadedCollatedOFstream();
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
new file mode 100644
index 0000000000000000000000000000000000000000..5d65cf2e298e308929459b1d83d955b27f6860c5
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
@@ -0,0 +1,666 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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 "fileOperation.H"
+#include "uncollatedFileOperation.H"
+#include "regIOobject.H"
+#include "argList.H"
+#include "HashSet.H"
+#include "masterUncollatedFileOperation.H"
+#include "objectRegistry.H"
+#include "decomposedBlockData.H"
+#include "polyMesh.H"
+#include "registerSwitch.H"
+
+/* * * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * * */
+
+namespace Foam
+{
+    autoPtr<fileOperation> fileOperation::fileHandlerPtr_;
+
+    defineTypeNameAndDebug(fileOperation, 0);
+    defineRunTimeSelectionTable(fileOperation, word);
+
+    class addArgsOptions
+    {
+        public:
+        addArgsOptions()
+        {
+            argList::addOption
+            (
+                "fileHandler",
+                "handler",
+                "override the fileHandler"
+            );
+        }
+    };
+
+    addArgsOptions intObj;
+
+    word fileOperation::defaultFileHandler
+    (
+        debug::optimisationSwitches().lookupOrAddDefault
+        (
+            "fileHandler",
+            //Foam::fileOperations::uncollatedFileOperation::typeName,
+            word("uncollated"),
+            false,
+            false
+        )
+    );
+
+    word fileOperation::processorsDir = "processors";
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+Foam::fileMonitor& Foam::fileOperation::monitor() const
+{
+    if (!monitorPtr_.valid())
+    {
+        monitorPtr_.reset
+        (
+            new fileMonitor
+            (
+                regIOobject::fileModificationChecking == IOobject::inotify
+             || regIOobject::fileModificationChecking == IOobject::inotifyMaster
+            )
+        );
+    }
+    return monitorPtr_();
+}
+
+
+Foam::instantList Foam::fileOperation::sortTimes
+(
+    const fileNameList& dirEntries,
+    const word& constantName
+)
+{
+    // Initialise instant list
+    instantList Times(dirEntries.size() + 1);
+    label nTimes = 0;
+
+    // Check for "constant"
+    bool haveConstant = false;
+    forAll(dirEntries, i)
+    {
+        if (dirEntries[i] == constantName)
+        {
+            Times[nTimes].value() = 0;
+            Times[nTimes].name() = dirEntries[i];
+            nTimes++;
+            haveConstant = true;
+            break;
+        }
+    }
+
+    // Read and parse all the entries in the directory
+    forAll(dirEntries, i)
+    {
+        //IStringStream timeStream(dirEntries[i]);
+        //token timeToken(timeStream);
+
+        //if (timeToken.isNumber() && timeStream.eof())
+        scalar timeValue;
+        if (readScalar(dirEntries[i].c_str(), timeValue))
+        {
+            Times[nTimes].value() = timeValue;
+            Times[nTimes].name() = dirEntries[i];
+            nTimes++;
+        }
+    }
+
+    // Reset the length of the times list
+    Times.setSize(nTimes);
+
+    if (haveConstant)
+    {
+        if (nTimes > 2)
+        {
+            std::sort(&Times[1], Times.end(), instant::less());
+        }
+    }
+    else if (nTimes > 1)
+    {
+        std::sort(&Times[0], Times.end(), instant::less());
+    }
+
+    return Times;
+}
+
+
+bool Foam::fileOperation::isFileOrDir(const bool isFile, const fileName& f)
+{
+    return
+        (isFile && Foam::isFile(f))
+     || (!isFile && Foam::isDir(f));
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::fileOperation::fileOperation()
+{}
+
+
+Foam::autoPtr<Foam::fileOperation> Foam::fileOperation::New
+(
+    const word& type,
+    const bool verbose
+)
+{
+    if (debug)
+    {
+        InfoInFunction << "Constructing fileOperation" << endl;
+    }
+
+    wordConstructorTable::iterator cstrIter =
+        wordConstructorTablePtr_->find(type);
+
+    if (cstrIter == wordConstructorTablePtr_->end())
+    {
+        FatalErrorInFunction
+            << "Unknown fileOperation type "
+            << type << nl << nl
+            << "Valid fileOperation types are" << endl
+            << wordConstructorTablePtr_->sortedToc()
+            << abort(FatalError);
+    }
+
+    return autoPtr<fileOperation>(cstrIter()(verbose));
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::fileOperation::~fileOperation()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::fileName Foam::fileOperation::objectPath
+(
+    const IOobject& io,
+    const word& typeName
+) const
+{
+    return io.objectPath();
+}
+
+
+bool Foam::fileOperation::writeObject
+(
+    const regIOobject& io,
+    IOstream::streamFormat fmt,
+    IOstream::versionNumber ver,
+    IOstream::compressionType cmp,
+    const bool valid
+) const
+{
+    if (valid)
+    {
+        fileName pathName(io.objectPath());
+
+        mkDir(pathName.path());
+
+        autoPtr<Ostream> osPtr
+        (
+            NewOFstream
+            (
+                pathName,
+                fmt,
+                ver,
+                cmp
+            )
+        );
+
+        if (!osPtr.valid())
+        {
+            return false;
+        }
+
+        Ostream& os = osPtr();
+
+        // If any of these fail, return (leave error handling to Ostream class)
+        if (!os.good())
+        {
+            return false;
+        }
+
+        if (!io.writeHeader(os))
+        {
+            return false;
+        }
+
+        // Write the data to the Ostream
+        if (!io.writeData(os))
+        {
+            return false;
+        }
+
+        IOobject::writeEndDivider(os);
+    }
+    return true;
+}
+
+
+//Foam::fileName Foam::fileOperation::objectPath(const fileName& fName) const
+//{
+//    return fName;
+//}
+
+
+Foam::fileName Foam::fileOperation::filePath(const fileName& fName) const
+{
+    fileName path;
+    fileName local;
+    label proci = fileOperations::masterUncollatedFileOperation::
+    splitProcessorPath
+    (
+        fName,
+        path,
+        local
+    );
+
+    fileName procsName(path/processorsDir/local);
+
+    // Give preference to processors variant
+    if (proci != -1 && exists(procsName))
+    {
+        return procsName;
+    }
+    else if (exists(fName))
+    {
+        return fName;
+    }
+    else
+    {
+        return fileName::null;
+    }
+}
+
+
+Foam::label Foam::fileOperation::addWatch(const fileName& fName) const
+{
+    return monitor().addWatch(fName);
+}
+
+
+bool Foam::fileOperation::removeWatch(const label watchIndex) const
+{
+    return monitor().removeWatch(watchIndex);
+}
+
+
+Foam::label Foam::fileOperation::findWatch
+(
+    const labelList& watchIndices,
+    const fileName& fName
+) const
+{
+    forAll(watchIndices, i)
+    {
+        if (getFile(watchIndices[i]) == fName)
+        {
+            return i;
+        }
+    }
+    return -1;
+}
+
+
+void Foam::fileOperation::addWatches
+(
+    regIOobject& rio,
+    const fileNameList& files
+) const
+{
+    const labelList& watchIndices = rio.watchIndices();
+
+    DynamicList<label> newWatchIndices;
+    labelHashSet removedWatches(watchIndices);
+
+    forAll(files, i)
+    {
+        const fileName& f = files[i];
+        label index = findWatch(watchIndices, f);
+
+        if (index == -1)
+        {
+            newWatchIndices.append(addWatch(f));
+        }
+        else
+        {
+            // Existing watch
+            newWatchIndices.append(watchIndices[index]);
+            removedWatches.erase(index);
+        }
+    }
+
+    // Remove any unused watches
+    forAllConstIter(labelHashSet, removedWatches, iter)
+    {
+        removeWatch(watchIndices[iter.key()]);
+    }
+
+    rio.watchIndices() = newWatchIndices;
+}
+
+
+Foam::fileName Foam::fileOperation::getFile(const label watchIndex) const
+{
+    return monitor().getFile(watchIndex);
+}
+
+
+void Foam::fileOperation::updateStates
+(
+    const bool masterOnly,
+    const bool syncPar
+) const
+{
+    monitor().updateStates(masterOnly, Pstream::parRun());
+}
+
+
+Foam::fileMonitor::fileState Foam::fileOperation::getState
+(
+    const label watchFd
+) const
+{
+    return monitor().getState(watchFd);
+}
+
+
+void Foam::fileOperation::setUnmodified(const label watchFd) const
+{
+    monitor().setUnmodified(watchFd);
+}
+
+
+Foam::instantList Foam::fileOperation::findTimes
+(
+    const fileName& directory,
+    const word& constantName
+) const
+{
+    if (debug)
+    {
+        Pout<< FUNCTION_NAME
+            << " : Finding times in directory " << directory << endl;
+    }
+
+    // Read directory entries into a list
+    fileNameList dirEntries
+    (
+        Foam::readDir
+        (
+            directory,
+            fileName::DIRECTORY
+        )
+    );
+
+    instantList times = sortTimes(dirEntries, constantName);
+
+    // Check if directory is processorXXX
+    fileName procsDir
+    (
+        fileOperations::masterUncollatedFileOperation::processorsPath
+        (
+            directory
+        )
+    );
+
+    if (!procsDir.empty() && procsDir != directory)
+    {
+        fileNameList extraEntries
+        (
+            Foam::readDir
+            (
+                procsDir,
+                fileName::DIRECTORY
+            )
+        );
+
+        instantList extraTimes = sortTimes(extraEntries, constantName);
+
+        if (extraTimes.size())
+        {
+            bool haveConstant =
+            (
+                times.size() > 0
+             && times[0].name() == constantName
+            );
+
+            bool haveExtraConstant =
+            (
+                extraTimes.size() > 0
+             && extraTimes[0].name() == constantName
+            );
+
+            // Combine times
+            instantList combinedTimes(times.size()+extraTimes.size());
+            label sz = 0;
+            label extrai = 0;
+            if (haveExtraConstant)
+            {
+                extrai = 1;
+                if (!haveConstant)
+                {
+                    combinedTimes[sz++] = extraTimes[0];    // constant
+                }
+            }
+            forAll(times, i)
+            {
+                combinedTimes[sz++] = times[i];
+            }
+            for (; extrai < extraTimes.size(); extrai++)
+            {
+                combinedTimes[sz++] = extraTimes[extrai];
+            }
+            combinedTimes.setSize(sz);
+            times.transfer(combinedTimes);
+
+            // Sort
+            if (times.size() > 1)
+            {
+                label starti = 0;
+                if (times[0].name() == constantName)
+                {
+                    starti = 1;
+                }
+                std::sort(&times[starti], times.end(), instant::less());
+
+                // Filter out duplicates
+                label newi = starti+1;
+                for (label i = newi; i < times.size(); i++)
+                {
+                    if (times[i].value() != times[i-1].value())
+                    {
+                        if (newi != i)
+                        {
+                            times[newi] = times[i];
+                        }
+                        newi++;
+                    }
+                }
+
+                times.setSize(newi);
+            }
+        }
+    }
+
+    if (debug)
+    {
+        Pout<< FUNCTION_NAME
+            << " : Found times:" << times << endl;
+    }
+    return times;
+}
+
+
+Foam::fileNameList Foam::fileOperation::readObjects
+(
+    const objectRegistry& db,
+    const fileName& instance,
+    const fileName& local,
+    word& newInstance
+) const
+{
+    if (debug)
+    {
+        Pout<< "fileOperation::readObjects :"
+            << " db:" << db.objectPath()
+            << " instance:" << instance << endl;
+    }
+
+    fileName path(db.path(instance, db.dbDir()/local));
+
+    newInstance = word::null;
+    fileNameList objectNames;
+
+    if (Foam::isDir(path))
+    {
+        newInstance = instance;
+        objectNames = Foam::readDir(path, fileName::FILE);
+    }
+    else
+    {
+        // Get processors equivalent of path
+
+        fileName prefix;
+        fileName postfix;
+        label proci = fileOperations::masterUncollatedFileOperation::
+        splitProcessorPath
+        (
+            path,
+            prefix,
+            postfix
+        );
+        fileName procsPath(prefix/processorsDir/postfix);
+
+        if (proci != -1 && Foam::isDir(procsPath))
+        {
+            newInstance = instance;
+            objectNames = Foam::readDir(procsPath, fileName::FILE);
+        }
+    }
+    return objectNames;
+}
+
+
+Foam::label Foam::fileOperation::nProcs
+(
+    const fileName& dir,
+    const fileName& local
+) const
+{
+    if (Foam::isDir(dir/processorsDir))
+    {
+        fileName pointsFile
+        (
+            dir
+           /processorsDir
+           /"constant"
+           /local
+           /polyMesh::meshSubDir
+           /"points"
+        );
+
+        if (Foam::isFile(pointsFile))
+        {
+            return decomposedBlockData::numBlocks(pointsFile);
+        }
+        else
+        {
+            WarningInFunction << "Cannot read file " << pointsFile
+                << " to determine the number of decompositions."
+                << " Falling back to looking for processor.*" << endl;
+        }
+    }
+
+    label nProcs = 0;
+    while
+    (
+        isDir
+        (
+            dir
+           /(word("processor") + name(nProcs))
+           /"constant"
+           /local
+           /polyMesh::meshSubDir
+        )
+    )
+    {
+        ++nProcs;
+    }
+
+    return nProcs;
+}
+
+
+const Foam::fileOperation& Foam::fileHandler()
+{
+    if (!fileOperation::fileHandlerPtr_.valid())
+    {
+        word handler(getEnv("FOAM_FILEHANDLER"));
+
+        if (!handler.size())
+        {
+            handler = fileOperation::defaultFileHandler;
+        }
+
+        fileOperation::fileHandlerPtr_ = fileOperation::New(handler, true);
+    }
+    return fileOperation::fileHandlerPtr_();
+}
+
+
+void Foam::fileHandler(autoPtr<fileOperation>& newHandlerPtr)
+{
+    if (fileOperation::fileHandlerPtr_.valid())
+    {
+        if
+        (
+            newHandlerPtr.valid()
+         && newHandlerPtr->type() == fileOperation::fileHandlerPtr_->type()
+        )
+        {
+            return;
+        }
+    }
+    fileOperation::fileHandlerPtr_.clear();
+
+    if (newHandlerPtr.valid())
+    {
+        fileOperation::fileHandlerPtr_ = newHandlerPtr;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H
new file mode 100644
index 0000000000000000000000000000000000000000..ccd55b2fdd9a24a8ed0c916758be87ae29f092c4
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H
@@ -0,0 +1,431 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::fileOperation
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef fileOperation_H
+#define fileOperation_H
+
+#include "ISstream.H"
+#include "Ostream.H"
+#include "autoPtr.H"
+#include "fileNameList.H"
+#include "instantList.H"
+#include "fileMonitor.H"
+#include "labelList.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+class IOobject;
+class regIOobject;
+class objectRegistry;
+class Time;
+
+/*---------------------------------------------------------------------------*\
+                         Class fileOperation Declaration
+\*---------------------------------------------------------------------------*/
+
+class fileOperation
+{
+protected:
+
+    // Protected data
+
+        //- file-change monitor for all registered files
+        mutable autoPtr<fileMonitor> monitorPtr_;
+
+
+   // Protected Member Functions
+
+        fileMonitor& monitor() const;
+
+        //- Sort directory entries according to time value
+        static instantList sortTimes(const fileNameList&, const word&);
+
+        //- Helper: check for file (isFile) or directory (!isFile)
+        static bool isFileOrDir(const bool isFile, const fileName&);
+
+public:
+
+    // Static data
+
+        //- Return the processors directory name (usually "processors")
+        static word processorsDir;
+
+        //- Default fileHandler
+        static word defaultFileHandler;
+
+
+    // Public data types
+
+        //- Enumeration for the location of an IOobject
+        enum pathType
+        {
+            NOTFOUND,               // not found
+            ABSOLUTE,               // instance is absolute directory
+            OBJECT,                 // objectPath exists
+            PROCESSORSOBJECT,       // objectPath exists in processors/
+            PARENTOBJECT,           // parent of object path
+            FINDINSTANCE,           // file found in time directory
+            PROCESSORSFINDINSTANCE  // as above but in processors/
+        };
+
+
+        //- Runtime type information
+        TypeName("fileOperation");
+
+
+    //- Static fileOperation
+    static autoPtr<fileOperation> fileHandlerPtr_;
+
+
+    // Constructors
+
+        //- Construct null
+        fileOperation();
+
+
+    // Declare run-time constructor selection table
+
+        declareRunTimeSelectionTable
+        (
+            autoPtr,
+            fileOperation,
+            word,
+            (
+                const bool verbose
+            ),
+            (verbose)
+        );
+
+
+    // Selectors
+
+        //- Select type
+        static autoPtr<fileOperation> New(const word& type, const bool verbose);
+
+
+    //- Destructor
+    virtual ~fileOperation();
+
+
+    // Member Functions
+
+        // OSSpecific equivalents
+
+            //- Make directory
+            virtual bool mkDir(const fileName&, mode_t=0777) const = 0;
+
+            //- Set the file mode
+            virtual bool chMod(const fileName&, const mode_t) const = 0;
+
+            //- Return the file mode
+            virtual mode_t mode
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const = 0;
+
+            //- Return the file type: DIRECTORY, FILE or LINK
+            virtual fileName::Type type
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const = 0;
+
+            //- Does the name exist (as DIRECTORY or FILE) in the file system?
+            //  Optionally enable/disable check for gzip file.
+            virtual bool exists
+            (
+                const fileName&,
+                const bool checkGzip=true,
+                const bool followLink = true
+            ) const = 0;
+
+            //- Does the name exist as a DIRECTORY in the file system?
+            virtual bool isDir
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const = 0;
+
+            //- Does the name exist as a FILE in the file system?
+            //  Optionally enable/disable check for gzip file.
+            virtual bool isFile
+            (
+                const fileName&,
+                const bool checkGzip=true,
+                const bool followLink = true
+            ) const = 0;
+
+            //- Return size of file
+            virtual off_t fileSize
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const = 0;
+
+            //- Return time of last file modification
+            virtual time_t lastModified
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const = 0;
+
+            //- Return time of last file modification
+            virtual double highResLastModified
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const = 0;
+
+            //- Read a directory and return the entries as a string list
+            virtual fileNameList readDir
+            (
+                const fileName&,
+                const fileName::Type=fileName::FILE,
+                const bool filtergz=true,
+                const bool followLink = true
+            ) const = 0;
+
+            //- Copy, recursively if necessary, the source to the destination
+            virtual bool cp
+            (
+                const fileName& src,
+                const fileName& dst,
+                const bool followLink = true
+            ) const = 0;
+
+            //- Create a softlink. dst should not exist. Returns true if
+            //  successful.
+            virtual bool ln(const fileName& src, const fileName& dst) const = 0;
+
+            //- Rename src to dst
+            virtual bool mv
+            (
+                const fileName& src,
+                const fileName& dst,
+                const bool followLink = false
+            ) const = 0;
+
+            //- Rename to a corresponding backup file
+            //  If the backup file already exists, attempt with
+            //  "01" .. "99" suffix
+            virtual bool mvBak
+            (
+                const fileName&,
+                const std::string& ext = "bak"
+            ) const = 0;
+
+            //- Remove a file, returning true if successful otherwise false
+            virtual bool rm(const fileName&) const = 0;
+
+            //- Remove a dirctory and its contents
+            virtual bool rmDir(const fileName&) const = 0;
+
+//            //- Open a shared library. Return handle to library. Print error
+//            //  message if library cannot be loaded (check = true)
+//            virtual void* dlOpen
+//            (
+//                const fileName& lib,
+//                const bool check = true
+//            ) const = 0;
+
+
+        // (reg)IOobject functinality
+
+            //- Generate disk file name for object. Opposite of filePath.
+            //  Optional wanted typeName.
+            virtual fileName objectPath
+            (
+                const IOobject& io,
+                const word& typeName
+            ) const;
+
+            //- Search for an object. checkGlobal : also check undecomposed case
+            //  Optional wanted typeName.
+            virtual fileName filePath
+            (
+                const bool checkGlobal,
+                const IOobject&,
+                const word& typeName
+            ) const = 0;
+
+            //- Search for a directory. checkGlobal : also check undecomposed
+            //  case
+            virtual fileName dirPath
+            (
+                const bool checkGlobal,
+                const IOobject&
+            ) const = 0;
+
+            //- Search directory for objects. Used in IOobjectList.
+            virtual fileNameList readObjects
+            (
+                const objectRegistry& db,
+                const fileName& instance,
+                const fileName& local,
+                word& newInstance
+            ) const;
+
+            //- Read object header from supplied file
+            virtual bool readHeader
+            (
+                IOobject&,
+                const fileName&,
+                const word& typeName
+            ) const = 0;
+
+            //- Reads header for regIOobject and returns an ISstream
+            //  to read the contents.
+            virtual autoPtr<ISstream> readStream
+            (
+                regIOobject&,
+                const fileName&,
+                const word& typeName,
+                const bool valid = true
+            ) const = 0;
+
+            //- Top-level read
+            virtual bool read
+            (
+                regIOobject&,
+                const bool masterOnly,
+                const IOstream::streamFormat format,
+                const word& typeName
+            ) const = 0;
+
+            //- Writes a regIOobject (so header, contents and divider).
+            //  Returns success state. Default action is to write to
+            //  the objectPath using writeData. If !valid the
+            //  file does not need to be written (this is used e.g. to
+            //  suppress empty local lagrangian data)
+            virtual bool writeObject
+            (
+                const regIOobject&,
+                IOstream::streamFormat format=IOstream::ASCII,
+                IOstream::versionNumber version=IOstream::currentVersion,
+                IOstream::compressionType compression=IOstream::UNCOMPRESSED,
+                const bool valid = true
+            ) const;
+
+
+        // Filename (not IOobject) operations
+
+            //- Search for a file or directory. Use IOobject version in
+            //  preference
+            virtual fileName filePath(const fileName&) const;
+
+            //- Generate an ISstream that reads a file
+            virtual autoPtr<ISstream> NewIFstream(const fileName&) const = 0;
+
+            //- Generate an Ostream that writes a file
+            virtual autoPtr<Ostream> NewOFstream
+            (
+                const fileName& pathname,
+                IOstream::streamFormat format=IOstream::ASCII,
+                IOstream::versionNumber version=IOstream::currentVersion,
+                IOstream::compressionType compression=IOstream::UNCOMPRESSED,
+                const bool valid = true
+            ) const = 0;
+
+
+        // File modification checking
+
+            //- Add watching of a file. Returns handle
+            virtual label addWatch(const fileName&) const;
+
+            //- Remove watch on a file (using handle)
+            virtual bool removeWatch(const label) const;
+
+            //- Find index (or -1) of file in list of handles
+            virtual label findWatch
+            (
+                const labelList& watchIndices,
+                const fileName&
+            ) const;
+
+            //- Helper: add watches for list of regIOobjects
+            virtual void addWatches(regIOobject&, const fileNameList&) const;
+
+            //- Get name of file being watched (using handle)
+            virtual fileName getFile(const label) const;
+
+            //- Update state of all files
+            virtual void updateStates
+            (
+                const bool masterOnly,
+                const bool syncPar
+            ) const;
+
+            //- Get current state of file (using handle)
+            virtual fileMonitor::fileState getState(const label) const;
+
+            //- Set current state of file (using handle) to unmodified
+            virtual void setUnmodified(const label) const;
+
+
+        // Other
+
+            //- Get number of processor directories/results. Used for e.g.
+            //  reconstructPar, argList checking
+            virtual label nProcs
+            (
+                const fileName& dir,
+                const fileName& local = ""
+            ) const;
+
+            //- Get sorted list of times
+            virtual instantList findTimes(const fileName&, const word&) const;
+
+            //- Callback for time change
+            virtual void setTime(const Time&) const
+            {}
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// Global declarations: defined in fileOperation.C
+
+//- Get current file handler
+const fileOperation& fileHandler();
+
+//- Reset file handler
+void fileHandler(autoPtr<fileOperation>&);
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C
new file mode 100644
index 0000000000000000000000000000000000000000..41cf4bc7a00d9535f7b523f06267b5c434d38f0d
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C
@@ -0,0 +1,1804 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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 "masterUncollatedFileOperation.H"
+#include "addToRunTimeSelectionTable.H"
+#include "Pstream.H"
+#include "Time.H"
+#include "instant.H"
+#include "IFstream.H"
+#include "masterOFstream.H"
+#include "decomposedBlockData.H"
+#include "registerSwitch.H"
+#include "dummyISstream.H"
+#include "SubList.H"
+
+/* * * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * * */
+
+namespace Foam
+{
+namespace fileOperations
+{
+    defineTypeNameAndDebug(masterUncollatedFileOperation, 0);
+    addToRunTimeSelectionTable
+    (
+        fileOperation,
+        masterUncollatedFileOperation,
+        word
+    );
+
+    float masterUncollatedFileOperation::maxMasterFileBufferSize
+    (
+        Foam::debug::floatOptimisationSwitch("maxMasterFileBufferSize", 1e9)
+    );
+    registerOptSwitch
+    (
+        "maxMasterFileBufferSize",
+        float,
+        masterUncollatedFileOperation::maxMasterFileBufferSize
+    );
+}
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+Foam::word
+Foam::fileOperations::masterUncollatedFileOperation::findInstancePath
+(
+    const instantList& timeDirs,
+    const instant& t
+)
+{
+    // Note:
+    // - times will include constant (with value 0) as first element.
+    //   For backwards compatibility make sure to find 0 in preference
+    //   to constant.
+    // - list is sorted so could use binary search
+
+    forAllReverse(timeDirs, i)
+    {
+        if (t.equal(timeDirs[i].value()))
+        {
+            return timeDirs[i].name();
+        }
+    }
+
+    return word::null;
+}
+
+
+Foam::fileName Foam::fileOperations::masterUncollatedFileOperation::filePathInfo
+(
+    const bool checkGlobal,
+    const bool isFile,
+    const IOobject& io,
+    pathType& searchType,
+    word& newInstancePath
+) const
+{
+    newInstancePath = word::null;
+
+    if (io.instance().isAbsolute())
+    {
+        fileName objectPath = io.instance()/io.name();
+
+        if (isFileOrDir(isFile, objectPath))
+        {
+            searchType = fileOperation::ABSOLUTE;
+            return objectPath;
+        }
+        else
+        {
+            searchType = fileOperation::NOTFOUND;
+            return fileName::null;
+        }
+    }
+    else
+    {
+        // 1. Check processors/
+        if (io.time().processorCase())
+        {
+            fileName objectPath = processorsPath(io, io.instance())/io.name();
+            if (isFileOrDir(isFile, objectPath))
+            {
+                searchType = fileOperation::PROCESSORSOBJECT;
+                return objectPath;
+            }
+        }
+        {
+            // 2. Check local
+            fileName localObjectPath = io.objectPath();
+
+            if (isFileOrDir(isFile, localObjectPath))
+            {
+                searchType = fileOperation::OBJECT;
+                return localObjectPath;
+            }
+        }
+
+
+
+        // Any global checks
+        if
+        (
+            checkGlobal
+         && io.time().processorCase()
+         && (
+                io.instance() == io.time().system()
+             || io.instance() == io.time().constant()
+            )
+        )
+        {
+            fileName parentObjectPath =
+                io.rootPath()/io.time().globalCaseName()
+               /io.instance()/io.db().dbDir()/io.local()/io.name();
+
+            if (isFileOrDir(isFile, parentObjectPath))
+            {
+                searchType = fileOperation::PARENTOBJECT;
+                return parentObjectPath;
+            }
+        }
+
+       // Check for approximately same time. E.g. if time = 1e-2 and
+       // directory is 0.01 (due to different time formats)
+       HashPtrTable<instantList>::const_iterator pathFnd
+        (
+            times_.find
+            (
+                io.time().path()
+            )
+        );
+       if (pathFnd != times_.end())
+       {
+           newInstancePath = findInstancePath
+           (
+               *pathFnd(),
+               instant(io.instance())
+           );
+
+           if (newInstancePath.size())
+           {
+               // 1. Try processors equivalent
+
+               fileName fName =
+                   processorsPath(io, newInstancePath)
+                  /io.name();
+               if (isFileOrDir(isFile, fName))
+               {
+                   searchType = fileOperation::PROCESSORSFINDINSTANCE;
+                   return fName;
+               }
+
+               fName =
+                   io.rootPath()/io.caseName()
+                  /newInstancePath/io.db().dbDir()/io.local()/io.name();
+
+               if (isFileOrDir(isFile, fName))
+               {
+                   searchType = fileOperation::FINDINSTANCE;
+                   return fName;
+               }
+           }
+       }
+
+        searchType = fileOperation::NOTFOUND;
+        return fileName::null;
+    }
+}
+
+
+Foam::fileName
+Foam::fileOperations::masterUncollatedFileOperation::processorsCasePath
+(
+    const IOobject& io
+)
+{
+    return
+        io.rootPath()
+       /io.time().globalCaseName()
+       /processorsDir;
+}
+
+
+Foam::fileName
+Foam::fileOperations::masterUncollatedFileOperation::processorsPath
+(
+    const IOobject& io,
+    const word& instance
+)
+{
+    return
+        processorsCasePath(io)
+       /instance
+       /io.db().dbDir()
+       /io.local();
+}
+
+
+Foam::fileName
+Foam::fileOperations::masterUncollatedFileOperation::processorsPath
+(
+    const fileName& dir
+)
+{
+    // Check if directory is processorXXX
+    word caseName(dir.name());
+
+    std::string::size_type pos = caseName.find("processor");
+    if (pos == 0)
+    {
+        return dir.path()/processorsDir;
+    }
+    else
+    {
+        return fileName::null;
+    }
+}
+
+
+Foam::label
+Foam::fileOperations::masterUncollatedFileOperation::splitProcessorPath
+(
+    const fileName& objectPath,
+    fileName& path,
+    fileName& local
+)
+{
+    // Search for processor at start of line or /processor
+    std::string::size_type pos = objectPath.find("processor");
+    if (pos == string::npos)
+    {
+        return -1;
+    }
+
+    if (pos == 0)
+    {
+        path = "";
+        local = objectPath.substr(pos+9);
+    }
+    else if (objectPath[pos-1] != '/')
+    {
+        return -1;
+    }
+    else
+    {
+        path = objectPath.substr(0, pos-1);
+        local = objectPath.substr(pos+9);
+    }
+
+    pos = local.find('/');
+    if (pos == string::npos)
+    {
+        // processorXXX without local
+        label proci;
+        if (Foam::read(local.c_str(), proci))
+        {
+            local.clear();
+            return proci;
+        }
+        return -1;
+    }
+    string procName(local.substr(0, pos));
+    label proci;
+    if (Foam::read(procName.c_str(), proci))
+    {
+        local = local.substr(pos+1);
+        return proci;
+    }
+    return -1;
+}
+
+
+Foam::fileName Foam::fileOperations::masterUncollatedFileOperation::objectPath
+(
+    const IOobject& io,
+    const pathType& searchType,
+    const word& instancePath
+)
+{
+    // Replacement for IOobject::objectPath()
+
+    switch (searchType)
+    {
+        case fileOperation::ABSOLUTE:
+        {
+            return io.instance()/io.name();
+        }
+        break;
+
+        case fileOperation::OBJECT:
+        {
+            return io.path()/io.name();
+        }
+        break;
+
+        case fileOperation::PROCESSORSOBJECT:
+        {
+            return processorsPath(io, io.instance())/io.name();
+        }
+        break;
+
+        case fileOperation::PARENTOBJECT:
+        {
+            return
+                io.rootPath()/io.time().globalCaseName()
+               /io.instance()/io.db().dbDir()/io.local()/io.name();
+        }
+        break;
+
+        case fileOperation::FINDINSTANCE:
+        {
+            return
+                io.rootPath()/io.caseName()
+               /instancePath/io.db().dbDir()/io.local()/io.name();
+        }
+        break;
+
+        case fileOperation::PROCESSORSFINDINSTANCE:
+        {
+            return processorsPath(io, instancePath)/io.name();
+        }
+        break;
+
+        case fileOperation::NOTFOUND:
+        {
+            return fileName::null;
+        }
+        break;
+
+        default:
+        {
+            NotImplemented;
+            return fileName::null;
+        }
+    }
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::uniformFile
+(
+    const fileNameList& filePaths
+)
+{
+    const fileName& object0 = filePaths[0];
+
+    for (label i = 1; i < filePaths.size(); i++)
+    {
+        if (filePaths[i] != object0)
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+
+void Foam::fileOperations::masterUncollatedFileOperation::readAndSend
+(
+    const fileName& filePath,
+    const IOstream::compressionType cmp,
+    const labelUList& procs,
+    PstreamBuffers& pBufs
+)
+{
+    if (cmp == IOstream::compressionType::COMPRESSED)
+    {
+        if (debug)
+        {
+            Pout<< "masterUncollatedFileOperation::readAndSend:"
+                << " opening compressed " << filePath << endl;
+        }
+
+        IFstream is(filePath, IOstream::streamFormat::BINARY);
+
+        std::ostringstream stringStr;
+        stringStr << is.stdStream().rdbuf();
+        string buf(stringStr.str());
+
+        forAll(procs, i)
+        {
+            UOPstream os(procs[i], pBufs);
+            os.write(&buf[0], buf.size());
+        }
+    }
+    else
+    {
+        off_t count(Foam::fileSize(filePath));
+        IFstream is(filePath, IOstream::streamFormat::BINARY);
+
+        if (debug)
+        {
+            Pout<< "masterUncollatedFileOperation::readStream:"
+                << " From " << filePath <<  " reading " << label(count)
+                << " bytes" << endl;
+        }
+        List<char> buf(static_cast<label>(count));
+        is.stdStream().read(buf.begin(), count);
+
+        forAll(procs, i)
+        {
+            UOPstream os(procs[i], pBufs);
+            os.write(buf.begin(), count);
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::fileOperations::masterUncollatedFileOperation::
+masterUncollatedFileOperation
+(
+    const bool verbose
+)
+{
+    if (verbose)
+    {
+        Info<< "I/O    : " << typeName
+            << " (maxMasterFileBufferSize " << maxMasterFileBufferSize << ')'
+            << endl;
+    }
+
+    if (regIOobject::fileModificationChecking == regIOobject::timeStampMaster)
+    {
+        if (verbose)
+        {
+            WarningInFunction
+                << "Resetting fileModificationChecking to timeStamp" << endl;
+        }
+        regIOobject::fileModificationChecking = regIOobject::timeStamp;
+    }
+    else if
+    (
+        regIOobject::fileModificationChecking
+     == regIOobject::inotifyMaster
+    )
+    {
+        if (verbose)
+        {
+            WarningInFunction
+                << "Resetting fileModificationChecking to inotify"
+                << endl;
+        }
+        regIOobject::fileModificationChecking = regIOobject::inotify;
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::fileOperations::masterUncollatedFileOperation::
+~masterUncollatedFileOperation()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+bool Foam::fileOperations::masterUncollatedFileOperation::mkDir
+(
+    const fileName& dir,
+    mode_t mode
+) const
+{
+    return masterOp<mode_t, mkDirOp>(dir, mkDirOp(mode));
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::chMod
+(
+    const fileName& fName,
+    mode_t mode
+) const
+{
+    return masterOp<mode_t, chModOp>(fName, chModOp(mode));
+}
+
+
+mode_t Foam::fileOperations::masterUncollatedFileOperation::mode
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return masterOp<mode_t, modeOp>(fName, modeOp(followLink));
+}
+
+
+Foam::fileName::Type Foam::fileOperations::masterUncollatedFileOperation::type
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return fileName::Type(masterOp<label, typeOp>(fName, typeOp(followLink)));
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::exists
+(
+    const fileName& fName,
+    const bool checkGzip,
+    const bool followLink
+) const
+{
+    return masterOp<bool, existsOp>(fName, existsOp(checkGzip, followLink));
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::isDir
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return masterOp<bool, isDirOp>(fName, isDirOp(followLink));
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::isFile
+(
+    const fileName& fName,
+    const bool checkGzip,
+    const bool followLink
+) const
+{
+    return masterOp<bool, isFileOp>(fName, isFileOp(checkGzip, followLink));
+}
+
+
+off_t Foam::fileOperations::masterUncollatedFileOperation::fileSize
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return masterOp<off_t, fileSizeOp>(fName, fileSizeOp(followLink));
+}
+
+
+time_t Foam::fileOperations::masterUncollatedFileOperation::lastModified
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return masterOp<time_t, lastModifiedOp>
+    (
+        fName,
+        lastModifiedOp(followLink)
+    );
+}
+
+
+double Foam::fileOperations::masterUncollatedFileOperation::highResLastModified
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return masterOp<double, lastModifiedHROp>
+    (
+        fName,
+        lastModifiedHROp(followLink)
+    );
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::mvBak
+(
+    const fileName& fName,
+    const std::string& ext
+) const
+{
+    return masterOp<bool, mvBakOp>(fName, mvBakOp(ext));
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::rm
+(
+    const fileName& fName
+) const
+{
+    return masterOp<bool, rmOp>(fName, rmOp());
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::rmDir
+(
+    const fileName& dir
+) const
+{
+    return masterOp<bool, rmDirOp>(dir, rmDirOp());
+}
+
+
+Foam::fileNameList Foam::fileOperations::masterUncollatedFileOperation::readDir
+(
+    const fileName& dir,
+    const fileName::Type type,
+    const bool filtergz,
+    const bool followLink
+) const
+{
+    return masterOp<fileNameList, readDirOp>
+    (
+        dir,
+        readDirOp(type, filtergz, followLink)
+    );
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::cp
+(
+    const fileName& src,
+    const fileName& dst,
+    const bool followLink
+) const
+{
+    return masterOp<bool, cpOp>(src, dst, cpOp(followLink));
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::ln
+(
+    const fileName& src,
+    const fileName& dst
+) const
+{
+    return masterOp<bool, lnOp>(src, dst, lnOp());
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::mv
+(
+    const fileName& src,
+    const fileName& dst,
+    const bool followLink
+) const
+{
+    return masterOp<bool, mvOp>(src, dst, mvOp(followLink));
+}
+
+
+Foam::fileName Foam::fileOperations::masterUncollatedFileOperation::filePath
+(
+    const bool checkGlobal,
+    const IOobject& io,
+    const word& typeName
+) const
+{
+    if (debug)
+    {
+        Pout<< "masterUncollatedFileOperation::filePath :"
+            << " objectPath:" << io.objectPath()
+            << " checkGlobal:" << checkGlobal << endl;
+    }
+
+    // Trigger caching of times
+    (void)findTimes(io.time().path(), io.time().constant());
+
+    // Determine master filePath and scatter
+
+    fileName objPath;
+    pathType searchType = NOTFOUND;
+    word newInstancePath;
+
+    if (Pstream::master())
+    {
+        objPath =
+            filePathInfo
+            (
+                checkGlobal,
+                true,
+                io,
+                search,
+                searchType,
+                newInstancePath
+            );
+    }
+
+    {
+        label masterType(searchType);
+        Pstream::scatter(masterType);
+        searchType = pathType(masterType);
+    }
+
+    Pstream::scatter(newInstancePath);
+
+
+    // Use the master type to determine if additional information is
+    // needed to construct the local equivalent
+    switch (searchType)
+    {
+        case fileOperation::ABSOLUTE:
+        case fileOperation::PROCESSORSOBJECT:
+        case fileOperation::PARENTOBJECT:
+        case fileOperation::FINDINSTANCE:
+        case fileOperation::PROCESSORSFINDINSTANCE:
+        {
+            // Construct equivalent local path
+            objPath = objectPath(io, searchType, newInstancePath);
+        }
+        break;
+
+        case fileOperation::OBJECT:
+        case fileOperation::NOTFOUND:
+        {
+            // Retest all processors separately since some processors might
+            // have the file and some not (e.g. lagrangian data)
+            objPath = masterOp<fileName, fileOrNullOp>
+            (
+                io.objectPath(),
+                fileOrNullOp(true)
+            );
+        }
+        break;
+    }
+
+    if (debug)
+    {
+        Pout<< "masterUncollatedFileOperation::filePath :"
+            << " Returning from file searching:" << endl
+            << "    objectPath:" << io.objectPath() << endl
+            << "    filePath  :" << objPath << endl << endl;
+    }
+    return objPath;
+}
+
+
+Foam::fileName Foam::fileOperations::masterUncollatedFileOperation::dirPath
+(
+    const bool checkGlobal,
+    const IOobject& io
+) const
+{
+    if (debug)
+    {
+        Pout<< "masterUncollatedFileOperation::dirPath :"
+            << " objectPath:" << io.objectPath()
+            << " checkGlobal:" << checkGlobal << endl;
+    }
+
+    // Determine master dirPath and scatter
+
+    fileName objPath;
+    pathType searchType = NOTFOUND;
+    word newInstancePath;
+
+    if (Pstream::master())
+    {
+        objPath =
+            filePathInfo
+            (
+                checkGlobal,
+                false,
+                io,
+                search,
+                searchType,
+                newInstancePath
+            );
+    }
+    {
+        label masterType(searchType);
+        Pstream::scatter(masterType);
+        searchType = pathType(masterType);
+    }
+    Pstream::scatter(newInstancePath);
+
+
+    // Use the master type to determine if additional information is
+    // needed to construct the local equivalent
+    switch (searchType)
+    {
+        case fileOperation::ABSOLUTE:
+        case fileOperation::PROCESSORSOBJECT:
+        case fileOperation::PARENTOBJECT:
+        case fileOperation::FINDINSTANCE:
+        case fileOperation::PROCESSORSFINDINSTANCE:
+        {
+            // Construct equivalent local path
+            objPath = objectPath(io, searchType, newInstancePath);
+        }
+        break;
+
+        case fileOperation::OBJECT:
+        case fileOperation::NOTFOUND:
+        {
+            // Retest all processors separately since some processors might
+            // have the file and some not (e.g. lagrangian data)
+            objPath = masterOp<fileName, fileOrNullOp>
+            (
+                io.objectPath(),
+                fileOrNullOp(false)
+            );
+        }
+        break;
+    }
+
+    if (debug)
+    {
+        Pout<< "masterUncollatedFileOperation::dirPath :"
+            << " Returning from file searching:" << endl
+            << "    objectPath:" << io.objectPath() << endl
+            << "    filePath  :" << objPath << endl << endl;
+    }
+    return objPath;
+}
+
+
+Foam::fileNameList
+Foam::fileOperations::masterUncollatedFileOperation::readObjects
+(
+    const objectRegistry& db,
+    const fileName& instance,
+    const fileName& local,
+    word& newInstance
+) const
+{
+    if (debug)
+    {
+        Pout<< "masterUncollatedFileOperation::readObjects :"
+            << " db:" << db.objectPath()
+            << " instance:" << instance << endl;
+    }
+
+    fileNameList objectNames;
+    newInstance = word::null;
+
+    if (Pstream::master())
+    {
+        //- Use non-time searching version
+        objectNames = fileOperation::readObjects
+        (
+            db,
+            instance,
+            local,
+            newInstance
+        );
+
+        if (newInstance.empty())
+        {
+            // Find similar time
+
+            // Copy of Time::findInstancePath. We want to avoid the
+            // parallel call to findTimes. Alternative is to have
+            // version of findInstancePath that takes instantList ...
+            const instantList timeDirs
+            (
+                fileOperation::findTimes
+                (
+                    db.time().path(),
+                    db.time().constant()
+                )
+            );
+
+            const instant t(instance);
+            forAllReverse(timeDirs, i)
+            {
+                if (t.equal(timeDirs[i].value()))
+                {
+                    objectNames = fileOperation::readObjects
+                    (
+                        db,
+                        timeDirs[i].name(),     // newly found time
+                        local,
+                        newInstance
+                    );
+                    break;
+                }
+            }
+        }
+    }
+
+    Pstream::scatter(newInstance);
+    Pstream::scatter(objectNames);
+
+    if (debug)
+    {
+        Pout<< "masterUncollatedFileOperation::readObjects :"
+            << " newInstance:" << newInstance
+            << " objectNames:" << objectNames << endl;
+    }
+
+    return objectNames;
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::readHeader
+(
+    IOobject& io,
+    const fileName& fName,
+    const word& typeName
+) const
+{
+    bool ok = false;
+
+    if (debug)
+    {
+        Pout<< "masterUncollatedFileOperation::readHeader:" << endl
+            << "    objectPath:" << io.objectPath() << endl
+            << "    fName     :" << fName << endl;
+    }
+
+    fileNameList filePaths(Pstream::nProcs());
+    filePaths[Pstream::myProcNo()] = fName;
+    Pstream::gatherList(filePaths);
+
+    bool uniform = uniformFile(filePaths);
+    Pstream::scatter(uniform);
+
+    if (uniform)
+    {
+        if (Pstream::master())
+        {
+            if (!fName.empty())
+            {
+                IFstream is(fName);
+
+                if (is.good())
+                {
+                    ok = io.readHeader(is);
+
+                    if (io.headerClassName() == decomposedBlockData::typeName)
+                    {
+                        // Read the header inside the container (master data)
+                        ok = decomposedBlockData::readMasterHeader(io, is);
+                    }
+                }
+            }
+        }
+        Pstream::scatter(ok);
+        Pstream::scatter(io.headerClassName());
+        Pstream::scatter(io.note());
+    }
+    else
+    {
+        boolList result(Pstream::nProcs(), false);
+        wordList headerClassName(Pstream::nProcs());
+        stringList note(Pstream::nProcs());
+        if (Pstream::master())
+        {
+            forAll(filePaths, proci)
+            {
+                if (!filePaths[proci].empty())
+                {
+                    IFstream is(filePaths[proci]);
+
+                    if (is.good())
+                    {
+                        result[proci] = io.readHeader(is);
+                        headerClassName[proci] = io.headerClassName();
+                        note[proci] = io.note();
+
+                        if
+                        (
+                            io.headerClassName()
+                         == decomposedBlockData::typeName
+                        )
+                        {
+                            FatalErrorInFunction
+                                << "Unexpected decomposedBlockData container"
+                                << " for processor " << proci
+                                << " file:" << filePaths[proci]
+                                << ". A decomposedBlockData container should"
+                                << " produce the same file name on all"
+                                << " processors" << exit(FatalError);
+                        }
+                    }
+                }
+            }
+        }
+        ok = scatterList(result);
+        io.headerClassName() = scatterList(headerClassName);
+        io.note() = scatterList(note);
+    }
+
+    if (debug)
+    {
+        Pout<< "masterUncollatedFileOperation::readHeader:" << " ok:" << ok
+            << " class:" << io.headerClassName() << endl;
+    }
+    return ok;
+}
+
+
+Foam::autoPtr<Foam::ISstream>
+Foam::fileOperations::masterUncollatedFileOperation::readStream
+(
+    regIOobject& io,
+    const fileName& fName,
+    const word& typeName,
+    const bool valid
+) const
+{
+    if (debug)
+    {
+        Pout<< "masterUncollatedFileOperation::readStream:"
+            << " object : " << io.name()
+            << " fName : " << fName << " valid:" << valid << endl;
+    }
+
+
+    autoPtr<ISstream> isPtr;
+    bool isCollated = false;
+    if (UPstream::master())
+    {
+        if (!fName.empty())
+        {
+            // This can happen in lagrangian field reading some processors
+            // have no file to read from. This will only happen when using
+            // normal writing since then the fName for the valid processors is
+            // processorDDD/<instance>/.. . In case of collocated writing
+            // the fName is already rewritten to processors/.
+
+            isPtr.reset(new IFstream(fName));
+
+            if (isPtr().good())
+            {
+                // Read header data (on copy)
+                IOobject headerIO(io);
+                headerIO.readHeader(isPtr());
+
+                if (headerIO.headerClassName() == decomposedBlockData::typeName)
+                {
+                    isCollated = true;
+                }
+            }
+
+            if (!isCollated)
+            {
+                // Close file. Reopened below.
+                isPtr.clear();
+            }
+        }
+    }
+
+    Pstream::scatter(isCollated);
+
+    if (isCollated)
+    {
+        if (debug)
+        {
+            Pout<< "masterUncollatedFileOperation::readStream:"
+                << " for object : " << io.name()
+                << " starting collating input from " << fName << endl;
+        }
+
+        List<char> data;
+        if (!Pstream::parRun())
+        {
+            // Analyse the objectpath to find out the processor we're trying
+            // to access
+            fileName path;
+            fileName local;
+            label proci = fileOperations::masterUncollatedFileOperation::
+            splitProcessorPath
+            (
+                io.objectPath(),
+                path,
+                local
+            );
+
+            if (proci == -1)
+            {
+                FatalIOErrorInFunction(isPtr())
+                    << "Could not detect processor number"
+                    << " from objectPath:" << io.objectPath()
+                    << exit(FatalIOError);
+            }
+
+            return decomposedBlockData::readBlock(proci, isPtr(), io);
+        }
+        else
+        {
+            // Get size of file (on master, scatter to slaves)
+            off_t sz = fileSize(fName);
+
+            // Read my data
+            return decomposedBlockData::readBlocks
+            (
+                UPstream::worldComm,
+                fName,
+                isPtr,
+                io,
+                (
+                    sz > off_t(maxMasterFileBufferSize)
+                  ? UPstream::commsTypes::scheduled
+                  : UPstream::commsTypes::nonBlocking
+                )
+            );
+        }
+    }
+    else
+    {
+        if (debug)
+        {
+            Pout<< "masterUncollatedFileOperation::readStream:"
+                << " for object : " << io.name()
+                << " starting separated input from " << fName << endl;
+        }
+
+        fileNameList filePaths(Pstream::nProcs());
+        filePaths[Pstream::myProcNo()] = fName;
+        Pstream::gatherList(filePaths);
+        boolList procValid(Pstream::nProcs());
+        procValid[Pstream::myProcNo()] = valid;
+        Pstream::gatherList(procValid);
+
+        PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
+
+        if (Pstream::master())
+        {
+            //const bool uniform = uniformFile(filePaths);
+
+            if (valid)
+            {
+                if (fName.empty())
+                {
+                    FatalErrorInFunction
+                        << "cannot find file " << io.objectPath()
+                        << exit(FatalError);
+                }
+                else
+                {
+                    autoPtr<IFstream> ifsPtr(new IFstream(fName));
+
+                    // Read header
+                    if (!io.readHeader(ifsPtr()))
+                    {
+                        FatalIOErrorInFunction(ifsPtr())
+                            << "problem while reading header for object "
+                            << io.name() << exit(FatalIOError);
+                    }
+
+                    // Open master (steal from ifsPtr)
+                    isPtr.reset(ifsPtr.ptr());
+                }
+            }
+
+            // Read slave files
+            for (label proci = 1; proci < Pstream::nProcs(); proci++)
+            {
+                if (debug)
+                {
+                    Pout<< "masterUncollatedFileOperation::readStream:"
+                        << " For processor " << proci
+                        << " opening " << filePaths[proci] << endl;
+                }
+
+                if (procValid[proci] && !filePaths[proci].empty())
+                {
+                    // Note: handle compression ourselves since size cannot
+                    // be determined without actually uncompressing
+
+                    if (Foam::exists(filePaths[proci]+".gz", false))
+                    {
+                        readAndSend
+                        (
+                            filePaths[proci],
+                            IOstream::compressionType::COMPRESSED,
+                            labelList(1, proci),
+                            pBufs
+                        );
+                    }
+                    else
+                    {
+                        readAndSend
+                        (
+                            filePaths[proci],
+                            IOstream::compressionType::UNCOMPRESSED,
+                            labelList(1, proci),
+                            pBufs
+                        );
+                    }
+                }
+            }
+        }
+
+        labelList recvSizes;
+        pBufs.finishedSends(recvSizes);
+
+        // isPtr will be valid on master. Else the information is in the
+        // PstreamBuffers
+
+        if (Pstream::master())
+        {
+            if (!isPtr.valid())
+            {
+                return autoPtr<ISstream>(new dummyISstream());
+            }
+            else
+            {
+                return isPtr;
+            }
+        }
+        else
+        {
+            if (valid)
+            {
+                UIPstream is(Pstream::masterNo(), pBufs);
+                string buf(recvSizes[Pstream::masterNo()], '\0');
+                if (recvSizes[Pstream::masterNo()] > 0)
+                {
+                    is.read(&buf[0], recvSizes[Pstream::masterNo()]);
+                }
+
+                if (debug)
+                {
+                    Pout<< "masterUncollatedFileOperation::readStream:"
+                        << " Done reading " << buf.size() << " bytes" << endl;
+                }
+                isPtr.reset(new IStringStream(fName, buf));
+
+                if (!io.readHeader(isPtr()))
+                {
+                    FatalIOErrorInFunction(isPtr())
+                        << "problem while reading header for object "
+                        << io.name() << exit(FatalIOError);
+                }
+
+                return isPtr;
+            }
+            else
+            {
+                return autoPtr<ISstream>(new dummyISstream());
+            }
+        }
+    }
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::read
+(
+    regIOobject& io,
+    const bool masterOnly,
+    const IOstream::streamFormat format,
+    const word& typeName
+) const
+{
+    bool ok = true;
+
+    if (io.globalObject())
+    {
+        if (debug)
+        {
+            Pout<< "masterUncollatedFileOperation::read:"
+                << "reading global object " << io.name() << endl;
+        }
+
+        bool ok = false;
+        if (Pstream::master())
+        {
+            // Do master-only reading always.
+            bool oldParRun = UPstream::parRun();
+            UPstream::parRun() = false;
+
+            ok = io.readData(io.readStream(typeName));
+            io.close();
+
+            UPstream::parRun() = oldParRun;
+        }
+
+        Pstream::scatter(ok);
+        Pstream::scatter(io.headerClassName());
+        Pstream::scatter(io.note());
+
+
+        // scatter operation for regIOobjects
+
+        // Get my communication order
+        const List<Pstream::commsStruct>& comms =
+        (
+            (Pstream::nProcs() < Pstream::nProcsSimpleSum)
+          ? Pstream::linearCommunication()
+          : Pstream::treeCommunication()
+        );
+        const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
+
+        // Reveive from up
+        if (myComm.above() != -1)
+        {
+            IPstream fromAbove
+            (
+                Pstream::commsTypes::scheduled,
+                myComm.above(),
+                0,
+                Pstream::msgType(),
+                Pstream::worldComm,
+                format
+            );
+            ok = io.readData(fromAbove);
+        }
+
+        // Send to my downstairs neighbours
+        forAll(myComm.below(), belowI)
+        {
+            OPstream toBelow
+            (
+                Pstream::commsTypes::scheduled,
+                myComm.below()[belowI],
+                0,
+                Pstream::msgType(),
+                Pstream::worldComm,
+                format
+            );
+            bool okWrite = io.writeData(toBelow);
+            ok = ok && okWrite;
+        }
+    }
+    else
+    {
+        if (debug)
+        {
+            Pout<< "masterUncollatedFileOperation::read:"
+                << "reading local object " << io.name() << endl;
+        }
+
+        ok = io.readData(io.readStream(typeName));
+        io.close();
+    }
+
+    return ok;
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::writeObject
+(
+    const regIOobject& io,
+    IOstream::streamFormat fmt,
+    IOstream::versionNumber ver,
+    IOstream::compressionType cmp,
+    const bool valid
+) const
+{
+    fileName pathName(io.objectPath());
+
+    if (debug)
+    {
+        Pout<< "masterUncollatedFileOperation::writeObject:"
+            << " io:" << pathName << " valid:" << valid << endl;
+    }
+
+    // Make sure to pick up any new times
+    setTime(io.time());
+
+    autoPtr<Ostream> osPtr
+    (
+        NewOFstream
+        (
+            pathName,
+            fmt,
+            ver,
+            cmp,
+            valid
+        )
+    );
+    Ostream& os = osPtr();
+
+    // If any of these fail, return (leave error handling to Ostream class)
+    if (!os.good())
+    {
+        return false;
+    }
+
+    if (!io.writeHeader(os))
+    {
+        return false;
+    }
+
+    // Write the data to the Ostream
+    if (!io.writeData(os))
+    {
+        return false;
+    }
+
+    IOobject::writeEndDivider(os);
+
+    return true;
+}
+
+
+Foam::instantList Foam::fileOperations::masterUncollatedFileOperation::findTimes
+(
+    const fileName& directory,
+    const word& constantName
+) const
+{
+    if (debug)
+    {
+        Pout<< "masterUncollatedFileOperation::findTimes:"
+            << " Finding times in directory " << directory << endl;
+    }
+
+    HashPtrTable<instantList>::const_iterator iter = times_.find(directory);
+    if (iter != times_.end())
+    {
+        if (debug)
+        {
+            Pout<< "masterUncollatedFileOperation::findTimes:"
+                << " Found cached times:" << *iter() << endl;
+        }
+        return *iter();
+    }
+    else
+    {
+        instantList times;
+        if (Pstream::master())
+        {
+            times = fileOperation::findTimes(directory, constantName);
+        }
+        Pstream::scatter(times);
+
+        instantList* tPtr = new instantList(times.xfer());
+
+        times_.insert(directory, tPtr);
+
+        if (debug)
+        {
+            Pout<< "masterUncollatedFileOperation::findTimes:"
+                << " Caching times:" << *tPtr << endl;
+        }
+        return *tPtr;
+    }
+}
+
+
+void Foam::fileOperations::masterUncollatedFileOperation::setTime
+(
+    const Time& tm
+) const
+{
+    HashPtrTable<instantList>::const_iterator iter = times_.find(tm.path());
+    if (iter != times_.end())
+    {
+        if (debug)
+        {
+            Pout<< "masterUncollatedFileOperation::setTime:"
+                << " Caching time " << tm.timeName()
+                << " for case:" << tm.path() << endl;
+        }
+
+        instantList& times = *iter();
+        const instant timeNow(tm.value(), tm.timeName());
+
+        if (times.size() > 0 && times[0].name() == tm.constant())
+        {
+            // Exclude constant
+            SubList<instant> realTimes(times, times.size()-1, 1);
+            if
+            (
+                findSortedIndex
+                (
+                    SubList<instant>(times, times.size()-1, 1),
+                    timeNow
+                )
+             == -1
+            )
+            {
+                times.append(timeNow);
+                SubList<instant> realTimes(times, times.size()-1, 1);
+                Foam::stableSort(realTimes);
+            }
+        }
+        else
+        {
+            if (findSortedIndex(times, timeNow) == -1)
+            {
+                times.append(timeNow);
+                Foam::stableSort(times);
+            }
+        }
+    }
+    fileOperation::setTime(tm);
+}
+
+
+Foam::autoPtr<Foam::ISstream>
+Foam::fileOperations::masterUncollatedFileOperation::NewIFstream
+(
+    const fileName& filePath
+) const
+{
+    if (Pstream::parRun())
+    {
+        // Insert logic of filePath. We assume that if a file is absolute
+        // on the master it is absolute also on the slaves etc.
+
+        fileNameList filePaths(Pstream::nProcs());
+        filePaths[Pstream::myProcNo()] = filePath;
+        Pstream::gatherList(filePaths);
+
+        PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
+
+        if (Pstream::master())
+        {
+            const bool uniform = uniformFile(filePaths);
+
+            if (uniform)
+            {
+                if (debug)
+                {
+                    Pout<< "masterUncollatedFileOperation::NewIFstream:"
+                        << " Opening global file " << filePath << endl;
+                }
+
+                IOstream::compressionType cmp
+                (
+                    Foam::exists(filePath+".gz", false)
+                  ? IOstream::compressionType::COMPRESSED
+                  : IOstream::compressionType::UNCOMPRESSED
+                );
+
+                labelList procs(Pstream::nProcs()-1);
+                for (label proci = 1; proci < Pstream::nProcs(); proci++)
+                {
+                    procs[proci-1] = proci;
+                }
+
+                readAndSend(filePath, cmp, procs, pBufs);
+            }
+            else
+            {
+                for (label proci = 1; proci < Pstream::nProcs(); proci++)
+                {
+                    IOstream::compressionType cmp
+                    (
+                        Foam::exists(filePaths[proci]+".gz", false)
+                      ? IOstream::compressionType::COMPRESSED
+                      : IOstream::compressionType::UNCOMPRESSED
+                    );
+
+                    readAndSend
+                    (
+                        filePaths[proci],
+                        cmp,
+                        labelList(1, proci),
+                        pBufs
+                    );
+                }
+            }
+        }
+
+
+        labelList recvSizes;
+        pBufs.finishedSends(recvSizes);
+
+        if (Pstream::master())
+        {
+            // Read myself
+            return autoPtr<ISstream>
+            (
+                new IFstream(filePaths[Pstream::masterNo()])
+            );
+        }
+        else
+        {
+            if (debug)
+            {
+                Pout<< "masterUncollatedFileOperation::NewIFstream:"
+                    << " Reading " << filePath
+                    << " from processor " << Pstream::masterNo() << endl;
+            }
+
+            UIPstream is(Pstream::masterNo(), pBufs);
+            string buf(recvSizes[Pstream::masterNo()], '\0');
+            is.read(&buf[0], recvSizes[Pstream::masterNo()]);
+
+            if (debug)
+            {
+                Pout<< "masterUncollatedFileOperation::NewIFstream:"
+                    << " Done reading " << buf.size() << " bytes" << endl;
+            }
+
+            // Note: IPstream is not an IStream so use a IStringStream to
+            //       convert the buffer. Note that we construct with a string
+            //       so it holds a copy of the buffer.
+            return autoPtr<ISstream>(new IStringStream(filePath, buf));
+        }
+    }
+    else
+    {
+        // Read myself
+        return autoPtr<ISstream>(new IFstream(filePath));
+    }
+}
+
+
+Foam::autoPtr<Foam::Ostream>
+Foam::fileOperations::masterUncollatedFileOperation::NewOFstream
+(
+    const fileName& pathName,
+    IOstream::streamFormat fmt,
+    IOstream::versionNumber ver,
+    IOstream::compressionType cmp,
+    const bool valid
+) const
+{
+    return autoPtr<Ostream>
+    (
+        new masterOFstream
+        (
+            pathName,
+            fmt,
+            ver,
+            cmp,
+            false,      // append
+            valid
+        )
+    );
+}
+
+
+Foam::label Foam::fileOperations::masterUncollatedFileOperation::addWatch
+(
+    const fileName& fName
+) const
+{
+    label watchFd;
+    if (Pstream::master())
+    {
+        watchFd = monitor().addWatch(fName);
+    }
+    Pstream::scatter(watchFd);
+    return watchFd;
+}
+
+
+bool Foam::fileOperations::masterUncollatedFileOperation::removeWatch
+(
+    const label watchIndex
+) const
+{
+    bool ok;
+    if (Pstream::master())
+    {
+        ok = monitor().removeWatch(watchIndex);
+    }
+    Pstream::scatter(ok);
+    return ok;
+}
+
+
+Foam::label Foam::fileOperations::masterUncollatedFileOperation::findWatch
+(
+    const labelList& watchIndices,
+    const fileName& fName
+) const
+{
+    label index = -1;
+
+    if (Pstream::master())
+    {
+        forAll(watchIndices, i)
+        {
+            if (monitor().getFile(watchIndices[i]) == fName)
+            {
+                index = i;
+                break;
+            }
+        }
+    }
+    Pstream::scatter(index);
+    return index;
+}
+
+
+void Foam::fileOperations::masterUncollatedFileOperation::addWatches
+(
+    regIOobject& rio,
+    const fileNameList& files
+) const
+{
+    const labelList& watchIndices = rio.watchIndices();
+
+    DynamicList<label> newWatchIndices;
+    labelHashSet removedWatches(watchIndices);
+
+    forAll(files, i)
+    {
+        const fileName& f = files[i];
+        label index = findWatch(watchIndices, f);
+
+        if (index == -1)
+        {
+            newWatchIndices.append(addWatch(f));
+        }
+        else
+        {
+            // Existing watch
+            newWatchIndices.append(watchIndices[index]);
+            removedWatches.erase(index);
+        }
+    }
+
+    // Remove any unused watches
+    forAllConstIter(labelHashSet, removedWatches, iter)
+    {
+        removeWatch(watchIndices[iter.key()]);
+    }
+
+    rio.watchIndices() = newWatchIndices;
+}
+
+
+Foam::fileName Foam::fileOperations::masterUncollatedFileOperation::getFile
+(
+    const label watchIndex
+) const
+{
+    fileName fName;
+    if (Pstream::master())
+    {
+        fName = monitor().getFile(watchIndex);
+    }
+    Pstream::scatter(fName);
+    return fName;
+}
+
+
+void Foam::fileOperations::masterUncollatedFileOperation::updateStates
+(
+    const bool masterOnly,
+    const bool syncPar
+) const
+{
+    if (Pstream::master())
+    {
+        monitor().updateStates(true, false);
+    }
+}
+
+
+Foam::fileMonitor::fileState
+Foam::fileOperations::masterUncollatedFileOperation::getState
+(
+    const label watchFd
+) const
+{
+    unsigned int state = fileMonitor::UNMODIFIED;
+    if (Pstream::master())
+    {
+        state = monitor().getState(watchFd);
+    }
+    Pstream::scatter(state);
+    return fileMonitor::fileState(state);
+}
+
+
+void Foam::fileOperations::masterUncollatedFileOperation::setUnmodified
+(
+    const label watchFd
+) const
+{
+    if (Pstream::master())
+    {
+        monitor().setUnmodified(watchFd);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H
new file mode 100644
index 0000000000000000000000000000000000000000..73c15fa6515e79be4ec2d1196de7fffd8be4a522
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H
@@ -0,0 +1,716 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::fileOperations::masterUncollatedFileOperation
+
+Description
+    fileOperations that performs all file operations on the master processor.
+    Requires the calls to be parallel synchronised!
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef fileOperations_masterUncollatedFileOperation_H
+#define fileOperations_masterUncollatedFileOperation_H
+
+#include "fileOperation.H"
+#include "OSspecific.H"
+#include "HashPtrTable.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+class PstreamBuffers;
+
+namespace fileOperations
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class masterUncollatedFileOperation Declaration
+\*---------------------------------------------------------------------------*/
+
+class masterUncollatedFileOperation
+:
+    public fileOperation
+{
+protected:
+
+    // Protected data
+
+        //- Cached times for a given directory
+        mutable HashPtrTable<instantList> times_;
+
+
+    // Protected classes
+
+        class mkDirOp
+        {
+            const mode_t mode_;
+        public:
+            mkDirOp(const mode_t mode)
+            :
+                mode_(mode)
+            {}
+
+            bool operator()(const fileName& fName) const
+            {
+                return Foam::mkDir(fName, mode_);
+            }
+        };
+
+        class chModOp
+        {
+            const mode_t mode_;
+        public:
+            chModOp(const mode_t mode)
+            :
+                mode_(mode)
+            {}
+
+            bool operator()(const fileName& fName) const
+            {
+                return Foam::chMod(fName, mode_);
+            }
+        };
+
+        class modeOp
+        {
+            const bool followLink_;
+        public:
+            modeOp(const bool followLink)
+            :
+                followLink_(followLink)
+            {}
+
+            mode_t operator()(const fileName& fName) const
+            {
+                return Foam::mode(fName, followLink_);
+            }
+        };
+
+        class typeOp
+        {
+            const bool followLink_;
+        public:
+            typeOp(const bool followLink)
+            :
+                followLink_(followLink)
+            {}
+
+            label operator()(const fileName& fName) const
+            {
+                return Foam::type(fName, followLink_);
+            }
+        };
+
+        class existsOp
+        {
+            const bool checkGzip_;
+            const bool followLink_;
+        public:
+            existsOp(const bool checkGzip, const bool followLink)
+            :
+                checkGzip_(checkGzip),
+                followLink_(followLink)
+            {}
+
+            bool operator()(const fileName& fName) const
+            {
+                return Foam::exists(fName, checkGzip_, followLink_);
+            }
+        };
+
+        class isDirOp
+        {
+            const bool followLink_;
+        public:
+            isDirOp(const bool followLink)
+            :
+                followLink_(followLink)
+            {}
+
+        public:
+            bool operator()(const fileName& fName) const
+            {
+                return Foam::isDir(fName, followLink_);
+            }
+        };
+
+        class isFileOp
+        {
+            const bool checkGzip_;
+            const bool followLink_;
+        public:
+            isFileOp(const bool checkGzip, const bool followLink)
+            :
+                checkGzip_(checkGzip),
+                followLink_(followLink)
+            {}
+        public:
+            bool operator()(const fileName& fName) const
+            {
+                return Foam::isFile(fName, checkGzip_, followLink_);
+            }
+        };
+
+        class fileSizeOp
+        {
+            const bool followLink_;
+        public:
+            fileSizeOp(const bool followLink)
+            :
+                followLink_(followLink)
+            {}
+
+        public:
+            off_t operator()(const fileName& fName) const
+            {
+                return Foam::fileSize(fName, followLink_);
+            }
+        };
+
+        class lastModifiedOp
+        {
+            const bool followLink_;
+        public:
+            lastModifiedOp(const bool followLink)
+            :
+                followLink_(followLink)
+            {}
+
+        public:
+            time_t operator()(const fileName& fName) const
+            {
+                return Foam::lastModified(fName, followLink_);
+            }
+        };
+
+        class lastModifiedHROp
+        {
+            const bool followLink_;
+        public:
+            lastModifiedHROp(const bool followLink)
+            :
+                followLink_(followLink)
+            {}
+
+        public:
+            double operator()(const fileName& fName) const
+            {
+                return Foam::highResLastModified(fName, followLink_);
+            }
+        };
+
+        class mvBakOp
+        {
+            std::string ext_;
+        public:
+            mvBakOp(const std::string& ext)
+            :
+                ext_(ext)
+            {}
+
+            bool operator()(const fileName& fName) const
+            {
+                return Foam::mvBak(fName, ext_);
+            }
+        };
+
+        class rmOp
+        {
+        public:
+            bool operator()(const fileName& fName) const
+            {
+                return Foam::rm(fName);
+            }
+        };
+
+        class rmDirOp
+        {
+        public:
+            bool operator()(const fileName& fName) const
+            {
+                return Foam::rmDir(fName);
+            }
+        };
+
+        class cpOp
+        {
+            const bool followLink_;
+        public:
+            cpOp(const bool followLink)
+            :
+                followLink_(followLink)
+            {}
+
+        public:
+            bool operator()(const fileName& src, const fileName& dest) const
+            {
+                return Foam::cp(src, dest, followLink_);
+            }
+        };
+
+        class lnOp
+        {
+        public:
+            bool operator()(const fileName& src, const fileName& dest) const
+            {
+                return Foam::ln(src, dest);
+            }
+        };
+
+        class mvOp
+        {
+            const bool followLink_;
+        public:
+            mvOp(const bool followLink)
+            :
+                followLink_(followLink)
+            {}
+
+        public:
+            bool operator()(const fileName& src, const fileName& dest) const
+            {
+                return Foam::mv(src, dest, followLink_);
+            }
+        };
+
+        class fileOrNullOp
+        {
+            const bool isFile_;
+        public:
+            fileOrNullOp(const bool isFile)
+            :
+                isFile_(isFile)
+            {}
+
+            fileName operator()(const fileName& fName) const
+            {
+                return
+                (
+                    (isFile_ && Foam::isFile(fName))
+                 || (!isFile_ && Foam::isDir(fName))
+                  ? fName
+                  : fileName::null
+                );
+            }
+        };
+
+        class readDirOp
+        {
+            const fileName::Type type_;
+            const bool filtergz_;
+            const bool followLink_;
+        public:
+            readDirOp
+            (
+                const fileName::Type type,
+                const bool filtergz,
+                const bool followLink
+            )
+            :
+                type_(type),
+                filtergz_(filtergz),
+                followLink_(followLink)
+            {}
+
+            fileNameList operator()(const fileName& fName) const
+            {
+                return Foam::readDir(fName, type_, filtergz_, followLink_);
+            }
+        };
+
+
+    // Private Member Functions
+
+        template<class Type>
+        Type scatterList(const UList<Type>&) const;
+
+        template<class Type, class fileOp>
+        Type masterOp(const fileName&, const fileOp& fop) const;
+
+        template<class Type, class fileOp>
+        Type masterOp
+        (
+            const fileName&,
+            const fileName&,
+            const fileOp& fop
+        ) const;
+
+        //- Equivalent of Time::findInstance
+        static word findInstancePath
+        (
+            const instantList& timeDirs,
+            const instant& t
+        );
+
+        //- Search for object; return info on how it was found
+        //    checkGlobal : also check undecomposed case
+        //    isFile      : true:check for file; false:check for directory
+        fileName filePathInfo
+        (
+            const bool checkGlobal,
+            const bool isFile,
+            const IOobject& io,
+            const bool search,
+            pathType&,
+            word&
+        ) const;
+
+        //- Construct filePath
+        static fileName objectPath
+        (
+            const IOobject&,
+            const pathType&,
+            const word&
+        );
+
+        //- Read file contents and send to processors
+        static void readAndSend
+        (
+            const fileName& filePath,
+            const IOstream::compressionType cmp,
+            const labelUList& procs,
+            PstreamBuffers& pBufs
+        );
+
+
+public:
+
+        //- Runtime type information
+        TypeName("masterUncollated");
+
+
+    // Static data
+
+        //- Max size of parallel communications. Switches from non-blocking
+        //  to scheduled when reading/writing files. Read as float to enable
+        //  easy specificiation of large sizes.
+        static float maxMasterFileBufferSize;
+
+
+    // Constructors
+
+        //- Construct null
+        masterUncollatedFileOperation(const bool verbose);
+
+
+    //- Destructor
+    virtual ~masterUncollatedFileOperation();
+
+
+    // Member Functions
+
+        // OSSpecific equivalents
+
+            //- Make directory
+            virtual bool mkDir(const fileName&, mode_t=0777) const;
+
+            //- Set the file mode
+            virtual bool chMod(const fileName&, const mode_t) const;
+
+            //- Return the file mode
+            virtual mode_t mode
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Return the file type: DIRECTORY, FILE or LINK
+            virtual fileName::Type type
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Does the name exist (as DIRECTORY or FILE) in the file system?
+            //  Optionally enable/disable check for gzip file.
+            virtual bool exists
+            (
+                const fileName&,
+                const bool checkGzip=true,
+                const bool followLink = true
+            ) const;
+
+            //- Does the name exist as a DIRECTORY in the file system?
+            virtual bool isDir
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Does the name exist as a FILE in the file system?
+            //  Optionally enable/disable check for gzip file.
+            virtual bool isFile
+            (
+                const fileName&,
+                const bool checkGzip=true,
+                const bool followLink = true
+            ) const;
+
+            //- Return size of file
+            virtual off_t fileSize
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Return time of last file modification
+            virtual time_t lastModified
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Return time of last file modification
+            virtual double highResLastModified
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Read a directory and return the entries as a string list
+            virtual fileNameList readDir
+            (
+                const fileName&,
+                const fileName::Type=fileName::FILE,
+                const bool filtergz=true,
+                const bool followLink = true
+            ) const;
+
+            //- Copy, recursively if necessary, the source to the destination
+            virtual bool cp
+            (
+                const fileName& src,
+                const fileName& dst,
+                const bool followLink = true
+            ) const;
+
+            //- Create a softlink. dst should not exist. Returns true if
+            //  successful.
+            virtual bool ln(const fileName& src, const fileName& dst) const;
+
+            //- Rename src to dst
+            virtual bool mv
+            (
+                const fileName& src,
+                const fileName& dst,
+                const bool followLink = false
+            ) const;
+
+            //- Rename to a corresponding backup file
+            //  If the backup file already exists, attempt with
+            //  "01" .. "99" suffix
+            virtual bool mvBak
+            (
+                const fileName&,
+                const std::string& ext = "bak"
+            ) const;
+
+            //- Remove a file, returning true if successful otherwise false
+            virtual bool rm(const fileName&) const;
+
+            //- Remove a dirctory and its contents
+            virtual bool rmDir(const fileName&) const;
+
+//            //- Open a shared library. Return handle to library. Print error
+//            //  message if library cannot be loaded (check = true)
+//            virtual void* dlOpen
+//            (
+//                const fileName& lib,
+//                const bool check = true
+//            ) const;
+
+
+        // (reg)IOobject functinality
+
+            //- Search for an object. checkGlobal : also check undecomposed case
+            virtual fileName filePath
+            (
+                const bool checkGlobal,
+                const IOobject&,
+                const word& typeName
+            ) const;
+
+            //- Search for a directory. checkGlobal : also check undecomposed
+            //  case
+            virtual fileName dirPath
+            (
+                const bool checkGlobal,
+                const IOobject&
+            ) const;
+
+            //- Search directory for objects. Used in IOobjectList.
+            virtual fileNameList readObjects
+            (
+                const objectRegistry& db,
+                const fileName& instance,
+                const fileName& local,
+                word& newInstance
+            ) const;
+
+            //- Read object header from supplied file
+            virtual bool readHeader
+            (
+                IOobject&,
+                const fileName&,
+                const word& typeName
+            ) const;
+
+            //- Reads header for regIOobject and returns an ISstream
+            //  to read the contents.
+            virtual autoPtr<ISstream> readStream
+            (
+                regIOobject&,
+                const fileName&,
+                const word& typeName,
+                const bool valid = true
+            ) const;
+
+            //- Top-level read
+            virtual bool read
+            (
+                regIOobject&,
+                const bool masterOnly,
+                const IOstream::streamFormat format,
+                const word& typeName
+            ) const;
+
+            //- Writes a regIOobject (so header, contents and divider).
+            //  Returns success state.
+            virtual bool writeObject
+            (
+                const regIOobject&,
+                IOstream::streamFormat format=IOstream::ASCII,
+                IOstream::versionNumber version=IOstream::currentVersion,
+                IOstream::compressionType compression=IOstream::UNCOMPRESSED,
+                const bool valid = true
+            ) const;
+
+            //- Generate an ISstream that reads a file
+            virtual autoPtr<ISstream> NewIFstream(const fileName&) const;
+
+            //- Generate an Ostream that writes a file
+            virtual autoPtr<Ostream> NewOFstream
+            (
+                const fileName& pathname,
+                IOstream::streamFormat format=IOstream::ASCII,
+                IOstream::versionNumber version=IOstream::currentVersion,
+                IOstream::compressionType compression=IOstream::UNCOMPRESSED,
+                const bool valid = true
+            ) const;
+
+
+        // File modification checking
+
+            //- Add watching of a file. Returns handle
+            virtual label addWatch(const fileName&) const;
+
+            //- Remove watch on a file (using handle)
+            virtual bool removeWatch(const label) const;
+
+            //- Find index (or -1) of file in list of handles
+            virtual label findWatch
+            (
+                const labelList& watchIndices,
+                const fileName&
+            ) const;
+
+            //- Helper: add watches for list of regIOobjects
+            virtual void addWatches(regIOobject&, const fileNameList&) const;
+
+            //- Get name of file being watched (using handle)
+            virtual fileName getFile(const label) const;
+
+            //- Update state of all files
+            virtual void updateStates
+            (
+                const bool masterOnly,
+                const bool syncPar
+            ) const;
+
+            //- Get current state of file (using handle)
+            virtual fileMonitor::fileState getState(const label) const;
+
+            //- Set current state of file (using handle) to unmodified
+            virtual void setUnmodified(const label) const;
+
+
+        // Other
+
+            //- Same file?
+            static bool uniformFile(const fileNameList&);
+
+            //- Get sorted list of times
+            virtual instantList findTimes(const fileName&, const word&) const;
+
+            //- Callback for time change
+            virtual void setTime(const Time&) const;
+
+            //- root+casename with any 'processorXXX' replaced by 'processsors'
+            static fileName processorsCasePath(const IOobject&);
+
+            //- Like io.path with provided instance and any 'processorXXX'
+            //  replaced by 'processsors'
+            static fileName processorsPath(const IOobject&, const word&);
+
+            //- Operating on fileName: replace processorXXX with processors
+            static fileName processorsPath(const fileName&);
+
+            //- Split fileName into part before processor and part after.
+            //  Returns -1 or processor number. Use with care.
+            //  - path/"processor" + Foam::name(proci)/local reconstructs input
+            //  - path/"processors"/local reconstructs processors equivalence
+            static label splitProcessorPath
+            (
+                const fileName&,
+                fileName& path,
+                fileName& local
+            );
+
+            //- Return cached times
+            const HashPtrTable<instantList>& times() const
+            {
+                return times_;
+            }
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace fileOperations
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "masterUncollatedFileOperationTemplates.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperationTemplates.C b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperationTemplates.C
new file mode 100644
index 0000000000000000000000000000000000000000..5c1a5b0716446688561569053356728cd65252dc
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperationTemplates.C
@@ -0,0 +1,148 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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 "Pstream.H"
+#include "IFstream.H"
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+Type Foam::fileOperations::masterUncollatedFileOperation::scatterList
+(
+    const UList<Type>& masterLst
+) const
+{
+    // TBD: more efficient scatter
+    PstreamBuffers pBufs(UPstream::commsTypes::nonBlocking);
+    if (Pstream::master())
+    {
+        for (label proci = 1; proci < Pstream::nProcs(); proci++)
+        {
+            UOPstream os(proci, pBufs);
+            os << masterLst[proci];
+        }
+    }
+    pBufs.finishedSends();
+
+    Type myResult;
+
+    if (Pstream::master())
+    {
+        myResult = masterLst[Pstream::myProcNo()];
+    }
+    else
+    {
+        UIPstream is(Pstream::masterNo(), pBufs);
+        is >> myResult;
+    }
+    return myResult;
+}
+
+
+template<class Type, class fileOp>
+Type Foam::fileOperations::masterUncollatedFileOperation::masterOp
+(
+    const fileName& fName,
+    const fileOp& fop
+) const
+{
+    if (IFstream::debug)
+    {
+        Pout<< "masterUncollatedFileOperation : Operation on " << fName << endl;
+    }
+    if (Pstream::parRun())
+    {
+        List<fileName> filePaths(Pstream::nProcs());
+        filePaths[Pstream::myProcNo()] = fName;
+        Pstream::gatherList(filePaths);
+
+        List<Type> result(Pstream::nProcs());
+        if (Pstream::master())
+        {
+            result = fop(filePaths[0]);
+            for (label i = 1; i < filePaths.size(); i++)
+            {
+                if (filePaths[i] != filePaths[0])
+                {
+                    result[i] = fop(filePaths[i]);
+                }
+            }
+        }
+
+        return scatterList(result);
+    }
+    else
+    {
+        return fop(fName);
+    }
+}
+
+
+template<class Type, class fileOp>
+Type Foam::fileOperations::masterUncollatedFileOperation::masterOp
+(
+    const fileName& src,
+    const fileName& dest,
+    const fileOp& fop
+) const
+{
+    if (IFstream::debug)
+    {
+        Pout<< "masterUncollatedFileOperation : Operation on src:" << src
+            << " dest:" << dest << endl;
+    }
+    if (Pstream::parRun())
+    {
+        List<fileName> srcs(Pstream::nProcs());
+        srcs[Pstream::myProcNo()] = src;
+        Pstream::gatherList(srcs);
+
+        List<fileName> dests(Pstream::nProcs());
+        dests[Pstream::myProcNo()] = dest;
+        Pstream::gatherList(dests);
+
+        List<Type> result(Pstream::nProcs());
+        if (Pstream::master())
+        {
+            result = fop(srcs[0], dests[0]);
+            for (label i = 1; i < srcs.size(); i++)
+            {
+                if (srcs[i] != srcs[0])
+                {
+                    result[i] = fop(srcs[i], dests[i]);
+                }
+            }
+        }
+
+        return scatterList(result);
+    }
+    else
+    {
+        return fop(src, dest);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/uncollatedFileOperation/uncollatedFileOperation.C b/src/OpenFOAM/global/fileOperations/uncollatedFileOperation/uncollatedFileOperation.C
new file mode 100644
index 0000000000000000000000000000000000000000..ca0dc84ccb5ebed03f3b482532a8ac90ebb9335a
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/uncollatedFileOperation/uncollatedFileOperation.C
@@ -0,0 +1,673 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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 "uncollatedFileOperation.H"
+#include "Time.H"
+#include "IFstream.H"
+#include "OFstream.H"
+#include "addToRunTimeSelectionTable.H"
+#include "masterUncollatedFileOperation.H"
+#include "decomposedBlockData.H"
+#include "dummyISstream.H"
+
+/* * * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * * */
+
+namespace Foam
+{
+namespace fileOperations
+{
+    defineTypeNameAndDebug(uncollatedFileOperation, 0);
+    addToRunTimeSelectionTable(fileOperation, uncollatedFileOperation, word);
+}
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+Foam::fileName Foam::fileOperations::uncollatedFileOperation::filePathInfo
+(
+    const bool checkGlobal,
+    const bool isFile,
+    const IOobject& io
+) const
+{
+    if (io.instance().isAbsolute())
+    {
+        fileName objectPath = io.instance()/io.name();
+
+        if (isFileOrDir(isFile, objectPath))
+        {
+            return objectPath;
+        }
+        else
+        {
+            return fileName::null;
+        }
+    }
+    else
+    {
+        fileName path = io.path();
+        fileName objectPath = path/io.name();
+
+        if (isFileOrDir(isFile, objectPath))
+        {
+            return objectPath;
+        }
+        else
+        {
+            if
+            (
+                checkGlobal
+             && io.time().processorCase()
+             && (
+                    io.instance() == io.time().system()
+                 || io.instance() == io.time().constant()
+                )
+            )
+            {
+                // Constant & system can come from global case
+
+                fileName parentObjectPath =
+                    io.rootPath()/io.time().globalCaseName()
+                   /io.instance()/io.db().dbDir()/io.local()/io.name();
+
+                if (isFileOrDir(isFile, parentObjectPath))
+                {
+                    return parentObjectPath;
+                }
+            }
+
+            // Check if parallel "procesors" directory
+            if (io.time().processorCase())
+            {
+                fileName path = fileOperations::masterUncollatedFileOperation::
+                processorsPath
+                (
+                    io,
+                    io.instance()
+                );
+                fileName objectPath = path/io.name();
+
+                if (isFileOrDir(isFile, objectPath))
+                {
+                    return objectPath;
+                }
+            }
+
+
+            // Check for approximately same time. E.g. if time = 1e-2 and
+            // directory is 0.01 (due to different time formats)
+            if (!Foam::isDir(path))
+            {
+                word newInstancePath = io.time().findInstancePath
+                (
+                    instant(io.instance())
+                );
+
+                if (newInstancePath.size())
+                {
+                    fileName fName
+                    (
+                        io.rootPath()/io.caseName()
+                       /newInstancePath/io.db().dbDir()/io.local()/io.name()
+                    );
+
+                    if (isFileOrDir(isFile, fName))
+                    {
+                        return fName;
+                    }
+                }
+            }
+        }
+
+        return fileName::null;
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::fileOperations::uncollatedFileOperation::uncollatedFileOperation
+(
+    const bool verbose
+)
+{
+    if (verbose)
+    {
+        Info<< "I/O    : " << typeName << endl;
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::fileOperations::uncollatedFileOperation::~uncollatedFileOperation()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+bool Foam::fileOperations::uncollatedFileOperation::mkDir
+(
+    const fileName& dir,
+    mode_t mode
+) const
+{
+    return Foam::mkDir(dir, mode);
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::chMod
+(
+    const fileName& fName,
+    mode_t mode
+) const
+{
+    return Foam::chMod(fName, mode);
+}
+
+
+mode_t Foam::fileOperations::uncollatedFileOperation::mode
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return Foam::mode(fName, followLink);
+}
+
+
+Foam::fileName::Type Foam::fileOperations::uncollatedFileOperation::type
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return Foam::type(fName, followLink);
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::exists
+(
+    const fileName& fName,
+    const bool checkGzip,
+    const bool followLink
+) const
+{
+    return Foam::exists(fName, checkGzip, followLink);
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::isDir
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return Foam::isDir(fName, followLink);
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::isFile
+(
+    const fileName& fName,
+    const bool checkGzip,
+    const bool followLink
+) const
+{
+    return Foam::isFile(fName, checkGzip, followLink);
+}
+
+
+off_t Foam::fileOperations::uncollatedFileOperation::fileSize
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return Foam::fileSize(fName, followLink);
+}
+
+
+time_t Foam::fileOperations::uncollatedFileOperation::lastModified
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return Foam::lastModified(fName, followLink);
+}
+
+
+double Foam::fileOperations::uncollatedFileOperation::highResLastModified
+(
+    const fileName& fName,
+    const bool followLink
+) const
+{
+    return Foam::highResLastModified(fName, followLink);
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::mvBak
+(
+    const fileName& fName,
+    const std::string& ext
+) const
+{
+    return Foam::mvBak(fName, ext);
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::rm
+(
+    const fileName& fName
+) const
+{
+    return Foam::rm(fName);
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::rmDir
+(
+    const fileName& dir
+) const
+{
+    return Foam::rmDir(dir);
+}
+
+
+Foam::fileNameList Foam::fileOperations::uncollatedFileOperation::readDir
+(
+    const fileName& dir,
+    const fileName::Type type,
+    const bool filtergz,
+    const bool followLink
+) const
+{
+    return Foam::readDir(dir, type, filtergz, followLink);
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::cp
+(
+    const fileName& src,
+    const fileName& dst,
+    const bool followLink
+) const
+{
+    return Foam::cp(src, dst, followLink);
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::ln
+(
+    const fileName& src,
+    const fileName& dst
+) const
+{
+    return Foam::ln(src, dst);
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::mv
+(
+    const fileName& src,
+    const fileName& dst,
+    const bool followLink
+) const
+{
+    return Foam::mv(src, dst, followLink);
+}
+
+
+Foam::fileName Foam::fileOperations::uncollatedFileOperation::filePath
+(
+    const bool checkGlobal,
+    const IOobject& io,
+    const word& typeName
+) const
+{
+    if (debug)
+    {
+        Pout<< "uncollatedFileOperation::filePath :"
+            << " objectPath:" << io.objectPath()
+            << " checkGlobal:" << checkGlobal << endl;
+    }
+
+    fileName objPath(filePathInfo(checkGlobal, true, io, search));
+
+    if (debug)
+    {
+        Pout<< "uncollatedFileOperation::filePath :"
+            << " Returning from file searching:" << endl
+            << "    objectPath:" << io.objectPath() << endl
+            << "    filePath  :" << objPath << endl << endl;
+    }
+    return objPath;
+}
+
+
+Foam::fileName Foam::fileOperations::uncollatedFileOperation::dirPath
+(
+    const bool checkGlobal,
+    const IOobject& io
+) const
+{
+    if (debug)
+    {
+        Pout<< "uncollatedFileOperation::dirPath :"
+            << " objectPath:" << io.objectPath()
+            << " checkGlobal:" << checkGlobal << endl;
+    }
+
+    fileName objPath(filePathInfo(checkGlobal, false, io, search));
+
+    if (debug)
+    {
+        Pout<< "uncollatedFileOperation::dirPath :"
+            << " Returning from directory searching:" << endl
+            << "    objectPath:" << io.objectPath() << endl
+            << "    dirPath   :" << objPath << endl << endl;
+    }
+    return objPath;
+}
+
+
+Foam::fileNameList Foam::fileOperations::uncollatedFileOperation::readObjects
+(
+    const objectRegistry& db,
+    const fileName& instance,
+    const fileName& local,
+    word& newInstance
+) const
+{
+    if (debug)
+    {
+        Pout<< "uncollatedFileOperation::readObjects :"
+            << " db:" << db.objectPath()
+            << " instance:" << instance << endl;
+    }
+
+    //- Use non-time searching version
+    fileNameList objectNames
+    (
+        fileOperation::readObjects(db, instance, local, newInstance)
+    );
+
+    if (newInstance.empty())
+    {
+        // Find similar time
+        fileName newInst = db.time().findInstancePath(instant(instance));
+        if (!newInst.empty() && newInst != instance)
+        {
+            // Try with new time
+            objectNames = fileOperation::readObjects
+            (
+                db,
+                newInst,
+                local,
+                newInstance
+            );
+        }
+    }
+
+    if (debug)
+    {
+        Pout<< "uncollatedFileOperation::readObjects :"
+            << " newInstance:" << newInstance
+            << " objectNames:" << objectNames << endl;
+    }
+
+    return objectNames;
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::readHeader
+(
+    IOobject& io,
+    const fileName& fName,
+    const word& typeName
+) const
+{
+    if (fName.empty())
+    {
+        if (IOobject::debug)
+        {
+            InfoInFunction
+                << "file " << io.objectPath() << " could not be opened"
+                << endl;
+        }
+
+        return false;
+    }
+
+    autoPtr<ISstream> isPtr(NewIFstream(fName));
+
+    if (!isPtr.valid() || !isPtr->good())
+    {
+        return false;
+    }
+
+    bool ok = io.readHeader(isPtr());
+
+    if (io.headerClassName() == decomposedBlockData::typeName)
+    {
+        // Read the header inside the container (master data)
+        ok = decomposedBlockData::readMasterHeader(io, isPtr());
+    }
+
+    return ok;
+}
+
+
+Foam::autoPtr<Foam::ISstream>
+Foam::fileOperations::uncollatedFileOperation::readStream
+(
+    regIOobject& io,
+    const fileName& fName,
+    const word& typeName,
+    const bool valid
+) const
+{
+    autoPtr<ISstream> isPtr;
+
+    if (!valid)
+    {
+        isPtr = autoPtr<ISstream>(new dummyISstream());
+        return isPtr;
+    }
+
+    if (fName.empty())
+    {
+        FatalErrorInFunction
+            << "cannot find file " << io.objectPath()
+            << exit(FatalError);
+    }
+
+    isPtr = NewIFstream(fName);
+
+    if (!isPtr.valid() || !isPtr->good())
+    {
+        FatalIOError
+        (
+            "uncollatedFileOperation::readStream()",
+            __FILE__,
+            __LINE__,
+            fName,
+            0
+        )   << "cannot open file"
+            << exit(FatalIOError);
+    }
+    else if (!io.readHeader(isPtr()))
+    {
+        FatalIOErrorInFunction(isPtr())
+            << "problem while reading header for object " << io.name()
+            << exit(FatalIOError);
+    }
+
+    if (io.headerClassName() != decomposedBlockData::typeName)
+    {
+        return isPtr;
+    }
+    else
+    {
+        // Analyse the objectpath to find out the processor we're trying
+        // to access
+        fileName path;
+        fileName local;
+        label proci = fileOperations::masterUncollatedFileOperation::
+        splitProcessorPath
+        (
+            io.objectPath(),
+            path,
+            local
+        );
+
+        if (proci == -1)
+        {
+            FatalIOErrorInFunction(isPtr())
+                << "could not detect processor number"
+                << " from objectPath:" << io.objectPath()
+                << exit(FatalIOError);
+        }
+
+        // Read data and return as stream
+        return decomposedBlockData::readBlock(proci, isPtr(), io);
+    }
+}
+
+
+bool Foam::fileOperations::uncollatedFileOperation::read
+(
+    regIOobject& io,
+    const bool masterOnly,
+    const IOstream::streamFormat format,
+    const word& typeName
+) const
+{
+    bool ok = true;
+    if (Pstream::master() || !masterOnly)
+    {
+        if (debug)
+        {
+            Pout<< "uncollatedFileOperation::read() : "
+                << "reading object " << io.objectPath()
+                << " from file " << endl;
+        }
+
+        // Set flag for e.g. codeStream
+        const bool oldGlobal = io.globalObject();
+        io.globalObject() = masterOnly;
+        // If codeStream originates from dictionary which is
+        // not IOdictionary we have a problem so use global
+        const bool oldFlag = regIOobject::masterOnlyReading;
+        regIOobject::masterOnlyReading = masterOnly;
+
+        // Read file
+        ok = io.readData(io.readStream(typeName));
+        io.close();
+
+        // Restore flags
+        io.globalObject() = oldGlobal;
+        regIOobject::masterOnlyReading = oldFlag;
+    }
+
+    if (masterOnly && Pstream::parRun())
+    {
+        // Master reads headerclassname from file. Make sure this gets
+        // transfered as well as contents.
+        Pstream::scatter(io.headerClassName());
+        Pstream::scatter(io.note());
+
+        // Get my communication order
+        const List<Pstream::commsStruct>& comms =
+        (
+            (Pstream::nProcs() < Pstream::nProcsSimpleSum)
+          ? Pstream::linearCommunication()
+          : Pstream::treeCommunication()
+        );
+        const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
+
+        // Reveive from up
+        if (myComm.above() != -1)
+        {
+            IPstream fromAbove
+            (
+                Pstream::commsTypes::scheduled,
+                myComm.above(),
+                0,
+                Pstream::msgType(),
+                Pstream::worldComm,
+                format
+            );
+            ok = io.readData(fromAbove);
+        }
+
+        // Send to my downstairs neighbours
+        forAll(myComm.below(), belowI)
+        {
+            OPstream toBelow
+            (
+                Pstream::commsTypes::scheduled,
+                myComm.below()[belowI],
+                0,
+                Pstream::msgType(),
+                Pstream::worldComm,
+                format
+            );
+            bool okWrite = io.writeData(toBelow);
+            ok = ok && okWrite;
+        }
+    }
+    return ok;
+}
+
+
+Foam::autoPtr<Foam::ISstream>
+Foam::fileOperations::uncollatedFileOperation::NewIFstream
+(
+    const fileName& filePath
+) const
+{
+    return autoPtr<ISstream>(new IFstream(filePath));
+}
+
+
+Foam::autoPtr<Foam::Ostream>
+Foam::fileOperations::uncollatedFileOperation::NewOFstream
+(
+    const fileName& pathName,
+    IOstream::streamFormat fmt,
+    IOstream::versionNumber ver,
+    IOstream::compressionType cmp,
+    const bool valid
+) const
+{
+    return autoPtr<Ostream>(new OFstream(pathName, fmt, ver, cmp));
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/uncollatedFileOperation/uncollatedFileOperation.H b/src/OpenFOAM/global/fileOperations/uncollatedFileOperation/uncollatedFileOperation.H
new file mode 100644
index 0000000000000000000000000000000000000000..9ff5e55b32866a6176ffdd76e59796424269dc6c
--- /dev/null
+++ b/src/OpenFOAM/global/fileOperations/uncollatedFileOperation/uncollatedFileOperation.H
@@ -0,0 +1,283 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::fileOperations::uncollatedFileOperation
+
+Description
+    fileOperation that assumes file operations are local.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef fileOperations_uncollatedFileOperation_H
+#define fileOperations_uncollatedFileOperation_H
+
+#include "fileOperation.H"
+#include "OSspecific.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace fileOperations
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class uncollatedFileOperation Declaration
+\*---------------------------------------------------------------------------*/
+
+class uncollatedFileOperation
+:
+    public fileOperation
+{
+    // Private Member Functions
+
+        //- Search for an object.
+        //    checkGlobal : also check undecomposed case
+        //    isFile      : true:check for file  false:check for directory
+        fileName filePathInfo
+        (
+            const bool checkGlobal,
+            const bool isFile,
+            const IOobject&
+        ) const;
+
+
+public:
+
+        //- Runtime type information
+        TypeName("uncollated");
+
+
+    // Constructors
+
+        //- Construct null
+        uncollatedFileOperation(const bool verbose);
+
+
+    //- Destructor
+    virtual ~uncollatedFileOperation();
+
+
+    // Member Functions
+
+        // OSSpecific equivalents
+
+            //- Make directory
+            virtual bool mkDir(const fileName&, mode_t=0777) const;
+
+            //- Set the file mode
+            virtual bool chMod(const fileName&, const mode_t) const;
+
+            //- Return the file mode
+            virtual mode_t mode
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Return the file type: DIRECTORY, FILE or LINK
+            virtual fileName::Type type
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Does the name exist (as DIRECTORY or FILE) in the file system?
+            //  Optionally enable/disable check for gzip file.
+            virtual bool exists
+            (
+                const fileName&,
+                const bool checkGzip=true,
+                const bool followLink = true
+            ) const;
+
+            //- Does the name exist as a DIRECTORY in the file system?
+            virtual bool isDir
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Does the name exist as a FILE in the file system?
+            //  Optionally enable/disable check for gzip file.
+            virtual bool isFile
+            (
+                const fileName&,
+                const bool checkGzip=true,
+                const bool followLink = true
+            ) const;
+
+            //- Return size of file
+            virtual off_t fileSize
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Return time of last file modification
+            virtual time_t lastModified
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Return time of last file modification
+            virtual double highResLastModified
+            (
+                const fileName&,
+                const bool followLink = true
+            ) const;
+
+            //- Read a directory and return the entries as a string list
+            virtual fileNameList readDir
+            (
+                const fileName&,
+                const fileName::Type=fileName::FILE,
+                const bool filtergz=true,
+                const bool followLink = true
+            ) const;
+
+            //- Copy, recursively if necessary, the source to the destination
+            virtual bool cp
+            (
+                const fileName& src,
+                const fileName& dst,
+                const bool followLink = true
+            ) const;
+
+             //- Create a softlink. dst should not exist. Returns true if
+            //  successful.
+            virtual bool ln(const fileName& src, const fileName& dst) const;
+
+            //- Rename src to dst
+            virtual bool mv
+            (
+                const fileName& src,
+                const fileName& dst,
+                const bool followLink = false
+            ) const;
+
+            //- Rename to a corresponding backup file
+            //  If the backup file already exists, attempt with
+            //  "01" .. "99" suffix
+            virtual bool mvBak
+            (
+                const fileName&,
+                const std::string& ext = "bak"
+            ) const;
+
+            //- Remove a file, returning true if successful otherwise false
+            virtual bool rm(const fileName&) const;
+
+            //- Remove a dirctory and its contents
+            virtual bool rmDir(const fileName&) const;
+
+//            //- Open a shared library. Return handle to library. Print error
+//            //  message if library cannot be loaded (check = true)
+//            virtual void* dlOpen
+//            (
+//                const fileName& lib,
+//                const bool check = true
+//            ) const;
+
+
+        // (reg)IOobject functinality
+
+            //- Search for an object. checkGlobal : also check undecomposed case
+            virtual fileName filePath
+            (
+                const bool checkGlobal,
+                const IOobject&,
+                const word& typeName
+            ) const;
+
+            //- Search for a directory. checkGlobal : also check undecomposed
+            //  case
+            virtual fileName dirPath
+            (
+                const bool checkGlobal,
+                const IOobject&
+            ) const;
+
+            //- Search directory for objects. Used in IOobjectList.
+            virtual fileNameList readObjects
+            (
+                const objectRegistry& db,
+                const fileName& instance,
+                const fileName& local,
+                word& newInstance
+            ) const;
+
+            //- Read object header from supplied file
+            virtual bool readHeader
+            (
+                IOobject&,
+                const fileName&,
+                const word& typeName
+            ) const;
+
+            //- Reads header for regIOobject and returns an ISstream
+            //  to read the contents.
+            virtual autoPtr<ISstream> readStream
+            (
+                regIOobject&,
+                const fileName&,
+                const word& typeName,
+                const bool procValid = true
+            ) const;
+
+            //- Top-level read
+            virtual bool read
+            (
+                regIOobject&,
+                const bool masterOnly,
+                const IOstream::streamFormat format,
+                const word& typeName
+            ) const;
+
+            //- Generate an ISstream that reads a file
+            virtual autoPtr<ISstream> NewIFstream(const fileName&) const;
+
+            //- Generate an Ostream that writes a file
+            virtual autoPtr<Ostream> NewOFstream
+            (
+                const fileName& pathname,
+                IOstream::streamFormat format=IOstream::ASCII,
+                IOstream::versionNumber version=IOstream::currentVersion,
+                IOstream::compressionType compression=IOstream::UNCOMPRESSED,
+                const bool valid = true
+            ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace fileOperations
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/include/OSspecific.H b/src/OpenFOAM/include/OSspecific.H
index 6dee7af27be33e0159e15d2d633e532d7b8f5e67..421ec9e25f6a1f6bc587ca6cd4dd9b0d3b458edc 100644
--- a/src/OpenFOAM/include/OSspecific.H
+++ b/src/OpenFOAM/include/OSspecific.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -146,7 +146,7 @@ time_t lastModified(const fileName& name, const bool followLink=true);
 
 //- Return time of last file modification
 //  Using an empty name is a no-op and always returns 0.
-double highResLastModified(const fileName& name);
+double highResLastModified(const fileName&, const bool followLink = true);
 
 //- Read a directory and return the entries as a fileName List.
 //  Using an empty directory name returns an empty list.
@@ -258,6 +258,33 @@ label osRandomInteger(List<char>& buffer);
 scalar osRandomDouble(List<char>& buffer);
 
 
+// Thread handling
+
+//- Allocate a thread
+label allocateThread();
+
+//- Start a thread
+void createThread(const label, void *(*start_routine) (void *), void *arg);
+
+//- Wait for thread
+void joinThread(const label);
+
+//- Delete a thread
+void freeThread(const label);
+
+//- Allocate a mutex variable
+label allocateMutex();
+
+//- Lock a mutex variable
+void lockMutex(const label);
+
+//- Unlock a mutex variable
+void unlockMutex(const label);
+
+//- Free a mutex variable
+void freeMutex(const label);
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 } // End namespace Foam
diff --git a/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.C b/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.C
index d4c4cca0d0b433d6fd937398dcd948c82014073a..8c88009ab8ad3a4c75cab3c063cb7cf77b3b0085 100644
--- a/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.C
+++ b/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.C
@@ -23,7 +23,7 @@ License
 
 \*---------------------------------------------------------------------------*/
 
-#include "IFstream.H"
+//#include "IFstream.H"
 #include "openFoamTableReader.H"
 
 // * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C b/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C
index 012e47d2fd6b8ad8cdce8acd1361166751f05989..2e31e93723d588632abb78ba4a69ded0e8bbac67 100644
--- a/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C
+++ b/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C
@@ -24,7 +24,6 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "interpolationTable.H"
-#include "IFstream.H"
 #include "openFoamTableReader.H"
 
 // * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/interpolations/interpolationTable/tableReaders/csv/csvTableReader.C b/src/OpenFOAM/interpolations/interpolationTable/tableReaders/csv/csvTableReader.C
index 130f5b9c932ed5f32e1cac43e5a0feb5fb34a416..ae2c0cb5e06b499e53e6343492564c4fdbcd615e 100644
--- a/src/OpenFOAM/interpolations/interpolationTable/tableReaders/csv/csvTableReader.C
+++ b/src/OpenFOAM/interpolations/interpolationTable/tableReaders/csv/csvTableReader.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -24,7 +24,7 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "csvTableReader.H"
-#include "IFstream.H"
+#include "fileOperation.H"
 #include "DynamicList.H"
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
@@ -108,7 +108,9 @@ void Foam::csvTableReader<Type>::operator()
     List<Tuple2<scalar, Type>>& data
 )
 {
-    IFstream in(fName);
+    //IFstream in(fName);
+    autoPtr<ISstream> inPtr(fileHandler().NewIFstream(fName));
+    ISstream& in = inPtr();
 
     DynamicList<Tuple2<scalar, Type>> values;
 
diff --git a/src/OpenFOAM/interpolations/interpolationTable/tableReaders/openFoam/openFoamTableReader.C b/src/OpenFOAM/interpolations/interpolationTable/tableReaders/openFoam/openFoamTableReader.C
index dc5451a5028cf2615bb9cd34a64879b99d6cb9a7..1a7f42628b2f6706c1944b6e1705cefa79260330 100644
--- a/src/OpenFOAM/interpolations/interpolationTable/tableReaders/openFoam/openFoamTableReader.C
+++ b/src/OpenFOAM/interpolations/interpolationTable/tableReaders/openFoam/openFoamTableReader.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -24,7 +24,7 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "openFoamTableReader.H"
-#include "IFstream.H"
+#include "fileOperation.H"
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
@@ -52,7 +52,7 @@ void Foam::openFoamTableReader<Type>::operator()
 )
 {
     // Read data from file
-    IFstream(fName)() >> data;
+    fileHandler().NewIFstream(fName)()() >> data;
 }
 
 
@@ -64,7 +64,7 @@ void Foam::openFoamTableReader<Type>::operator()
 )
 {
     // Read data from file
-    IFstream(fName)() >> data;
+    fileHandler().NewIFstream(fName)()() >> data;
 }
 
 
diff --git a/src/OpenFOAM/interpolations/uniformInterpolationTable/uniformInterpolationTable.C b/src/OpenFOAM/interpolations/uniformInterpolationTable/uniformInterpolationTable.C
index b078c9dea8ce691947b8e01d27bb3f8fceb43fd6..3a296f55002606cf6615c621ab4d254eeb247dd2 100644
--- a/src/OpenFOAM/interpolations/uniformInterpolationTable/uniformInterpolationTable.C
+++ b/src/OpenFOAM/interpolations/uniformInterpolationTable/uniformInterpolationTable.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -26,6 +26,7 @@ License
 #include "uniformInterpolationTable.H"
 #include "Time.H"
 #include "IOstream.H"
+#include "IOdictionary.H"
 
 // * * * * * * * * * * * *  Private Member Functions * * * * * * * * * * * * //
 
diff --git a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C
index 08c5f5c2fdac523c1019f9c9d03ec44084aa0b6e..a0e3cffeadcb4b888a411d79053d3bab301017c3 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C
+++ b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C
@@ -1119,10 +1119,11 @@ bool Foam::polyBoundaryMesh::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
-    return regIOobject::writeObject(fmt, ver, IOstream::UNCOMPRESSED);
+    return regIOobject::writeObject(fmt, ver, IOstream::UNCOMPRESSED, valid);
 }
 
 // * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H
index 6193b98f4505fae884c0444e726510d99d6084b5..61ed872fa6709376c2535b0e2287bb58d74f9f39 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H
+++ b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -236,7 +236,8 @@ public:
         (
             IOstream::streamFormat fmt,
             IOstream::versionNumber ver,
-            IOstream::compressionType cmp
+            IOstream::compressionType cmp,
+            const bool valid
         ) const;
 
 
diff --git a/src/OpenFOAM/meshes/polyMesh/polyMesh.C b/src/OpenFOAM/meshes/polyMesh/polyMesh.C
index 41ea107049bea2d39254aba592a5727fb6c7ca3d..6c44d9e8d1b42269e9ba9eb8b302404d46388ed6 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyMesh.C
+++ b/src/OpenFOAM/meshes/polyMesh/polyMesh.C
@@ -292,7 +292,7 @@ Foam::polyMesh::polyMesh(const IOobject& io)
     curMotionTimeIndex_(time().timeIndex()),
     oldPointsPtr_(nullptr)
 {
-    if (exists(owner_.objectPath()))
+    if (!owner_.headerClassName().empty())
     {
         initMesh();
     }
diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshIO.C b/src/OpenFOAM/meshes/polyMesh/polyMeshIO.C
index 544ef0ecfc770b3f7a5fb8a9e5aa403c5f5af2c4..e290c689f968c7fdb7445fa7798dbdce0539526b 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyMeshIO.C
+++ b/src/OpenFOAM/meshes/polyMesh/polyMeshIO.C
@@ -238,7 +238,7 @@ Foam::polyMesh::readUpdateState Foam::polyMesh::readUpdate()
         // Boundary is set so can use initMesh now (uses boundary_ to
         // determine internal and active faces)
 
-        if (exists(owner_.objectPath()))
+        if (!owner_.headerClassName().empty())
         {
             initMesh();
         }
diff --git a/src/OpenFOAM/meshes/preservePatchTypes/preservePatchTypes.C b/src/OpenFOAM/meshes/preservePatchTypes/preservePatchTypes.C
index 69ad923ba3cd7a7cfd9ba43468332f39ec3992b2..4d5c14be5f5004bc7e9d395433bae0d75fa273fb 100644
--- a/src/OpenFOAM/meshes/preservePatchTypes/preservePatchTypes.C
+++ b/src/OpenFOAM/meshes/preservePatchTypes/preservePatchTypes.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2014 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/OpenFOAM/primitives/functions/Function1/CSV/CSV.C b/src/OpenFOAM/primitives/functions/Function1/CSV/CSV.C
index e05e3c4fb42255f2f6c5bebbb79101b184799bf6..5643805fd7d6f1ba2353a805f0f0839aa60d7638 100644
--- a/src/OpenFOAM/primitives/functions/Function1/CSV/CSV.C
+++ b/src/OpenFOAM/primitives/functions/Function1/CSV/CSV.C
@@ -25,7 +25,7 @@ License
 
 #include "CSV.H"
 #include "DynamicList.H"
-#include "IFstream.H"
+//#include "IFstream.H"
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
@@ -92,7 +92,9 @@ template<class Type>
 void Foam::Function1Types::CSV<Type>::read()
 {
     fileName expandedFile(fName_);
-    IFstream is(expandedFile.expand());
+    //IFstream is(expandedFile.expand());
+    autoPtr<ISstream> isPtr(fileHandler().NewIFstream(expandedFile.expand()));
+    ISstream& is = isPtr();
 
     if (!is.good())
     {
diff --git a/src/OpenFOAM/primitives/functions/Function1/TableFile/TableFile.C b/src/OpenFOAM/primitives/functions/Function1/TableFile/TableFile.C
index d867d4a52d8302d4d17eafdf0e08c22763e55ebd..4304aa1ee4ec455e516596186ceffe9cb10a9ed7 100644
--- a/src/OpenFOAM/primitives/functions/Function1/TableFile/TableFile.C
+++ b/src/OpenFOAM/primitives/functions/Function1/TableFile/TableFile.C
@@ -40,7 +40,9 @@ Foam::Function1Types::TableFile<Type>::TableFile
     dict.lookup("file") >> fName_;
 
     fileName expandedFile(fName_);
-    IFstream is(expandedFile.expand());
+    //IFstream is(expandedFile.expand());
+    autoPtr<ISstream> isPtr(fileHandler().NewIFstream(expandedFile.expand()));
+    ISstream& is = isPtr();
 
     if (!is.good())
     {
diff --git a/src/OpenFOAM/primitives/strings/fileName/fileName.C b/src/OpenFOAM/primitives/strings/fileName/fileName.C
index 097da220f61fc6f5017cf473bda0e4e145d14e02..d191c46d5e4e6d27614f29863474d89cbc4a0e00 100644
--- a/src/OpenFOAM/primitives/strings/fileName/fileName.C
+++ b/src/OpenFOAM/primitives/strings/fileName/fileName.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -28,6 +28,7 @@ License
 #include "DynamicList.H"
 #include "OSspecific.H"
 #include "wordRe.H"
+#include "fileOperation.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -436,7 +437,7 @@ Foam::fileName Foam::operator/(const string& a, const string& b)
 Foam::fileName Foam::search(const word& file, const fileName& directory)
 {
     // Search the current directory for the file
-    fileNameList files(readDir(directory));
+    fileNameList files(fileHandler().readDir(directory));
     forAll(files, i)
     {
         if (files[i] == file)
@@ -446,7 +447,7 @@ Foam::fileName Foam::search(const word& file, const fileName& directory)
     }
 
     // If not found search each of the sub-directories
-    fileNameList dirs(readDir(directory, fileName::DIRECTORY));
+    fileNameList dirs(fileHandler().readDir(directory, fileName::DIRECTORY));
     forAll(dirs, i)
     {
         fileName path = search(file, directory/dirs[i]);
diff --git a/src/OpenFOAM/primitives/strings/fileName/fileName.H b/src/OpenFOAM/primitives/strings/fileName/fileName.H
index 841c0e35b2b4e74fdea39c59b5271744f0f09fdc..a0a3ece3ce8db34de9b568c5285af945e5a53e0f 100644
--- a/src/OpenFOAM/primitives/strings/fileName/fileName.H
+++ b/src/OpenFOAM/primitives/strings/fileName/fileName.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
diff --git a/src/OpenFOAM/primitives/strings/string/string.H b/src/OpenFOAM/primitives/strings/string/string.H
index b739965c39dc0ad7e4939b34199666526f1b813f..78a25c00f2a930a6e698f7bcd73d1ed700473f43 100644
--- a/src/OpenFOAM/primitives/strings/string/string.H
+++ b/src/OpenFOAM/primitives/strings/string/string.H
@@ -150,6 +150,9 @@ public:
         //- Construct from a single character
         inline string(const char c);
 
+        //- Construct from copies of a single character
+        inline string(const size_type, const char);
+
         //- Construct from Istream
         string(Istream& is);
 
diff --git a/src/OpenFOAM/primitives/strings/string/stringI.H b/src/OpenFOAM/primitives/strings/string/stringI.H
index 96520dd7585fa0bdc51a18d42fa0134335fcfcf0..9c485deda3d82ed95f9045b534956dd620c2d4ee 100644
--- a/src/OpenFOAM/primitives/strings/string/stringI.H
+++ b/src/OpenFOAM/primitives/strings/string/stringI.H
@@ -93,6 +93,12 @@ inline Foam::string::string(const char c)
 {}
 
 
+inline Foam::string::string(const size_type len, const char c)
+:
+    std::string(len, c)
+{}
+
+
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class String>
diff --git a/src/Pstream/mpi/UPstream.C b/src/Pstream/mpi/UPstream.C
index 9eadaf48e23c0e5465e911962f4f2e807e5b80da..501dec2241226e730c9621e116ec48f74bbd6478 100644
--- a/src/Pstream/mpi/UPstream.C
+++ b/src/Pstream/mpi/UPstream.C
@@ -68,7 +68,15 @@ void Foam::UPstream::addValidParOptions(HashTable<string>& validParOptions)
 
 bool Foam::UPstream::init(int& argc, char**& argv)
 {
-    MPI_Init(&argc, &argv);
+    //MPI_Init(&argc, &argv);
+    int provided_thread_support;
+    MPI_Init_thread
+    (
+        &argc,
+        &argv,
+        MPI_THREAD_MULTIPLE,
+        &provided_thread_support
+    );
 
     int numprocs;
     MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
@@ -93,6 +101,15 @@ bool Foam::UPstream::init(int& argc, char**& argv)
     // Initialise parallel structure
     setParRun(numprocs);
 
+    if (Pstream::master() && provided_thread_support != MPI_THREAD_MULTIPLE)
+    {
+        WarningInFunction
+            << "mpi does not seem to have thread support."
+            << " There might be issues with e.g. threaded IO"
+            << endl;
+    }
+
+
     #ifndef SGIMPI
     {
         // Normally use UPstream::mpiBufferSize (optimisationSwitch),
diff --git a/src/conversion/common/reader/meshReader.C b/src/conversion/common/reader/meshReader.C
index 4a6356910cb76d13e11e8d34a6c0d8273068af13..69161a47cbe3fedd72acf83ecbcd2ff695c59473 100644
--- a/src/conversion/common/reader/meshReader.C
+++ b/src/conversion/common/reader/meshReader.C
@@ -166,7 +166,8 @@ void Foam::meshReader::writeMesh
     (
         fmt,
         IOstream::currentVersion,
-        IOstream::UNCOMPRESSED
+        IOstream::UNCOMPRESSED,
+        true
     );
     writeAux(mesh);
 }
diff --git a/src/conversion/common/reader/meshReaderAux.C b/src/conversion/common/reader/meshReaderAux.C
index eb7c86248ccd4121589bf244155cdb302f74d468..1cec60e698bd8bd8df75978614cdb2d051597c0e 100644
--- a/src/conversion/common/reader/meshReaderAux.C
+++ b/src/conversion/common/reader/meshReaderAux.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -137,7 +137,8 @@ void Foam::meshReader::writeMeshLabelList
     (
         fmt,
         IOstream::currentVersion,
-        IOstream::UNCOMPRESSED
+        IOstream::UNCOMPRESSED,
+        true
     );
 }
 
diff --git a/src/dynamicFvMesh/dynamicRefineFvMesh/dynamicRefineFvMesh.C b/src/dynamicFvMesh/dynamicRefineFvMesh/dynamicRefineFvMesh.C
index bc9dbcddf33e5fd87a6b56154a720e1a8da90bc7..409f533269757bbd2a73d3cb93f25c978020ee01 100644
--- a/src/dynamicFvMesh/dynamicRefineFvMesh/dynamicRefineFvMesh.C
+++ b/src/dynamicFvMesh/dynamicRefineFvMesh/dynamicRefineFvMesh.C
@@ -1445,7 +1445,8 @@ bool Foam::dynamicRefineFvMesh::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     // Force refinement data to go to the current time directory.
@@ -1453,8 +1454,8 @@ bool Foam::dynamicRefineFvMesh::writeObject
 
     bool writeOk =
     (
-        dynamicFvMesh::writeObject(fmt, ver, cmp)
-     && meshCutter_.write()
+        dynamicFvMesh::writeObject(fmt, ver, cmp, valid)
+     && meshCutter_.write(valid)
     );
 
     if (dumpLevel_)
diff --git a/src/dynamicFvMesh/dynamicRefineFvMesh/dynamicRefineFvMesh.H b/src/dynamicFvMesh/dynamicRefineFvMesh/dynamicRefineFvMesh.H
index 1700732d530456f8ab47f63af1f64418019146a3..86a61e2b7440970acb1fc20494e20b0c00f98946 100644
--- a/src/dynamicFvMesh/dynamicRefineFvMesh/dynamicRefineFvMesh.H
+++ b/src/dynamicFvMesh/dynamicRefineFvMesh/dynamicRefineFvMesh.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -241,7 +241,8 @@ public:
         (
             IOstream::streamFormat fmt,
             IOstream::versionNumber ver,
-            IOstream::compressionType cmp
+            IOstream::compressionType cmp,
+            const bool valid
         ) const;
 
 };
diff --git a/src/dynamicMesh/motionSolvers/componentDisplacement/componentDisplacementMotionSolver.C b/src/dynamicMesh/motionSolvers/componentDisplacement/componentDisplacementMotionSolver.C
index e2ff6507514c4b6948080bb34dcf4dbd570c88d6..6aef7e60200b76ca9abe9e8d8bcefef2608458fa 100644
--- a/src/dynamicMesh/motionSolvers/componentDisplacement/componentDisplacementMotionSolver.C
+++ b/src/dynamicMesh/motionSolvers/componentDisplacement/componentDisplacementMotionSolver.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2012-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/dynamicMesh/motionSolvers/displacement/points0/points0MotionSolver.C b/src/dynamicMesh/motionSolvers/displacement/points0/points0MotionSolver.C
index f8a006d6fee0e422e826cc6172dafa10184c2317..ccb13f30a7df6e85a491283d02bb9eb7b2e1b919 100644
--- a/src/dynamicMesh/motionSolvers/displacement/points0/points0MotionSolver.C
+++ b/src/dynamicMesh/motionSolvers/displacement/points0/points0MotionSolver.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2012-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
diff --git a/src/dynamicMesh/motionSolvers/motionSolver/motionSolver.C b/src/dynamicMesh/motionSolvers/motionSolver/motionSolver.C
index 054524a29b22ae8bf762caea07760b8e8096b4c2..6e5decf0355c5ebe0e3a0f55d1acb786a41abf1a 100644
--- a/src/dynamicMesh/motionSolvers/motionSolver/motionSolver.C
+++ b/src/dynamicMesh/motionSolvers/motionSolver/motionSolver.C
@@ -220,7 +220,8 @@ bool Foam::motionSolver::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     return true;
diff --git a/src/dynamicMesh/motionSolvers/motionSolver/motionSolver.H b/src/dynamicMesh/motionSolvers/motionSolver/motionSolver.H
index b0349cdc1ba8f00bd3128e3d3938cb154eb09455..7397ee064f6b8815f549956ab1c2470ba590b5fa 100644
--- a/src/dynamicMesh/motionSolvers/motionSolver/motionSolver.H
+++ b/src/dynamicMesh/motionSolvers/motionSolver/motionSolver.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -174,7 +174,8 @@ public:
         (
             IOstream::streamFormat fmt,
             IOstream::versionNumber ver,
-            IOstream::compressionType cmp
+            IOstream::compressionType cmp,
+            const bool valid
         ) const;
 
         //- Read dynamicMeshDict dictionary
diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C
index e68fb0b4b4e5fb2c931d541b5bd218ba6d1bbbd4..38a96855df9eb030c9ceefef6b64c503c052bfa1 100644
--- a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C
+++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C
@@ -5741,16 +5741,16 @@ void Foam::hexRef8::setUnrefinement
 
 
 // Write refinement to polyMesh directory.
-bool Foam::hexRef8::write() const
+bool Foam::hexRef8::write(const bool valid) const
 {
     bool writeOk =
-        cellLevel_.write()
-     && pointLevel_.write()
-     && level0Edge_.write();
+        cellLevel_.write(valid)
+     && pointLevel_.write(valid)
+     && level0Edge_.write(valid);
 
     if (history_.active())
     {
-        writeOk = writeOk && history_.write();
+        writeOk = writeOk && history_.write(valid);
     }
     else
     {
diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.H b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.H
index e14e9761c762bac03c912bc021a9e6dc415ca2c9..9e5cf7639f79a6bfefb164190cc5b551dcd1ce30 100644
--- a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.H
+++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -566,7 +566,7 @@ public:
             void setInstance(const fileName& inst);
 
             //- Force writing refinement+history to polyMesh directory.
-            bool write() const;
+            bool write(const bool valid = true) const;
 
             //- Helper: remove all relevant files from mesh instance
             static void removeFiles(const polyMesh&);
diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8Data.C b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8Data.C
index d4b88beeec7971424db6c1cb77a462c5b1b30208..b8631f8edbbe354d01e0b753f1edda6e568be6a5 100644
--- a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8Data.C
+++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8Data.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2015-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2015-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
diff --git a/src/engine/engineTime/engineTime.H b/src/engine/engineTime/engineTime.H
index 84d33c0a4c1dc684685195fbfd2ef686a88f7984..2ccb142a1266675ea79e7f5d2b1447e376b3f24d 100644
--- a/src/engine/engineTime/engineTime.H
+++ b/src/engine/engineTime/engineTime.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -54,7 +54,7 @@ SourceFiles
 #define engineTime_H
 
 #include "Time.H"
-#include "dictionary.H"
+#include "IOdictionary.H"
 #include "dimensionedScalar.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/finiteVolume/cfdTools/general/MRF/IOMRFZoneList.C b/src/finiteVolume/cfdTools/general/MRF/IOMRFZoneList.C
index be5ba78443004b310c5eb00e2d37f3aebecfacb5..7fe0e73a58a279c2081526f956f228ab24289faf 100644
--- a/src/finiteVolume/cfdTools/general/MRF/IOMRFZoneList.C
+++ b/src/finiteVolume/cfdTools/general/MRF/IOMRFZoneList.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012-2014 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2012-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/finiteVolume/cfdTools/general/fvOptions/fvOptions.C b/src/finiteVolume/cfdTools/general/fvOptions/fvOptions.C
index 3aedb4a78853839505ba96628e695007b538cb4e..267a5510b41eaa203b221413bfc904d63aa6550e 100644
--- a/src/finiteVolume/cfdTools/general/fvOptions/fvOptions.C
+++ b/src/finiteVolume/cfdTools/general/fvOptions/fvOptions.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/finiteVolume/fvMesh/fvMesh.C b/src/finiteVolume/fvMesh/fvMesh.C
index a904f8092bf8f35c5bdfb14254ad484dc4b65997..6a15c27d8f41efcad0da492aba04f99c4209814f 100644
--- a/src/finiteVolume/fvMesh/fvMesh.C
+++ b/src/finiteVolume/fvMesh/fvMesh.C
@@ -271,7 +271,7 @@ Foam::fvMesh::fvMesh(const IOobject& io)
 
     // Check the existence of the cell volumes and read if present
     // and set the storage of V00
-    if (isFile(time().timePath()/"V0"))
+    if (fileHandler().isFile(time().timePath()/"V0"))
     {
         V0Ptr_ = new DimensionedField<scalar, volMesh>
         (
@@ -292,7 +292,7 @@ Foam::fvMesh::fvMesh(const IOobject& io)
 
     // Check the existence of the mesh fluxes, read if present and set the
     // mesh to be moving
-    if (isFile(time().timePath()/"meshPhi"))
+    if (fileHandler().isFile(time().timePath()/"meshPhi"))
     {
         phiPtr_ = new surfaceScalarField
         (
@@ -858,13 +858,14 @@ bool Foam::fvMesh::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     bool ok = true;
     if (phiPtr_)
     {
-        ok = phiPtr_->write();
+        ok = phiPtr_->write(valid);
         // NOTE: The old old time mesh phi might be necessary for certain
         // solver smooth restart using second order time schemes.
         //ok = phiPtr_->oldTime().write();
@@ -872,16 +873,16 @@ bool Foam::fvMesh::writeObject
     if (V0Ptr_ && V0Ptr_->writeOpt() == IOobject::AUTO_WRITE)
     {
         // For second order restarts we need to write V0
-        ok = V0Ptr_->write();
+        ok = V0Ptr_->write(valid);
     }
 
-    return ok && polyMesh::writeObject(fmt, ver, cmp);
+    return ok && polyMesh::writeObject(fmt, ver, cmp, valid);
 }
 
 
-bool Foam::fvMesh::write() const
+bool Foam::fvMesh::write(const bool valid) const
 {
-    return polyMesh::write();
+    return polyMesh::write(valid);
 }
 
 
diff --git a/src/finiteVolume/fvMesh/fvMesh.H b/src/finiteVolume/fvMesh/fvMesh.H
index 6132523c6ce155f434d4531430301113cb793293..d68f5243094fd210ace21d7e9d1bdcb1fc43064e 100644
--- a/src/finiteVolume/fvMesh/fvMesh.H
+++ b/src/finiteVolume/fvMesh/fvMesh.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -429,11 +429,12 @@ public:
             (
                 IOstream::streamFormat fmt,
                 IOstream::versionNumber ver,
-                IOstream::compressionType cmp
+                IOstream::compressionType cmp,
+                const bool valid
             ) const;
 
             //- Write mesh using IO settings from time
-            virtual bool write() const;
+            virtual bool write(const bool valid = true) const;
 
 
     // Member Operators
diff --git a/src/functionObjects/field/fieldCoordinateSystemTransform/fieldCoordinateSystemTransformTemplates.C b/src/functionObjects/field/fieldCoordinateSystemTransform/fieldCoordinateSystemTransformTemplates.C
index e0d65cc70781b5e608fecf92de1ad7379bfbd9eb..2e26c96343c6ca95d2c1973947b764c6fe3f3969 100644
--- a/src/functionObjects/field/fieldCoordinateSystemTransform/fieldCoordinateSystemTransformTemplates.C
+++ b/src/functionObjects/field/fieldCoordinateSystemTransform/fieldCoordinateSystemTransformTemplates.C
@@ -2,8 +2,8 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -85,7 +85,7 @@ void Foam::functionObjects::fieldCoordinateSystemTransform::transform
             IOobject::NO_WRITE
         );
 
-        if (fieldHeader.typeHeaderOk<VolFieldType>(true))
+        if (fieldHeader.typeHeaderOk<VolFieldType>(true, true, false))
         {
             DebugInfo
                 << type() << ": Field " << fieldName << " read from file"
@@ -96,7 +96,7 @@ void Foam::functionObjects::fieldCoordinateSystemTransform::transform
                 lookupObject<VolFieldType>(fieldName)
             );
         }
-        else if (fieldHeader.typeHeaderOk<SurfaceFieldType>(true))
+        else if (fieldHeader.typeHeaderOk<SurfaceFieldType>(true, true, false))
         {
             DebugInfo
                 << type() << ": Field " << fieldName << " read from file"
diff --git a/src/functionObjects/field/readFields/readFieldsTemplates.C b/src/functionObjects/field/readFields/readFieldsTemplates.C
index 326b8f2156215c0c790c254e98c2f9de836e5919..4552936ce511a15041d1560368ec117714454358 100644
--- a/src/functionObjects/field/readFields/readFieldsTemplates.C
+++ b/src/functionObjects/field/readFields/readFieldsTemplates.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -68,7 +68,7 @@ bool Foam::functionObjects::readFields::loadField(const word& fieldName)
             IOobject::NO_WRITE
         );
 
-        if (fieldHeader.typeHeaderOk<VolFieldType>(true))
+        if (fieldHeader.typeHeaderOk<VolFieldType>(true, true, false))
         {
             // Store field on mesh database
             Log << "    Reading " << fieldName << endl;
@@ -76,7 +76,7 @@ bool Foam::functionObjects::readFields::loadField(const word& fieldName)
             mesh_.objectRegistry::store(vfPtr);
             return true;
         }
-        else if (fieldHeader.typeHeaderOk<SurfaceFieldType>(true))
+        else if (fieldHeader.typeHeaderOk<SurfaceFieldType>(true, true, false))
         {
             // Store field on mesh database
             Log << "    Reading " << fieldName << endl;
diff --git a/src/functionObjects/field/streamLine/streamLineParticle.C b/src/functionObjects/field/streamLine/streamLineParticle.C
index 58dd0b403076aeaff68f0aefdd374372a5a4282e..217ad4f1751041650ea57438b73655d4062a0d6d 100644
--- a/src/functionObjects/field/streamLine/streamLineParticle.C
+++ b/src/functionObjects/field/streamLine/streamLineParticle.C
@@ -357,22 +357,25 @@ void Foam::streamLineParticle::hitPatch
 
 void Foam::streamLineParticle::readFields(Cloud<streamLineParticle>& c)
 {
-    if (!c.size())
-    {
-        return;
-    }
+//    if (!c.size())
+//    {
+//        return;
+//    }
+    bool valid = c.size();
 
     particle::readFields(c);
 
     IOField<label> lifeTime
     (
-        c.fieldIOobject("lifeTime", IOobject::MUST_READ)
+        c.fieldIOobject("lifeTime", IOobject::MUST_READ),
+        valid
     );
     c.checkFieldIOobject(c, lifeTime);
 
     vectorFieldIOField sampledPositions
     (
-        c.fieldIOobject("sampledPositions", IOobject::MUST_READ)
+        c.fieldIOobject("sampledPositions", IOobject::MUST_READ),
+        valid
     );
     c.checkFieldIOobject(c, sampledPositions);
 
@@ -390,7 +393,7 @@ void Foam::streamLineParticle::writeFields(const Cloud<streamLineParticle>& c)
 {
     particle::writeFields(c);
 
-    label np =  c.size();
+    label np = c.size();
 
     IOField<label> lifeTime
     (
@@ -411,8 +414,8 @@ void Foam::streamLineParticle::writeFields(const Cloud<streamLineParticle>& c)
         i++;
     }
 
-    lifeTime.write();
-    sampledPositions.write();
+    lifeTime.write(np > 0);
+    sampledPositions.write(np > 0);
 }
 
 
diff --git a/src/functionObjects/utilities/writeDictionary/writeDictionary.C b/src/functionObjects/utilities/writeDictionary/writeDictionary.C
index 7d2c6c74b08c84b401f7deb873bec3ab0a56c295..ab36d93772b3e5382236351282f0978e2f2f3009 100644
--- a/src/functionObjects/utilities/writeDictionary/writeDictionary.C
+++ b/src/functionObjects/utilities/writeDictionary/writeDictionary.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2013-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -27,6 +27,7 @@ License
 #include "Time.H"
 #include "polyMesh.H"
 #include "addToRunTimeSelectionTable.H"
+#include "IOdictionary.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -65,7 +66,7 @@ bool Foam::functionObjects::writeDictionary::tryDirectory
         false
     );
 
-    if (dictIO.typeHeaderOk<IOdictionary>(false))
+    if (dictIO.typeHeaderOk<IOdictionary>(true))
     {
         IOdictionary dict(dictIO);
 
diff --git a/src/fvMotionSolver/fvMotionSolvers/displacement/laplacian/displacementLaplacianFvMotionSolver.C b/src/fvMotionSolver/fvMotionSolvers/displacement/laplacian/displacementLaplacianFvMotionSolver.C
index fc35fa61662466d32f636d5c0db59e74be6f6b45..96d035e68ae4b648a11fe6be8c86ba6d301b35aa 100644
--- a/src/fvMotionSolver/fvMotionSolvers/displacement/laplacian/displacementLaplacianFvMotionSolver.C
+++ b/src/fvMotionSolver/fvMotionSolvers/displacement/laplacian/displacementLaplacianFvMotionSolver.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
diff --git a/src/lagrangian/DSMC/parcels/Templates/DSMCParcel/DSMCParcelIO.C b/src/lagrangian/DSMC/parcels/Templates/DSMCParcel/DSMCParcelIO.C
index 155280d17cef3e2c11d75468fde9a1a74185d49b..dcc6e5ecc6ee3fad68c44a9599d77fab390d49d3 100644
--- a/src/lagrangian/DSMC/parcels/Templates/DSMCParcel/DSMCParcelIO.C
+++ b/src/lagrangian/DSMC/parcels/Templates/DSMCParcel/DSMCParcelIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -73,20 +73,21 @@ Foam::DSMCParcel<ParcelType>::DSMCParcel
 template<class ParcelType>
 void Foam::DSMCParcel<ParcelType>::readFields(Cloud<DSMCParcel<ParcelType>>& c)
 {
-    if (!c.size())
-    {
-        return;
-    }
+    bool valid = c.size();
 
     ParcelType::readFields(c);
 
-    IOField<vector> U(c.fieldIOobject("U", IOobject::MUST_READ));
+    IOField<vector> U(c.fieldIOobject("U", IOobject::MUST_READ), valid);
     c.checkFieldIOobject(c, U);
 
-    IOField<scalar> Ei(c.fieldIOobject("Ei", IOobject::MUST_READ));
+    IOField<scalar> Ei(c.fieldIOobject("Ei", IOobject::MUST_READ), valid);
     c.checkFieldIOobject(c, Ei);
 
-    IOField<label> typeId(c.fieldIOobject("typeId", IOobject::MUST_READ));
+    IOField<label> typeId
+    (
+        c.fieldIOobject("typeId", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, typeId);
 
     label i = 0;
@@ -110,7 +111,7 @@ void Foam::DSMCParcel<ParcelType>::writeFields
 {
     ParcelType::writeFields(c);
 
-    label np =  c.size();
+    label np = c.size();
 
     IOField<vector> U(c.fieldIOobject("U", IOobject::NO_READ), np);
     IOField<scalar> Ei(c.fieldIOobject("Ei", IOobject::NO_READ), np);
@@ -127,9 +128,9 @@ void Foam::DSMCParcel<ParcelType>::writeFields
         i++;
     }
 
-    U.write();
-    Ei.write();
-    typeId.write();
+    U.write(np > 0);
+    Ei.write(np > 0);
+    typeId.write(np > 0);
 }
 
 
diff --git a/src/lagrangian/basic/Cloud/Cloud.H b/src/lagrangian/basic/Cloud/Cloud.H
index 27be0c3a69745c14b01abeeaec8d06c5d67b7e50..aa35eb3b478fc6c90e83913fec36096fca444272 100644
--- a/src/lagrangian/basic/Cloud/Cloud.H
+++ b/src/lagrangian/basic/Cloud/Cloud.H
@@ -300,7 +300,8 @@ public:
             (
                 IOstream::streamFormat fmt,
                 IOstream::versionNumber ver,
-                IOstream::compressionType cmp
+                IOstream::compressionType cmp,
+                const bool valid
             ) const;
 
             //- Write positions to \<cloudName\>_positions.obj file
diff --git a/src/lagrangian/basic/Cloud/CloudIO.C b/src/lagrangian/basic/Cloud/CloudIO.C
index 7e5131fd9b956db9d566a60bb1b7bc4affb5fd4d..596b2fe1fd7860eb00ffa345165f90e564bca7f7 100644
--- a/src/lagrangian/basic/Cloud/CloudIO.C
+++ b/src/lagrangian/basic/Cloud/CloudIO.C
@@ -26,6 +26,7 @@ License
 #include "Cloud.H"
 #include "Time.H"
 #include "IOPosition.H"
+#include "IOdictionary.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -101,7 +102,8 @@ void Foam::Cloud<ParticleType>::writeCloudUniformProperties() const
     (
         IOstream::ASCII,
         IOstream::currentVersion,
-        time().writeCompression()
+        time().writeCompression(),
+        true
     );
 }
 
@@ -113,19 +115,19 @@ void Foam::Cloud<ParticleType>::initCloud(const bool checkClass)
 
     IOPosition<Cloud<ParticleType>> ioP(*this);
 
-    if (ioP.headerOk())
+    bool valid = ioP.headerOk();
+    Istream& is = ioP.readStream(checkClass ? typeName : "", valid);
+    if (valid)
     {
-        ioP.readData(*this, checkClass);
+        ioP.readData(is, *this);
         ioP.close();
     }
-    else
+
+    if (!valid && debug)
     {
-        if (debug)
-        {
-            Pout<< "Cannot read particle positions file:" << nl
-                << "    " << ioP.objectPath() << nl
-                << "Assuming the initial cloud contains 0 particles." << endl;
-        }
+        Pout<< "Cannot read particle positions file:" << nl
+            << "    " << ioP.objectPath() << nl
+            << "Assuming the initial cloud contains 0 particles." << endl;
     }
 
     // Ask for the tetBasePtIs to trigger all processors to build
@@ -219,10 +221,7 @@ void Foam::Cloud<ParticleType>::checkFieldFieldIOobject
 template<class ParticleType>
 void Foam::Cloud<ParticleType>::writeFields() const
 {
-    if (this->size())
-    {
-        ParticleType::writeFields(*this);
-    }
+    ParticleType::writeFields(*this);
 }
 
 
@@ -231,20 +230,14 @@ bool Foam::Cloud<ParticleType>::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool
 ) const
 {
     writeCloudUniformProperties();
 
-    if (this->size())
-    {
-        writeFields();
-        return cloud::writeObject(fmt, ver, cmp);
-    }
-    else
-    {
-        return true;
-    }
+    writeFields();
+    return cloud::writeObject(fmt, ver, cmp, this->size());
 }
 
 
diff --git a/src/lagrangian/basic/IOPosition/IOPosition.C b/src/lagrangian/basic/IOPosition/IOPosition.C
index 5c977b54d29754244db1fea82c9321cb3e568af8..08d6e8e437db41c374e1cc5f1e0fe6dd95fc93a7 100644
--- a/src/lagrangian/basic/IOPosition/IOPosition.C
+++ b/src/lagrangian/basic/IOPosition/IOPosition.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -48,16 +48,9 @@ Foam::IOPosition<CloudType>::IOPosition(const CloudType& c)
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class CloudType>
-bool Foam::IOPosition<CloudType>::write() const
+bool Foam::IOPosition<CloudType>::write(const bool valid) const
 {
-    if (cloud_.size())
-    {
-        return regIOobject::write();
-    }
-    else
-    {
-        return true;
-    }
+    return regIOobject::write(cloud_.size());
 }
 
 
@@ -79,12 +72,10 @@ bool Foam::IOPosition<CloudType>::writeData(Ostream& os) const
 
 
 template<class CloudType>
-void Foam::IOPosition<CloudType>::readData(CloudType& c, bool checkClass)
+void Foam::IOPosition<CloudType>::readData(Istream& is, CloudType& c)
 {
     const polyMesh& mesh = c.pMesh();
 
-    Istream& is = readStream(checkClass ? typeName : "");
-
     token firstToken(is);
 
     if (firstToken.isLabel())
@@ -92,7 +83,10 @@ void Foam::IOPosition<CloudType>::readData(CloudType& c, bool checkClass)
         label s = firstToken.labelToken();
 
         // Read beginning of contents
-        is.readBeginList("IOPosition<CloudType>::readData(CloudType, bool)");
+        is.readBeginList
+        (
+            "IOPosition<CloudType>::readData(Istream&, CloudType&)"
+        );
 
         for (label i=0; i<s; i++)
         {
@@ -101,7 +95,7 @@ void Foam::IOPosition<CloudType>::readData(CloudType& c, bool checkClass)
         }
 
         // Read end of contents
-        is.readEndList("IOPosition<CloudType>::readData(CloudType, bool)");
+        is.readEndList("IOPosition<CloudType>::readData(Istream&, CloudType&)");
     }
     else if (firstToken.isPunctuation())
     {
@@ -125,7 +119,7 @@ void Foam::IOPosition<CloudType>::readData(CloudType& c, bool checkClass)
         {
             is.putBack(lastToken);
 
-            // Write position only
+            // Read position only
             c.append(new typename CloudType::particleType(mesh, is, false));
             is  >> lastToken;
         }
diff --git a/src/lagrangian/basic/IOPosition/IOPosition.H b/src/lagrangian/basic/IOPosition/IOPosition.H
index 002e4e2ac9a7d5806593857975dd8a7c1121662b..fff078e18a43a9ba8398f4297773f49b947ea417 100644
--- a/src/lagrangian/basic/IOPosition/IOPosition.H
+++ b/src/lagrangian/basic/IOPosition/IOPosition.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -80,9 +80,9 @@ public:
         //- Inherit readData from regIOobject
         using regIOobject::readData;
 
-        virtual void readData(CloudType& c, bool checkClass);
+        virtual void readData(Istream&, CloudType&);
 
-        virtual bool write() const;
+        virtual bool write(const bool valid = true) const;
 
         virtual bool writeData(Ostream& os) const;
 };
diff --git a/src/lagrangian/basic/particle/particleTemplates.C b/src/lagrangian/basic/particle/particleTemplates.C
index e812a201460cccfc2b18f8b28e2f5f4588d923f3..34a540c68ff57f2240ed330306f39737d92209a8 100644
--- a/src/lagrangian/basic/particle/particleTemplates.C
+++ b/src/lagrangian/basic/particle/particleTemplates.C
@@ -104,29 +104,29 @@ void Foam::particle::correctAfterParallelTransfer
 template<class CloudType>
 void Foam::particle::readFields(CloudType& c)
 {
-    if (!c.size())
-    {
-        return;
-    }
+    bool valid = c.size();
 
     IOobject procIO(c.fieldIOobject("origProcId", IOobject::MUST_READ));
 
-    if (procIO.typeHeaderOk<IOField<label>>(true))
-    {
-        IOField<label> origProcId(procIO);
-        c.checkFieldIOobject(c, origProcId);
-        IOField<label> origId(c.fieldIOobject("origId", IOobject::MUST_READ));
-        c.checkFieldIOobject(c, origId);
+    bool haveFile = procIO.typeHeaderOk<IOField<label>>(true);
 
-        label i = 0;
-        forAllIter(typename CloudType, c, iter)
-        {
-            particle& p = iter();
+    IOField<label> origProcId(procIO, valid && haveFile);
+    c.checkFieldIOobject(c, origProcId);
+    IOField<label> origId
+    (
+        c.fieldIOobject("origId", IOobject::MUST_READ),
+        valid && haveFile
+    );
+    c.checkFieldIOobject(c, origId);
 
-            p.origProc_ = origProcId[i];
-            p.origId_ = origId[i];
-            i++;
-        }
+    label i = 0;
+    forAllIter(typename CloudType, c, iter)
+    {
+        particle& p = iter();
+
+        p.origProc_ = origProcId[i];
+        p.origId_ = origId[i];
+        i++;
     }
 }
 
@@ -134,11 +134,11 @@ void Foam::particle::readFields(CloudType& c)
 template<class CloudType>
 void Foam::particle::writeFields(const CloudType& c)
 {
-    IOPosition<CloudType> ioP(c);
-    ioP.write();
-
     label np = c.size();
 
+    IOPosition<CloudType> ioP(c);
+    ioP.write(np > 0);
+
     IOField<label> origProc
     (
         c.fieldIOobject("origProcId", IOobject::NO_READ),
@@ -158,8 +158,8 @@ void Foam::particle::writeFields(const CloudType& c)
         i++;
     }
 
-    origProc.write();
-    origId.write();
+    origProc.write(np > 0);
+    origId.write(np > 0);
 }
 
 
diff --git a/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloud.C b/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloud.C
index 0a5bdb45fa6d5c0c4ac04cb14349e969a5f1741b..aa48ff4c6523ee10897abc3f7143c07e136e406e 100644
--- a/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloud.C
+++ b/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloud.C
@@ -242,7 +242,8 @@ void Foam::KinematicCloud<CloudType>::postEvolve()
         (
             IOstream::ASCII,
             IOstream::currentVersion,
-            this->db().time().writeCompression()
+            this->db().time().writeCompression(),
+            true
         );
     }
 }
diff --git a/src/lagrangian/intermediate/clouds/Templates/ReactingCloud/ReactingCloud.C b/src/lagrangian/intermediate/clouds/Templates/ReactingCloud/ReactingCloud.C
index 04862d198ecf29c397e3310bc5c7fb1f8fa022f6..d88104d46410a90f5c47f82dd5834792433cb0cc 100644
--- a/src/lagrangian/intermediate/clouds/Templates/ReactingCloud/ReactingCloud.C
+++ b/src/lagrangian/intermediate/clouds/Templates/ReactingCloud/ReactingCloud.C
@@ -351,7 +351,7 @@ void Foam::ReactingCloud<CloudType>::info()
 template<class CloudType>
 void Foam::ReactingCloud<CloudType>::writeFields() const
 {
-    if (this->size())
+    if (compositionModel_.valid())
     {
         CloudType::particleType::writeFields(*this, this->composition());
     }
diff --git a/src/lagrangian/intermediate/clouds/Templates/ReactingMultiphaseCloud/ReactingMultiphaseCloud.C b/src/lagrangian/intermediate/clouds/Templates/ReactingMultiphaseCloud/ReactingMultiphaseCloud.C
index 3d9d76d60c6c40c74e045ab356777d1f3182fdec..032c382e4bf762286e495885a1a949444d4b8cb7 100644
--- a/src/lagrangian/intermediate/clouds/Templates/ReactingMultiphaseCloud/ReactingMultiphaseCloud.C
+++ b/src/lagrangian/intermediate/clouds/Templates/ReactingMultiphaseCloud/ReactingMultiphaseCloud.C
@@ -278,7 +278,7 @@ void Foam::ReactingMultiphaseCloud<CloudType>::info()
 template<class CloudType>
 void Foam::ReactingMultiphaseCloud<CloudType>::writeFields() const
 {
-    if (this->size())
+    if (this->compositionModel_.valid())
     {
         CloudType::particleType::writeFields(*this, this->composition());
     }
diff --git a/src/lagrangian/intermediate/parcels/Templates/CollidingParcel/CollidingParcelIO.C b/src/lagrangian/intermediate/parcels/Templates/CollidingParcel/CollidingParcelIO.C
index f63e02daf069dc90586b16d23ada49232c53366d..a5004adac7a7c43f7c1fe205d9d0e653a54158c7 100644
--- a/src/lagrangian/intermediate/parcels/Templates/CollidingParcel/CollidingParcelIO.C
+++ b/src/lagrangian/intermediate/parcels/Templates/CollidingParcel/CollidingParcelIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -81,28 +81,31 @@ template<class ParcelType>
 template<class CloudType>
 void Foam::CollidingParcel<ParcelType>::readFields(CloudType& c)
 {
-    if (!c.size())
-    {
-        return;
-    }
+    bool valid = c.size();
 
     ParcelType::readFields(c);
 
-    IOField<vector> f(c.fieldIOobject("f", IOobject::MUST_READ));
+    IOField<vector> f(c.fieldIOobject("f", IOobject::MUST_READ), valid);
     c.checkFieldIOobject(c, f);
 
     IOField<vector> angularMomentum
     (
-        c.fieldIOobject("angularMomentum", IOobject::MUST_READ)
+        c.fieldIOobject("angularMomentum", IOobject::MUST_READ),
+        valid
     );
     c.checkFieldIOobject(c, angularMomentum);
 
-    IOField<vector> torque(c.fieldIOobject("torque", IOobject::MUST_READ));
+    IOField<vector> torque
+    (
+        c.fieldIOobject("torque", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, torque);
 
     labelFieldCompactIOField collisionRecordsPairAccessed
     (
-        c.fieldIOobject("collisionRecordsPairAccessed", IOobject::MUST_READ)
+        c.fieldIOobject("collisionRecordsPairAccessed", IOobject::MUST_READ),
+        valid
     );
     c.checkFieldFieldIOobject(c, collisionRecordsPairAccessed);
 
@@ -112,7 +115,8 @@ void Foam::CollidingParcel<ParcelType>::readFields(CloudType& c)
         (
             "collisionRecordsPairOrigProcOfOther",
             IOobject::MUST_READ
-        )
+        ),
+        valid
     );
     c.checkFieldFieldIOobject(c, collisionRecordsPairOrigProcOfOther);
 
@@ -122,31 +126,36 @@ void Foam::CollidingParcel<ParcelType>::readFields(CloudType& c)
         (
             "collisionRecordsPairOrigIdOfOther",
             IOobject::MUST_READ
-        )
+        ),
+        valid
     );
     c.checkFieldFieldIOobject(c, collisionRecordsPairOrigProcOfOther);
 
     pairDataFieldCompactIOField collisionRecordsPairData
     (
-        c.fieldIOobject("collisionRecordsPairData", IOobject::MUST_READ)
+        c.fieldIOobject("collisionRecordsPairData", IOobject::MUST_READ),
+        valid
     );
     c.checkFieldFieldIOobject(c, collisionRecordsPairData);
 
     labelFieldCompactIOField collisionRecordsWallAccessed
     (
-        c.fieldIOobject("collisionRecordsWallAccessed", IOobject::MUST_READ)
+        c.fieldIOobject("collisionRecordsWallAccessed", IOobject::MUST_READ),
+        valid
     );
     c.checkFieldFieldIOobject(c, collisionRecordsWallAccessed);
 
     vectorFieldCompactIOField collisionRecordsWallPRel
     (
-        c.fieldIOobject("collisionRecordsWallPRel", IOobject::MUST_READ)
+        c.fieldIOobject("collisionRecordsWallPRel", IOobject::MUST_READ),
+        valid
     );
     c.checkFieldFieldIOobject(c, collisionRecordsWallPRel);
 
     wallDataFieldCompactIOField collisionRecordsWallData
     (
-        c.fieldIOobject("collisionRecordsWallData", IOobject::MUST_READ)
+        c.fieldIOobject("collisionRecordsWallData", IOobject::MUST_READ),
+        valid
     );
     c.checkFieldFieldIOobject(c, collisionRecordsWallData);
 
@@ -182,7 +191,7 @@ void Foam::CollidingParcel<ParcelType>::writeFields(const CloudType& c)
 {
     ParcelType::writeFields(c);
 
-    label np =  c.size();
+    label np = c.size();
 
     IOField<vector> f(c.fieldIOobject("f", IOobject::NO_READ), np);
     IOField<vector> angularMomentum
@@ -255,17 +264,19 @@ void Foam::CollidingParcel<ParcelType>::writeFields(const CloudType& c)
         i++;
     }
 
-    f.write();
-    angularMomentum.write();
-    torque.write();
-
-    collisionRecordsPairAccessed.write();
-    collisionRecordsPairOrigProcOfOther.write();
-    collisionRecordsPairOrigIdOfOther.write();
-    collisionRecordsPairData.write();
-    collisionRecordsWallAccessed.write();
-    collisionRecordsWallPRel.write();
-    collisionRecordsWallData.write();
+    const bool valid = (np > 0);
+
+    f.write(valid);
+    angularMomentum.write(valid);
+    torque.write(valid);
+
+    collisionRecordsPairAccessed.write(valid);
+    collisionRecordsPairOrigProcOfOther.write(valid);
+    collisionRecordsPairOrigIdOfOther.write(valid);
+    collisionRecordsPairData.write(valid);
+    collisionRecordsWallAccessed.write(valid);
+    collisionRecordsWallPRel.write(valid);
+    collisionRecordsWallData.write(valid);
 }
 
 
diff --git a/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcelIO.C b/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcelIO.C
index 7e3b838d7c658bdccd2ba327efcb671313133156..7f4800fdb4d9534cc518e01bb65b1ec6169630bc 100644
--- a/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcelIO.C
+++ b/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcelIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -100,42 +100,78 @@ template<class ParcelType>
 template<class CloudType>
 void Foam::KinematicParcel<ParcelType>::readFields(CloudType& c)
 {
-    if (!c.size())
-    {
-        return;
-    }
+    bool valid = c.size();
 
     ParcelType::readFields(c);
 
-    IOField<label> active(c.fieldIOobject("active", IOobject::MUST_READ));
+    IOField<label> active
+    (
+        c.fieldIOobject("active", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, active);
 
-    IOField<label> typeId(c.fieldIOobject("typeId", IOobject::MUST_READ));
+    IOField<label> typeId
+    (
+        c.fieldIOobject("typeId", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, typeId);
 
-    IOField<scalar>
-        nParticle(c.fieldIOobject("nParticle", IOobject::MUST_READ));
+    IOField<scalar> nParticle
+    (
+        c.fieldIOobject("nParticle", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, nParticle);
 
-    IOField<scalar> d(c.fieldIOobject("d", IOobject::MUST_READ));
+    IOField<scalar> d
+    (
+        c.fieldIOobject("d", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, d);
 
-    IOField<scalar> dTarget(c.fieldIOobject("dTarget", IOobject::MUST_READ));
+    IOField<scalar> dTarget
+    (
+        c.fieldIOobject("dTarget", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, dTarget);
 
-    IOField<vector> U(c.fieldIOobject("U", IOobject::MUST_READ));
+    IOField<vector> U
+    (
+        c.fieldIOobject("U", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, U);
 
-    IOField<scalar> rho(c.fieldIOobject("rho", IOobject::MUST_READ));
+    IOField<scalar> rho
+    (
+        c.fieldIOobject("rho", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, rho);
 
-    IOField<scalar> age(c.fieldIOobject("age", IOobject::MUST_READ));
+    IOField<scalar> age
+    (
+        c.fieldIOobject("age", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, age);
 
-    IOField<scalar> tTurb(c.fieldIOobject("tTurb", IOobject::MUST_READ));
+    IOField<scalar> tTurb
+    (
+        c.fieldIOobject("tTurb", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, tTurb);
 
-    IOField<vector> UTurb(c.fieldIOobject("UTurb", IOobject::MUST_READ));
+    IOField<vector> UTurb
+    (
+        c.fieldIOobject("UTurb", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, UTurb);
 
     label i = 0;
@@ -203,16 +239,18 @@ void Foam::KinematicParcel<ParcelType>::writeFields(const CloudType& c)
         i++;
     }
 
-    active.write();
-    typeId.write();
-    nParticle.write();
-    d.write();
-    dTarget.write();
-    U.write();
-    rho.write();
-    age.write();
-    tTurb.write();
-    UTurb.write();
+    const bool valid = np > 0;
+
+    active.write(valid);
+    typeId.write(valid);
+    nParticle.write(valid);
+    d.write(valid);
+    dTarget.write(valid);
+    U.write(valid);
+    rho.write(valid);
+    age.write(valid);
+    tTurb.write(valid);
+    UTurb.write(valid);
 }
 
 
diff --git a/src/lagrangian/intermediate/parcels/Templates/MPPICParcel/MPPICParcelIO.C b/src/lagrangian/intermediate/parcels/Templates/MPPICParcel/MPPICParcelIO.C
index ec582209c6e75380c2ffcde3139240bec0a72ee7..238cf3ebf365c9946ac3e7c2f2077b9c0a0526c6 100644
--- a/src/lagrangian/intermediate/parcels/Templates/MPPICParcel/MPPICParcelIO.C
+++ b/src/lagrangian/intermediate/parcels/Templates/MPPICParcel/MPPICParcelIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2013-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -77,14 +77,15 @@ template<class ParcelType>
 template<class CloudType>
 void Foam::MPPICParcel<ParcelType>::readFields(CloudType& c)
 {
-    if (!c.size())
-    {
-        return;
-    }
+    bool valid = c.size();
 
     ParcelType::readFields(c);
 
-    IOField<vector> UCorrect(c.fieldIOobject("UCorrect", IOobject::MUST_READ));
+    IOField<vector> UCorrect
+    (
+        c.fieldIOobject("UCorrect", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, UCorrect);
 
     label i = 0;
@@ -122,7 +123,7 @@ void Foam::MPPICParcel<ParcelType>::writeFields(const CloudType& c)
         i++;
     }
 
-    UCorrect.write();
+    UCorrect.write(np > 0);
 }
 
 
diff --git a/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcelIO.C b/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcelIO.C
index 399f67879d8472654229a63c4a0c02e6b7f44e39..6f3633c031fddbae68ee7031724d3785db536a39 100644
--- a/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcelIO.C
+++ b/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcelIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -86,11 +86,6 @@ template<class ParcelType>
 template<class CloudType>
 void Foam::ReactingMultiphaseParcel<ParcelType>::readFields(CloudType& c)
 {
-    if (!c.size())
-    {
-        return;
-    }
-
     ParcelType::readFields(c);
 }
 
@@ -103,10 +98,7 @@ void Foam::ReactingMultiphaseParcel<ParcelType>::readFields
     const CompositionType& compModel
 )
 {
-    if (!c.size())
-    {
-        return;
-    }
+    bool valid = c.size();
 
     ParcelType::readFields(c, compModel);
 
@@ -137,7 +129,8 @@ void Foam::ReactingMultiphaseParcel<ParcelType>::readFields
             (
                 "Y" + gasNames[j] + stateLabels[idGas],
                 IOobject::MUST_READ
-            )
+            ),
+            valid
         );
 
         label i = 0;
@@ -161,7 +154,8 @@ void Foam::ReactingMultiphaseParcel<ParcelType>::readFields
             (
                 "Y" + liquidNames[j] + stateLabels[idLiquid],
                  IOobject::MUST_READ
-            )
+            ),
+            valid
         );
 
         label i = 0;
@@ -185,7 +179,8 @@ void Foam::ReactingMultiphaseParcel<ParcelType>::readFields
             (
                 "Y" + solidNames[j] + stateLabels[idSolid],
                 IOobject::MUST_READ
-            )
+            ),
+            valid
         );
 
         label i = 0;
@@ -224,7 +219,6 @@ void Foam::ReactingMultiphaseParcel<ParcelType>::writeFields
     label np = c.size();
 
     // Write the composition fractions
-    if (np > 0)
     {
         const wordList& stateLabels = compModel.stateLabels();
 
@@ -254,7 +248,7 @@ void Foam::ReactingMultiphaseParcel<ParcelType>::writeFields
                 YGas[i++] = p0.YGas()[j]*p0.Y()[GAS];
             }
 
-            YGas.write();
+            YGas.write(np > 0);
         }
 
         const label idLiquid = compModel.idLiquid();
@@ -283,7 +277,7 @@ void Foam::ReactingMultiphaseParcel<ParcelType>::writeFields
                 YLiquid[i++] = p0.YLiquid()[j]*p0.Y()[LIQ];
             }
 
-            YLiquid.write();
+            YLiquid.write(np > 0);
         }
 
         const label idSolid = compModel.idSolid();
@@ -312,7 +306,7 @@ void Foam::ReactingMultiphaseParcel<ParcelType>::writeFields
                 YSolid[i++] = p0.YSolid()[j]*p0.Y()[SLD];
             }
 
-            YSolid.write();
+            YSolid.write(np > 0);
         }
     }
 }
diff --git a/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcelIO.C b/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcelIO.C
index 6574af96cf185ea2ac07201e7924e6f455253d2b..dccbd67800118545faece669c933025ca2f327a8 100644
--- a/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcelIO.C
+++ b/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcelIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -83,11 +83,6 @@ template<class ParcelType>
 template<class CloudType>
 void Foam::ReactingParcel<ParcelType>::readFields(CloudType& c)
 {
-    if (!c.size())
-    {
-        return;
-    }
-
     ParcelType::readFields(c);
 }
 
@@ -100,14 +95,15 @@ void Foam::ReactingParcel<ParcelType>::readFields
     const CompositionType& compModel
 )
 {
-    if (!c.size())
-    {
-        return;
-    }
+    bool valid = c.size();
 
     ParcelType::readFields(c);
 
-    IOField<scalar> mass0(c.fieldIOobject("mass0", IOobject::MUST_READ));
+    IOField<scalar> mass0
+    (
+        c.fieldIOobject("mass0", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, mass0);
 
     label i = 0;
@@ -143,7 +139,8 @@ void Foam::ReactingParcel<ParcelType>::readFields
             (
                 "Y" + phaseTypes[j] + stateLabels[j],
                  IOobject::MUST_READ
-            )
+            ),
+            valid
         );
 
         label i = 0;
@@ -176,7 +173,6 @@ void Foam::ReactingParcel<ParcelType>::writeFields
 
     const label np = c.size();
 
-    if (np > 0)
     {
         IOField<scalar> mass0(c.fieldIOobject("mass0", IOobject::NO_READ), np);
 
@@ -186,7 +182,7 @@ void Foam::ReactingParcel<ParcelType>::writeFields
             const ReactingParcel<ParcelType>& p = iter();
             mass0[i++] = p.mass0_;
         }
-        mass0.write();
+        mass0.write(np > 0);
 
         // Write the composition fractions
         const wordList& phaseTypes = compModel.phaseTypes();
@@ -219,7 +215,7 @@ void Foam::ReactingParcel<ParcelType>::writeFields
                 Y[i++] = p.Y()[j];
             }
 
-            Y.write();
+            Y.write(np > 0);
         }
     }
 }
diff --git a/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcelIO.C b/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcelIO.C
index f23059e22fba52ef83361e1feda2f9c52dd5493a..e9b1b64194925eec36283fc53687304168a98f64 100644
--- a/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcelIO.C
+++ b/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcelIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -81,17 +81,14 @@ template<class ParcelType>
 template<class CloudType>
 void Foam::ThermoParcel<ParcelType>::readFields(CloudType& c)
 {
-    if (!c.size())
-    {
-        return;
-    }
+    bool valid = c.size();
 
     ParcelType::readFields(c);
 
-    IOField<scalar> T(c.fieldIOobject("T", IOobject::MUST_READ));
+    IOField<scalar> T(c.fieldIOobject("T", IOobject::MUST_READ), valid);
     c.checkFieldIOobject(c, T);
 
-    IOField<scalar> Cp(c.fieldIOobject("Cp", IOobject::MUST_READ));
+    IOField<scalar> Cp(c.fieldIOobject("Cp", IOobject::MUST_READ), valid);
     c.checkFieldIOobject(c, Cp);
 
 
@@ -128,8 +125,8 @@ void Foam::ThermoParcel<ParcelType>::writeFields(const CloudType& c)
         i++;
     }
 
-    T.write();
-    Cp.write();
+    T.write(np > 0);
+    Cp.write(np > 0);
 }
 
 
diff --git a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/CloudFunctionObject/CloudFunctionObject.C b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/CloudFunctionObject/CloudFunctionObject.C
index 20d230625c099161e2a9e933d735236ea0d93a16..072a5bae28f2a9fc0a4d2ae4498b7552ffcb7200 100644
--- a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/CloudFunctionObject/CloudFunctionObject.C
+++ b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/CloudFunctionObject/CloudFunctionObject.C
@@ -70,6 +70,7 @@ Foam::CloudFunctionObject<CloudType>::CloudFunctionObject
     {
         outputDir_ = outputDir_/relPath;
     }
+    outputDir_.clean();
 }
 
 
diff --git a/src/lagrangian/intermediate/submodels/MPPIC/AveragingMethods/AveragingMethod/AveragingMethod.C b/src/lagrangian/intermediate/submodels/MPPIC/AveragingMethods/AveragingMethod/AveragingMethod.C
index 2c87e3e23d8a6c2600108d71f79541bdeff79aa8..c7c18285a36c67c95949e68cb37ea3a16adb050e 100644
--- a/src/lagrangian/intermediate/submodels/MPPIC/AveragingMethods/AveragingMethod/AveragingMethod.C
+++ b/src/lagrangian/intermediate/submodels/MPPIC/AveragingMethods/AveragingMethod/AveragingMethod.C
@@ -141,7 +141,7 @@ bool Foam::AveragingMethod<Type>::writeData(Ostream& os) const
 
 
 template<class Type>
-bool Foam::AveragingMethod<Type>::write() const
+bool Foam::AveragingMethod<Type>::write(const bool valid) const
 {
     const pointMesh pointMesh_(mesh_);
 
@@ -237,10 +237,10 @@ bool Foam::AveragingMethod<Type>::write() const
     pointGrad.primitiveFieldRef() /= pointVolume;
 
     // write
-    if (!cellValue.write()) return false;
-    if (!cellGrad.write()) return false;
-    if (!pointValue.write()) return false;
-    if (!pointGrad.write()) return false;
+    if (!cellValue.write(valid)) return false;
+    if (!cellGrad.write(valid)) return false;
+    if (!pointValue.write(valid)) return false;
+    if (!pointGrad.write(valid)) return false;
 
     return true;
 }
diff --git a/src/lagrangian/intermediate/submodels/MPPIC/AveragingMethods/AveragingMethod/AveragingMethod.H b/src/lagrangian/intermediate/submodels/MPPIC/AveragingMethods/AveragingMethod/AveragingMethod.H
index 1d41ee3a6c049fea4121afc30b5a3c9659a01285..39e084c9e2a0a5aacb5de4f5b94f1da1069ff0d9 100644
--- a/src/lagrangian/intermediate/submodels/MPPIC/AveragingMethods/AveragingMethod/AveragingMethod.H
+++ b/src/lagrangian/intermediate/submodels/MPPIC/AveragingMethods/AveragingMethod/AveragingMethod.H
@@ -165,7 +165,7 @@ public:
         virtual bool writeData(Ostream&) const;
 
         //- Write using setting from DB
-        virtual bool write() const;
+        virtual bool write(const bool valid = true) const;
 
         //- Return an internal field of the average
         virtual tmp<Field<Type>> primitiveField() const = 0;
diff --git a/src/lagrangian/molecularDynamics/molecule/molecule/moleculeIO.C b/src/lagrangian/molecularDynamics/molecule/molecule/moleculeIO.C
index d0fe212e6c8eea30f099a9ecddc78c3121e47434..e1c44b0587912993ebaa51dce1635d51f6cbdea0 100644
--- a/src/lagrangian/molecularDynamics/molecule/molecule/moleculeIO.C
+++ b/src/lagrangian/molecularDynamics/molecule/molecule/moleculeIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -88,38 +88,40 @@ Foam::molecule::molecule
 
 void Foam::molecule::readFields(Cloud<molecule>& mC)
 {
-    if (!mC.size())
-    {
-        return;
-    }
+    bool valid = mC.size();
 
     particle::readFields(mC);
 
-    IOField<tensor> Q(mC.fieldIOobject("Q", IOobject::MUST_READ));
+    IOField<tensor> Q(mC.fieldIOobject("Q", IOobject::MUST_READ), valid);
     mC.checkFieldIOobject(mC, Q);
 
-    IOField<vector> v(mC.fieldIOobject("v", IOobject::MUST_READ));
+    IOField<vector> v(mC.fieldIOobject("v", IOobject::MUST_READ), valid);
     mC.checkFieldIOobject(mC, v);
 
-    IOField<vector> a(mC.fieldIOobject("a", IOobject::MUST_READ));
+    IOField<vector> a(mC.fieldIOobject("a", IOobject::MUST_READ), valid);
     mC.checkFieldIOobject(mC, a);
 
-    IOField<vector> pi(mC.fieldIOobject("pi", IOobject::MUST_READ));
+    IOField<vector> pi(mC.fieldIOobject("pi", IOobject::MUST_READ), valid);
     mC.checkFieldIOobject(mC, pi);
 
-    IOField<vector> tau(mC.fieldIOobject("tau", IOobject::MUST_READ));
+    IOField<vector> tau(mC.fieldIOobject("tau", IOobject::MUST_READ), valid);
     mC.checkFieldIOobject(mC, tau);
 
     IOField<vector> specialPosition
     (
-        mC.fieldIOobject("specialPosition", IOobject::MUST_READ)
+        mC.fieldIOobject("specialPosition", IOobject::MUST_READ),
+        valid
     );
     mC.checkFieldIOobject(mC, specialPosition);
 
-    IOField<label> special(mC.fieldIOobject("special", IOobject::MUST_READ));
+    IOField<label> special
+    (
+        mC.fieldIOobject("special", IOobject::MUST_READ),
+        valid
+    );
     mC.checkFieldIOobject(mC, special);
 
-    IOField<label> id(mC.fieldIOobject("id", IOobject::MUST_READ));
+    IOField<label> id(mC.fieldIOobject("id", IOobject::MUST_READ), valid);
     mC.checkFieldIOobject(mC, id);
 
     label i = 0;
@@ -215,21 +217,23 @@ void Foam::molecule::writeFields(const Cloud<molecule>& mC)
         i++;
     }
 
-    Q.write();
-    v.write();
-    a.write();
-    pi.write();
-    tau.write();
-    specialPosition.write();
-    special.write();
-    id.write();
-
-    piGlobal.write();
-    tauGlobal.write();
-
-    orientation1.write();
-    orientation2.write();
-    orientation3.write();
+    const bool valid = np > 0;
+
+    Q.write(valid);
+    v.write(valid);
+    a.write(valid);
+    pi.write(valid);
+    tau.write(valid);
+    specialPosition.write(valid);
+    special.write(valid);
+    id.write(valid);
+
+    piGlobal.write(valid);
+    tauGlobal.write(valid);
+
+    orientation1.write(valid);
+    orientation2.write(valid);
+    orientation3.write(valid);
 
     Info<< "writeFields " << mC.name() << endl;
 
diff --git a/src/lagrangian/molecularDynamics/potential/pairPotential/pairPotentialList/pairPotentialList.C b/src/lagrangian/molecularDynamics/potential/pairPotential/pairPotentialList/pairPotentialList.C
index 6a7da5a59ae025d9a8034ca547cee94ea0683964..a5aa685226d00ec87373a269f7c173f62ea7db62 100644
--- a/src/lagrangian/molecularDynamics/potential/pairPotential/pairPotentialList/pairPotentialList.C
+++ b/src/lagrangian/molecularDynamics/potential/pairPotential/pairPotentialList/pairPotentialList.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -116,19 +116,26 @@ void Foam::pairPotentialList::readPairPotentialDict
 
             if ((*this)[pairPotentialIndex(a, b)].writeTables())
             {
-                OFstream ppTabFile(mesh.time().path()/pairPotentialName);
+                fileHandler().mkDir(mesh.time().path());
+                autoPtr<Ostream> ppTabFile
+                (
+                    fileHandler().NewOFstream
+                    (
+                        mesh.time().path()/pairPotentialName
+                    )
+                );
 
                 if
                 (
                     !(*this)[pairPotentialIndex(a, b)].writeEnergyAndForceTables
                     (
-                        ppTabFile
+                        ppTabFile()
                     )
                 )
                 {
                     FatalErrorInFunction
                         << "Failed writing to "
-                        << ppTabFile.name() << nl
+                        << ppTabFile().name() << nl
                         << abort(FatalError);
                 }
             }
@@ -155,13 +162,20 @@ void Foam::pairPotentialList::readPairPotentialDict
 
     if (electrostaticPotential_->writeTables())
     {
-        OFstream ppTabFile(mesh.time().path()/"electrostatic");
+        fileHandler().mkDir(mesh.time().path());
+        autoPtr<Ostream> ppTabFile
+        (
+            fileHandler().NewOFstream
+            (
+                mesh.time().path()/"electrostatic"
+            )
+        );
 
-        if (!electrostaticPotential_->writeEnergyAndForceTables(ppTabFile))
+        if (!electrostaticPotential_->writeEnergyAndForceTables(ppTabFile()))
         {
             FatalErrorInFunction
                 << "Failed writing to "
-                << ppTabFile.name() << nl
+                << ppTabFile().name() << nl
                 << abort(FatalError);
         }
     }
diff --git a/src/lagrangian/solidParticle/solidParticleIO.C b/src/lagrangian/solidParticle/solidParticleIO.C
index 7cecee7418386936d4674c5fe346dbec343520d7..537bf9d7dc0061cc7eda12221d2477fb6b1b46e7 100644
--- a/src/lagrangian/solidParticle/solidParticleIO.C
+++ b/src/lagrangian/solidParticle/solidParticleIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -64,17 +64,14 @@ Foam::solidParticle::solidParticle
 
 void Foam::solidParticle::readFields(Cloud<solidParticle>& c)
 {
-    if (!c.size())
-    {
-        return;
-    }
+    bool valid = c.size();
 
     particle::readFields(c);
 
-    IOField<scalar> d(c.fieldIOobject("d", IOobject::MUST_READ));
+    IOField<scalar> d(c.fieldIOobject("d", IOobject::MUST_READ), valid);
     c.checkFieldIOobject(c, d);
 
-    IOField<vector> U(c.fieldIOobject("U", IOobject::MUST_READ));
+    IOField<vector> U(c.fieldIOobject("U", IOobject::MUST_READ), valid);
     c.checkFieldIOobject(c, U);
 
     label i = 0;
@@ -108,8 +105,8 @@ void Foam::solidParticle::writeFields(const Cloud<solidParticle>& c)
         i++;
     }
 
-    d.write();
-    U.write();
+    d.write(np > 0);
+    U.write(np > 0);
 }
 
 
diff --git a/src/lagrangian/spray/parcels/Templates/SprayParcel/SprayParcelIO.C b/src/lagrangian/spray/parcels/Templates/SprayParcel/SprayParcelIO.C
index 4f421eed0f790ca8b532cf9248a5d70081f0a45a..3e1cc6c3721747fdc388c328ff54ee1cc8a4c276 100644
--- a/src/lagrangian/spray/parcels/Templates/SprayParcel/SprayParcelIO.C
+++ b/src/lagrangian/spray/parcels/Templates/SprayParcel/SprayParcelIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -101,11 +101,6 @@ template<class ParcelType>
 template<class CloudType>
 void Foam::SprayParcel<ParcelType>::readFields(CloudType& c)
 {
-    if (!c.size())
-    {
-        return;
-    }
-
     ParcelType::readFields(c);
 }
 
@@ -118,56 +113,87 @@ void Foam::SprayParcel<ParcelType>::readFields
     const CompositionType& compModel
 )
 {
-    if (!c.size())
-    {
-        return;
-    }
+    bool valid = c.size();
 
     ParcelType::readFields(c, compModel);
 
-    IOField<scalar> d0(c.fieldIOobject("d0", IOobject::MUST_READ));
+    IOField<scalar> d0(c.fieldIOobject("d0", IOobject::MUST_READ), valid);
     c.checkFieldIOobject(c, d0);
 
     IOField<vector> position0
     (
-        c.fieldIOobject("position0", IOobject::MUST_READ)
+        c.fieldIOobject("position0", IOobject::MUST_READ),
+        valid
     );
     c.checkFieldIOobject(c, position0);
 
-    IOField<scalar> sigma(c.fieldIOobject("sigma", IOobject::MUST_READ));
+    IOField<scalar> sigma(c.fieldIOobject("sigma", IOobject::MUST_READ), valid);
     c.checkFieldIOobject(c, sigma);
 
-    IOField<scalar> mu(c.fieldIOobject("mu", IOobject::MUST_READ));
+    IOField<scalar> mu(c.fieldIOobject("mu", IOobject::MUST_READ), valid);
     c.checkFieldIOobject(c, mu);
 
-    IOField<scalar> liquidCore(c.fieldIOobject
+    IOField<scalar> liquidCore
     (
-        "liquidCore", IOobject::MUST_READ)
+        c.fieldIOobject("liquidCore", IOobject::MUST_READ),
+        valid
     );
     c.checkFieldIOobject(c, liquidCore);
 
-    IOField<scalar> KHindex(c.fieldIOobject("KHindex", IOobject::MUST_READ));
+    IOField<scalar> KHindex
+    (
+        c.fieldIOobject("KHindex", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, KHindex);
 
-    IOField<scalar> y(c.fieldIOobject("y", IOobject::MUST_READ));
+    IOField<scalar> y
+    (
+        c.fieldIOobject("y", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, y);
 
-    IOField<scalar> yDot(c.fieldIOobject("yDot", IOobject::MUST_READ));
+    IOField<scalar> yDot
+    (
+        c.fieldIOobject("yDot", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, yDot);
 
-    IOField<scalar> tc(c.fieldIOobject("tc", IOobject::MUST_READ));
+    IOField<scalar> tc
+    (
+        c.fieldIOobject("tc", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, tc);
 
-    IOField<scalar> ms(c.fieldIOobject("ms", IOobject::MUST_READ));
+    IOField<scalar> ms
+    (
+        c.fieldIOobject("ms", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, ms);
 
-    IOField<scalar> injector(c.fieldIOobject("injector", IOobject::MUST_READ));
+    IOField<scalar> injector
+    (
+        c.fieldIOobject("injector", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, injector);
 
-    IOField<scalar> tMom(c.fieldIOobject("tMom", IOobject::MUST_READ));
+    IOField<scalar> tMom
+    (
+        c.fieldIOobject("tMom", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, tMom);
 
-    IOField<scalar> user(c.fieldIOobject("user", IOobject::MUST_READ));
+    IOField<scalar> user
+    (
+        c.fieldIOobject("user", IOobject::MUST_READ),
+        valid
+    );
     c.checkFieldIOobject(c, user);
 
     label i = 0;
@@ -258,19 +284,21 @@ void Foam::SprayParcel<ParcelType>::writeFields
         i++;
     }
 
-    d0.write();
-    position0.write();
-    sigma.write();
-    mu.write();
-    liquidCore.write();
-    KHindex.write();
-    y.write();
-    yDot.write();
-    tc.write();
-    ms.write();
-    injector.write();
-    tMom.write();
-    user.write();
+    const bool valid = np > 0;
+
+    d0.write(valid);
+    position0.write(valid);
+    sigma.write(valid);
+    mu.write(valid);
+    liquidCore.write(valid);
+    KHindex.write(valid);
+    y.write(valid);
+    yDot.write(valid);
+    tc.write(valid);
+    ms.write(valid);
+    injector.write(valid);
+    tMom.write(valid);
+    user.write(valid);
 }
 
 
diff --git a/src/meshTools/edgeMesh/extendedEdgeMesh/extendedFeatureEdgeMesh/extendedFeatureEdgeMesh.H b/src/meshTools/edgeMesh/extendedEdgeMesh/extendedFeatureEdgeMesh/extendedFeatureEdgeMesh.H
index 928d7f4dab397435f2b8608fff07068245bb638f..7e723a68618c547b0b5440f5ba2cf94e5b48212e 100644
--- a/src/meshTools/edgeMesh/extendedEdgeMesh/extendedFeatureEdgeMesh/extendedFeatureEdgeMesh.H
+++ b/src/meshTools/edgeMesh/extendedEdgeMesh/extendedFeatureEdgeMesh/extendedFeatureEdgeMesh.H
@@ -145,9 +145,8 @@ public:
         //  either in the case/processor or case otherwise null
         virtual fileName filePath() const
         {
-            return globalFilePath();
+            return globalFilePath(type());
         }
-
 };
 
 
diff --git a/src/meshTools/edgeMesh/featureEdgeMesh/featureEdgeMesh.H b/src/meshTools/edgeMesh/featureEdgeMesh/featureEdgeMesh.H
index 95552422247a15a0a90d3b7df93235183845854c..af5950c2f3f5453cfae7fbf960520b263b907a3d 100644
--- a/src/meshTools/edgeMesh/featureEdgeMesh/featureEdgeMesh.H
+++ b/src/meshTools/edgeMesh/featureEdgeMesh/featureEdgeMesh.H
@@ -96,7 +96,7 @@ public:
         //  either in the case/processor or case otherwise null
         virtual fileName filePath() const
         {
-            return globalFilePath();
+            return globalFilePath(type());
         }
 };
 
diff --git a/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.C b/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.C
index 307278ea9aceeec172b14611b98e29c836645389..64af5e5298dcbc3ff62787c7e43c9cd0eea09369 100644
--- a/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.C
+++ b/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.C
@@ -51,8 +51,8 @@ Foam::fileName Foam::triSurfaceMesh::checkFile
     const fileName fName
     (
         isGlobal
-      ? io.globalFilePath()
-      : io.localFilePath()
+      ? io.globalFilePath(typeName)
+      : io.localFilePath(typeName)
     );
     if (fName.empty())
     {
@@ -89,7 +89,12 @@ Foam::fileName Foam::triSurfaceMesh::checkFile
     }
     else
     {
-        fName = (isGlobal ? io.globalFilePath() : io.localFilePath());
+        fName =
+        (
+            isGlobal
+          ? io.globalFilePath(typeName)
+          : io.localFilePath(typeName)
+        );
 
         if (!exists(fName))
         {
@@ -884,7 +889,8 @@ bool Foam::triSurfaceMesh::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     const Time& runTime = searchableSurface::time();
diff --git a/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.H b/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.H
index d1691dba1861e9e24a399fa9307190a47fcf62c1..d35abbad2ebf98b26aa631f9aee7a227fe7bf952 100644
--- a/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.H
+++ b/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.H
@@ -301,7 +301,8 @@ public:
             (
                 IOstream::streamFormat fmt,
                 IOstream::versionNumber ver,
-                IOstream::compressionType cmp
+                IOstream::compressionType cmp,
+                const bool valid
             ) const;
 
             //- Is object global
@@ -314,7 +315,7 @@ public:
             //  either in the case/processor or case otherwise null
             virtual fileName filePath() const
             {
-                return searchableSurface::globalFilePath();
+                return searchableSurface::globalFilePath(type());
             }
 };
 
diff --git a/src/meshTools/sets/cellSources/fieldToCell/fieldToCell.C b/src/meshTools/sets/cellSources/fieldToCell/fieldToCell.C
index b6640eaa03649a5e8a8237fc514e04db66cb86a5..08ce936c46523f7ef01b02781bdada71dc3af4d0 100644
--- a/src/meshTools/sets/cellSources/fieldToCell/fieldToCell.C
+++ b/src/meshTools/sets/cellSources/fieldToCell/fieldToCell.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/meshTools/sets/topoSets/cellZoneSet.C b/src/meshTools/sets/topoSets/cellZoneSet.C
index 9551827c29103201bc02509f6b1c1074b5ccd268..4892ff617a5a2736609493bda56cf2474a873e17 100644
--- a/src/meshTools/sets/topoSets/cellZoneSet.C
+++ b/src/meshTools/sets/topoSets/cellZoneSet.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -248,13 +248,14 @@ bool cellZoneSet::writeObject
 (
     IOstream::streamFormat s,
     IOstream::versionNumber v,
-    IOstream::compressionType c
+    IOstream::compressionType c,
+    const bool valid
 ) const
 {
     // Write shadow cellSet
     word oldTypeName = typeName;
     const_cast<word&>(type()) = cellSet::typeName;
-    bool ok = cellSet::writeObject(s, v, c);
+    bool ok = cellSet::writeObject(s, v, c, valid);
     const_cast<word&>(type()) = oldTypeName;
 
     // Modify cellZone
@@ -284,7 +285,7 @@ bool cellZoneSet::writeObject
     }
     cellZones.clearAddressing();
 
-    return ok && cellZones.write();
+    return ok && cellZones.write(valid);
 }
 
 
diff --git a/src/meshTools/sets/topoSets/cellZoneSet.H b/src/meshTools/sets/topoSets/cellZoneSet.H
index ee7a3ebb63951e60d0179c2239cc5d9c06714263..9df3c0c4db45e3700a29cee42243998ccb99b057 100644
--- a/src/meshTools/sets/topoSets/cellZoneSet.H
+++ b/src/meshTools/sets/topoSets/cellZoneSet.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -142,7 +142,8 @@ public:
         (
             IOstream::streamFormat,
             IOstream::versionNumber,
-            IOstream::compressionType
+            IOstream::compressionType,
+            const bool valid
         ) const;
 
         //- Update any stored data for new labels
diff --git a/src/meshTools/sets/topoSets/faceZoneSet.C b/src/meshTools/sets/topoSets/faceZoneSet.C
index 608109f7d522707f0b5641518608656b8a5f3836..39561a939e0adba6c416e06554f227dba744b572 100644
--- a/src/meshTools/sets/topoSets/faceZoneSet.C
+++ b/src/meshTools/sets/topoSets/faceZoneSet.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -463,13 +463,14 @@ bool faceZoneSet::writeObject
 (
     IOstream::streamFormat s,
     IOstream::versionNumber v,
-    IOstream::compressionType c
+    IOstream::compressionType c,
+    const bool valid
 ) const
 {
     // Write shadow faceSet
     word oldTypeName = typeName;
     const_cast<word&>(type()) = faceSet::typeName;
-    bool ok = faceSet::writeObject(s, v, c);
+    bool ok = faceSet::writeObject(s, v, c, valid);
     const_cast<word&>(type()) = oldTypeName;
 
     // Modify faceZone
@@ -500,7 +501,7 @@ bool faceZoneSet::writeObject
     }
     faceZones.clearAddressing();
 
-    return ok && faceZones.write();
+    return ok && faceZones.write(valid);
 }
 
 
diff --git a/src/meshTools/sets/topoSets/faceZoneSet.H b/src/meshTools/sets/topoSets/faceZoneSet.H
index 35a0133041f5c97b77361fef2a687d665e6bc028..375d0b96938ab378f2f21d53274f4464bf5fb3ea 100644
--- a/src/meshTools/sets/topoSets/faceZoneSet.H
+++ b/src/meshTools/sets/topoSets/faceZoneSet.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -159,7 +159,8 @@ public:
         (
             IOstream::streamFormat,
             IOstream::versionNumber,
-            IOstream::compressionType
+            IOstream::compressionType,
+            const bool valid
         ) const;
 
         //- Update any stored data for new labels
diff --git a/src/meshTools/sets/topoSets/pointZoneSet.C b/src/meshTools/sets/topoSets/pointZoneSet.C
index 726dc77777f8a43be43f2c9c24aafa70e82c920a..3c8989c5f795e15dfef67d729208936bb23ca2b7 100644
--- a/src/meshTools/sets/topoSets/pointZoneSet.C
+++ b/src/meshTools/sets/topoSets/pointZoneSet.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -249,13 +249,14 @@ bool pointZoneSet::writeObject
 (
     IOstream::streamFormat s,
     IOstream::versionNumber v,
-    IOstream::compressionType c
+    IOstream::compressionType c,
+    const bool valid
 ) const
 {
     // Write shadow pointSet
     word oldTypeName = typeName;
     const_cast<word&>(type()) = pointSet::typeName;
-    bool ok = pointSet::writeObject(s, v, c);
+    bool ok = pointSet::writeObject(s, v, c, valid);
     const_cast<word&>(type()) = oldTypeName;
 
     // Modify pointZone
@@ -285,7 +286,7 @@ bool pointZoneSet::writeObject
     }
     pointZones.clearAddressing();
 
-    return ok && pointZones.write();
+    return ok && pointZones.write(valid);
 }
 
 
diff --git a/src/meshTools/sets/topoSets/pointZoneSet.H b/src/meshTools/sets/topoSets/pointZoneSet.H
index daaf4bdc0f2853971d4f843075044fe82e9270f8..47823e2dee565e651b340dde6ba45fc11bdc6572 100644
--- a/src/meshTools/sets/topoSets/pointZoneSet.H
+++ b/src/meshTools/sets/topoSets/pointZoneSet.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -146,7 +146,8 @@ public:
         (
             IOstream::streamFormat,
             IOstream::versionNumber,
-            IOstream::compressionType
+            IOstream::compressionType,
+            const bool valid
         ) const;
 
         //- Update any stored data for new labels
diff --git a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C
index 8ceb27f37ccc34a0154eceaf319e17c750e755d6..fc7aa24aef37f8b88f38b805dbb425a208ff4c85 100644
--- a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C
+++ b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C
@@ -2377,7 +2377,8 @@ bool Foam::distributedTriSurfaceMesh::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     // Make sure dictionary goes to same directory as surface
@@ -2404,7 +2405,7 @@ bool Foam::distributedTriSurfaceMesh::writeObject
     }
 
     // Dictionary needs to be written in ascii - binary output not supported.
-    return dict_.writeObject(IOstream::ASCII, ver, cmp);
+    return dict_.writeObject(IOstream::ASCII, ver, cmp, true);
 }
 
 
diff --git a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.H b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.H
index 8294da4a0ca1b72175d4eaa46d95f1ba78e181c2..7e44c1d68055e8420e68ed81da2d39192dffb76a 100644
--- a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.H
+++ b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2015 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -457,12 +457,33 @@ public:
             (
                 IOstream::streamFormat fmt,
                 IOstream::versionNumber ver,
-                IOstream::compressionType cmp
+                IOstream::compressionType cmp,
+                const bool valid
             ) const;
 
+            //- Is object global
+            virtual bool global() const
+            {
+                return false;
+            }
+
+            //- Return complete path + object name if the file exists
+            //  either in the case/processor or case otherwise null
+            virtual fileName filePath() const
+            {
+                return searchableSurface::localFilePath(type());
+            }
 };
 
 
+//- Template function for obtaining global status
+template<>
+inline bool typeGlobal<distributedTriSurfaceMesh>()
+{
+    return false;
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 } // End namespace Foam
diff --git a/src/parallel/reconstruct/reconstruct/reconstructLagrangianFields.C b/src/parallel/reconstruct/reconstruct/reconstructLagrangianFields.C
index efd476685ca5852125710d3817f3f7021b293394..eea4d38658286e991352a0be5fc0f36554ae1ded 100644
--- a/src/parallel/reconstruct/reconstruct/reconstructLagrangianFields.C
+++ b/src/parallel/reconstruct/reconstruct/reconstructLagrangianFields.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/regionModels/regionModel/regionModel/regionModel.C b/src/regionModels/regionModel/regionModel/regionModel.C
index c1446d7cafe3f6204400a9e6cad660635aecae2d..6ab4eb18db4f69d7907da433bf43cb0cc8602989 100644
--- a/src/regionModels/regionModel/regionModel/regionModel.C
+++ b/src/regionModels/regionModel/regionModel/regionModel.C
@@ -505,7 +505,8 @@ void Foam::regionModels::regionModel::evolve()
             (
                 IOstream::ASCII,
                 IOstream::currentVersion,
-                time_.writeCompression()
+                time_.writeCompression(),
+                true
             );
         }
     }
diff --git a/src/rigidBodyMeshMotion/rigidBodyMeshMotion/rigidBodyMeshMotion.C b/src/rigidBodyMeshMotion/rigidBodyMeshMotion/rigidBodyMeshMotion.C
index 5c08e42a74c55a10eebfe4c43da5041914695629..428ff83c0fb1f509bf780f62c7cc97650cdb7d71 100644
--- a/src/rigidBodyMeshMotion/rigidBodyMeshMotion/rigidBodyMeshMotion.C
+++ b/src/rigidBodyMeshMotion/rigidBodyMeshMotion/rigidBodyMeshMotion.C
@@ -338,7 +338,8 @@ bool Foam::rigidBodyMeshMotion::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     IOdictionary dict
diff --git a/src/rigidBodyMeshMotion/rigidBodyMeshMotion/rigidBodyMeshMotion.H b/src/rigidBodyMeshMotion/rigidBodyMeshMotion/rigidBodyMeshMotion.H
index af5df08f099ea1225e79e678dd371023094609a3..63820d5e8a025ffc56ab27ff0d3b4e0fb929a326 100644
--- a/src/rigidBodyMeshMotion/rigidBodyMeshMotion/rigidBodyMeshMotion.H
+++ b/src/rigidBodyMeshMotion/rigidBodyMeshMotion/rigidBodyMeshMotion.H
@@ -172,7 +172,8 @@ public:
         (
             IOstream::streamFormat fmt,
             IOstream::versionNumber ver,
-            IOstream::compressionType cmp
+            IOstream::compressionType cmp,
+            const bool valid
         ) const;
 
         //- Read dynamicMeshDict dictionary
diff --git a/src/rigidBodyMeshMotion/rigidBodyMeshMotionSolver/rigidBodyMeshMotionSolver.C b/src/rigidBodyMeshMotion/rigidBodyMeshMotionSolver/rigidBodyMeshMotionSolver.C
index dbe3eee194df215bcfdbb8745e52bcfa85d86e01..4746876226e56d110eb9eb989af719da053a0c2a 100644
--- a/src/rigidBodyMeshMotion/rigidBodyMeshMotionSolver/rigidBodyMeshMotionSolver.C
+++ b/src/rigidBodyMeshMotion/rigidBodyMeshMotionSolver/rigidBodyMeshMotionSolver.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2016-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -80,7 +80,7 @@ Foam::rigidBodyMeshMotionSolver::rigidBodyMeshMotionSolver
             mesh.time().timeName(),
             "uniform",
             mesh
-        ).typeHeaderOk<IOdictionary>(false)
+        ).typeHeaderOk<IOdictionary>(true)
       ? IOdictionary
         (
             IOobject
@@ -282,7 +282,8 @@ bool Foam::rigidBodyMeshMotionSolver::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     IOdictionary dict
diff --git a/src/rigidBodyMeshMotion/rigidBodyMeshMotionSolver/rigidBodyMeshMotionSolver.H b/src/rigidBodyMeshMotion/rigidBodyMeshMotionSolver/rigidBodyMeshMotionSolver.H
index 26dfb21899be8b1faa7187db64bda0074f4b3e0f..5d820cddf8e5537c2556a6cd1a26ec580ad85fae 100644
--- a/src/rigidBodyMeshMotion/rigidBodyMeshMotionSolver/rigidBodyMeshMotionSolver.H
+++ b/src/rigidBodyMeshMotion/rigidBodyMeshMotionSolver/rigidBodyMeshMotionSolver.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2016-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -159,7 +159,8 @@ public:
         (
             IOstream::streamFormat fmt,
             IOstream::versionNumber ver,
-            IOstream::compressionType cmp
+            IOstream::compressionType cmp,
+            const bool valid
         ) const;
 
         //- Read dynamicMeshDict dictionary
diff --git a/src/sampling/probes/probes.C b/src/sampling/probes/probes.C
index 0dd50907d7b4737531cd91cd9ed145c90d0aff9a..5ba634c1d443a690947b72c1e3d4c5b0b4012d5d 100644
--- a/src/sampling/probes/probes.C
+++ b/src/sampling/probes/probes.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2015-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -214,6 +214,8 @@ Foam::label Foam::probes::prepare()
         {
             probeDir = mesh_.time().path()/probeSubDir;
         }
+        // Remove ".."
+        probeDir.clean();
 
         // ignore known fields, close streams for fields that no longer exist
         forAllIter(HashPtrTable<OFstream>, probeFilePtrs_, iter)
diff --git a/src/sampling/sampledSet/sampledSets/sampledSets.C b/src/sampling/sampledSet/sampledSets/sampledSets.C
index 2115280372a92feb071317142001cfcb30bc166f..088c794728f779d1e7dee6d4b96cbf2ab6fda098 100644
--- a/src/sampling/sampledSet/sampledSets/sampledSets.C
+++ b/src/sampling/sampledSet/sampledSets/sampledSets.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -166,6 +166,8 @@ Foam::sampledSets::sampledSets
     {
         outputPath_ = outputPath_/mesh_.name();
     }
+    // Remove ".."
+    outputPath_.clean();
 
     read(dict);
 }
@@ -200,6 +202,8 @@ Foam::sampledSets::sampledSets
     {
         outputPath_ = outputPath_/mesh_.name();
     }
+    // Remove ".."
+    outputPath_.clean();
 
     read(dict);
 }
diff --git a/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.C b/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.C
index 5bb6cd0b5914f4c7adca4ff7469b09e3ee67a328..ddf3ebe114abe8f8beb4239a1301705d9dec9c4e 100644
--- a/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.C
+++ b/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
diff --git a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C
index 39568568524f490ea0922ba49771d3358b106d4d..1f881bd32125c96d26dda7cb6ba80db05bb6569c 100644
--- a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C
+++ b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -143,6 +143,8 @@ Foam::sampledSurfaces::sampledSurfaces
     {
         outputPath_ = mesh_.time().path()/"postProcessing"/name;
     }
+    // Remove ".."
+    outputPath_.clean();
 
     read(dict);
 }
@@ -176,6 +178,8 @@ Foam::sampledSurfaces::sampledSurfaces
     {
         outputPath_ = time_.path()/"postProcessing"/name;
     }
+    // Remove ".."
+    outputPath_.clean();
 
     read(dict);
 }
diff --git a/src/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionSolver/sixDoFRigidBodyMotionSolver.C b/src/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionSolver/sixDoFRigidBodyMotionSolver.C
index 3c0a2aa983fa0c25bfef4f91465a9ee7359703cb..cacc1c8a9c8a087975f3cb2a6de6554a88db68c1 100644
--- a/src/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionSolver/sixDoFRigidBodyMotionSolver.C
+++ b/src/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionSolver/sixDoFRigidBodyMotionSolver.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2013-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -256,7 +256,8 @@ bool Foam::sixDoFRigidBodyMotionSolver::writeObject
 (
     IOstream::streamFormat fmt,
     IOstream::versionNumber ver,
-    IOstream::compressionType cmp
+    IOstream::compressionType cmp,
+    const bool valid
 ) const
 {
     IOdictionary dict
diff --git a/src/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionSolver/sixDoFRigidBodyMotionSolver.H b/src/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionSolver/sixDoFRigidBodyMotionSolver.H
index 9204df198189c19b5c944be66fa7ad4f9fa6967b..c7ca01f29faee123cc680384443e697218241977 100644
--- a/src/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionSolver/sixDoFRigidBodyMotionSolver.H
+++ b/src/sixDoFRigidBodyMotion/sixDoFRigidBodyMotionSolver/sixDoFRigidBodyMotionSolver.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2013-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -138,7 +138,8 @@ public:
         (
             IOstream::streamFormat fmt,
             IOstream::versionNumber ver,
-            IOstream::compressionType cmp
+            IOstream::compressionType cmp,
+            const bool valid
         ) const;
 
         //- Read dynamicMeshDict dictionary
diff --git a/src/thermophysicalModels/radiation/radiationModels/radiationModel/radiationModelNew.C b/src/thermophysicalModels/radiation/radiationModels/radiationModel/radiationModelNew.C
index 21fc0f4f226c1b252bf4bccf03d9575711e8162e..5aec71b774f853a9ea875c8301bccfe6602a8131 100644
--- a/src/thermophysicalModels/radiation/radiationModels/radiationModel/radiationModelNew.C
+++ b/src/thermophysicalModels/radiation/radiationModels/radiationModel/radiationModelNew.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/thermophysicalModels/reactionThermo/mixtures/basicMultiComponentMixture/basicMultiComponentMixture.C b/src/thermophysicalModels/reactionThermo/mixtures/basicMultiComponentMixture/basicMultiComponentMixture.C
index 029af1b808f07fc1d478b07b7ab403b004d6c027..c21a75e636aa9afd219380678d10deb9ec7a9f86 100644
--- a/src/thermophysicalModels/reactionThermo/mixtures/basicMultiComponentMixture/basicMultiComponentMixture.C
+++ b/src/thermophysicalModels/reactionThermo/mixtures/basicMultiComponentMixture/basicMultiComponentMixture.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -89,32 +89,45 @@ Foam::basicMultiComponentMixture::basicMultiComponentMixture
             {
                 word YdefaultName(IOobject::groupName("Ydefault", phaseName));
 
-                tYdefault = new volScalarField
+                IOobject timeIO
                 (
-                    IOobject
-                    (
-                        YdefaultName,
-                        exists
-                        (
-                            mesh.time().path()/mesh.time().timeName()
-                           /YdefaultName
-                        )
-                      ? mesh.time().timeName()
-                      : (
-                            exists
-                            (
-                                mesh.time().path()/mesh.time().constant()
-                               /YdefaultName
-                            )
-                          ? mesh.time().constant()
-                          : Time::timeName(0)
-                        ),
-                        mesh,
-                        IOobject::MUST_READ,
-                        IOobject::NO_WRITE
-                    ),
-                    mesh
+                    YdefaultName,
+                    mesh.time().timeName(),
+                    mesh,
+                    IOobject::MUST_READ,
+                    IOobject::NO_WRITE
                 );
+
+                IOobject constantIO
+                (
+                    YdefaultName,
+                    mesh.time().constant(),
+                    mesh,
+                    IOobject::MUST_READ,
+                    IOobject::NO_WRITE
+                );
+
+                IOobject time0IO
+                (
+                    YdefaultName,
+                    Time::timeName(0),
+                    mesh,
+                    IOobject::MUST_READ,
+                    IOobject::NO_WRITE
+                );
+
+                if (timeIO.typeHeaderOk<volScalarField>(true))
+                {
+                    tYdefault = new volScalarField(timeIO, mesh);
+                }
+                else if (constantIO.typeHeaderOk<volScalarField>(true))
+                {
+                    tYdefault = new volScalarField(constantIO, mesh);
+                }
+                else
+                {
+                    tYdefault = new volScalarField(time0IO, mesh);
+                }
             }
 
             Y_.set
diff --git a/src/thermophysicalModels/solidChemistryModel/pyrolysisChemistryModel/pyrolysisChemistryModel.C b/src/thermophysicalModels/solidChemistryModel/pyrolysisChemistryModel/pyrolysisChemistryModel.C
index 12fd3462b48a968cb8c001b83619083f547c1822..7f18977b716abe01fda604a51e23dfd9907ef5f4 100644
--- a/src/thermophysicalModels/solidChemistryModel/pyrolysisChemistryModel/pyrolysisChemistryModel.C
+++ b/src/thermophysicalModels/solidChemistryModel/pyrolysisChemistryModel/pyrolysisChemistryModel.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2013-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2017 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/tutorials/IO/fileHandler/0/U b/tutorials/IO/fileHandler/0/U
new file mode 100644
index 0000000000000000000000000000000000000000..75ed42fbdb44afad496e78afbf6667413c48fba6
--- /dev/null
+++ b/tutorials/IO/fileHandler/0/U
@@ -0,0 +1,38 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      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
+{
+    outlet
+    {
+        type            zeroGradient;
+        value           uniform (0 0 0);
+    }
+    walls
+    {
+        type            noSlip;
+    }
+    frontAndBack
+    {
+        type            noSlip;
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/IO/fileHandler/Allrun b/tutorials/IO/fileHandler/Allrun
new file mode 100755
index 0000000000000000000000000000000000000000..d032798abbd2aa188c17a8c24176fa361bded855
--- /dev/null
+++ b/tutorials/IO/fileHandler/Allrun
@@ -0,0 +1,28 @@
+#!/bin/sh
+cd ${0%/*} || exit 1    # Run from this directory
+
+# Source tutorial run functions
+. $WM_PROJECT_DIR/bin/tools/RunFunctions
+
+runApplication blockMesh
+
+#- Test writing collated format
+runApplication decomposePar -fileHandler collated
+runParallel `getApplication` -fileHandler collated
+runApplication reconstructPar -latestTime -fileHandler collated
+
+#- Delete collated files
+rm -rf processors
+
+#- Test writing uncollated format
+runApplication -s uncollated decomposePar -fileHandler uncollated
+runParallel -s uncollated `getApplication` -fileHandler uncollated
+
+#- Restart from uncollated
+runParallel -s collated `getApplication` -fileHandler collated
+runApplication -s collated reconstructPar -latestTime -fileHandler collated
+
+#- Convert the parallel format to uncollated
+runParallel foamFormatConvert -fileHandler uncollated
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/IO/fileHandler/constant/g b/tutorials/IO/fileHandler/constant/g
new file mode 100644
index 0000000000000000000000000000000000000000..0cc222ca3457ed24bf9753d0926fbee84359e624
--- /dev/null
+++ b/tutorials/IO/fileHandler/constant/g
@@ -0,0 +1,22 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       uniformDimensionedVectorField;
+    location    "constant";
+    object      g;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 -2 0 0 0 0];
+value           (0 -9.81 0);
+
+
+// ************************************************************************* //
diff --git a/tutorials/IO/fileHandler/constant/kinematicCloudPositions b/tutorials/IO/fileHandler/constant/kinematicCloudPositions
new file mode 100644
index 0000000000000000000000000000000000000000..1e2be4ebc84a21e14d489a9feba3dd9b048060d1
--- /dev/null
+++ b/tutorials/IO/fileHandler/constant/kinematicCloudPositions
@@ -0,0 +1,92 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       vectorField;
+    object      kinematicCloudPositions;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
+(
+(0.286 0.077 0.0032)
+(0.286 0.083 0.0032)
+(0.286 0.089 0.0032)
+(0.286 0.095 0.0032)
+(0.286 0.101 0.0032)
+(0.286 0.107 0.0032)
+(0.286 0.113 0.0032)
+(0.286 0.119 0.0032)
+(0.286 0.125 0.0032)
+(0.286 0.131 0.0032)
+(0.286 0.137 0.0032)
+(0.286 0.143 0.0032)
+(0.286 0.149 0.0032)
+(0.286 0.155 0.0032)
+(0.286 0.161 0.0032)
+(0.286 0.167 0.0032)
+(0.286 0.173 0.0032)
+(0.286 0.179 0.0032)
+(0.286 0.185 0.0032)
+(0.286 0.191 0.0032)
+(0.286 0.197 0.0032)
+(0.286 0.203 0.0032)
+(0.286 0.209 0.0032)
+(0.286 0.215 0.0032)
+(0.286 0.221 0.0032)
+(0.286 0.227 0.0032)
+(0.286 0.233 0.0032)
+(0.286 0.239 0.0032)
+(0.286 0.245 0.0032)
+(0.286 0.251 0.0032)
+(0.286 0.257 0.0032)
+(0.286 0.263 0.0032)
+(0.286 0.269 0.0032)
+(0.286 0.275 0.0032)
+(0.286 0.281 0.0032)
+(0.286 0.287 0.0032)
+(0.286 0.293 0.0032)
+(0.286 0.299 0.0032)
+(0.286 0.305 0.0032)
+(0.286 0.311 0.0032)
+(0.286 0.317 0.0032)
+(0.286 0.323 0.0032)
+(0.286 0.329 0.0032)
+(0.286 0.335 0.0032)
+(0.286 0.341 0.0032)
+(0.286 0.347 0.0032)
+(0.286 0.353 0.0032)
+(0.286 0.359 0.0032)
+(0.286 0.365 0.0032)
+(0.286 0.371 0.0032)
+(0.286 0.377 0.0032)
+(0.286 0.383 0.0032)
+(0.286 0.389 0.0032)
+(0.286 0.395 0.0032)
+(0.286 0.401 0.0032)
+(0.286 0.407 0.0032)
+(0.286 0.413 0.0032)
+(0.286 0.419 0.0032)
+(0.286 0.425 0.0032)
+(0.286 0.431 0.0032)
+(0.286 0.437 0.0032)
+(0.286 0.443 0.0032)
+(0.286 0.449 0.0032)
+(0.286 0.455 0.0032)
+(0.286 0.461 0.0032)
+(0.286 0.467 0.0032)
+(0.286 0.473 0.0032)
+(0.286 0.479 0.0032)
+(0.286 0.485 0.0032)
+(0.286 0.491 0.0032)
+(0.286 0.497 0.0032)
+)
+
+// ************************************************************************* //
diff --git a/tutorials/IO/fileHandler/constant/kinematicCloudProperties b/tutorials/IO/fileHandler/constant/kinematicCloudProperties
new file mode 100644
index 0000000000000000000000000000000000000000..41b8c64e80dc955344145935f27a2e3d8625b230
--- /dev/null
+++ b/tutorials/IO/fileHandler/constant/kinematicCloudProperties
@@ -0,0 +1,138 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      kinematicCloudProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solution
+{
+    active          true;
+    coupled         false;
+    transient       yes;
+    cellValueSourceCorrection off;
+    maxCo           0.3;
+
+    interpolationSchemes
+    {
+        rho             cell;
+        U               cellPoint;
+        mu              cell;
+    }
+
+    integrationSchemes
+    {
+        U               Euler;
+    }
+}
+
+constantProperties
+{
+    rho0            964;
+    youngsModulus   6e8;
+    poissonsRatio   0.35;
+}
+
+subModels
+{
+    particleForces
+    {
+        sphereDrag;
+        gravity;
+    }
+
+    injectionModels
+    {
+        model1
+        {
+            type            manualInjection;
+            massTotal       0;
+            parcelBasisType fixed;
+            nParticle       1;
+            SOI             0;
+            positionsFile   "kinematicCloudPositions";
+            U0              (0 0 0);
+            sizeDistribution
+            {
+                type        fixedValue;
+                fixedValueDistribution
+                {
+                    value   0.006;
+                }
+            }
+        }
+    }
+
+    dispersionModel none;
+
+    patchInteractionModel none;
+
+    surfaceFilmModel none;
+
+    stochasticCollisionModel none;
+
+    collisionModel pairCollision;
+
+    pairCollisionCoeffs
+    {
+        // Maximum possible particle diameter expected at any time
+        maxInteractionDistance  0.006;
+
+        writeReferredParticleCloud no;
+
+        pairModel pairSpringSliderDashpot;
+
+        pairSpringSliderDashpotCoeffs
+        {
+            useEquivalentSize   no;
+            alpha               0.12;
+            b                   1.5;
+            mu                  0.52;
+            cohesionEnergyDensity 0;
+            collisionResolutionSteps 12;
+        };
+
+        wallModel    wallLocalSpringSliderDashpot;
+
+        wallLocalSpringSliderDashpotCoeffs
+        {
+            useEquivalentSize no;
+            collisionResolutionSteps 12;
+            walls
+            {
+                youngsModulus   1e10;
+                poissonsRatio   0.23;
+                alpha           0.12;
+                b               1.5;
+                mu              0.43;
+                cohesionEnergyDensity 0;
+            }
+            frontAndBack
+            {
+                youngsModulus   1e10;
+                poissonsRatio   0.23;
+                alpha           0.12;
+                b               1.5;
+                mu              0.1;
+                cohesionEnergyDensity 0;
+            }
+        };
+    }
+}
+
+
+cloudFunctions
+{}
+
+
+// ************************************************************************* //
diff --git a/tutorials/IO/fileHandler/constant/transportProperties b/tutorials/IO/fileHandler/constant/transportProperties
new file mode 100644
index 0000000000000000000000000000000000000000..dbbab9e9f0a37e238aae89ea3025bf9c5f8948fa
--- /dev/null
+++ b/tutorials/IO/fileHandler/constant/transportProperties
@@ -0,0 +1,24 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      transportProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+rhoInf          [1 -3 0 0 0 0 0] 1.2;
+
+transportModel  Newtonian;
+
+nu              [0 2 -1 0 0 0 0] 1e-05;
+
+// ************************************************************************* //
diff --git a/tutorials/IO/fileHandler/constant/turbulenceProperties b/tutorials/IO/fileHandler/constant/turbulenceProperties
new file mode 100644
index 0000000000000000000000000000000000000000..c2c3b28a1b4e8f4a2cae55f58bd61f9b1a67b488
--- /dev/null
+++ b/tutorials/IO/fileHandler/constant/turbulenceProperties
@@ -0,0 +1,21 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      turbulenceProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+simulationType  laminar;
+
+
+// ************************************************************************* //
diff --git a/tutorials/IO/fileHandler/system/blockMeshDict b/tutorials/IO/fileHandler/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..359a48779aa64f4ab175ee53bf963ae6bd891e7f
--- /dev/null
+++ b/tutorials/IO/fileHandler/system/blockMeshDict
@@ -0,0 +1,72 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+convertToMeters 0.001;
+
+vertices
+(
+    (0 77.9423 6.2)
+    (135 0 6.2)
+    (165 0 6.2)
+    (300 77.9423 6.2)
+    (300 500 6.2)
+    (0 500 6.2)
+    (0 77.9423 0)
+    (135 0 0)
+    (165 0 0)
+    (300 77.9423 0)
+    (300 500 0)
+    (0 500 0)
+);
+
+
+blocks
+(
+    hex (6 9 10 11 0 3 4 5 ) (20 40 1) simpleGrading (1 1 1)
+    hex (7 8 9 6 1 2 3 0) (20 8 1) simpleGrading (1 1 1)
+);
+
+boundary
+(
+    walls
+    {
+        type wall;
+        faces
+        (
+            (1 7 8 2)
+            (0 6 7 1)
+            (2 8 9 3)
+            (0 5 11 6)
+            (3 4 10 9)
+            (4 10 11 5)
+        );
+    }
+
+    frontAndBack
+    {
+        type wall;
+        faces
+        (
+            (0 3 4 5)
+            (1 2 3 0)
+            (6 11 10 9)
+            (6 9 8 7)
+        );
+    }
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/IO/fileHandler/system/controlDict b/tutorials/IO/fileHandler/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..2ac8dc578761cff7aac28a19995a59970091e00b
--- /dev/null
+++ b/tutorials/IO/fileHandler/system/controlDict
@@ -0,0 +1,53 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+application     icoUncoupledKinematicParcelFoam;
+
+startFrom       latestTime;
+
+startTime       0;
+
+stopAt          writeNow;
+
+endTime         0.25;
+
+deltaT          5e-5;
+
+writeControl    runTime;
+
+writeInterval   0.05;
+
+purgeWrite      0;
+
+writeFormat     binary;
+
+writePrecision  6;
+
+writeCompression uncompressed;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable yes;
+
+// OptimisationSwitches
+// {
+//     fileHandler collated;
+// }
+
+// ************************************************************************* //
diff --git a/tutorials/IO/fileHandler/system/decomposeParDict b/tutorials/IO/fileHandler/system/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..0f07bb6aa8ba3f26536b73674eecd5e523fc6953
--- /dev/null
+++ b/tutorials/IO/fileHandler/system/decomposeParDict
@@ -0,0 +1,45 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+numberOfSubdomains 4;
+
+method          simple;
+
+simpleCoeffs
+{
+    n               (4 1 1);
+    delta           0.001;
+}
+
+hierarchicalCoeffs
+{
+    n               (4 1 1);
+    delta           0.001;
+    order           xyz;
+}
+
+manualCoeffs
+{
+    dataFile        "";
+}
+
+distributed     no;
+
+roots           ( );
+
+
+// ************************************************************************* //
diff --git a/tutorials/IO/fileHandler/system/fvSchemes b/tutorials/IO/fileHandler/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..12c112d4e08c5b98258dc62f526d3b9df7739cb5
--- /dev/null
+++ b/tutorials/IO/fileHandler/system/fvSchemes
@@ -0,0 +1,43 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default         none;
+}
+
+gradSchemes
+{
+    default         none;
+}
+
+divSchemes
+{
+    default         none;
+}
+
+laplacianSchemes
+{
+    default         none;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/IO/fileHandler/system/fvSolution b/tutorials/IO/fileHandler/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..740eb61a4bcb97e64ae0b33558f5c7057e7a6d20
--- /dev/null
+++ b/tutorials/IO/fileHandler/system/fvSolution
@@ -0,0 +1,22 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+}
+
+// ************************************************************************* //
diff --git a/tutorials/heatTransfer/buoyantBoussinesqPimpleFoam/BernardCells/system/blockMeshDict b/tutorials/heatTransfer/buoyantBoussinesqPimpleFoam/BernardCells/system/blockMeshDict
index 1f58ded07ef8ec4d82c3573efac69b840e3d2fe0..5c8a9d3f92fe5446fb47e2e6e9fc363c3bbb4edd 100644
--- a/tutorials/heatTransfer/buoyantBoussinesqPimpleFoam/BernardCells/system/blockMeshDict
+++ b/tutorials/heatTransfer/buoyantBoussinesqPimpleFoam/BernardCells/system/blockMeshDict
@@ -72,11 +72,10 @@ boundary
         type empty;
         faces
         (
-	    (0 3 2 1)
-	    (4 5 6 7)
+            (0 3 2 1)
+            (4 5 6 7)
         );
     }
-
 );
 
 mergePatchPairs
diff --git a/tutorials/heatTransfer/buoyantBoussinesqSimpleFoam/iglooWithFridges/Allrun b/tutorials/heatTransfer/buoyantBoussinesqSimpleFoam/iglooWithFridges/Allrun
index 29414545d79957f2a52f3a2701b069cbef51a4a5..ca4be116d7c1a5e2f696d2f833e87347c1278983 100755
--- a/tutorials/heatTransfer/buoyantBoussinesqSimpleFoam/iglooWithFridges/Allrun
+++ b/tutorials/heatTransfer/buoyantBoussinesqSimpleFoam/iglooWithFridges/Allrun
@@ -5,7 +5,23 @@ cd ${0%/*} || exit 1    # Run from this directory
 . $WM_PROJECT_DIR/bin/tools/RunFunctions
 
 runApplication blockMesh
+
+# Serial
 runApplication snappyHexMesh -overwrite
 runApplication $(getApplication)
 
+## Parallel
+#runApplication decomposePar -fileHandler collated
+#runParallel snappyHexMesh -overwrite -fileHandler collated
+## Remove any include files from the field dictionaries
+#(   mkdir -p processors/0 && \
+#    cd 0 && \
+#    for f in *; do [ -f "$f" ] && \
+#    foamDictionary "$f" > "../processors/0/$f"; done \
+#)
+#
+#runParallel `getApplication` -fileHandler collated
+#runApplication reconstructParMesh -constant  -mergeTol 1e-6
+#runApplication reconstructPar
+
 #------------------------------------------------------------------------------