From d8d6030ab688b7d6abae158608ace0c35c3a5485 Mon Sep 17 00:00:00 2001
From: Andrew Heather <a.heather@opencfd.co.uk>
Date: Fri, 7 Jul 2017 11:39:56 +0100
Subject: [PATCH] INT: Integration of Mattijs' collocated parallel IO additions

Original commit message:
------------------------

Parallel IO: New collated file format

When an OpenFOAM simulation runs in parallel, the data for decomposed fields and
mesh(es) has historically been stored in multiple files within separate
directories for each processor.  Processor directories are named 'processorN',
where N is the processor number.

This commit introduces an alternative "collated" file format where the data for
each decomposed field (and mesh) is collated into a single file, which is
written and read on the master processor.  The files are stored in a single
directory named 'processors'.

The new format produces significantly fewer files - one per field, instead of N
per field.  For large parallel cases, this avoids the restriction on the number
of open files imposed by the operating system limits.

The file writing can be threaded allowing the simulation to continue running
while the data is being written to file.  NFS (Network File System) is not
needed when using the the collated format and additionally, there is an option
to run without NFS with the original uncollated approach, known as
"masterUncollated".

The controls for the file handling are in the OptimisationSwitches of
etc/controlDict:

OptimisationSwitches
{
    ...

    //- 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;
}

When using the collated file handling, memory is allocated for the data in the
thread.  maxThreadFileBufferSize sets the maximum size of memory in bytes that
is allocated.  If the data exceeds this size, the write does not use threading.

When using the masterUncollated file handling, non-blocking MPI communication
requires a sufficiently large memory buffer on the master node.
maxMasterFileBufferSize sets the maximum size in bytes of the buffer.  If the
data exceeds this size, the system uses scheduled communication.

The installation defaults for the fileHandler choice, maxThreadFileBufferSize
and maxMasterFileBufferSize (set in etc/controlDict) can be over-ridden within
the case controlDict file, like other parameters.  Additionally the fileHandler
can be set by:
- the "-fileHandler" command line argument;
- a FOAM_FILEHANDLER environment variable.

A foamFormatConvert utility allows users to convert files between the collated
and uncollated formats, e.g.
    mpirun -np 2 foamFormatConvert -parallel -fileHandler uncollated

An example case demonstrating the file handling methods is provided in:
$FOAM_TUTORIALS/IO/fileHandling

The work was undertaken by Mattijs Janssens, in collaboration with Henry Weller.
---
 .../electromagnetics/mhdFoam/createPhiB.H     |    2 +-
 .../heatTransfer/thermoFoam/setAlphaEff.H     |    2 +-
 .../test/CompactIOList/Test-CompactIOList.C   |    8 +-
 applications/test/IOField/Make/files          |    3 +
 applications/test/IOField/Make/options        |    2 +
 applications/test/IOField/Test-IOField.C      |  189 ++
 .../test/decomposedBlockData/Make/files       |    3 +
 .../test/decomposedBlockData/Make/options     |    0
 .../Test-decomposedBlockData.C                |   98 +
 .../Test-surfaceMeshConvert.C                 |    6 +-
 .../mesh/advanced/modifyMesh/modifyMesh.C     |    3 +-
 .../mesh/advanced/selectCells/edgeStats.C     |   15 +-
 .../foamToStarMesh/foamToStarMesh.C           |    4 +-
 .../conversion/foamToSurface/foamToSurface.C  |    2 +-
 .../DelaunayMesh/DelaunayMeshIO.C             |    6 +-
 .../generation/snappyHexMesh/snappyHexMesh.C  |    1 +
 .../mesh/manipulation/checkMesh/checkMesh.C   |    3 +-
 .../mesh/manipulation/checkMesh/checkTools.C  |    9 +-
 .../manipulation/createPatch/createPatch.C    |    1 +
 .../mesh/manipulation/refineMesh/refineMesh.C |    3 +-
 .../mesh/manipulation/setSet/setSet.C         |    8 +-
 .../mesh/manipulation/stitchMesh/stitchMesh.C |    5 +-
 .../mesh/manipulation/topoSet/topoSet.C       |    9 +-
 .../foamFormatConvert/foamFormatConvert.C     |  289 ++-
 .../foamFormatConvert/writeMeshObject.H       |   14 +-
 .../decomposePar/decomposePar.C               |  104 +-
 .../decomposePar/domainDecomposition.C        |    3 -
 ...lagrangianFieldDecomposerDecomposeFields.C |   12 +-
 .../reconstructPar/reconstructPar.C           |  117 +-
 .../reconstructParMesh/reconstructParMesh.C   |   35 +-
 .../redistributePar/loadOrCreateMesh.C        |    9 +-
 .../foamToEnsight/checkMeshMoving.H           |    2 +-
 .../foamToEnsightParts/getTimeIndex.H         |    2 +-
 .../utilities/postProcessing/noise/noise.C    |    3 +-
 .../changeDictionary/changeDictionary.C       |  399 ++--
 .../mapFields/MapConsistentVolFields.H        |    6 +-
 .../preProcessing/mapFields/MapVolFields.H    |   15 +-
 .../surface/surfaceHookUp/surfaceHookUp.C     |    3 +-
 .../surfaceMeshTriangulate.C                  |    1 +
 .../equilibriumCO/equilibriumCO.C             |    1 +
 etc/controlDict                               |   14 +
 src/OSspecific/POSIX/POSIX.C                  |  300 ++-
 src/OSspecific/POSIX/regExp.H                 |    2 +-
 src/OpenFOAM/Make/files                       |   14 +-
 src/OpenFOAM/db/IOobject/IOobject.C           |  187 +-
 src/OpenFOAM/db/IOobject/IOobject.H           |   33 +-
 src/OpenFOAM/db/IOobject/IOobjectTemplates.C  |   56 +-
 .../db/IOobject/IOobjectWriteHeader.C         |    4 +-
 src/OpenFOAM/db/IOobjectList/IOobjectList.C   |   27 +-
 .../IOobjects/CompactIOField/CompactIOField.C |   75 +-
 .../IOobjects/CompactIOField/CompactIOField.H |   10 +-
 .../IOobjects/CompactIOList/CompactIOList.C   |   28 +-
 .../IOobjects/CompactIOList/CompactIOList.H   |    5 +-
 .../IOobjects/GlobalIOField/GlobalIOField.H   |    4 +-
 .../IOobjects/GlobalIOField/GlobalIOFields.C} |   41 +-
 .../db/IOobjects/GlobalIOList/GlobalIOList.H  |    4 +-
 .../db/IOobjects/GlobalIOList/globalIOLists.C |    1 +
 .../db/IOobjects/GlobalIOList/globalIOLists.H |    9 +-
 src/OpenFOAM/db/IOobjects/IOField/IOField.C   |   39 +-
 src/OpenFOAM/db/IOobjects/IOField/IOField.H   |    5 +-
 src/OpenFOAM/db/IOobjects/IOMap/IOMap.C       |    2 +-
 src/OpenFOAM/db/IOobjects/IOMap/IOMap.H       |    4 +-
 src/OpenFOAM/db/IOobjects/IOMap/IOMapName.C   |   10 +-
 .../db/IOobjects/IOPtrList/IOPtrList.C        |    2 +-
 .../db/IOobjects/IOdictionary/IOdictionary.C  |    2 +-
 .../db/IOobjects/IOdictionary/IOdictionary.H  |    5 +-
 .../IOobjects/IOdictionary/baseIOdictionary.H |    8 +-
 .../IOdictionary/localIOdictionary.C          |   17 +-
 .../IOdictionary/localIOdictionary.H          |   10 +-
 .../IOdictionary/unwatchedIOdictionary.H      |    4 +-
 .../decomposedBlockData/decomposedBlockData.C |  921 +++++++++
 .../decomposedBlockData/decomposedBlockData.H |  197 ++
 src/OpenFOAM/db/IOstreams/Fstreams/OFstream.C |   53 +-
 src/OpenFOAM/db/IOstreams/Fstreams/OFstream.H |    8 +-
 .../db/IOstreams/Fstreams/masterOFstream.C    |  168 ++
 .../db/IOstreams/Fstreams/masterOFstream.H    |  100 +
 .../IOstreams/dummyISstream/dummyISstream.H   |  160 ++
 .../db/IOstreams/dummyIstream/dummyIstream.H  |  161 ++
 src/OpenFOAM/db/Time/Time.C                   |  131 +-
 src/OpenFOAM/db/Time/Time.H                   |   52 +-
 src/OpenFOAM/db/Time/TimeIO.C                 |   56 +-
 src/OpenFOAM/db/Time/findInstance.C           |  147 +-
 src/OpenFOAM/db/Time/findTimes.C              |   60 +-
 src/OpenFOAM/db/Time/instant/instant.C        |   14 +-
 src/OpenFOAM/db/Time/instant/instant.H        |    6 +-
 src/OpenFOAM/db/Time/timeSelector.C           |    7 +-
 src/OpenFOAM/db/dictionary/dictionaryIO.C     |    3 +-
 .../functionEntries/codeStream/codeStream.C   |    2 +-
 .../functionEntries/codeStream/codeStream.H   |    2 +-
 .../includeEntry/includeEntry.C               |   15 +-
 .../includeEtcEntry/includeEtcEntry.C         |   15 +-
 .../includeIfPresentEntry.C                   |    9 +-
 .../dlLibraryTable/dlLibraryTable.C           |    8 +-
 .../functionObjectList/functionObjectList.C   |   14 +-
 .../db/functionObjects/writeFile/writeFile.C  |    5 +-
 .../db/objectRegistry/objectRegistry.C        |    7 +-
 .../db/objectRegistry/objectRegistry.H        |  355 ++--
 src/OpenFOAM/db/regIOobject/regIOobject.C     |   80 +-
 src/OpenFOAM/db/regIOobject/regIOobject.H     |   33 +-
 src/OpenFOAM/db/regIOobject/regIOobjectRead.C |  191 +-
 .../db/regIOobject/regIOobjectWrite.C         |   67 +-
 .../GeometricField/GeometricField.C           |    8 +-
 .../UniformDimensionedField.H                 |    4 +-
 ...eVaryingUniformFixedValuePointPatchField.C |    3 +-
 src/OpenFOAM/global/argList/argList.C         |   60 +-
 .../collatedFileOperation/OFstreamCollator.C  |  335 +++
 .../collatedFileOperation/OFstreamCollator.H  |  167 ++
 .../collatedFileOperation.C                   |  415 ++++
 .../collatedFileOperation.H                   |  138 ++
 .../threadedCollatedOFstream.C                |   65 +
 .../threadedCollatedOFstream.H                |   92 +
 .../fileOperation/fileOperation.C             |  666 ++++++
 .../fileOperation/fileOperation.H             |  431 ++++
 .../masterUncollatedFileOperation.C           | 1804 +++++++++++++++++
 .../masterUncollatedFileOperation.H           |  716 +++++++
 .../masterUncollatedFileOperationTemplates.C  |  148 ++
 .../uncollatedFileOperation.C                 |  673 ++++++
 .../uncollatedFileOperation.H                 |  283 +++
 src/OpenFOAM/include/OSspecific.H             |   31 +-
 .../interpolation2DTable.C                    |    2 +-
 .../interpolationTable/interpolationTable.C   |    1 -
 .../tableReaders/csv/csvTableReader.C         |    8 +-
 .../openFoam/openFoamTableReader.C            |    8 +-
 .../uniformInterpolationTable.C               |    3 +-
 .../polyBoundaryMesh/polyBoundaryMesh.C       |    5 +-
 .../polyBoundaryMesh/polyBoundaryMesh.H       |    5 +-
 src/OpenFOAM/meshes/polyMesh/polyMesh.C       |    2 +-
 src/OpenFOAM/meshes/polyMesh/polyMeshIO.C     |    2 +-
 .../preservePatchTypes/preservePatchTypes.C   |    2 +-
 .../primitives/functions/Function1/CSV/CSV.C  |    6 +-
 .../functions/Function1/TableFile/TableFile.C |    4 +-
 .../primitives/strings/fileName/fileName.C    |    7 +-
 .../primitives/strings/fileName/fileName.H    |    2 +-
 .../primitives/strings/string/string.H        |    3 +
 .../primitives/strings/string/stringI.H       |    6 +
 src/Pstream/mpi/UPstream.C                    |   19 +-
 src/conversion/common/reader/meshReader.C     |    3 +-
 src/conversion/common/reader/meshReaderAux.C  |    5 +-
 .../dynamicRefineFvMesh/dynamicRefineFvMesh.C |    7 +-
 .../dynamicRefineFvMesh/dynamicRefineFvMesh.H |    5 +-
 .../componentDisplacementMotionSolver.C       |    2 +-
 .../points0/points0MotionSolver.C             |    2 +-
 .../motionSolvers/motionSolver/motionSolver.C |    3 +-
 .../motionSolvers/motionSolver/motionSolver.H |    5 +-
 .../polyTopoChange/hexRef8/hexRef8.C          |   10 +-
 .../polyTopoChange/hexRef8/hexRef8.H          |    4 +-
 .../polyTopoChange/hexRef8/hexRef8Data.C      |    2 +-
 src/engine/engineTime/engineTime.H            |    4 +-
 .../cfdTools/general/MRF/IOMRFZoneList.C      |    2 +-
 .../cfdTools/general/fvOptions/fvOptions.C    |    2 +-
 src/finiteVolume/fvMesh/fvMesh.C              |   17 +-
 src/finiteVolume/fvMesh/fvMesh.H              |    7 +-
 .../fieldCoordinateSystemTransformTemplates.C |    8 +-
 .../field/readFields/readFieldsTemplates.C    |    6 +-
 .../field/streamLine/streamLineParticle.C     |   21 +-
 .../writeDictionary/writeDictionary.C         |    5 +-
 .../displacementLaplacianFvMotionSolver.C     |    2 +-
 .../Templates/DSMCParcel/DSMCParcelIO.C       |   25 +-
 src/lagrangian/basic/Cloud/Cloud.H            |    3 +-
 src/lagrangian/basic/Cloud/CloudIO.C          |   41 +-
 src/lagrangian/basic/IOPosition/IOPosition.C  |   26 +-
 src/lagrangian/basic/IOPosition/IOPosition.H  |    6 +-
 .../basic/particle/particleTemplates.C        |   46 +-
 .../Templates/KinematicCloud/KinematicCloud.C |    3 +-
 .../Templates/ReactingCloud/ReactingCloud.C   |    2 +-
 .../ReactingMultiphaseCloud.C                 |    2 +-
 .../CollidingParcel/CollidingParcelIO.C       |   65 +-
 .../KinematicParcel/KinematicParcelIO.C       |   90 +-
 .../Templates/MPPICParcel/MPPICParcelIO.C     |   15 +-
 .../ReactingMultiphaseParcelIO.C              |   28 +-
 .../ReactingParcel/ReactingParcelIO.C         |   26 +-
 .../Templates/ThermoParcel/ThermoParcelIO.C   |   15 +-
 .../CloudFunctionObject/CloudFunctionObject.C |    1 +
 .../AveragingMethod/AveragingMethod.C         |   10 +-
 .../AveragingMethod/AveragingMethod.H         |    2 +-
 .../molecule/molecule/moleculeIO.C            |   60 +-
 .../pairPotentialList/pairPotentialList.C     |   28 +-
 .../solidParticle/solidParticleIO.C           |   15 +-
 .../Templates/SprayParcel/SprayParcelIO.C     |  102 +-
 .../extendedFeatureEdgeMesh.H                 |    3 +-
 .../featureEdgeMesh/featureEdgeMesh.H         |    2 +-
 .../triSurfaceMesh/triSurfaceMesh.C           |   14 +-
 .../triSurfaceMesh/triSurfaceMesh.H           |    5 +-
 .../cellSources/fieldToCell/fieldToCell.C     |    2 +-
 src/meshTools/sets/topoSets/cellZoneSet.C     |    9 +-
 src/meshTools/sets/topoSets/cellZoneSet.H     |    5 +-
 src/meshTools/sets/topoSets/faceZoneSet.C     |    9 +-
 src/meshTools/sets/topoSets/faceZoneSet.H     |    5 +-
 src/meshTools/sets/topoSets/pointZoneSet.C    |    9 +-
 src/meshTools/sets/topoSets/pointZoneSet.H    |    5 +-
 .../distributedTriSurfaceMesh.C               |    5 +-
 .../distributedTriSurfaceMesh.H               |   25 +-
 .../reconstruct/reconstructLagrangianFields.C |    2 +-
 .../regionModel/regionModel/regionModel.C     |    3 +-
 .../rigidBodyMeshMotion/rigidBodyMeshMotion.C |    3 +-
 .../rigidBodyMeshMotion/rigidBodyMeshMotion.H |    3 +-
 .../rigidBodyMeshMotionSolver.C               |    7 +-
 .../rigidBodyMeshMotionSolver.H               |    5 +-
 src/sampling/probes/probes.C                  |    4 +-
 .../sampledSet/sampledSets/sampledSets.C      |    6 +-
 .../isoSurface/sampledIsoSurface.C            |    2 +-
 .../sampledSurfaces/sampledSurfaces.C         |    6 +-
 .../sixDoFRigidBodyMotionSolver.C             |    5 +-
 .../sixDoFRigidBodyMotionSolver.H             |    5 +-
 .../radiationModel/radiationModelNew.C        |    2 +-
 .../basicMultiComponentMixture.C              |   63 +-
 .../pyrolysisChemistryModel.C                 |    2 +-
 tutorials/IO/fileHandler/0/U                  |   38 +
 tutorials/IO/fileHandler/Allrun               |   28 +
 tutorials/IO/fileHandler/constant/g           |   22 +
 .../constant/kinematicCloudPositions          |   92 +
 .../constant/kinematicCloudProperties         |  138 ++
 .../fileHandler/constant/transportProperties  |   24 +
 .../fileHandler/constant/turbulenceProperties |   21 +
 tutorials/IO/fileHandler/system/blockMeshDict |   72 +
 tutorials/IO/fileHandler/system/controlDict   |   53 +
 .../IO/fileHandler/system/decomposeParDict    |   45 +
 tutorials/IO/fileHandler/system/fvSchemes     |   43 +
 tutorials/IO/fileHandler/system/fvSolution    |   22 +
 .../BernardCells/system/blockMeshDict         |    5 +-
 .../iglooWithFridges/Allrun                   |   16 +
 221 files changed, 11115 insertions(+), 1943 deletions(-)
 create mode 100644 applications/test/IOField/Make/files
 create mode 100644 applications/test/IOField/Make/options
 create mode 100644 applications/test/IOField/Test-IOField.C
 create mode 100644 applications/test/decomposedBlockData/Make/files
 create mode 100644 applications/test/decomposedBlockData/Make/options
 create mode 100644 applications/test/decomposedBlockData/Test-decomposedBlockData.C
 rename src/OpenFOAM/{fields/Fields/globalFields/globalIOFields.C => db/IOobjects/GlobalIOField/GlobalIOFields.C} (64%)
 create mode 100644 src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.C
 create mode 100644 src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.H
 create mode 100644 src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.C
 create mode 100644 src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.H
 create mode 100644 src/OpenFOAM/db/IOstreams/dummyISstream/dummyISstream.H
 create mode 100644 src/OpenFOAM/db/IOstreams/dummyIstream/dummyIstream.H
 create mode 100644 src/OpenFOAM/global/fileOperations/collatedFileOperation/OFstreamCollator.C
 create mode 100644 src/OpenFOAM/global/fileOperations/collatedFileOperation/OFstreamCollator.H
 create mode 100644 src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C
 create mode 100644 src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H
 create mode 100644 src/OpenFOAM/global/fileOperations/collatedFileOperation/threadedCollatedOFstream.C
 create mode 100644 src/OpenFOAM/global/fileOperations/collatedFileOperation/threadedCollatedOFstream.H
 create mode 100644 src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
 create mode 100644 src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H
 create mode 100644 src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C
 create mode 100644 src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H
 create mode 100644 src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperationTemplates.C
 create mode 100644 src/OpenFOAM/global/fileOperations/uncollatedFileOperation/uncollatedFileOperation.C
 create mode 100644 src/OpenFOAM/global/fileOperations/uncollatedFileOperation/uncollatedFileOperation.H
 create mode 100644 tutorials/IO/fileHandler/0/U
 create mode 100755 tutorials/IO/fileHandler/Allrun
 create mode 100644 tutorials/IO/fileHandler/constant/g
 create mode 100644 tutorials/IO/fileHandler/constant/kinematicCloudPositions
 create mode 100644 tutorials/IO/fileHandler/constant/kinematicCloudProperties
 create mode 100644 tutorials/IO/fileHandler/constant/transportProperties
 create mode 100644 tutorials/IO/fileHandler/constant/turbulenceProperties
 create mode 100644 tutorials/IO/fileHandler/system/blockMeshDict
 create mode 100644 tutorials/IO/fileHandler/system/controlDict
 create mode 100644 tutorials/IO/fileHandler/system/decomposeParDict
 create mode 100644 tutorials/IO/fileHandler/system/fvSchemes
 create mode 100644 tutorials/IO/fileHandler/system/fvSolution

diff --git a/applications/solvers/electromagnetics/mhdFoam/createPhiB.H b/applications/solvers/electromagnetics/mhdFoam/createPhiB.H
index 21076a51a59..02b48f8d280 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 c760349a6eb..e7da9c6af68 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 12d64c6bde9..2024e663e09 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 00000000000..74e614deae5
--- /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 00000000000..6a9e9810b3d
--- /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 00000000000..d49acaf8f57
--- /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 00000000000..3d33e10b616
--- /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 00000000000..e69de29bb2d
diff --git a/applications/test/decomposedBlockData/Test-decomposedBlockData.C b/applications/test/decomposedBlockData/Test-decomposedBlockData.C
new file mode 100644
index 00000000000..1c867654976
--- /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 39cc729ba3a..c74dcf96af7 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 8996c8afdc5..4ac6cf60173 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 980219c970f..907bb665f10 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 f8fe44f19fc..047e48be443 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 404b5b7e65a..7da047ad5ca 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 5d6232510b6..5a4b0bafde9 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 00f2c7d05d9..619d84eca5a 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 a8905b30a93..6d1cee15ad6 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 456ce03b8e8..b68047b11db 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 55060ae3989..251f7641e64 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 219513850fd..ecd1d89e077 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 df20caa2fff..3a7b554ee28 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 c056932f3c0..1fa978d1259 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 eb03d855f16..e3df780cabe 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 b024745f42a..c68438c0e48 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 06c064e077a..87afd6cf424 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 e2456987526..2ccf7cf4bbb 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 047c68b21a5..b2a14692578 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 79754c1c055..3528dfd5d34 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 4be4abb392d..716f8522abf 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 b1fa2872af2..47695496468 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 e8a082a271e..b219c65bcbe 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 9c0c612ed7f..7da98b7351b 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 70964a667d9..91c718994f1 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 089efeefac8..97f2cb775f3 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 f9be71c75fa..62442c9ca39 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 14f68275156..9fda2c5705b 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 f5be235de18..97aff73fff0 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 9cf697d8b4d..57351df046e 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 e97ab815491..8637ebd9f54 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 bbc5029e6ae..8b3eeb33d89 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 4b53bf4c368..03773787588 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 3a922ed016c..9fa15a2e524 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 1f82552d07f..6a03192cf27 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 0dd52536e95..46a3c7db22d 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 1dfeac42536..563eb9c5426 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 7b89997c8a5..c520fbd8909 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 58757394db7..c1eec9abea5 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 4e01787843e..96f47f61a65 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 f70f3e7ebfc..a91134d91c3 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 c5e369b1cf2..ef8e34185aa 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 231119e6a00..02fbedacc7f 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 8bb3aa009b3..887f03bacb4 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 80c902c73bf..78434784513 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 ee2dcbf79a5..f4b4124f871 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 e7d926afa39..51080e07eed 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 7230fd6c7d2..1f7cb9c4662 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 d7e1214fb5a..143b5e7cd65 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 c65a5619c62..9780a451a52 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 ce115c36f7b..41d386e2d50 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 c5029307db6..768c8b05ea8 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 39bf6c994f0..3e1cea8c958 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 1d79af3ec54..5dce64772f5 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 9ee8cb061ae..40f655d1b29 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 2c7e436faaf..9e39ab51503 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 e4302967c88..ae894d55f49 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 6fbf3a10b28..1422ecea5ba 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 abe9592abb0..5aeb311d6ff 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 efb05d8afa5..e431cd5bdb5 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 e7a753beb4c..b8c7142f211 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 66e064350ca..8431aa83597 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 00000000000..7afbd2fb82c
--- /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 00000000000..dc4e3d70f2a
--- /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 aad480a105a..17a2b7d1e42 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 84487809d25..732fd690101 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 00000000000..f25097a779e
--- /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 00000000000..6bc595d692c
--- /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 00000000000..a774271a11a
--- /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 00000000000..9e8549820db
--- /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 93d58ca42c3..39ee01ede9b 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 f43f74d360e..aac5d71738f 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 5c8c2c5c5ab..0659616f85c 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 ab24791b7fe..f10fad0d384 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 1046d82843e..52dcf50dcc0 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 bcbe24e55db..eb1e9e56ffc 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 be3ea4e0113..0eb4db8fcb4 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 875064b2e87..a6c7bc4b0bf 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 85e806ca470..ddc505c661e 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 2afbb718318..60d42062c75 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 172e84519bc..c91f724a879 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 9f25f28e043..a9ddde6632d 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 c9e12d0e123..c77204a5dd5 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 369e3b925b1..202e1408fe7 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 5248d230986..641a051a41d 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 762bfb3bf93..5f70e6fb5a1 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 210114175ff..3c71b2713d2 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 4a6c60c612e..c5f19d4c9da 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 77d390754f6..b0471ef9ba4 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 5a6177c3914..92216a1d63c 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 d345dc86024..2181b0c629f 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 8fa856d357d..2bd29561b51 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 733bd47ccc0..1617b8a0305 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 61b8aa4c957..cd0210b1ea2 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 f4223ec40a9..dec729bf592 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 1f434f4f2a6..dbd463810db 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 87c8c30f03e..b88047a1ee3 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 00000000000..b5c8ab49422
--- /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 00000000000..17904fc386d
--- /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 00000000000..b5dbb13517b
--- /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 00000000000..49a19e6735f
--- /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 00000000000..df919680fbd
--- /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 00000000000..e296e1132ca
--- /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 00000000000..5d65cf2e298
--- /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 00000000000..ccd55b2fdd9
--- /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 00000000000..41cf4bc7a00
--- /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 00000000000..73c15fa6515
--- /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 00000000000..5c1a5b07164
--- /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 00000000000..ca0dc84ccb5
--- /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 00000000000..9ff5e55b328
--- /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 6dee7af27be..421ec9e25f6 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 d4c4cca0d0b..8c88009ab8a 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 012e47d2fd6..2e31e93723d 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 130f5b9c932..ae2c0cb5e06 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 dc5451a5028..1a7f42628b2 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 b078c9dea8c..3a296f55002 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 08c5f5c2fda..a0e3cffeadc 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 6193b98f450..61ed872fa67 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 41ea107049b..6c44d9e8d1b 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 544ef0ecfc7..e290c689f96 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 69ad923ba3c..4d5c14be5f5 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 e05e3c4fb42..5643805fd7d 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 d867d4a52d8..4304aa1ee4e 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 097da220f61..d191c46d5e4 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 841c0e35b2b..a0a3ece3ce8 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 b739965c39d..78a25c00f2a 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 96520dd7585..9c485deda3d 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 9eadaf48e23..501dec22412 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 4a6356910cb..69161a47cbe 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 eb7c86248cc..1cec60e698b 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 bc9dbcddf33..409f5332697 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 1700732d530..86a61e2b744 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 e2ff6507514..6aef7e60200 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 f8a006d6fee..ccb13f30a7d 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 054524a29b2..6e5decf0355 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 b0349cdc1ba..7397ee064f6 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 e68fb0b4b4e..38a96855df9 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 e14e9761c76..9e5cf7639f7 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 d4b88beeec7..b8631f8edbb 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 84d33c0a4c1..2ccb142a126 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 be5ba784430..7fe0e73a58a 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 3aedb4a7885..267a5510b41 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 a904f8092bf..6a15c27d8f4 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 6132523c6ce..d68f5243094 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 e0d65cc7078..2e26c96343c 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 326b8f21562..4552936ce51 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 58dd0b40307..217ad4f1751 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 7d2c6c74b08..ab36d93772b 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 fc35fa61662..96d035e68ae 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 155280d17ce..dcc6e5ecc6e 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 27be0c3a697..aa35eb3b478 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 7e5131fd9b9..596b2fe1fd7 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 5c977b54d29..08d6e8e437d 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 002e4e2ac9a..fff078e18a4 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 e812a201460..34a540c68ff 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 0a5bdb45fa6..aa48ff4c652 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 04862d198ec..d88104d4641 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 3d9d76d60c6..032c382e4bf 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 f63e02daf06..a5004adac7a 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 7e3b838d7c6..7f4800fdb4d 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 ec582209c6e..238cf3ebf36 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 399f67879d8..6f3633c031f 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 6574af96cf1..dccbd678001 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 f23059e22fb..e9b1b641949 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 20d230625c0..072a5bae28f 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 2c87e3e23d8..c7c18285a36 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 1d41ee3a6c0..39e084c9e2a 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 d0fe212e6c8..e1c44b05879 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 6a7da5a59ae..a5aa685226d 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 7cecee74183..537bf9d7dc0 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 4f421eed0f7..3e1cc6c3721 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 928d7f4dab3..7e723a68618 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 95552422247..af5950c2f3f 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 307278ea9ac..64af5e5298d 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 d1691dba186..d35abbad2eb 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 b6640eaa036..08ce936c465 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 9551827c291..4892ff617a5 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 ee7a3ebb639..9df3c0c4db4 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 608109f7d52..39561a939e0 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 35a0133041f..375d0b96938 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 726dc77777f..3c8989c5f79 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 daaf4bdc0f2..47823e2dee5 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 8ceb27f37cc..fc7aa24aef3 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 8294da4a0ca..7e44c1d6805 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 efd476685ca..eea4d386582 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 c1446d7cafe..6ab4eb18db4 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 5c08e42a74c..428ff83c0fb 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 af5df08f099..63820d5e8a0 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 dbe3eee194d..4746876226e 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 26dfb21899b..5d820cddf8e 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 0dd50907d7b..5ba634c1d44 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 2115280372a..088c794728f 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 5bb6cd0b591..ddf3ebe114a 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 39568568524..1f881bd3212 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 3c0a2aa983f..cacc1c8a9c8 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 9204df19818..c7ca01f29fa 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 21fc0f4f226..5aec71b774f 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 029af1b808f..c21a75e636a 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 12fd3462b48..7f18977b716 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 00000000000..75ed42fbdb4
--- /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 00000000000..d032798abbd
--- /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 00000000000..0cc222ca345
--- /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 00000000000..1e2be4ebc84
--- /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 00000000000..41b8c64e80d
--- /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 00000000000..dbbab9e9f0a
--- /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 00000000000..c2c3b28a1b4
--- /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 00000000000..359a48779aa
--- /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 00000000000..2ac8dc57876
--- /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 00000000000..0f07bb6aa8b
--- /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 00000000000..12c112d4e08
--- /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 00000000000..740eb61a4bc
--- /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 1f58ded07ef..5c8a9d3f92f 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 29414545d79..ca4be116d7c 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
+
 #------------------------------------------------------------------------------
-- 
GitLab