diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/files b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/files
index 44c513a079bdb9707167566ccc85a334e91d4078..421e8392b88501e3efa3ae9323578c59721d8012 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/files
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/files
@@ -1,6 +1,5 @@
-itoa.C
 ensightMesh.C
-ensightParticlePositions.C
+ensightCloud.C
 foamToEnsight.C
 
 EXE = $(FOAM_APPBIN)/foamToEnsight
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options
index c818403451f07fe48e26f74f9685e135b019b16d..1424ecc5361b93a0e4bf21a950555405644d5ef2 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options
@@ -5,7 +5,8 @@ EXE_INC = \
     -I$(LIB_SRC)/dynamicMesh/lnInclude \
     -I$(LIB_SRC)/fileFormats/lnInclude \
     -I$(LIB_SRC)/sampling/lnInclude \
-    -I$(LIB_SRC)/lagrangian/basic/lnInclude
+    -I$(LIB_SRC)/lagrangian/basic/lnInclude \
+    -I$(LIB_SRC)/conversion/lnInclude
 
 EXE_LIBS = \
     -lfiniteVolume \
@@ -13,5 +14,5 @@ EXE_LIBS = \
     -lfileFormats \
     -lsampling \
     -lgenericPatchFields \
-    -llagrangian
-
+    -llagrangian \
+    -lconversion
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkData.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkData.H
index 47a3540da701cc037457f3bbb4dc460f98e75148..dcc3ddd4eae7c411ba92341b3239e34f05d56642 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkData.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkData.H
@@ -1,7 +1,7 @@
 // ignore special fields or fields that we don't handle
 //
 bool variableGood = true;
-for (label n1=0; n1<Times.size() && variableGood; ++n1)
+for (label n1=0; n1<timeDirs.size() && variableGood; ++n1)
 {
     // ignore _0 fields
     if (fieldName.size() > 2 && fieldName(fieldName.size() - 2, 2) == "_0")
@@ -13,7 +13,7 @@ for (label n1=0; n1<Times.size() && variableGood; ++n1)
         variableGood = IOobject
         (
             fieldName,
-            Times[n1].name(),
+            timeDirs[n1].name(),
             mesh,
             IOobject::NO_READ
         ).typeHeaderOk<volScalarField>(false);
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H
index d4027ad1c5abd9586064e78d14debc7cc259e0db..a1b23a53a9cec916b8db87e9a45c603c7176f6c5 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H
@@ -1,25 +1,25 @@
 // check for "points" in any of the result directories
 
 bool meshMoving = false;
-if (Times.size() > 1)
+if (timeDirs.size() > 1)
 {
     // We already loaded a mesh (usually from constant). See if any other
     // points files
-    forAll(Times, timeI)
+    forAll(timeDirs, timeI)
     {
-        if (Times[timeI].name() != mesh.pointsInstance())
+        if (timeDirs[timeI].name() != mesh.pointsInstance())
         {
-            IOobject io
+            meshMoving = IOobject
             (
                 "points",
-                Times[timeI].name(),
+                timeDirs[timeI].name(),
                 polyMesh::meshSubDir,
                 mesh,
                 IOobject::NO_READ
-            );
-            if (io.typeHeaderOk<pointIOField>(true))
+            ).typeHeaderOk<pointIOField>(true);
+
+            if (meshMoving)
             {
-                meshMoving = true;
                 break;
             }
         }
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightAsciiStream.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightAsciiStream.H
index 68eb88e1589a1fc853c07765eeeed2f5cac76a55..ceccc987aeae269798cf88d87adbcb315f0455bf 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightAsciiStream.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightAsciiStream.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -52,17 +52,17 @@ class ensightAsciiStream
 {
     // Private data
 
-        //- Description of data_
+        //- Output file stream
         OFstream str_;
 
 
     // Private Member Functions
 
         //- Disallow default bitwise copy construct
-        ensightAsciiStream(const ensightAsciiStream&);
+        ensightAsciiStream(const ensightAsciiStream&) = delete;
 
         //- Disallow default bitwise assignment
-        void operator=(const ensightAsciiStream&);
+        void operator=(const ensightAsciiStream&) = delete;
 
 
 public:
@@ -70,14 +70,14 @@ public:
     // Constructors
 
         //- Construct from components
-        ensightAsciiStream(const fileName& f, const Time& runTime)
+        ensightAsciiStream(const fileName& f)
         :
             ensightStream(f),
             str_
             (
                 f,
-                runTime.writeFormat(),
-                runTime.writeVersion(),
+                IOstream::ASCII,
+                IOstream::currentVersion,
                 IOstream::UNCOMPRESSED
             )
         {
@@ -139,14 +139,6 @@ public:
                 << setw(10) << partI << nl;
         }
 
-    // Member Operators
-
-    // Friend Functions
-
-    // Friend Operators
-
-    // IOstream Operators
-
 };
 
 
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightBinaryStream.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightBinaryStream.H
index d3435677228246e3da0fcc4074c4cfaf0488bd9c..d1c3d6e3b37aa7f9b10da495ae7612798845a23c 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightBinaryStream.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightBinaryStream.H
@@ -51,17 +51,17 @@ class ensightBinaryStream
 {
     // Private data
 
-        //- Description of data_
+        //- Output file stream
         autoPtr<std::ofstream> str_;
 
 
     // Private Member Functions
 
         //- Disallow default bitwise copy construct
-        ensightBinaryStream(const ensightBinaryStream&);
+        ensightBinaryStream(const ensightBinaryStream&) = delete;
 
         //- Disallow default bitwise assignment
-        void operator=(const ensightBinaryStream&);
+        void operator=(const ensightBinaryStream&) = delete;
 
 
 public:
@@ -69,7 +69,7 @@ public:
     // Constructors
 
         //- Construct from components
-        ensightBinaryStream(const fileName& f, const Time&)
+        ensightBinaryStream(const fileName& f)
         :
             ensightStream(f),
             str_
@@ -90,11 +90,6 @@ public:
 
     // Member Functions
 
-        virtual bool ascii() const
-        {
-            return false;
-        }
-
         virtual void write(const char* val)
         {
             char buffer[80];
@@ -141,14 +136,6 @@ public:
             write(partI);
         }
 
-    // Member Operators
-
-    // Friend Functions
-
-    // Friend Operators
-
-    // IOstream Operators
-
 };
 
 
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCaseTail.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCaseTail.H
index 6ec8373fcf07b708d36a899f60a03f09ac01a793..5a18a953c70b0f634621a3d03c95a01bf3a1887b 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCaseTail.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCaseTail.H
@@ -1,5 +1,8 @@
 if (Pstream::master())
 {
+    ensightCaseFile.setf(ios_base::scientific, ios_base::floatfield);
+    ensightCaseFile.precision(5);
+
     ensightCaseFile << nl << "TIME" << nl
         << "time set:                      " << 1 << nl
         << "number of steps:               " << nTimeSteps << nl
@@ -8,20 +11,17 @@ if (Pstream::master())
 
     ensightCaseFile << "time values:" << nl;
 
-    ensightCaseFile.setf(ios_base::scientific, ios_base::floatfield);
-    ensightCaseFile.precision(5);
-
     label count = 0;
     scalar Tcorr = 0.0;
-    if (Times[0].value() < 0)
+    if (timeDirs[0].value() < 0)
     {
-        Tcorr = - Times[0].value();
+        Tcorr = -timeDirs[0].value();
         Info<< "Correcting time values. Adding " << Tcorr << endl;
     }
 
-    forAll(Times, n)
+    forAll(timeDirs, n)
     {
-        ensightCaseFile << setw(12) << Times[n].value() + Tcorr << " ";
+        ensightCaseFile << setw(12) << timeDirs[n].value() + Tcorr << " ";
 
         if (++count % 6 == 0)
         {
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloud.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloud.C
new file mode 100644
index 0000000000000000000000000000000000000000..08779ff0a8c4b7d7a34cfdf35a234b342c4b8503
--- /dev/null
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloud.C
@@ -0,0 +1,180 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+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 "ensightCloud.H"
+#include "ensightFile.H"
+#include "fvMesh.H"
+#include "passiveParticle.H"
+#include "Cloud.H"
+#include "pointList.H"
+
+// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
+
+void Foam::ensightParticlePositions
+(
+    const fvMesh& mesh,
+    const fileName& dataDir,
+    const label timeIndex,
+    const word& cloudName,
+    const bool dataExists,
+    IOstream::streamFormat format
+)
+{
+    if (dataExists)
+    {
+        Info<< " positions";
+    }
+    else
+    {
+        Info<< " positions{0}";
+    }
+
+    // Total number of parcels on all processes
+    label nTotParcels = 0;
+    autoPtr<Cloud<passiveParticle>> cloudPtr;
+
+    if (dataExists)
+    {
+        cloudPtr.reset(new Cloud<passiveParticle>(mesh, cloudName, false));
+        nTotParcels = cloudPtr().size();
+    }
+    reduce(nTotParcels, sumOp<label>());
+
+    if (Pstream::master())
+    {
+        const fileName postFileName =
+            ensightFile::subDir(timeIndex)/cloud::prefix/cloudName/"positions";
+
+        // the ITER/lagrangian subdirectory must exist
+        mkDir(dataDir/postFileName.path());
+
+        ensightFile os(dataDir, postFileName, format);
+
+        // tag binary format (just like geometry files)
+        os.writeBinaryHeader();
+        os.write(postFileName); // description
+        os.newline();
+        os.write("particle coordinates");
+        os.newline();
+        os.write(nTotParcels, 8);   // unusual width
+        os.newline();
+
+        if (!nTotParcels)
+        {
+            return;  // DONE
+        }
+
+        if (format == IOstream::BINARY)
+        {
+            // binary write is Ensight6 - first ids, then positions
+
+            // 1-index
+            for (label parcelId = 0; parcelId < nTotParcels; ++parcelId)
+            {
+                os.write(parcelId+1);
+            }
+
+            // Master
+            forAllConstIter(Cloud<passiveParticle>, cloudPtr(), elmnt)
+            {
+                const point& p = elmnt().position();
+
+                os.write(p.x());
+                os.write(p.y());
+                os.write(p.z());
+            }
+
+            // Slaves
+            for (int slave=1; slave<Pstream::nProcs(); ++slave)
+            {
+                IPstream fromSlave(Pstream::scheduled, slave);
+                pointList points(fromSlave);
+
+                forAll(points, pti)
+                {
+                    const point& p = points[pti];
+
+                    os.write(p.x());
+                    os.write(p.y());
+                    os.write(p.z());
+                }
+            }
+        }
+        else
+        {
+            // ASCII id + position together
+
+            label parcelId = 0;
+            forAllConstIter(Cloud<passiveParticle>, cloudPtr(), elmnt)
+            {
+                const point& p = elmnt().position();
+
+                os.write(++parcelId, 8);    // unusual width
+                os.write(p.x());
+                os.write(p.y());
+                os.write(p.z());
+                os.newline();
+            }
+
+            // Slaves
+            for (int slave=1; slave<Pstream::nProcs(); ++slave)
+            {
+                IPstream fromSlave(Pstream::scheduled, slave);
+                pointList points(fromSlave);
+
+                forAll(points, pti)
+                {
+                    const point& p = points[pti];
+
+                    os.write(++parcelId, 8);    // unusual width
+                    os.write(p.x());
+                    os.write(p.y());
+                    os.write(p.z());
+                    os.newline();
+                }
+            }
+        }
+    }
+    else if (nTotParcels)
+    {
+        // SLAVE, and data exist
+        pointList points(cloudPtr().size());
+
+        label pti = 0;
+        forAllConstIter(Cloud<passiveParticle>, cloudPtr(), elmnt)
+        {
+            const point& p = elmnt().position();
+            points[pti++] = p;
+        }
+
+        {
+            OPstream toMaster(Pstream::scheduled, Pstream::masterNo());
+            toMaster<< points;
+        }
+    }
+
+}
+
+// ************************************************************************* //
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloudField.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloud.H
similarity index 71%
rename from applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloudField.H
rename to applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloud.H
index 57016c3254eb886bb777b500e1df1b319a45a299..14661506622e2919f1140bc2f1b6ed588c61c73d 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloudField.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloud.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,35 +27,62 @@ InApplication
 Description
 
 SourceFiles
-    ensightCloudField.C
+    ensightCloud.C
+    ensightCloudTemplates.C
 
 \*---------------------------------------------------------------------------*/
 
-#ifndef ensightCloudField_H
-#define ensightCloudField_H
+#ifndef ensightCloud_H
+#define ensightCloud_H
 
+#include "ensightFile.H"
+#include "fvMesh.H"
 #include "Cloud.H"
 #include "IOobject.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+namespace Foam
+{
+
+void ensightParticlePositions
+(
+    const fvMesh& mesh,
+    const fileName& dataDir,
+    const label timeIndex,
+    const word& cloudName,
+    const bool dataExists,
+    const IOstream::streamFormat format
+);
+
+
 template<class Type>
 void ensightCloudField
 (
     const IOobject& fieldObject,
-    const fileName& postProcPath,
-    const word& prepend,
+    const fileName& dataDir,
     const label timeIndex,
-    const word& timeFile,
     const word& cloudName,
+    const label cloudNo,
     Ostream& ensightCaseFile,
-    const bool dataExists
+    const bool dataExists,
+    const IOstream::streamFormat format
 );
 
+
+template<class Type>
+void writeCloudField
+(
+    const IOField<Type>& field,
+    ensightFile& os
+);
+
+}
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 #ifdef NoRepository
-    #include "ensightCloudField.C"
+    #include "ensightCloudTemplates.C"
 #endif
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloudField.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloudField.C
deleted file mode 100644
index 337380de135d7d9ecaac7672923a75c1af435811..0000000000000000000000000000000000000000
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloudField.C
+++ /dev/null
@@ -1,129 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 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 "ensightCloudField.H"
-#include "Time.H"
-#include "IOField.H"
-#include "OFstream.H"
-#include "IOmanip.H"
-#include "ensightPTraits.H"
-
-using namespace Foam;
-
-// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
-
-template<class Type>
-void ensightCloudField
-(
-    const IOobject& fieldObject,
-    const fileName& postProcPath,
-    const word& prepend,
-    const label timeIndex,
-    const word& cloudName,
-    Ostream& ensightCaseFile,
-    const bool dataExists
-)
-{
-    if (dataExists)
-    {
-        Info<< "Converting cloud " << cloudName
-            << " field " << fieldObject.name() << endl;
-    }
-    else
-    {
-        Info<< "Creating empty cloud " << cloudName
-            << " field "  << fieldObject.name() << endl;
-    }
-
-    word timeFile = prepend + itoa(timeIndex);
-
-    const Time& runTime = fieldObject.time();
-
-    if (timeIndex == 0 && Pstream::master())
-    {
-        ensightCaseFile
-            << pTraits<Type>::typeName << " per measured node:      1       ";
-        ensightCaseFile.width(15);
-        ensightCaseFile.setf(ios_base::left);
-        ensightCaseFile
-            << ("c" + fieldObject.name()).c_str()
-            << (' ' + prepend + "****." + cloudName
-              + "." + fieldObject.name()).c_str()
-            << nl;
-    }
-
-    fileName ensightFileName
-    (
-        timeFile + "." + cloudName +"." + fieldObject.name()
-    );
-
-    OFstream ensightFile
-    (
-        postProcPath/ensightFileName,
-        runTime.writeFormat(),
-        runTime.writeVersion(),
-        runTime.writeCompression()
-    );
-
-    ensightFile<< pTraits<Type>::typeName << " values" << nl;
-
-    if (dataExists)
-    {
-        IOField<Type> vf(fieldObject);
-
-        ensightFile.setf(ios_base::scientific, ios_base::floatfield);
-        ensightFile.precision(5);
-
-        label count = 0;
-        forAll(vf, i)
-        {
-            Type v = vf[i];
-
-            if (mag(v) < 1.0e-90)
-            {
-                v = Zero;
-            }
-
-            for (direction i=0; i < pTraits<Type>::nComponents; ++i)
-            {
-                label cmpt = ensightPTraits<Type>::componentOrder[i];
-
-                ensightFile << setw(12) << component(v, cmpt);
-                if (++count % 6 == 0)
-                {
-                    ensightFile << nl;
-                }
-            }
-        }
-
-        if ((count % 6 != 0) || (count==0))
-        {
-            ensightFile << nl;
-        }
-    }
-}
-
-
-// ************************************************************************* //
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloudTemplates.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloudTemplates.C
new file mode 100644
index 0000000000000000000000000000000000000000..efcd11beb97a27dce18d974bfde8e0a19ee2a6c7
--- /dev/null
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightCloudTemplates.C
@@ -0,0 +1,192 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  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.
+-------------------------------------------------------------------------------
+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 "ensightCloud.H"
+#include "ensightFile.H"
+#include "Time.H"
+#include "IOField.H"
+#include "OFstream.H"
+#include "IOmanip.H"
+#include "ensightPTraits.H"
+
+// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+void Foam::writeCloudField
+(
+    const Foam::IOField<Type>& field,
+    Foam::ensightFile& os
+)
+{
+    if (returnReduce(field.size(), sumOp<label>()) > 0)
+    {
+        if (Pstream::master())
+        {
+            // 6 values per line
+            label count = 0;
+
+            // Master
+            forAll(field, i)
+            {
+                Type val = field[i];
+
+                if (mag(val) < 1e-90)
+                {
+                    val = Zero;
+                }
+
+                for (direction i=0; i < pTraits<Type>::nComponents; ++i)
+                {
+                    label cmpt = ensightPTraits<Type>::componentOrder[i];
+                    os.write( component(val, cmpt) );
+
+                    if (++count % 6 == 0)
+                    {
+                        os.newline();
+                    }
+                }
+            }
+
+            // Slaves
+            for (int slave=1; slave<Pstream::nProcs(); ++slave)
+            {
+                IPstream fromSlave(Pstream::scheduled, slave);
+                Field<Type> slaveData(fromSlave);
+
+                forAll(slaveData, i)
+                {
+                    Type val = slaveData[i];
+
+                    if (mag(val) < 1e-90)
+                    {
+                        val = Zero;
+                    }
+
+                    for (direction i=0; i < pTraits<Type>::nComponents; ++i)
+                    {
+                        label cmpt = ensightPTraits<Type>::componentOrder[i];
+                        os.write( component(val, cmpt) );
+
+                        if (++count % 6 == 0)
+                        {
+                            os.newline();
+                        }
+                    }
+                }
+            }
+
+            // add final newline if required
+            if (count % 6)
+            {
+                os.newline();
+            }
+        }
+        else
+        {
+            OPstream toMaster(Pstream::scheduled, Pstream::masterNo());
+            toMaster<< field;
+        }
+    }
+}
+
+
+template<class Type>
+void Foam::ensightCloudField
+(
+    const Foam::IOobject& fieldObject,
+    const Foam::fileName& dataDir,
+    const Foam::label timeIndex,
+    const Foam::word& cloudName,
+    const Foam::label cloudNo,
+    Foam::Ostream& ensightCaseFile,
+    const bool dataExists,
+    Foam::IOstream::streamFormat format
+)
+{
+    const ensight::VarName varName(fieldObject.name());
+
+    if (dataExists)
+    {
+        Info<< ' ' << fieldObject.name();
+    }
+    else
+    {
+        Info<< ' ' << fieldObject.name() << "{0}"; // ie, empty field
+    }
+
+    ensightFile* filePtr(nullptr);
+    if (Pstream::master())
+    {
+        const fileName postFileName =
+            ensightFile::subDir(timeIndex)/cloud::prefix/cloudName/varName;
+
+        // the ITER/lagrangian subdirectory must exist
+        // the ITER/lagrangian subdirectory was already created
+        // when writing positions
+
+        mkDir(dataDir/postFileName.path());
+
+        if (timeIndex == 0)
+        {
+            const fileName dirName =
+                dataDir.name()/ensightFile::mask()/cloud::prefix/cloudName;
+
+            ensightCaseFile.setf(ios_base::left);
+
+            // prefix variables with 'c' (cloud)
+            ensightCaseFile
+                << ensightPTraits<Type>::typeName << " per "
+                << setw(20)
+                << "measured node:"
+                << " 1  "
+                << setw(15)
+                << ("c" + Foam::name(cloudNo) + varName).c_str() << ' '
+                << (dirName/varName).c_str()
+                << nl;
+        }
+
+        filePtr = new ensightFile(dataDir, postFileName, format);
+        filePtr->write
+        (
+            // description
+            string(postFileName + " <" + pTraits<Type>::typeName + ">")
+        );
+        filePtr->newline();
+    }
+
+    if (dataExists)
+    {
+        IOField<Type> field(fieldObject);
+        writeCloudField(field, *filePtr);
+    }
+
+    if (filePtr) // on master only
+    {
+        delete filePtr;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightField.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightField.C
index 11c3a9a7b6f6566a0c50351b8b36c137b5c2c5fd..40e115ef0912f8b46a4e531988186908c17f3be7 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightField.C
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightField.C
@@ -23,12 +23,12 @@ License
 
 \*---------------------------------------------------------------------------*/
 
+#include "ensightFile.H"
 #include "ensightField.H"
 #include "fvMesh.H"
 #include "volFields.H"
 #include "OFstream.H"
 #include "IOmanip.H"
-#include "itoa.H"
 #include "volPointInterpolation.H"
 #include "ensightBinaryStream.H"
 #include "ensightAsciiStream.H"
@@ -121,10 +121,8 @@ volField
 //    const IOobject& io,
 //    const fvMesh& mesh,
 //    const ensightMesh& eMesh,
-//    const fileName& postProcPath,
-//    const word& prepend,
+//    const fileName& dataDir,
 //    const label timeIndex,
-//    const bool binary,
 //    const bool nodeValues,
 //    Ostream& ensightCaseFile
 //)
@@ -134,10 +132,8 @@ volField
 //    (
 //        volField<typename Container::value_type>(meshSubsetter, fld),
 //        eMesh,
-//        postProcPath,
-//        prepend,
+//        dataDir,
 //        timeIndex,
-//        binary,
 //        nodeValues,
 //        ensightCaseFile
 //    );
@@ -175,26 +171,26 @@ void writeField
 (
     const char* key,
     const Field<Type>& vf,
-    ensightStream& ensightFile
+    ensightStream& os
 )
 {
     if (returnReduce(vf.size(), sumOp<label>()) > 0)
     {
         if (Pstream::master())
         {
-            ensightFile.write(key);
+            os.write(key);
 
             for (direction i=0; i < pTraits<Type>::nComponents; ++i)
             {
                 label cmpt = ensightPTraits<Type>::componentOrder[i];
 
-                ensightFile.write(vf.component(cmpt));
+                os.write(vf.component(cmpt));
 
                 for (int slave=1; slave<Pstream::nProcs(); slave++)
                 {
                     IPstream fromSlave(Pstream::scheduled, slave);
                     scalarField slaveData(fromSlave);
-                    ensightFile.write(slaveData);
+                    os.write(slaveData);
                 }
             }
         }
@@ -220,35 +216,35 @@ bool writePatchField
     const label ensightPatchI,
     const faceSets& boundaryFaceSet,
     const ensightMesh::nFacePrimitives& nfp,
-    ensightStream& ensightFile
+    ensightStream& os
 )
 {
     if (nfp.nTris || nfp.nQuads || nfp.nPolys)
     {
         if (Pstream::master())
         {
-            ensightFile.writePartHeader(ensightPatchI);
+            os.writePartHeader(ensightPatchI);
         }
 
         writeField
         (
             "tria3",
             Field<Type>(pf, boundaryFaceSet.tris),
-            ensightFile
+            os
         );
 
         writeField
         (
             "quad4",
             Field<Type>(pf, boundaryFaceSet.quads),
-            ensightFile
+            os
         );
 
         writeField
         (
             "nsided",
             Field<Type>(pf, boundaryFaceSet.polys),
-            ensightFile
+            os
         );
 
         return true;
@@ -267,15 +263,11 @@ void writePatchField
     const Field<Type>& pf,
     const word& patchName,
     const ensightMesh& eMesh,
-    const fileName& postProcPath,
-    const word& prepend,
+    const fileName& dataDir,
     const label timeIndex,
-    const bool binary,
     Ostream& ensightCaseFile
 )
 {
-    const Time& runTime = eMesh.mesh().time();
-
     const List<faceSets>& boundaryFaceSets = eMesh.boundaryFaceSets();
     const wordList& allPatchNames = eMesh.allPatchNames();
     const HashTable<ensightMesh::nFacePrimitives>&
@@ -295,54 +287,52 @@ void writePatchField
         ensightPatchI++;
     }
 
-
-    word pfName = patchName + '.' + fieldName;
-
-    word timeFile = prepend + itoa(timeIndex);
-
-    ensightStream* ensightFilePtr = NULL;
+    ensightStream* filePtr(nullptr);
     if (Pstream::master())
     {
+        // TODO: verify that these are indeed valid ensight variable names
+        const word varName = patchName + '.' + fieldName;
+        const fileName postFileName = ensightFile::subDir(timeIndex)/varName;
+
+        // the data/ITER subdirectory must exist
+        mkDir(dataDir/postFileName.path());
+
         if (timeIndex == 0)
         {
-            ensightCaseFile.setf(ios_base::left);
+            const fileName dirName = dataDir.name()/ensightFile::mask();
 
+            ensightCaseFile.setf(ios_base::left);
             ensightCaseFile
-                << ensightPTraits<Type>::typeName
-                << " per element:            1       "
-                << setw(15) << pfName
-                << (' ' + prepend + "****." + pfName).c_str()
+                << ensightPTraits<Type>::typeName << " per "
+                << setw(20)
+                << "element:"
+                << " 1  "
+                << setw(15)
+                << varName.c_str() << ' '
+                << (dirName/varName).c_str()
                 << nl;
         }
 
-        // set the filename of the ensight file
-        fileName ensightFileName(timeFile + "." + pfName);
-
-        if (binary)
+        if (eMesh.format() == IOstream::BINARY)
         {
-            ensightFilePtr = new ensightBinaryStream
+            filePtr = new ensightBinaryStream
             (
-                postProcPath/ensightFileName,
-                runTime
+                dataDir/postFileName
             );
         }
         else
         {
-            ensightFilePtr = new ensightAsciiStream
+            filePtr = new ensightAsciiStream
             (
-                postProcPath/ensightFileName,
-                runTime
+                dataDir/postFileName
             );
         }
-    }
-
-    ensightStream& ensightFile = *ensightFilePtr;
 
-    if (Pstream::master())
-    {
-        ensightFile.write(ensightPTraits<Type>::typeName);
+        filePtr->write(ensightPTraits<Type>::typeName);
     }
 
+    ensightStream& os = *filePtr;
+
     if (patchi >= 0)
     {
         writePatchField
@@ -352,7 +342,7 @@ void writePatchField
             ensightPatchI,
             boundaryFaceSets[patchi],
             nPatchPrims.find(patchName)(),
-            ensightFile
+            os
         );
     }
     else
@@ -366,13 +356,13 @@ void writePatchField
             ensightPatchI,
             nullFaceSets,
             nPatchPrims.find(patchName)(),
-            ensightFile
+            os
         );
     }
 
-    if (Pstream::master())
+    if (filePtr) // on master only
     {
-        delete ensightFilePtr;
+        delete filePtr;
     }
 }
 
@@ -382,19 +372,14 @@ void ensightField
 (
     const GeometricField<Type, fvPatchField, volMesh>& vf,
     const ensightMesh& eMesh,
-    const fileName& postProcPath,
-    const word& prepend,
+    const fileName& dataDir,
     const label timeIndex,
-    const bool binary,
     Ostream& ensightCaseFile
 )
 {
-    Info<< "Converting field " << vf.name() << endl;
-
-    word timeFile = prepend + itoa(timeIndex);
+    Info<< ' ' << vf.name();
 
     const fvMesh& mesh = eMesh.mesh();
-    const Time& runTime = mesh.time();
 
     const cellSets& meshCellSets = eMesh.meshCellSets();
     const List<faceSets>& boundaryFaceSets = eMesh.boundaryFaceSets();
@@ -414,91 +399,91 @@ void ensightField
     const labelList& hexes = meshCellSets.hexes;
     const labelList& polys = meshCellSets.polys;
 
-    ensightStream* ensightFilePtr = NULL;
+    ensightStream* filePtr(nullptr);
     if (Pstream::master())
     {
-        // set the filename of the ensight file
-        fileName ensightFileName(timeFile + "." + vf.name());
+        const ensight::VarName varName(vf.name());
+        const fileName postFileName = ensightFile::subDir(timeIndex)/varName;
+
+        // the data/ITER subdirectory must exist
+        mkDir(dataDir/postFileName.path());
+
+        if (timeIndex == 0)
+        {
+            const fileName dirName = dataDir.name()/ensightFile::mask();
+
+            ensightCaseFile.setf(ios_base::left);
+            ensightCaseFile
+                << ensightPTraits<Type>::typeName
+                << " per element:     1  "
+                << setw(15)
+                << varName.c_str() << ' '
+                << (dirName/varName).c_str()
+                << nl;
+        }
 
-        if (binary)
+        if (eMesh.format() == IOstream::BINARY)
         {
-            ensightFilePtr = new ensightBinaryStream
+            filePtr = new ensightBinaryStream
             (
-                postProcPath/ensightFileName,
-                runTime
+                dataDir/postFileName
             );
         }
         else
         {
-            ensightFilePtr = new ensightAsciiStream
+            filePtr = new ensightAsciiStream
             (
-                postProcPath/ensightFileName,
-                runTime
+                dataDir/postFileName
             );
         }
-    }
-
-    ensightStream& ensightFile = *ensightFilePtr;
-
-    if (Pstream::master())
-    {
-        if (timeIndex == 0)
-        {
-            ensightCaseFile.setf(ios_base::left);
-
-            ensightCaseFile
-                << ensightPTraits<Type>::typeName
-                << " per element:            1       "
-                << setw(15) << vf.name()
-                << (' ' + prepend + "****." + vf.name()).c_str()
-                << nl;
-        }
 
-        ensightFile.write(ensightPTraits<Type>::typeName);
+        filePtr->write(ensightPTraits<Type>::typeName);
     }
 
+    ensightStream& os = *filePtr;
+
     if (patchNames.empty())
     {
         eMesh.barrier();
 
         if (Pstream::master())
         {
-            ensightFile.writePartHeader(1);
+            os.writePartHeader(1);
         }
 
         writeField
         (
             "hexa8",
             map(vf, hexes, wedges),
-            ensightFile
+            os
         );
 
         writeField
         (
             "penta6",
             Field<Type>(vf, prisms),
-            ensightFile
+            os
         );
 
         writeField
         (
             "pyramid5",
             Field<Type>(vf, pyrs),
-            ensightFile
+            os
         );
 
         writeField
         (
             "tetra4",
             Field<Type>(vf, tets),
-            ensightFile
+            os
         );
 
         writeField
         (
             "nfaced",
             Field<Type>(vf, polys),
-            ensightFile
+            os
         );
     }
 
@@ -521,7 +506,7 @@ void ensightField
                     ensightPatchI,
                     boundaryFaceSets[patchi],
                     nPatchPrims.find(patchName)(),
-                    ensightFile
+                    os
                 )
             )
             {
@@ -546,8 +531,7 @@ void ensightField
 
             eMesh.barrier();
 
-            label zoneID = mesh.faceZones().findZoneID(faceZoneName);
-
+            const label zoneID = mesh.faceZones().findZoneID(faceZoneName);
             const faceZone& fz = mesh.faceZones()[zoneID];
 
             // Prepare data to write
@@ -595,7 +579,7 @@ void ensightField
                     ensightPatchI,
                     faceZoneFaceSets[zoneID],
                     nFaceZonePrims.find(faceZoneName)(),
-                    ensightFile
+                    os
                 )
             )
             {
@@ -603,9 +587,10 @@ void ensightField
             }
         }
     }
-    if (Pstream::master())
+
+    if (filePtr) // on master only
     {
-        delete ensightFilePtr;
+        delete filePtr;
     }
 }
 
@@ -615,80 +600,78 @@ void ensightPointField
 (
     const GeometricField<Type, pointPatchField, pointMesh>& pf,
     const ensightMesh& eMesh,
-    const fileName& postProcPath,
-    const word& prepend,
+    const fileName& dataDir,
     const label timeIndex,
-    const bool binary,
     Ostream& ensightCaseFile
 )
 {
-    Info<< "Converting field " << pf.name() << endl;
-
-    word timeFile = prepend + itoa(timeIndex);
+    Info<< ' ' << pf.name();
 
     const fvMesh& mesh = eMesh.mesh();
     const wordList& allPatchNames = eMesh.allPatchNames();
     const wordHashSet& patchNames = eMesh.patchNames();
     const wordHashSet& faceZoneNames = eMesh.faceZoneNames();
 
-
-    ensightStream* ensightFilePtr = NULL;
+    ensightStream* filePtr(nullptr);
     if (Pstream::master())
     {
-        // set the filename of the ensight file
-        fileName ensightFileName(timeFile + "." + pf.name());
+        const ensight::VarName varName(pf.name());
+        const fileName postFileName = ensightFile::subDir(timeIndex)/varName;
 
-        if (binary)
+        // the data/ITER subdirectory must exist
+        mkDir(dataDir/postFileName.path());
+
+        if (timeIndex == 0)
         {
-            ensightFilePtr = new ensightBinaryStream
+            const fileName dirName = dataDir.name()/ensightFile::mask();
+
+            ensightCaseFile.setf(ios_base::left);
+            ensightCaseFile
+                << ensightPTraits<Type>::typeName
+                << " per "
+                << setw(20)
+                << " node:"
+                << " 1  "
+                << setw(15)
+                << varName.c_str() << ' '
+                << (dirName/varName).c_str()
+                << nl;
+        }
+
+        if (eMesh.format() == IOstream::BINARY)
+        {
+            filePtr = new ensightBinaryStream
             (
-                postProcPath/ensightFileName,
-                mesh.time()
+                dataDir/postFileName
             );
         }
         else
         {
-            ensightFilePtr = new ensightAsciiStream
+            filePtr = new ensightAsciiStream
             (
-                postProcPath/ensightFileName,
-                mesh.time()
+                dataDir/postFileName
             );
         }
-    }
-
-    ensightStream& ensightFile = *ensightFilePtr;
-
-    if (Pstream::master())
-    {
-        if (timeIndex == 0)
-        {
-            ensightCaseFile.setf(ios_base::left);
-
-            ensightCaseFile
-                << ensightPTraits<Type>::typeName
-                << " per node:            1       "
-                << setw(15) << pf.name()
-                << (' ' + prepend + "****." + pf.name()).c_str()
-                << nl;
-        }
 
-        ensightFile.write(ensightPTraits<Type>::typeName);
+        filePtr->write(ensightPTraits<Type>::typeName);
     }
 
+    ensightStream& os = *filePtr;
+
     if (eMesh.patchNames().empty())
     {
         eMesh.barrier();
 
         if (Pstream::master())
         {
-            ensightFile.writePartHeader(1);
+            os.writePartHeader(1);
         }
 
         writeField
         (
             "coordinates",
             Field<Type>(pf.internalField(), eMesh.uniquePointMap()),
-            ensightFile
+            os
         );
     }
 
@@ -704,11 +687,8 @@ void ensightPointField
         if (patchNames.empty() || patchNames.found(patchName))
         {
             const fvPatch& p = mesh.boundary()[patchi];
-            if
-            (
-                returnReduce(p.size(), sumOp<label>())
-              > 0
-            )
+
+            if (returnReduce(p.size(), sumOp<label>()) > 0)
             {
                 // Renumber the patch points/faces into unique points
                 labelList pointToGlobal;
@@ -724,14 +704,14 @@ void ensightPointField
 
                 if (Pstream::master())
                 {
-                    ensightFile.writePartHeader(ensightPatchI);
+                    os.writePartHeader(ensightPatchI);
                 }
 
                 writeField
                 (
                     "coordinates",
                     Field<Type>(pf.internalField(), uniqueMeshPointLabels),
-                    ensightFile
+                    os
                 );
 
                 ensightPatchI++;
@@ -748,8 +728,7 @@ void ensightPointField
 
             eMesh.barrier();
 
-            label zoneID = mesh.faceZones().findZoneID(faceZoneName);
-
+            const label zoneID = mesh.faceZones().findZoneID(faceZoneName);
             const faceZone& fz = mesh.faceZones()[zoneID];
 
             if (returnReduce(fz().nPoints(), sumOp<label>()) > 0)
@@ -768,7 +747,7 @@ void ensightPointField
 
                 if (Pstream::master())
                 {
-                    ensightFile.writePartHeader(ensightPatchI);
+                    os.writePartHeader(ensightPatchI);
                 }
 
                 writeField
@@ -779,7 +758,7 @@ void ensightPointField
                         pf.internalField(),
                         uniqueMeshPointLabels
                     ),
-                    ensightFile
+                    os
                 );
 
                 ensightPatchI++;
@@ -787,9 +766,9 @@ void ensightPointField
         }
     }
 
-    if (Pstream::master())
+    if (filePtr) // on master only
     {
-        delete ensightFilePtr;
+        delete filePtr;
     }
 }
 
@@ -799,10 +778,8 @@ void ensightField
 (
     const GeometricField<Type, fvPatchField, volMesh>& vf,
     const ensightMesh& eMesh,
-    const fileName& postProcPath,
-    const word& prepend,
+    const fileName& dataDir,
     const label timeIndex,
-    const bool binary,
     const bool nodeValues,
     Ostream& ensightCaseFile
 )
@@ -819,10 +796,8 @@ void ensightField
         (
             pfld,
             eMesh,
-            postProcPath,
-            prepend,
+            dataDir,
             timeIndex,
-            binary,
             ensightCaseFile
         );
     }
@@ -832,10 +807,8 @@ void ensightField
         (
             vf,
             eMesh,
-            postProcPath,
-            prepend,
+            dataDir,
             timeIndex,
-            binary,
             ensightCaseFile
         );
     }
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightField.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightField.H
index 813fea468eb74cd9d07f52bcd6cc2429352de7f1..175ef1ac7da68d0bc6513db7f1232bb6ca19ac41 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightField.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightField.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -69,10 +69,8 @@ void ensightField
 (
     const Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>& vf,
     const Foam::ensightMesh& eMesh,
-    const Foam::fileName& postProcPath,
-    const Foam::word& prepend,
+    const Foam::fileName& dataDir,
     const Foam::label timeIndex,
-    const bool binary,
     const bool nodeValues,
     Foam::Ostream& ensightCaseFile
 );
@@ -85,8 +83,7 @@ void writePatchField
     const Foam::Field<Type>& pf,
     const Foam::word& patchName,
     const Foam::ensightMesh& eMesh,
-    const Foam::fileName& postProcPath,
-    const Foam::word& prepend,
+    const Foam::fileName& dataDir,
     const Foam::label timeIndex,
     Foam::Ostream& ensightCaseFile
 );
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightMesh.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightMesh.C
index da9f080aa018e459ec8332f18c9d92f6ae5c700a..1a06c2933bd92bcf92c166e46e95a9888b8ed191 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightMesh.C
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightMesh.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -32,16 +32,21 @@ License
 #include "processorPolyPatch.H"
 #include "cellModeller.H"
 #include "IOmanip.H"
-#include "itoa.H"
 #include "globalIndex.H"
 #include "mapDistribute.H"
 #include "stringListOps.H"
 
+#include "ensightFile.H"
 #include "ensightBinaryStream.H"
 #include "ensightAsciiStream.H"
 
 #include <fstream>
 
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+const char* Foam::ensightMesh::geometryName = "geometry";
+
+
 // * * * * * * * * * * * * * Private Functions * * * * * * * * * * * * * * //
 
 void Foam::ensightMesh::correct()
@@ -403,7 +408,7 @@ Foam::ensightMesh::ensightMesh
     const bool faceZones,
     const wordReList& faceZonePatterns,
 
-    const bool binary
+    const IOstream::streamFormat format
 )
 :
     mesh_(mesh),
@@ -412,7 +417,7 @@ Foam::ensightMesh::ensightMesh
     patchPatterns_(patchPatterns),
     faceZones_(faceZones),
     faceZonePatterns_(faceZonePatterns),
-    binary_(binary),
+    format_(format),
     meshCellSets_(mesh.nCells())
 {
     correct();
@@ -521,7 +526,7 @@ void Foam::ensightMesh::writePrims
     // Create a temp int array
     if (cellShapes.size())
     {
-        if (ensightGeometryFile.ascii())
+        if (format_ == IOstream::ASCII)
         {
             // Workaround for paraview issue : write one cell per line
 
@@ -1018,63 +1023,55 @@ void Foam::ensightMesh::writeAllPoints
 
 void Foam::ensightMesh::write
 (
-    const fileName& postProcPath,
-    const word& prepend,
+    const fileName& dataDir,
     const label timeIndex,
     const bool meshMoving,
     Ostream& ensightCaseFile
 ) const
 {
-    const Time& runTime = mesh_.time();
     const cellShapeList& cellShapes = mesh_.cellShapes();
 
-
-    word timeFile = prepend;
-
-    if (timeIndex == 0)
-    {
-        timeFile += "0000.";
-    }
-    else if (meshMoving)
+    ensightStream* filePtr(nullptr);
+    if (Pstream::master())
     {
-        timeFile += itoa(timeIndex) + '.';
-    }
+        // set the filename of the ensight file
+        fileName geoFileName = dataDir.path()/ensightMesh::geometryName;
 
-    // set the filename of the ensight file
-    fileName ensightGeometryFileName = timeFile + "mesh";
+        if (meshMoving)
+        {
+            geoFileName =
+                dataDir/ensightFile::subDir(timeIndex)/ensightMesh::geometryName;
 
-    ensightStream* ensightGeometryFilePtr = NULL;
-    if (Pstream::master())
-    {
-        if (binary_)
+            mkDir(geoFileName.path());
+        }
+
+        if (format_ == IOstream::BINARY)
         {
-            ensightGeometryFilePtr = new ensightBinaryStream
+            filePtr = new ensightBinaryStream
             (
-                postProcPath/ensightGeometryFileName,
-                runTime
+                geoFileName
             );
-            ensightGeometryFilePtr->write("C binary");
+            filePtr->write("C binary");
         }
         else
         {
-            ensightGeometryFilePtr = new ensightAsciiStream
+            filePtr = new ensightAsciiStream
             (
-                postProcPath/ensightGeometryFileName,
-                runTime
+                geoFileName
             );
         }
     }
 
-    ensightStream& ensightGeometryFile = *ensightGeometryFilePtr;
+    ensightStream& os = *filePtr;
 
     if (Pstream::master())
     {
         string desc = string("written by OpenFOAM-") + Foam::FOAMversion;
 
-        ensightGeometryFile.write("EnSight Geometry File");
-        ensightGeometryFile.write(desc.c_str());
-        ensightGeometryFile.write("node id assign");
-        ensightGeometryFile.write("element id assign");
+        os.write("EnSight Geometry File");
+        os.write(desc.c_str());
+        os.write("node id assign");
+        os.write("element id assign");
     }
 
     if (patchNames_.empty())
@@ -1089,7 +1086,7 @@ void Foam::ensightMesh::write
             "internalMesh",
             uniquePoints,
             nPoints,
-            ensightGeometryFile
+            os
         );
 
         writeAllPrims
@@ -1103,7 +1100,7 @@ void Foam::ensightMesh::write
                 meshCellSets_.wedges,
                 pointToGlobal_
             ),
-            ensightGeometryFile
+            os
         );
 
         writeAllPrims
@@ -1111,7 +1108,7 @@ void Foam::ensightMesh::write
             "penta6",
             meshCellSets_.nPrisms,
             map(cellShapes, meshCellSets_.prisms, pointToGlobal_),
-            ensightGeometryFile
+            os
         );
 
         writeAllPrims
@@ -1119,7 +1116,7 @@ void Foam::ensightMesh::write
             "pyramid5",
             meshCellSets_.nPyrs,
             map(cellShapes, meshCellSets_.pyrs, pointToGlobal_),
-            ensightGeometryFile
+            os
         );
 
         writeAllPrims
@@ -1127,13 +1124,13 @@ void Foam::ensightMesh::write
             "tetra4",
             meshCellSets_.nTets,
             map(cellShapes, meshCellSets_.tets, pointToGlobal_),
-            ensightGeometryFile
+            os
         );
 
         writeAllPolys
         (
             pointToGlobal_,
-            ensightGeometryFile
+            os
         );
     }
 
@@ -1182,7 +1179,7 @@ void Foam::ensightMesh::write
                     patchName,
                     uniquePoints,
                     globalPointsPtr().size(),
-                    ensightGeometryFile
+                    os
                 );
 
                 writeAllFacePrims
@@ -1191,7 +1188,7 @@ void Foam::ensightMesh::write
                     tris,
                     nfp.nTris,
                     patchFaces,
-                    ensightGeometryFile
+                    os
                 );
 
                 writeAllFacePrims
@@ -1200,7 +1197,7 @@ void Foam::ensightMesh::write
                     quads,
                     nfp.nQuads,
                     patchFaces,
-                    ensightGeometryFile
+                    os
                 );
 
                 writeAllNSided
@@ -1208,7 +1205,7 @@ void Foam::ensightMesh::write
                     polys,
                     nfp.nPolys,
                     patchFaces,
-                    ensightGeometryFile
+                    os
                 );
             }
         }
@@ -1287,7 +1284,7 @@ void Foam::ensightMesh::write
                 faceZoneName,
                 uniquePoints,
                 globalPointsPtr().size(),
-                ensightGeometryFile
+                os
             );
 
             writeAllFacePrims
@@ -1296,7 +1293,7 @@ void Foam::ensightMesh::write
                 tris,
                 nfp.nTris,
                 faceZoneMasterFaces,
-                ensightGeometryFile
+                os
             );
 
             writeAllFacePrims
@@ -1305,7 +1302,7 @@ void Foam::ensightMesh::write
                 quads,
                 nfp.nQuads,
                 faceZoneMasterFaces,
-                ensightGeometryFile
+                os
             );
 
             writeAllNSided
@@ -1313,14 +1310,14 @@ void Foam::ensightMesh::write
                 polys,
                 nfp.nPolys,
                 faceZoneMasterFaces,
-                ensightGeometryFile
+                os
             );
         }
     }
 
-    if (Pstream::master())
+    if (filePtr) // only on master
     {
-        delete ensightGeometryFilePtr;
+        delete filePtr;
     }
 }
 
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightMesh.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightMesh.H
index e1f7e8384b9b124ffbfe740c3a177ace95699f3b..321c9899691e82e4ad0a14278148e9a34144b2e9 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightMesh.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightMesh.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -63,6 +63,11 @@ class ensightStream;
 class ensightMesh
 {
 public:
+
+    //- The name for geometry files
+    static const char* geometryName;
+
+        //- Helper class for managing face primitives
         class nFacePrimitives
         {
         public:
@@ -97,8 +102,8 @@ private:
         const bool faceZones_;
         const wordReList faceZonePatterns_;
 
-        //- Set binary file output
-        const bool binary_;
+        //- Ascii/Binary file output
+        const IOstream::streamFormat format_;
 
         //- The ensight part id for the first patch
         label patchPartOffset_;
@@ -140,10 +145,10 @@ private:
     // Private Member Functions
 
         //- Disallow default bitwise copy construct
-        ensightMesh(const ensightMesh&);
+        ensightMesh(const ensightMesh&) = delete;
 
         //- Disallow default bitwise assignment
-        void operator=(const ensightMesh&);
+        void operator=(const ensightMesh&) = delete;
 
         void writePoints
         (
@@ -267,7 +272,7 @@ public:
             const wordReList& patchPatterns,
             const bool faceZones,
             const wordReList& faceZonePatterns,
-            const bool binary
+            const IOstream::streamFormat format = IOstream::BINARY
         );
 
 
@@ -284,6 +289,11 @@ public:
                 return mesh_;
             }
 
+            IOstream::streamFormat format() const
+            {
+                return format_;
+            }
+
             const cellSets& meshCellSets() const
             {
                 return meshCellSets_;
@@ -352,8 +362,6 @@ public:
             }
 
 
-
-
     // Other
 
         //- Update for new mesh
@@ -371,8 +379,7 @@ public:
 
         void write
         (
-            const fileName& postProcPath,
-            const word& prepend,
+            const fileName& ensightDir,
             const label timeIndex,
             const bool meshMoving,
             Ostream& ensightCaseFile
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightParticlePositions.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightParticlePositions.C
deleted file mode 100644
index d736b3fa930c79d949c0e0269b06cf774a026e7b..0000000000000000000000000000000000000000
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightParticlePositions.C
+++ /dev/null
@@ -1,103 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 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 "ensightParticlePositions.H"
-#include "fvMesh.H"
-#include "passiveParticle.H"
-#include "Cloud.H"
-#include "OFstream.H"
-#include "IOmanip.H"
-#include "itoa.H"
-
-using namespace Foam;
-
-// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
-
-void ensightParticlePositions
-(
-    const fvMesh& mesh,
-    const fileName& postProcPath,
-    const word& timeFile,
-    const word& cloudName,
-    const bool dataExists
-)
-{
-    if (dataExists)
-    {
-        Info<< "Converting cloud " << cloudName << " positions" <<  endl;
-    }
-    else
-    {
-        Info<< "Creating empty cloud " << cloudName << " positions" << endl;
-    }
-
-    const Time& runTime = mesh.time();
-
-    fileName ensightFileName(timeFile + "." + cloudName);
-    OFstream ensightFile
-    (
-        postProcPath/ensightFileName,
-        runTime.writeFormat(),
-        runTime.writeVersion(),
-        runTime.writeCompression()
-    );
-
-    // Output header
-    ensightFile
-        << cloudName.c_str() << nl
-        << "particle coordinates" << nl;
-
-    if (dataExists)
-    {
-        Cloud<passiveParticle> parcels(mesh, cloudName, false);
-
-        // Set Format
-        ensightFile.setf(ios_base::scientific, ios_base::floatfield);
-        ensightFile.precision(5);
-
-        ensightFile<< setw(8) << parcels.size() << nl;
-
-        label nParcels = 0;
-
-        // Output positions
-        forAllConstIter(Cloud<passiveParticle>, parcels, elmnt)
-        {
-            const vector& p = elmnt().position();
-
-            ensightFile
-                << setw(8) << ++nParcels
-                << setw(12) << p.x() << setw(12) << p.y() << setw(12) << p.z()
-                << nl;
-        }
-    }
-    else
-    {
-        label nParcels = 0;
-        ensightFile<< setw(8) << nParcels << nl;
-    }
-}
-
-
-// ************************************************************************* //
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightParticlePositions.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightParticlePositions.H
deleted file mode 100644
index 902a9ba658bd0d23dd083c28296f9faa898bfde0..0000000000000000000000000000000000000000
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightParticlePositions.H
+++ /dev/null
@@ -1,54 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 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/>.
-
-InApplication
-    foamToEnsight
-
-Description
-
-SourceFiles
-    ensightParticlePositions.C
-
-\*---------------------------------------------------------------------------*/
-
-#ifndef ensightParticlePositions_H
-#define ensightParticlePositions_H
-
-#include "fvMesh.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-void ensightParticlePositions
-(
-    const Foam::fvMesh& mesh,
-    const Foam::fileName& postProcPath,
-    const Foam::word& timeFile,
-    const Foam::word& CloudName,
-    const bool dataExists
-);
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-#endif
-
-// ************************************************************************* //
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightStream.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightStream.H
index e7369778482c66972bfcb3b571091fc2af256c6d..89146e11023a703e3cfe8087864f2f1e7a215935 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightStream.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/ensightStream.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -57,10 +57,10 @@ class ensightStream
     // Private Member Functions
 
         //- Disallow default bitwise copy construct
-        ensightStream(const ensightStream&);
+        ensightStream(const ensightStream&) = delete;
 
         //- Disallow default bitwise assignment
-        void operator=(const ensightStream&);
+        void operator=(const ensightStream&) = delete;
 
 
 public:
@@ -86,8 +86,6 @@ public:
             return name_;
         }
 
-        virtual bool ascii() const = 0;
-
         virtual void write(const char*) = 0;
 
         virtual void write(const int) = 0;
@@ -98,8 +96,6 @@ public:
 
         virtual void writePartHeader(const label) = 0;
 
-
-
 };
 
 
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C
index af56283641f99f1c0701a7a2c8ef1aa2e1fb1139..ecfb4fe74d80e2e994b737fc28c1be8a44737a57 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.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  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -34,11 +34,14 @@ Description
 
 Usage
     - foamToEnsight [OPTION] \n
-    Translates OpenFOAM data to Ensight format
+    Translates OpenFOAM data to EnSight format
 
     \param -ascii \n
     Write Ensight data in ASCII format instead of "C Binary"
 
+    \param -noZero \n
+    Exclude the often incomplete initial conditions.
+
     \param -patches patchList \n
     Specify particular patches to write.
     Specifying an empty list suppresses writing the internalMesh.
@@ -52,6 +55,9 @@ Usage
     \param -cellZone zoneName \n
     Specify single cellZone to write (not lagrangian)
 
+    \param -width \<n\>\n
+    Width of EnSight data subdir (default: 8)
+
 Note
     Parallel support for cloud data is not supported
     - writes to \a EnSight directory to avoid collisions with foamToEnsightParts
@@ -70,14 +76,12 @@ Note
 #include "scalarIOField.H"
 #include "tensorIOField.H"
 
+#include "ensightFile.H"
 #include "ensightMesh.H"
 #include "ensightField.H"
-
-#include "ensightParticlePositions.H"
-#include "ensightCloudField.H"
+#include "ensightCloud.H"
 
 #include "fvc.H"
-
 #include "cellSet.H"
 #include "fvMeshSubset.H"
 
@@ -151,32 +155,21 @@ int main(int argc, char *argv[])
         "word",
         "specify cellZone to write"
     );
+    argList::addOption
+    (
+        "name",
+        "subdir",
+        "define sub-directory name to use for ensight data "
+        "(default: 'EnSight')"
+    );
+    argList::addOption
+    (
+        "width",
+        "n",
+        "width of ensight data subdir"
+    );
 
-    #include "setRootCase.H"
-
-    // Check options
-    const bool binary = !args.optionFound("ascii");
-    const bool nodeValues = args.optionFound("nodeValues");
-
-    cpuTime timer;
-    memInfo mem;
-    Info<< "Initial memory "
-        << mem.update().size() << " kB" << endl;
-
-    #include "createTime.H"
-
-    instantList Times = timeSelector::select0(runTime, args);
-
-    #include "createNamedMesh.H"
-
-    // Mesh instance (region0 gets filtered out)
-    fileName regionPrefix = "";
-
-    if (regionName != polyMesh::defaultRegion)
-    {
-        regionPrefix = regionName;
-    }
-
+    // the volume field types that we handle
     const label nVolFieldTypes = 10;
     const word volFieldTypes[] =
     {
@@ -193,38 +186,88 @@ int main(int argc, char *argv[])
         volTensorField::DimensionedInternalField::typeName
     };
 
+    #include "setRootCase.H"
+
+    // default to binary output, unless otherwise specified
+    const enum IOstream::streamFormat format =
+    (
+        args.optionFound("ascii")
+      ? IOstream::ASCII
+      : IOstream::BINARY
+    );
+
+    const bool nodeValues = args.optionFound("nodeValues");
+
+    cpuTime timer;
+    memInfo mem;
+    Info<< "Initial memory "
+        << mem.update().size() << " kB" << endl;
+
+    #include "createTime.H"
+
+    instantList timeDirs = timeSelector::select0(runTime, args);
+
+    // adjust output width
+    if (args.optionFound("width"))
+    {
+        ensightFile::subDirWidth(args.optionRead<label>("width"));
+    }
+
+    // define sub-directory name to use for EnSight data
+    fileName ensightDir = "EnSight";
+    args.optionReadIfPresent("name", ensightDir);
+
     // Path to EnSight directory at case level only
     // - For parallel cases, data only written from master
-    fileName ensightDir = args.rootPath()/args.globalCaseName()/"EnSight";
+    if (!ensightDir.isAbsolute())
+    {
+        ensightDir = args.rootPath()/args.globalCaseName()/ensightDir;
+    }
+
+    const fileName dataDir  = ensightDir/"data";
+    const fileName dataMask = dataDir.name()/ensightFile::mask();
 
     if (Pstream::master())
     {
+        // EnSight and EnSight/data directories must exist
+        // - remove old data for a clean conversion of everything
         if (isDir(ensightDir))
         {
             rmDir(ensightDir);
         }
 
-        mkDir(ensightDir);
+        mkDir(dataDir);
+    }
+
+    #include "createNamedMesh.H"
+
+    // Mesh instance (region0 gets filtered out)
+    fileName regionPrefix;
+    if (regionName != polyMesh::defaultRegion)
+    {
+        regionPrefix = regionName;
     }
 
     // Start of case file header output
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    const word prepend = args.globalCaseName() + '.';
-
-    OFstream *ensightCaseFilePtr = NULL;
+    OFstream *ensightCaseFilePtr(nullptr);
     if (Pstream::master())
     {
-        fileName caseFileName = prepend + "case";
+        fileName caseFileName = args.globalCaseName() + ".case";
         Info<< nl << "write case: " << caseFileName.c_str() << endl;
 
-        // the case file is always ASCII
+        // The case file is always ASCII
         ensightCaseFilePtr = new OFstream
         (
             ensightDir/caseFileName,
             IOstream::ASCII
         );
 
+        ensightCaseFilePtr->setf(ios_base::left);
+        ensightCaseFilePtr->setf(ios_base::scientific, ios_base::floatfield);
+        ensightCaseFilePtr->precision(5);
+
         *ensightCaseFilePtr
             << "FORMAT" << nl
             << "type: ensight gold" << nl << nl;
@@ -280,11 +323,11 @@ int main(int argc, char *argv[])
         patchPatterns,
         selectedZones,
         zonePatterns,
-        binary
+        format
     );
 
     // Set Time to the last time before looking for the lagrangian objects
-    runTime.setTime(Times.last(), Times.size()-1);
+    runTime.setTime(timeDirs.last(), timeDirs.size()-1);
 
     IOobjectList objects(mesh, runTime.timeName());
 
@@ -296,88 +339,99 @@ int main(int argc, char *argv[])
             << " Writing meshes for every timestep." << endl;
     }
 
-
-    wordHashSet allCloudNames;
     if (Pstream::master())
     {
-        word geomFileName = prepend + "0000";
+        // test the pre-check variable if there is a moving mesh
+        // time-set for geometries
+        // TODO: split off into separate time-set,
+        // but need to verify ensight spec
 
-        // test pre check variable if there is a moving mesh
         if (meshMoving)
         {
-            geomFileName = prepend + "****";
+            ensightCaseFile
+                << "GEOMETRY" << nl
+                << setw(16) << "model: 1"
+                << (dataMask/ensightMesh::geometryName).c_str() << nl;
+        }
+        else
+        {
+            ensightCaseFile
+                << "GEOMETRY" << nl
+                << setw(16) << "model:"
+                << ensightMesh::geometryName << nl;
         }
-
-        ensightCaseFile
-            << "GEOMETRY" << nl
-            << "model:        1     "
-            << (geomFileName + ".mesh").c_str() << nl;
     }
 
-    // Identify if lagrangian data exists at each time, and add clouds
-    // to the 'allCloudNames' hash set
-    forAll(Times, timeI)
+    // Identify if lagrangian data exists any time step, and add clouds
+    // to the 'cloudNames' (sorted list)
+    wordList cloudNames;
     {
-        runTime.setTime(Times[timeI], timeI);
+        wordHashSet allCloudNames;
 
-        fileNameList cloudDirs = readDir
-        (
-            runTime.timePath()/regionPrefix/cloud::prefix,
-            fileName::DIRECTORY
-        );
-
-        forAll(cloudDirs, cloudI)
+        forAll(timeDirs, timeI)
         {
-            IOobjectList cloudObjs
+            runTime.setTime(timeDirs[timeI], timeI);
+
+            fileNameList cloudDirs = readDir
             (
-                mesh,
-                runTime.timeName(),
-                cloud::prefix/cloudDirs[cloudI]
+                runTime.timePath()/regionPrefix/cloud::prefix,
+                fileName::DIRECTORY
             );
 
-            IOobject* positionsPtr = cloudObjs.lookup(word("positions"));
-
-            if (positionsPtr)
+            forAll(cloudDirs, cloudI)
             {
-                allCloudNames.insert(cloudDirs[cloudI]);
+                IOobjectList cloudObjs
+                (
+                    mesh,
+                    runTime.timeName(),
+                    cloud::prefix/cloudDirs[cloudI]
+                );
+
+                IOobject* positionsPtr = cloudObjs.lookup(word("positions"));
+
+                if (positionsPtr)
+                {
+                    allCloudNames.insert(cloudDirs[cloudI]);
+                }
             }
         }
+
+        // sorted for consistency
+        cloudNames = allCloudNames.sortedToc();
     }
 
     HashTable<HashTable<word>> allCloudFields;
-    forAllConstIter(wordHashSet, allCloudNames, cloudIter)
+    forAll(cloudNames, cloudNo)
     {
+        const word& cloudName = cloudNames[cloudNo];
+
         // Add the name of the cloud(s) to the case file header
         if (Pstream::master())
         {
             ensightCaseFile
-            <<  (
-                    "measured:     1     "
-                  + prepend
-                  + "****."
-                  + cloudIter.key()
-                ).c_str()
-            << nl;
+                << setw(16) << "measured: 1"
+                << fileName(dataMask/cloud::prefix/cloudName/"positions").c_str()
+                << nl;
         }
 
         // Create a new hash table for each cloud
-        allCloudFields.insert(cloudIter.key(), HashTable<word>());
+        allCloudFields.insert(cloudName, HashTable<word>());
 
         // Identify the new cloud in the hash table
         HashTable<HashTable<word>>::iterator newCloudIter =
-            allCloudFields.find(cloudIter.key());
+            allCloudFields.find(cloudName);
 
         // Loop over all times to build list of fields and field types
         // for each cloud
-        forAll(Times, timeI)
+        forAll(timeDirs, timeI)
         {
-            runTime.setTime(Times[timeI], timeI);
+            runTime.setTime(timeDirs[timeI], timeI);
 
             IOobjectList cloudObjs
             (
                 mesh,
                 runTime.timeName(),
-                cloud::prefix/cloudIter.key()
+                cloud::prefix/cloudName
             );
 
             forAllConstIter(IOobjectList, cloudObjs, fieldIter)
@@ -398,15 +452,26 @@ int main(int argc, char *argv[])
     }
 
     label nTimeSteps = 0;
-    forAll(Times, timeIndex)
+    forAll(timeDirs, timeIndex)
     {
-        nTimeSteps++;
-        runTime.setTime(Times[timeIndex], timeIndex);
+        ++nTimeSteps;
+        runTime.setTime(timeDirs[timeIndex], timeIndex);
 
-        word timeName = itoa(timeIndex);
-        word timeFile = prepend + timeName;
+        Info<< "Time [" << timeIndex << "] = " << runTime.timeName() << nl;
 
-        Info<< "Translating time = " << runTime.timeName() << nl;
+        if (Pstream::master())
+        {
+            // the data/ITER subdirectory must exist
+            // Note that data/ITER is indeed a valid ensight::FileName
+            const fileName subDir = ensightFile::subDir(timeIndex);
+            mkDir(dataDir/subDir);
+
+            // place a timestamp in the directory for future reference
+            OFstream timeStamp(dataDir/subDir/"time");
+            timeStamp
+                << "#   timestep time" << nl
+                << subDir.c_str() << " " << runTime.timeName() << nl;
+        }
 
         polyMesh::readUpdateState meshState = mesh.readUpdate();
         if (timeIndex != 0 && meshSubsetter.hasSubMesh())
@@ -420,7 +485,6 @@ int main(int argc, char *argv[])
             meshSubsetter.setLargeCellSubset(c0, 0);
         }
 
-
         if (meshState != polyMesh::UNCHANGED)
         {
             eMesh.correct();
@@ -430,8 +494,7 @@ int main(int argc, char *argv[])
         {
             eMesh.write
             (
-                ensightDir,
-                prepend,
+                dataDir,
                 timeIndex,
                 meshMoving,
                 ensightCaseFile
@@ -450,6 +513,7 @@ int main(int argc, char *argv[])
 
         // Cell field data output
         // ~~~~~~~~~~~~~~~~~~~~~~
+        Info<< "Write volume field (";
 
         for (label i=0; i<nVolFieldTypes; i++)
         {
@@ -491,10 +555,8 @@ int main(int argc, char *argv[])
                     (
                         volField(meshSubsetter, vf),
                         eMesh,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
-                        binary,
                         nodeValues,
                         ensightCaseFile
                     );
@@ -506,10 +568,8 @@ int main(int argc, char *argv[])
                     (
                         volField(meshSubsetter, vf),
                         eMesh,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
-                        binary,
                         nodeValues,
                         ensightCaseFile
                     );
@@ -521,10 +581,8 @@ int main(int argc, char *argv[])
                     (
                         volField(meshSubsetter, vf),
                         eMesh,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
-                        binary,
                         nodeValues,
                         ensightCaseFile
                     );
@@ -536,10 +594,8 @@ int main(int argc, char *argv[])
                     (
                         volField(meshSubsetter, vf),
                         eMesh,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
-                        binary,
                         nodeValues,
                         ensightCaseFile
                     );
@@ -551,10 +607,8 @@ int main(int argc, char *argv[])
                     (
                         volField(meshSubsetter, vf),
                         eMesh,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
-                        binary,
                         nodeValues,
                         ensightCaseFile
                     );
@@ -575,10 +629,8 @@ int main(int argc, char *argv[])
                     (
                         volField<scalar>(meshSubsetter, df),
                         eMesh,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
-                        binary,
                         nodeValues,
                         ensightCaseFile
                     );
@@ -598,10 +650,8 @@ int main(int argc, char *argv[])
                     (
                         volField<vector>(meshSubsetter, df),
                         eMesh,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
-                        binary,
                         nodeValues,
                         ensightCaseFile
                     );
@@ -621,10 +671,8 @@ int main(int argc, char *argv[])
                     (
                         volField<sphericalTensor>(meshSubsetter, df),
                         eMesh,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
-                        binary,
                         nodeValues,
                         ensightCaseFile
                     );
@@ -644,10 +692,8 @@ int main(int argc, char *argv[])
                     (
                         volField<symmTensor>(meshSubsetter, df),
                         eMesh,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
-                        binary,
                         nodeValues,
                         ensightCaseFile
                     );
@@ -667,24 +713,30 @@ int main(int argc, char *argv[])
                     (
                         volField<tensor>(meshSubsetter, df),
                         eMesh,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
-                        binary,
                         nodeValues,
                         ensightCaseFile
                     );
                 }
             }
         }
+        Info<< " )" << endl;
 
 
         // Cloud field data output
         // ~~~~~~~~~~~~~~~~~~~~~~~
 
-        forAllConstIter(HashTable<HashTable<word>>, allCloudFields, cloudIter)
+        forAll(cloudNames, cloudNo)
         {
-            const word& cloudName = cloudIter.key();
+            const word& cloudName = cloudNames[cloudNo];
+            if (!allCloudFields.found(cloudName))
+            {
+                // extra safety
+                continue;
+            }
+
+            const HashTable<word>& cloudFields = allCloudFields[cloudName];
 
             fileNameList currentCloudDirs = readDir
             (
@@ -692,17 +744,22 @@ int main(int argc, char *argv[])
                 fileName::DIRECTORY
             );
 
+            Info<< "Write " << cloudName << " (";
+
             bool cloudExists = inFileNameList(currentCloudDirs, cloudName);
+            reduce(cloudExists, orOp<bool>());
+
             ensightParticlePositions
             (
                 mesh,
-                ensightDir,
-                timeFile,
+                dataDir,
+                timeIndex,
                 cloudName,
-                cloudExists
+                cloudExists,
+                format
             );
 
-            forAllConstIter(HashTable<word>, cloudIter(), fieldIter)
+            forAllConstIter(HashTable<word>, cloudFields, fieldIter)
             {
                 const word& fieldName = fieldIter.key();
                 const word& fieldType = fieldIter();
@@ -720,17 +777,20 @@ int main(int argc, char *argv[])
                 (
                     false
                 );
+                reduce(fieldExists, orOp<bool>());
+
                 if (fieldType == scalarIOField::typeName)
                 {
                     ensightCloudField<scalar>
                     (
                         fieldObject,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
                         cloudName,
+                        cloudNo,
                         ensightCaseFile,
-                        fieldExists
+                        fieldExists,
+                        format
                     );
                 }
                 else if (fieldType == vectorIOField::typeName)
@@ -738,37 +798,34 @@ int main(int argc, char *argv[])
                     ensightCloudField<vector>
                     (
                         fieldObject,
-                        ensightDir,
-                        prepend,
+                        dataDir,
                         timeIndex,
                         cloudName,
+                        cloudNo,
                         ensightCaseFile,
-                        fieldExists
+                        fieldExists,
+                        format
                     );
                 }
-                else
-                {
-                    Info<< "Unable to convert field type " << fieldType
-                        << " for field " << fieldName << endl;
-                }
             }
+            Info<< " )" << endl;
         }
 
         Info<< "Wrote in "
             << timer.cpuTimeIncrement() << " s, "
-            << mem.update().size() << " kB" << endl;
+            << mem.update().size() << " kB" << nl << endl;
     }
 
     #include "ensightCaseTail.H"
 
-    if (Pstream::master())
+    if (ensightCaseFilePtr) // on master only
     {
         delete ensightCaseFilePtr;
     }
 
-    Info<< "\nEnd: "
+    Info<< "End: "
         << timer.elapsedCpuTime() << " s, "
-        << mem.update().peak() << " kB (peak)\n" << endl;
+        << mem.update().peak() << " kB (peak)" << nl << endl;
 
     return 0;
 }
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/itoa.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/itoa.C
deleted file mode 100644
index 0975da93d30f87fbacbfe7ab0bba0637a7d05cd0..0000000000000000000000000000000000000000
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/itoa.C
+++ /dev/null
@@ -1,61 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2013 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 "itoa.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-word itoa(const label n)
-{
-    const label offset = '0';
-    const label length = 4;
-
-    char val[length + 1];
-
-    label leftOfN = n;
-
-    for (label i=0; i<length; i++)
-    {
-        label j = label(leftOfN/pow(10, length - i - 1));
-        leftOfN -= j*pow(10, length - i - 1);
-        val[i] = offset + j;
-    }
-
-    val[length] = 0;
-
-    return val;
-}
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
-// ************************************************************************* //
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/itoa.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/itoa.H
deleted file mode 100644
index 0977a38960c15e24a75f9d3cede1813350609343..0000000000000000000000000000000000000000
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/itoa.H
+++ /dev/null
@@ -1,47 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 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/>.
-
-InApplication
-    foamToEnsight
-
-Description
-
-\*---------------------------------------------------------------------------*/
-
-#include "word.H"
-#include "label.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-word itoa(const label n);
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
-// ************************************************************************* //