From 3dd1a13b0f6acb1f01a349ebcd9be12238da2fc8 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Tue, 29 Jan 2019 15:18:17 +0100
Subject: [PATCH] ENH: restructuring of ensight output files

- changed ensightOutput from a class solely comprising static methods to
  a namespace and added in sub-namespaces Detail and Serial.

  This makes it easier to "mix-in" functions at different levels.
  Refactored and combined some serial/parallel code where possible.

  The general ensightOutput namespace has now shifted to be in the
  fileFormats lib, while leaving volField outputs in the conversion lib
  and cloud outputs in the lagrangian-intermediate lib.

  The ensightCloud namespace is now simply folded into the new
  ensightOutput namespace.

  These changes clean up some code, reduce fragmentation and
  duplication and removes the previous libconversion dependency for
  sampling.

- use int for ensight nTypes constexpr

Note: issue #1176 is unaffected except for the change in file name:

   ensightOutputTemplates.C -> ensightOutputVolFieldTemplates.C
---
 .../foamToEnsight/convertLagrangian.H         |   6 +-
 .../foamToEnsight/foamToEnsight.C             |   2 +-
 .../foamToEnsight/writeVolFields.H            |   4 +-
 .../foamToEnsightParts/convertLagrangian.H    |   6 +-
 .../foamToEnsightParts/foamToEnsightParts.C   |   2 +-
 .../foamToEnsightParts/writeVolFields.H       |   5 +-
 src/conversion/ensight/output/ensightOutput.H | 164 ---------
 .../ensight/output/ensightOutputVolField.H    | 148 ++++++++
 ...tes.C => ensightOutputVolFieldTemplates.C} | 310 +++++++----------
 .../ensight/output/ensightSerialOutput.H      | 146 --------
 .../output/ensightSerialOutputTemplates.C     | 174 ----------
 .../ensight/output/ensightOutput.H            | 146 ++++++++
 .../ensight/output/ensightOutputTemplates.C   | 323 ++++++++++++++++++
 src/fileFormats/ensight/part/ensightCells.H   |   2 +-
 src/fileFormats/ensight/part/ensightFaces.H   |   2 +-
 .../ensight/part/ensightPartCells.C           |   6 +-
 .../ensight/part/ensightPartFaces.C           |   8 +-
 .../ensightWrite/ensightWriteTemplates.C      |   8 +-
 .../conversion/ensight/ensightOutputCloud.C   |   8 +-
 .../conversion/ensight/ensightOutputCloud.H   |  19 +-
 .../ensight/ensightOutputCloudTemplates.C     |   6 +-
 src/sampling/Make/options                     |   2 -
 .../ensight/ensightSurfaceWriterImpl.C        |  61 +++-
 23 files changed, 820 insertions(+), 738 deletions(-)
 delete mode 100644 src/conversion/ensight/output/ensightOutput.H
 create mode 100644 src/conversion/ensight/output/ensightOutputVolField.H
 rename src/conversion/ensight/output/{ensightOutputTemplates.C => ensightOutputVolFieldTemplates.C} (62%)
 delete mode 100644 src/conversion/ensight/output/ensightSerialOutput.H
 delete mode 100644 src/conversion/ensight/output/ensightSerialOutputTemplates.C
 create mode 100644 src/fileFormats/ensight/output/ensightOutput.H
 create mode 100644 src/fileFormats/ensight/output/ensightOutputTemplates.C

diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H
index 46989a4e64..7f94597067 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H
@@ -56,7 +56,7 @@ if (doLagrangian)
         {
             autoPtr<ensightFile> os = ensCase.newCloud(cloudName);
 
-            ensightCloud::writePositions
+            ensightOutput::writeCloudPositions
             (
                 mesh,
                 cloudName,
@@ -104,7 +104,7 @@ if (doLagrangian)
                 autoPtr<ensightFile> os =
                     ensCase.newCloudData<scalar>(cloudName, fieldName);
 
-                wrote = ensightCloud::writeCloudField<scalar>
+                wrote = ensightOutput::writeCloudField<scalar>
                 (
                     fieldObject, fieldExists, os
                 );
@@ -114,7 +114,7 @@ if (doLagrangian)
                 autoPtr<ensightFile> os =
                     ensCase.newCloudData<vector>(cloudName, fieldName);
 
-                wrote = ensightCloud::writeCloudField<vector>
+                wrote = ensightOutput::writeCloudField<vector>
                 (
                     fieldObject, fieldExists, os
                 );
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C
index 68815b8bfe..e90b846240 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C
@@ -99,8 +99,8 @@ Note
 #include "ensightCase.H"
 #include "ensightGeoFile.H"
 #include "ensightMesh.H"
-#include "ensightOutput.H"
 #include "ensightOutputCloud.H"
+#include "ensightOutputVolField.H"
 #include "fvMeshSubsetProxy.H"
 
 // local files
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeVolFields.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeVolFields.H
index 98f388d9ec..f72c74db59 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeVolFields.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeVolFields.H
@@ -62,11 +62,11 @@ bool writeVolField
 
     autoPtr<ensightFile> os = ensCase.newData<Type>(field.name());
 
-    bool wrote = ensightOutput::writeField<Type>
+    bool wrote = ensightOutput::writeVolField<Type>
     (
         field,
         ensMesh,
-        os,
+        os.ref(),
         nodeValues
     );
 
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertLagrangian.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertLagrangian.H
index 827500474b..ce1f9b4d64 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertLagrangian.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertLagrangian.H
@@ -55,7 +55,7 @@ if (doLagrangian)
         {
             autoPtr<ensightFile> os = ensCase.newCloud(cloudName);
 
-            ensightCloud::writePositions
+            ensightOutput::writeCloudPositions
             (
                 mesh,
                 cloudName,
@@ -103,7 +103,7 @@ if (doLagrangian)
                 autoPtr<ensightFile> os =
                     ensCase.newCloudData<scalar>(cloudName, fieldName);
 
-                wrote = ensightCloud::writeCloudField<scalar>
+                wrote = ensightOutput::writeCloudField<scalar>
                 (
                     fieldObject, fieldExists, os
                 );
@@ -113,7 +113,7 @@ if (doLagrangian)
                 autoPtr<ensightFile> os =
                     ensCase.newCloudData<vector>(cloudName, fieldName);
 
-                wrote = ensightCloud::writeCloudField<vector>
+                wrote = ensightOutput::writeCloudField<vector>
                 (
                     fieldObject, fieldExists, os
                 );
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/foamToEnsightParts.C b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/foamToEnsightParts.C
index 4aa572c436..c3460ea729 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/foamToEnsightParts.C
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/foamToEnsightParts.C
@@ -94,8 +94,8 @@ Note
 #include "ensightCase.H"
 #include "ensightGeoFile.H"
 #include "ensightParts.H"
-#include "ensightSerialOutput.H"
 #include "ensightOutputCloud.H"
+#include "ensightOutputVolField.H"
 #include "fvMeshSubsetProxy.H"
 
 // local files
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/writeVolFields.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/writeVolFields.H
index 303f97ad53..017ef31bf0 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/writeVolFields.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/writeVolFields.H
@@ -61,11 +61,12 @@ bool writeVolField
 
     autoPtr<ensightFile> os = ensCase.newData<Type>(field.name());
 
-    bool wrote = ensightSerialOutput::writeField<Type>
+    // Currently serial only
+    bool wrote = ensightOutput::Serial::writeVolField<Type>
     (
         field,
         ensParts,
-        os
+        os.ref()
     );
 
     tfield.clear();
diff --git a/src/conversion/ensight/output/ensightOutput.H b/src/conversion/ensight/output/ensightOutput.H
deleted file mode 100644
index 2649fd5b76..0000000000
--- a/src/conversion/ensight/output/ensightOutput.H
+++ /dev/null
@@ -1,164 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  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/>.
-
-Class
-    Foam::ensightOutput
-
-Description
-    A collection of functions for writing ensight file content in parallel.
-
-SourceFiles
-    ensightOutput.C
-    ensightOutputTemplates.C
-
-\*---------------------------------------------------------------------------*/
-
-#ifndef ensightOutput_H
-#define ensightOutput_H
-
-#include "ensightFile.H"
-#include "ensightMesh.H"
-#include "autoPtr.H"
-#include "volFields.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-
-namespace Foam
-{
-
-/*---------------------------------------------------------------------------*\
-                        Class ensightOutput Declaration
-\*---------------------------------------------------------------------------*/
-
-class ensightOutput
-{
-    // Private Methods
-
-    //- Write field content (component-wise) for the given ensight element type
-    template<template<typename> class FieldContainer, class Type>
-    static void writeFieldContent
-    (
-        const char* key,
-        const FieldContainer<Type>& fld,
-        ensightFile& os
-    );
-
-    //- Write a field of faces values as an indirect list,
-    //  using the face ids from ensightFaces
-    template<class Type>
-    static bool writeFaceField
-    (
-        const Field<Type>& fld,
-        const ensightFaces&,
-        ensightFile& os
-    );
-
-    //- Write a field of faces values as a sublist,
-    //  using the sublist sizes ensightFaces
-    template<class Type>
-    static bool writeFaceSubField
-    (
-        const Field<Type>& fld,
-        const ensightFaces&,
-        ensightFile& os
-    );
-
-    //- Write a field of cell values as an indirect list,
-    //  using the cell ids from ensightCells
-    template<class Type>
-    static bool writeCellField
-    (
-        const Field<Type>& fld,
-        const ensightCells&,
-        ensightFile& os
-    );
-
-
-    //- Write volume field component-wise
-    template<class Type>
-    static bool writeField
-    (
-        const GeometricField<Type, fvPatchField, volMesh>& vf,
-        const ensightMesh& ensMesh,
-        ensightFile& os
-    );
-
-    //- Write point field component-wise
-    template<class Type>
-    static bool ensightPointField
-    (
-        const GeometricField<Type, pointPatchField, pointMesh>& pf,
-        const ensightMesh& ensMesh,
-        ensightFile& os
-    );
-
-    //- No null constructor
-    ensightOutput() = delete;
-
-
-public:
-
-    // Public Methods
-
-    //- Write volume field component-wise
-    template<class Type>
-    static bool writeField
-    (
-        const GeometricField<Type, fvPatchField, volMesh>&,
-        const ensightMesh& ensMesh,
-        ensightFile& os,
-        const bool nodeValues
-    );
-
-
-    //- Write volume field component-wise
-    template<class Type>
-    static inline bool writeField
-    (
-        const GeometricField<Type, fvPatchField, volMesh>& vf,
-        const ensightMesh& ensMesh,
-        autoPtr<ensightFile>& output,
-        const bool nodeValues = false
-    )
-    {
-        return writeField(vf, ensMesh, output.ref(), nodeValues);
-    }
-
-};
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-#ifdef NoRepository
-    #include "ensightOutputTemplates.C"
-#endif
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-#endif
-
-// ************************************************************************* //
diff --git a/src/conversion/ensight/output/ensightOutputVolField.H b/src/conversion/ensight/output/ensightOutputVolField.H
new file mode 100644
index 0000000000..fd3bf9506a
--- /dev/null
+++ b/src/conversion/ensight/output/ensightOutputVolField.H
@@ -0,0 +1,148 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2016-2019 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+InNamespace
+    Foam::ensightOutput
+
+Description
+    A collection of functions for writing volField content in ensight format.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef ensightOutputVolField_H
+#define ensightOutputVolField_H
+
+#include "ensightOutput.H"
+#include "ensightPart.H"
+#include "ensightParts.H"
+#include "ensightPartFaces.H"
+#include "ensightPartCells.H"
+#include "volFields.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declarations
+class ensightMesh;
+
+namespace ensightOutput
+{
+
+/*---------------------------------------------------------------------------*\
+                        Namespace ensightOutput::Detail
+\*---------------------------------------------------------------------------*/
+
+namespace Detail
+{
+
+//- Write volume field component-wise
+template<class Type>
+bool writeVolField
+(
+    const GeometricField<Type, fvPatchField, volMesh>& vf,
+    const ensightMesh& ensMesh,
+    ensightFile& os
+);
+
+//- Write point field component-wise
+template<class Type>
+bool writePointField
+(
+    const GeometricField<Type, pointPatchField, pointMesh>& pf,
+    const ensightMesh& ensMesh,
+    ensightFile& os
+);
+
+} // End namespace Detail
+
+
+/*---------------------------------------------------------------------------*\
+                            Namespace ensightOutput
+\*---------------------------------------------------------------------------*/
+
+//- Write volume field component-wise
+template<class Type>
+bool writeVolField
+(
+    const GeometricField<Type, fvPatchField, volMesh>&,
+    const ensightMesh& ensMesh,
+    ensightFile& os,
+    const bool nodeValues = false
+);
+
+
+/*---------------------------------------------------------------------------*\
+                        Namespace ensightOutput::Serial
+\*---------------------------------------------------------------------------*/
+
+namespace Serial
+{
+
+//- Write volume field component-wise for specified faces
+template<class Type>
+bool writeVolField
+(
+    const GeometricField<Type, fvPatchField, volMesh>& vf,
+    const ensightPartFaces& part,
+    ensightFile& os
+);
+
+
+//- Write volume field component-wise for specified cells
+template<class Type>
+bool writeVolField
+(
+    const GeometricField<Type, fvPatchField, volMesh>& vf,
+    const ensightPartCells& part,
+    ensightFile& os
+);
+
+
+//- Write volume field component-wise
+template<class Type>
+bool writeVolField
+(
+    const GeometricField<Type, fvPatchField, volMesh>& vf,
+    const ensightParts& list,
+    ensightFile& os
+);
+
+} // End namespace Serial
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace ensightOutput
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "ensightOutputVolFieldTemplates.C"
+#endif
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/conversion/ensight/output/ensightOutputTemplates.C b/src/conversion/ensight/output/ensightOutputVolFieldTemplates.C
similarity index 62%
rename from src/conversion/ensight/output/ensightOutputTemplates.C
rename to src/conversion/ensight/output/ensightOutputVolFieldTemplates.C
index 5176845e6f..4a22d74d8a 100644
--- a/src/conversion/ensight/output/ensightOutputTemplates.C
+++ b/src/conversion/ensight/output/ensightOutputVolFieldTemplates.C
@@ -23,191 +23,29 @@ License
 
 \*---------------------------------------------------------------------------*/
 
-#include "ensightFile.H"
-#include "ensightOutput.H"
-#include "ensightPTraits.H"
+#include "ensightOutputVolField.H"
+#include "ensightMesh.H"
 
 #include "fvMesh.H"
-#include "volFields.H"
-#include "IOField.H"
-#include "OFstream.H"
-#include "IOmanip.H"
-#include "Time.H"
-#include "volPointInterpolation.H"
 #include "globalIndex.H"
-#include "uindirectPrimitivePatch.H"
+#include "volPointInterpolation.H"
 #include "interpolation.H"
 #include "linear.H"
 #include "processorFvPatch.H"
+#include "uindirectPrimitivePatch.H"
 
-// * * * * * * * * * * Static Private Member Functions * * * * * * * * * * * //
-
-template<template<typename> class FieldContainer, class Type>
-void Foam::ensightOutput::writeFieldContent
-(
-    const char* key,
-    const FieldContainer<Type>& fld,
-    ensightFile& os
-)
-{
-    if (returnReduce(fld.size(), sumOp<label>()) > 0)
-    {
-        if (Pstream::master())
-        {
-            os.writeKeyword(key);
-
-            for (direction d=0; d < pTraits<Type>::nComponents; ++d)
-            {
-                const label cmpt = ensightPTraits<Type>::componentOrder[d];
-
-                os.writeList(fld.component(cmpt));
-
-                for (int slave=1; slave<Pstream::nProcs(); ++slave)
-                {
-                    IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
-                    scalarField received(fromSlave);
-                    os.writeList(received);
-                }
-            }
-        }
-        else
-        {
-            for (direction d=0; d < pTraits<Type>::nComponents; ++d)
-            {
-                const label cmpt = ensightPTraits<Type>::componentOrder[d];
-
-                OPstream toMaster
-                (
-                    Pstream::commsTypes::scheduled,
-                    Pstream::masterNo()
-                );
-
-                toMaster
-                    << fld.component(cmpt);
-            }
-        }
-    }
-}
-
-
-template<class Type>
-bool Foam::ensightOutput::writeFaceField
-(
-    const Field<Type>& pf,
-    const ensightFaces& ensFaces,
-    Foam::ensightFile& os
-)
-{
-    if (ensFaces.total())
-    {
-        if (Pstream::master())
-        {
-            os.beginPart(ensFaces.index());
-        }
-
-        for (label typei=0; typei < ensightFaces::nTypes; ++typei)
-        {
-            const ensightFaces::elemType what =
-                ensightFaces::elemType(typei);
-
-            writeFieldContent
-            (
-                ensightFaces::key(what),
-                Field<Type>(pf, ensFaces.faceIds(what)),
-                os
-            );
-        }
-
-        return true;
-    }
-
-    return false;
-}
-
-
-template<class Type>
-bool Foam::ensightOutput::writeFaceSubField
-(
-    const Field<Type>& pf,
-    const ensightFaces& ensFaces,
-    Foam::ensightFile& os
-)
-{
-    if (ensFaces.total())
-    {
-        if (Pstream::master())
-        {
-            os.beginPart(ensFaces.index());
-        }
-
-        label start = 0; // start of sublist
-        for (label typei=0; typei < ensightFaces::nTypes; ++typei)
-        {
-            const ensightFaces::elemType what =
-                ensightFaces::elemType(typei);
-
-            const label size = ensFaces.faceIds(what).size();
-
-            writeFieldContent
-            (
-                ensightFaces::key(what),
-                SubField<Type>(pf, size, start),
-                os
-            );
-
-            start += size; // start of next sublist
-        }
-
-        return true;
-    }
-
-    return false;
-}
-
-
-template<class Type>
-bool Foam::ensightOutput::writeCellField
-(
-    const Field<Type>& vf,
-    const ensightCells& ensCells,
-    ensightFile& os
-)
-{
-    if (ensCells.total())
-    {
-        if (Pstream::master())
-        {
-            os.beginPart(ensCells.index());
-        }
-
-        for (label typei=0; typei < ensightCells::nTypes; ++typei)
-        {
-            const ensightCells::elemType what =
-                ensightCells::elemType(typei);
-
-            writeFieldContent
-            (
-                ensightCells::key(what),
-                Field<Type>(vf, ensCells.cellIds(what)),
-                os
-            );
-        }
-
-        return true;
-    }
-
-    return false;
-}
-
+// * * * * * * * * * * * * * * * *  Detail * * * * * * * * * * * * * * * * * //
 
 template<class Type>
-bool Foam::ensightOutput::writeField
+bool Foam::ensightOutput::Detail::writeVolField
 (
     const GeometricField<Type, fvPatchField, volMesh>& vf,
     const ensightMesh& ensMesh,
     ensightFile& os
 )
 {
+    constexpr bool parallel = true;
+
     const fvMesh& mesh = ensMesh.mesh();
     const ensightCells& meshCells = ensMesh.meshCells();
     const Map<word>&  patchLookup = ensMesh.patches();
@@ -219,7 +57,7 @@ bool Foam::ensightOutput::writeField
     //
     if (ensMesh.useInternalMesh())
     {
-        writeCellField(vf, meshCells, os);
+        Detail::writeCellField(vf, meshCells, os, parallel);
     }
 
     //
@@ -230,13 +68,14 @@ bool Foam::ensightOutput::writeField
     for (const label patchId : patchIds)
     {
         const word& patchName = patchLookup[patchId];
-        const ensightFaces& ensFaces = patchFaces[patchName];
+        const ensightFaces& part = patchFaces[patchName];
 
         writeFaceField
         (
             vf.boundaryField()[patchId],
-            ensFaces,
-            os
+            part,
+            os,
+            parallel
         );
     }
 
@@ -291,17 +130,17 @@ bool Foam::ensightOutput::writeField
 
         for (const word& zoneName : zoneNames)
         {
-            const ensightFaces& ensFaces = zoneFaces[zoneName];
+            const ensightFaces& part = zoneFaces[zoneName];
 
             // Field (local size)
-            Field<Type> values(ensFaces.size());
+            Field<Type> values(part.size());
 
             // Loop over face ids to store the needed field values
             // - internal faces use linear interpolation
             // - boundary faces use the corresponding patch value
-            forAll(ensFaces, i)
+            forAll(part, i)
             {
-                const label faceId = ensFaces[i];
+                const label faceId = part[i];
                 values[i] =
                 (
                     mesh.isInternalFace(faceId)
@@ -312,7 +151,7 @@ bool Foam::ensightOutput::writeField
 
             // The field is already copied in the proper order
             // - just need its corresponding sub-fields
-            writeFaceSubField(values, ensFaces, os);
+            Detail::writeFaceSubField(values, part, os, parallel);
         }
     }
 
@@ -321,13 +160,15 @@ bool Foam::ensightOutput::writeField
 
 
 template<class Type>
-bool Foam::ensightOutput::ensightPointField
+bool Foam::ensightOutput::Detail::writePointField
 (
     const GeometricField<Type, pointPatchField, pointMesh>& pf,
     const ensightMesh& ensMesh,
     ensightFile& os
 )
 {
+    constexpr bool parallel = true;
+
     const fvMesh& mesh = ensMesh.mesh();
     const Map<word>& patchLookup  = ensMesh.patches();
 
@@ -344,11 +185,12 @@ bool Foam::ensightOutput::ensightPointField
             os.beginPart(0); // 0 = internalMesh
         }
 
-        writeFieldContent
+        Detail::writeFieldComponents
         (
             "coordinates",
             Field<Type>(pf.internalField(), ensMesh.uniquePointMap()),
-            os
+            os,
+            parallel
         );
     }
 
@@ -360,7 +202,7 @@ bool Foam::ensightOutput::ensightPointField
     for (const label patchId : patchIds)
     {
         const word& patchName = patchLookup[patchId];
-        const ensightFaces& ensFaces = patchFaces[patchName];
+        const ensightFaces& part = patchFaces[patchName];
 
         const fvPatch& p = mesh.boundary()[patchId];
 
@@ -378,14 +220,15 @@ bool Foam::ensightOutput::ensightPointField
 
         if (Pstream::master())
         {
-            os.beginPart(ensFaces.index());
+            os.beginPart(part.index());
         }
 
-        writeFieldContent
+        Detail::writeFieldComponents
         (
             "coordinates",
             Field<Type>(pf.internalField(), uniqueMeshPointLabels),
-            os
+            os,
+            parallel
         );
     }
 
@@ -395,14 +238,14 @@ bool Foam::ensightOutput::ensightPointField
     const wordList zoneNames = zoneFaces.sortedToc();
     for (const word& zoneName : zoneNames)
     {
-        const ensightFaces& ensFaces = zoneFaces[zoneName];
+        const ensightFaces& part = zoneFaces[zoneName];
 
         uindirectPrimitivePatch p
         (
             UIndirectList<face>
             (
                 mesh.faces(),
-                ensFaces.faceIds()
+                part.faceIds()
             ),
             mesh.points()
         );
@@ -421,14 +264,15 @@ bool Foam::ensightOutput::ensightPointField
 
         if (Pstream::master())
         {
-            os.beginPart(ensFaces.index());
+            os.beginPart(part.index());
         }
 
-        writeFieldContent
+        Detail::writeFieldComponents
         (
             "coordinates",
             Field<Type>(pf.internalField(), uniqueMeshPointLabels),
-            os
+            os,
+            parallel
         );
     }
 
@@ -436,10 +280,10 @@ bool Foam::ensightOutput::ensightPointField
 }
 
 
-// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 template<class Type>
-bool Foam::ensightOutput::writeField
+bool Foam::ensightOutput::writeVolField
 (
     const GeometricField<Type, fvPatchField, volMesh>& vf,
     const ensightMesh& ensMesh,
@@ -456,12 +300,86 @@ bool Foam::ensightOutput::writeField
         pfld.ref().checkOut();
         pfld.ref().rename(vf.name());
 
-        return ensightPointField<Type>(pfld, ensMesh, os);
+        return Detail::writePointField<Type>(pfld, ensMesh, os);
     }
-    else
+
+    return Detail::writeVolField<Type>(vf, ensMesh, os);
+}
+
+
+// * * * * * * * * * * * * * * * *  Serial * * * * * * * * * * * * * * * * * //
+
+template<class Type>
+bool Foam::ensightOutput::Serial::writeVolField
+(
+    const GeometricField<Type, fvPatchField, volMesh>& vf,
+    const ensightPartFaces& part,
+    ensightFile& os
+)
+{
+    const label patchi = part.patchIndex();
+
+    if (patchi >= 0 && patchi < vf.boundaryField().size())
     {
-        return writeField<Type>(vf, ensMesh, os);
+        return ensightOutput::Detail::writeFaceField
+        (
+            vf.boundaryField()[patchi],
+            part,
+            os,
+            false // serial
+        );
     }
+
+    return false;
+}
+
+
+template<class Type>
+bool Foam::ensightOutput::Serial::writeVolField
+(
+    const GeometricField<Type, fvPatchField, volMesh>& vf,
+    const ensightPartCells& part,
+    ensightFile& os
+)
+{
+    return ensightOutput::Detail::writeCellField
+    (
+        vf.internalField(),
+        part,
+        os,
+        false // serial
+    );
+}
+
+
+template<class Type>
+bool Foam::ensightOutput::Serial::writeVolField
+(
+    const GeometricField<Type, fvPatchField, volMesh>& vf,
+    const ensightParts& list,
+    ensightFile& os
+)
+{
+    for (const ensightPart& part : list)
+    {
+        const ensightPartFaces* fptr = isA<ensightPartFaces>(part);
+
+        if (fptr)
+        {
+            Serial::writeVolField(vf, *fptr, os);
+            continue;
+        }
+
+        const ensightPartCells* cptr = isA<ensightPartCells>(part);
+
+        if (cptr)
+        {
+            Serial::writeVolField(vf, *cptr, os);
+            continue;
+        }
+    }
+
+    return true;
 }
 
 
diff --git a/src/conversion/ensight/output/ensightSerialOutput.H b/src/conversion/ensight/output/ensightSerialOutput.H
deleted file mode 100644
index 5fa1c359d3..0000000000
--- a/src/conversion/ensight/output/ensightSerialOutput.H
+++ /dev/null
@@ -1,146 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
-     \\/     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::ensightSerialOutput
-
-Description
-    A collection of functions for writing ensight file content in serial.
-    Can be considered transitional and may eventually merge with ensightOutput.
-
-SourceFiles
-    ensightSerialOutputTemplates.C
-
-\*---------------------------------------------------------------------------*/
-
-#ifndef ensightSerialOutput_H
-#define ensightSerialOutput_H
-
-#include "ensightPart.H"
-#include "ensightPartFaces.H"
-#include "ensightPartCells.H"
-#include "ensightParts.H"
-#include "volFields.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-
-/*---------------------------------------------------------------------------*\
-                     Class ensightSerialOutput Declaration
-\*---------------------------------------------------------------------------*/
-
-class ensightSerialOutput
-{
-    // Private Methods
-
-    //- Write field content (component-wise) for the given ensight element type
-    template<template<typename> class FieldContainer, class Type>
-    static void writeFieldContent
-    (
-        const word& key,
-        const FieldContainer<Type>& fld,
-        ensightFile& os
-    );
-
-    //- No null constructor
-    ensightSerialOutput() = delete;
-
-
-public:
-
-    // Public Methods
-
-    //- Write field component-wise
-    template<class Type>
-    static bool writeField
-    (
-        const Field<Type>&,
-        const ensightPartFaces& part,
-        ensightFile& os,
-        const bool nodeValues
-    );
-
-
-    //- Write volume field component-wise
-    template<class Type>
-    static bool writeField
-    (
-        const GeometricField<Type, fvPatchField, volMesh>&,
-        const ensightPartCells& part,
-        ensightFile& os
-    );
-
-
-    //- Write volume field component-wise
-    template<class Type>
-    static bool writeField
-    (
-        const GeometricField<Type, fvPatchField, volMesh>&,
-        const ensightParts& list,
-        ensightFile& os
-    );
-
-
-    //- Write volume field component-wise
-    template<class Type>
-    static inline bool writeField
-    (
-        const GeometricField<Type, fvPatchField, volMesh>& vf,
-        const ensightPartCells& part,
-        autoPtr<ensightFile>& output
-    )
-    {
-        return writeField(vf, part, output.ref());
-    }
-
-
-    //- Write volume field component-wise
-    template<class Type>
-    static inline bool writeField
-    (
-        const GeometricField<Type, fvPatchField, volMesh>& vf,
-        const ensightParts& list,
-        autoPtr<ensightFile>& output
-    )
-    {
-        return writeField(vf, list, output.ref());
-    }
-
-};
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-#ifdef NoRepository
-    #include "ensightSerialOutputTemplates.C"
-#endif
-
-#endif
-
-// ************************************************************************* //
diff --git a/src/conversion/ensight/output/ensightSerialOutputTemplates.C b/src/conversion/ensight/output/ensightSerialOutputTemplates.C
deleted file mode 100644
index 3a027ab6dd..0000000000
--- a/src/conversion/ensight/output/ensightSerialOutputTemplates.C
+++ /dev/null
@@ -1,174 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
-     \\/     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 "ensightPart.H"
-#include "ensightParts.H"
-#include "ensightPTraits.H"
-#include "direction.H"
-#include "typeInfo.H"
-
-// * * * * * * * * * * Static Private Member Functions * * * * * * * * * * * //
-
-template<template<typename> class FieldContainer, class Type>
-void Foam::ensightSerialOutput::writeFieldContent
-(
-    const word& key,
-    const FieldContainer<Type>& fld,
-    ensightFile& os
-)
-{
-    if (fld.size())
-    {
-        os.writeKeyword(key);
-
-        for (direction d=0; d < pTraits<Type>::nComponents; ++d)
-        {
-            const label cmpt = ensightPTraits<Type>::componentOrder[d];
-
-            os.writeList(fld.component(cmpt));
-        }
-    }
-}
-
-
-// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
-
-template<class Type>
-bool Foam::ensightSerialOutput::writeField
-(
-    const Field<Type>& fld,
-    const ensightPartFaces& part,
-    ensightFile& os,
-    const bool nodeValues
-)
-{
-    if (part.size() && fld.size())
-    {
-        if (nodeValues)
-        {
-            os.beginPart(part.index());
-
-            os.writeKeyword("coordinates");
-            for (direction d=0; d < pTraits<Type>::nComponents; ++d)
-            {
-                const label cmpt = ensightPTraits<Type>::componentOrder[d];
-
-                os.writeList(fld.component(cmpt));
-            }
-        }
-        else
-        {
-            os.beginPart(part.index());
-
-            for (label typei=0; typei < ensightFaces::nTypes; ++typei)
-            {
-                const ensightFaces::elemType what =
-                    ensightFaces::elemType(typei);
-
-                writeFieldContent
-                (
-                    ensightFaces::key(what),
-                    Field<Type>(fld, part.faceIds(what)),
-                    os
-                );
-            }
-        }
-    }
-
-    return true;
-}
-
-
-template<class Type>
-bool Foam::ensightSerialOutput::writeField
-(
-    const GeometricField<Type, fvPatchField, volMesh>& fld,
-    const ensightPartCells& part,
-    ensightFile& os
-)
-{
-    if (part.size() && fld.size())
-    {
-        os.beginPart(part.index());
-
-        for (label typei=0; typei < ensightCells::nTypes; ++typei)
-        {
-            const ensightCells::elemType what =
-                ensightCells::elemType(typei);
-
-            writeFieldContent
-            (
-                ensightCells::key(what),
-                Field<Type>(fld, part.cellIds(what)),
-                os
-            );
-        }
-    }
-
-    return true;
-}
-
-
-template<class Type>
-bool Foam::ensightSerialOutput::writeField
-(
-    const GeometricField<Type, fvPatchField, volMesh>& vf,
-    const ensightParts& list,
-    ensightFile& os
-)
-{
-    forAllConstIter(ensightParts::StorageType, list, iter)
-    {
-        if (isA<ensightPartFaces>(*iter))
-        {
-            const ensightPartFaces& part =
-                dynamicCast<const ensightPartFaces&>(*iter);
-
-            const label patchi = part.patchIndex();
-            if (patchi >= 0 && patchi < vf.boundaryField().size())
-            {
-                writeField
-                (
-                    vf.boundaryField()[patchi],
-                    part,
-                    os,
-                    false
-                );
-            }
-        }
-        else
-        {
-            const ensightPartCells& part =
-                dynamicCast<const ensightPartCells&>(*iter);
-
-            writeField(vf, part, os);
-        }
-    }
-
-    return true;
-}
-
-
-// ************************************************************************* //
diff --git a/src/fileFormats/ensight/output/ensightOutput.H b/src/fileFormats/ensight/output/ensightOutput.H
new file mode 100644
index 0000000000..326580a421
--- /dev/null
+++ b/src/fileFormats/ensight/output/ensightOutput.H
@@ -0,0 +1,146 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2016-2019 OpenCFD Ltd.
+     \\/     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/>.
+
+Namespace
+    Foam::ensightOutput
+
+Description
+    A collection of functions for writing ensight file content.
+
+SourceFiles
+    ensightOutputTemplates.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef ensightOutput_H
+#define ensightOutput_H
+
+#include "ensightFile.H"
+#include "ensightCells.H"
+#include "ensightFaces.H"
+#include "ensightPTraits.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
+namespace Foam
+{
+namespace ensightOutput
+{
+
+/*---------------------------------------------------------------------------*\
+                        Namespace ensightOutput::Detail
+\*---------------------------------------------------------------------------*/
+
+//- \brief Implementation details and output backends that would not normally
+//- be called directly by a user.
+
+namespace Detail
+{
+
+//- Write field content (component-wise) for the given ensight element type
+template<template<typename> class FieldContainer, class Type>
+bool writeFieldComponents
+(
+    const char* key,
+    const FieldContainer<Type>& fld,
+    ensightFile& os,
+    bool parallel         //!< Collective write?
+);
+
+
+//- Write a field of faces values as an indirect list,
+//- using the face ids from ensightFaces
+template<class Type>
+bool writeFaceField
+(
+    const Field<Type>& fld,
+    const ensightFaces& part,
+    ensightFile& os,
+    bool parallel         //!< Collective write?
+);
+
+
+//- Write a sub-field of faces values as an indirect list,
+//- using the sublist sizing information from ensightFaces
+template<class Type>
+bool writeFaceSubField
+(
+    const Field<Type>& fld,
+    const ensightFaces& part,
+    ensightFile& os,
+    bool parallel         //!< Collective write?
+);
+
+
+
+//- Write a field of cell values as an indirect list,
+//- using the cell ids from ensightCells
+template<class Type>
+bool writeCellField
+(
+    const Field<Type>& fld,
+    const ensightCells& part,
+    ensightFile& os,
+    bool parallel         //!< Collective write?
+);
+
+} // End namespace Detail
+
+
+/*---------------------------------------------------------------------------*\
+                        Namespace ensightOutput::Serial
+\*---------------------------------------------------------------------------*/
+
+//- \brief Output routines that are either designed for serial-only,
+//- or for which parallelization is pending.
+namespace Serial
+{
+
+//- Write a field of point (node) values (already compacted?)
+template<class Type>
+bool writePointField
+(
+    const Field<Type>& fld,
+    const ensightFaces& part,
+    ensightFile& os
+);
+
+} // End namespace Serial
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace ensightOutput
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "ensightOutputTemplates.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/ensight/output/ensightOutputTemplates.C b/src/fileFormats/ensight/output/ensightOutputTemplates.C
new file mode 100644
index 0000000000..1ddaaf4c61
--- /dev/null
+++ b/src/fileFormats/ensight/output/ensightOutputTemplates.C
@@ -0,0 +1,323 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
+     \\/     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 "ensightOutput.H"
+#include "ensightPTraits.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+template<template<typename> class FieldContainer, class Type>
+bool Foam::ensightOutput::Detail::writeFieldComponents
+(
+    const char* key,
+    const FieldContainer<Type>& fld,
+    ensightFile& os,
+    bool parallel
+)
+{
+    // Preliminary checks
+    // ~~~~~~~~~~~~~~~~~~
+
+    parallel = parallel && Pstream::parRun();
+
+    bool hasField = !fld.empty();
+
+    if (parallel)
+    {
+        reduce(hasField, orOp<bool>());
+    }
+
+    // Nothing to write
+    if (!hasField) return false;
+
+    // End preliminary checks
+    // ~~~~~~~~~~~~~~~~~~~~~~
+
+
+    if (Pstream::master())
+    {
+        os.writeKeyword(key);
+
+        if (!parallel)
+        {
+            // Serial output
+            for (direction d=0; d < pTraits<Type>::nComponents; ++d)
+            {
+                const label cmpt = ensightPTraits<Type>::componentOrder[d];
+
+                os.writeList(fld.component(cmpt));
+            }
+        }
+        else
+        {
+            // Parallel (master)
+
+            for (direction d=0; d < pTraits<Type>::nComponents; ++d)
+            {
+                const label cmpt = ensightPTraits<Type>::componentOrder[d];
+
+                os.writeList(fld.component(cmpt));
+
+                for (int slave=1; slave<Pstream::nProcs(); ++slave)
+                {
+                    IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
+                    scalarField received(fromSlave);
+                    os.writeList(received);
+                }
+            }
+        }
+    }
+    else if (parallel)
+    {
+        // Parallel (slaves)
+
+        for (direction d=0; d < pTraits<Type>::nComponents; ++d)
+        {
+            const label cmpt = ensightPTraits<Type>::componentOrder[d];
+
+            OPstream toMaster
+            (
+                Pstream::commsTypes::scheduled,
+                Pstream::masterNo()
+            );
+
+            toMaster
+                << fld.component(cmpt);
+        }
+    }
+
+    return true;
+}
+
+
+template<class Type>
+bool Foam::ensightOutput::Detail::writeFaceField
+(
+    const Field<Type>& fld,
+    const ensightFaces& part,
+    ensightFile& os,
+    bool parallel
+)
+{
+    // Preliminary checks
+    // ~~~~~~~~~~~~~~~~~~
+
+    parallel = parallel && Pstream::parRun();
+
+    bool hasGeom = (parallel ? part.total() : part.size());
+    bool hasField = !fld.empty();
+
+    if (parallel)
+    {
+        // Used 'pre-reduced' information for hasGeom
+        reduce(hasField, orOp<bool>());
+    }
+
+    // Nothing to write
+    if (!hasGeom || !hasField) return false;
+
+    // End preliminary checks
+    // ~~~~~~~~~~~~~~~~~~~~~~
+
+
+    if (Pstream::master())
+    {
+        os.beginPart(part.index());
+    }
+
+    for (int typei=0; typei < ensightFaces::nTypes; ++typei)
+    {
+        const ensightFaces::elemType what = ensightFaces::elemType(typei);
+
+        writeFieldComponents
+        (
+            ensightFaces::key(what),
+            Field<Type>(fld, part.faceIds(what)),
+            os,
+            parallel
+        );
+    }
+
+    return true;
+}
+
+
+template<class Type>
+bool Foam::ensightOutput::Detail::writeFaceSubField
+(
+    const Field<Type>& fld,
+    const ensightFaces& part,
+    ensightFile& os,
+    bool parallel
+)
+{
+    // Preliminary checks
+    // ~~~~~~~~~~~~~~~~~~
+
+    parallel = parallel && Pstream::parRun();
+
+    bool hasGeom = (parallel ? part.total() : part.size());
+    bool hasField = !fld.empty();
+
+    if (parallel)
+    {
+        // Used 'pre-reduced' information for hasGeom
+        reduce(hasField, orOp<bool>());
+    }
+
+    // Nothing to write
+    if (!hasGeom || !hasField) return false;
+
+    // End preliminary checks
+    // ~~~~~~~~~~~~~~~~~~~~~~
+
+
+    if (Pstream::master())
+    {
+        os.beginPart(part.index());
+    }
+
+
+    label start = 0; // The start of the sub-list
+    for (int typei=0; typei < ensightFaces::nTypes; ++typei)
+    {
+        const ensightFaces::elemType what = ensightFaces::elemType(typei);
+
+        const label size = part.faceIds(what).size();
+
+        writeFieldComponents
+        (
+            ensightFaces::key(what),
+            SubField<Type>(fld, size, start),
+            os,
+            parallel
+        );
+
+        start += size;  // Advance the start for next sub-list
+    }
+
+    return true;
+}
+
+
+template<class Type>
+bool Foam::ensightOutput::Serial::writePointField
+(
+    const Field<Type>& fld,
+    const ensightFaces& part,
+    ensightFile& os
+)
+{
+    // Preliminary checks
+    // ~~~~~~~~~~~~~~~~~~
+
+    bool parallel = false && Pstream::parRun();
+
+    bool hasGeom = (parallel ? part.total() : part.size());
+    bool hasField = !fld.empty();
+
+    if (parallel)
+    {
+        // Used 'pre-reduced' information for hasGeom
+        reduce(hasField, orOp<bool>());
+    }
+
+    // Nothing to write
+    if (!hasGeom || !hasField) return false;
+
+    // End preliminary checks
+    // ~~~~~~~~~~~~~~~~~~~~~~
+
+
+    if (Pstream::master())
+    {
+        os.beginPart(part.index());
+    }
+
+    ensightOutput::Detail::writeFieldComponents
+    (
+        "coordinates",
+        fld,
+        os,
+        parallel
+    );
+
+    return true;
+}
+
+
+template<class Type>
+bool Foam::ensightOutput::Detail::writeCellField
+(
+    const Field<Type>& fld,
+    const ensightCells& part,
+    ensightFile& os,
+    bool parallel
+)
+{
+    // Preliminary checks
+    // ~~~~~~~~~~~~~~~~~~
+
+    parallel = parallel && Pstream::parRun();
+
+    bool hasGeom = (parallel ? part.total() : part.size());
+    bool hasField = !fld.empty();
+
+    if (parallel)
+    {
+        // Used 'pre-reduced' information for hasGeom
+        reduce(hasField, orOp<bool>());
+    }
+
+    // Nothing to write
+    if (!hasGeom || !hasField) return false;
+
+    // End preliminary checks
+    // ~~~~~~~~~~~~~~~~~~~~~~
+
+
+    if (Pstream::master())
+    {
+        os.beginPart(part.index());
+    }
+
+    for (int typei=0; typei < ensightCells::nTypes; ++typei)
+    {
+        const ensightCells::elemType what = ensightCells::elemType(typei);
+
+        Detail::writeFieldComponents
+        (
+            ensightCells::key(what),
+            Field<Type>(fld, part.cellIds(what)),
+            os,
+            parallel
+        );
+    }
+
+    return true;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/ensight/part/ensightCells.H b/src/fileFormats/ensight/part/ensightCells.H
index 00cd99b438..83c5200d81 100644
--- a/src/fileFormats/ensight/part/ensightCells.H
+++ b/src/fileFormats/ensight/part/ensightCells.H
@@ -66,7 +66,7 @@ public:
         };
 
         //- Number of element types (5)
-        static constexpr label nTypes = 5;
+        static constexpr int nTypes = 5;
 
         //- The ensight element type names
         static const char* elemNames[5];
diff --git a/src/fileFormats/ensight/part/ensightFaces.H b/src/fileFormats/ensight/part/ensightFaces.H
index 4022076f69..c079f39744 100644
--- a/src/fileFormats/ensight/part/ensightFaces.H
+++ b/src/fileFormats/ensight/part/ensightFaces.H
@@ -62,7 +62,7 @@ public:
         };
 
         //- Number of element types (3)
-        static constexpr label nTypes = 3;
+        static constexpr int nTypes = 3;
 
         //- The ensight element type names
         static const char* elemNames[3];
diff --git a/src/fileFormats/ensight/part/ensightPartCells.C b/src/fileFormats/ensight/part/ensightPartCells.C
index 1623806050..afb8b8deed 100644
--- a/src/fileFormats/ensight/part/ensightPartCells.C
+++ b/src/fileFormats/ensight/part/ensightPartCells.C
@@ -269,8 +269,8 @@ void Foam::ensightPartCells::write
             }
         }
 
-        // write each element type
-        for (label typei=0; typei < ensightCells::nTypes; ++typei)
+        // Write each element type
+        for (int typei=0; typei < ensightCells::nTypes; ++typei)
         {
             const ensightCells::elemType what = ensightCells::elemType(typei);
 
@@ -312,7 +312,7 @@ void Foam::ensightPartCells::dumpInfo(Ostream& os) const
     os.writeEntry("name",   name());
     os.writeEntry("size",   size());
 
-    for (label typei=0; typei < ensightCells::nTypes; ++typei)
+    for (int typei=0; typei < ensightCells::nTypes; ++typei)
     {
         const ensightCells::elemType what = ensightCells::elemType(typei);
         const labelUList& addr = this->cellIds(what);
diff --git a/src/fileFormats/ensight/part/ensightPartFaces.C b/src/fileFormats/ensight/part/ensightPartFaces.C
index f3fdc68e7c..f81789fdca 100644
--- a/src/fileFormats/ensight/part/ensightPartFaces.C
+++ b/src/fileFormats/ensight/part/ensightPartFaces.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) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -219,8 +219,8 @@ void Foam::ensightPartFaces::write
             }
         }
 
-        // write part
-        for (label typei=0; typei < ensightFaces::nTypes; ++typei)
+        // Write part
+        for (int typei=0; typei < ensightFaces::nTypes; ++typei)
         {
             const ensightFaces::elemType what = ensightFaces::elemType(typei);
 
@@ -264,7 +264,7 @@ void Foam::ensightPartFaces::dumpInfo(Ostream& os) const
     os.writeEntry("start",  start_);
     os.writeEntry("size",   size());
 
-    for (label typei=0; typei < ensightFaces::nTypes; ++typei)
+    for (int typei=0; typei < ensightFaces::nTypes; ++typei)
     {
         const ensightFaces::elemType what = ensightFaces::elemType(typei);
         const labelUList& addr = this->faceIds(what);
diff --git a/src/functionObjects/utilities/ensightWrite/ensightWriteTemplates.C b/src/functionObjects/utilities/ensightWrite/ensightWriteTemplates.C
index 9649a26bac..7747f0277e 100644
--- a/src/functionObjects/utilities/ensightWrite/ensightWriteTemplates.C
+++ b/src/functionObjects/utilities/ensightWrite/ensightWriteTemplates.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016-2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -23,7 +23,7 @@ License
 
 \*---------------------------------------------------------------------------*/
 
-#include "ensightOutput.H"
+#include "ensightOutputVolField.H"
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
@@ -54,11 +54,11 @@ Foam::label Foam::functionObjects::ensightWrite::writeVolFields
 
         autoPtr<ensightFile> os = ensCase().newData<Type>(fieldName);
 
-        ensightOutput::writeField<Type>
+        ensightOutput::writeVolField<Type>
         (
             field,
             ensMesh(),
-            os,
+            os.ref(),
             caseOpts_.nodeValues()
         );
 
diff --git a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C
index 7fef643f0d..e00086fec7 100644
--- a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C
+++ b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016-2017 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -73,7 +73,7 @@ namespace Foam
 
 // * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
 
-bool Foam::ensightCloud::writePositions
+bool Foam::ensightOutput::writeCloudPositions
 (
     const fvMesh& mesh,
     const word& cloudName,
@@ -92,9 +92,9 @@ bool Foam::ensightCloud::writePositions
 
         auto outIter = positions.begin();
 
-        forAllConstIters(parcels, iter)
+        for (const passiveParticle& p : parcels)
         {
-            *outIter = iter().position();
+            *outIter = p.position();
             ++outIter;
         }
     }
diff --git a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H
index 4707f42350..0607e4a087 100644
--- a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H
+++ b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016-2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -21,12 +21,11 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-Namespace
-    Foam::ensightCloud
+InNamespace
+    Foam::ensightOutput
 
 Description
-    A collection of global functions for writing clouds as
-    ensight file content.
+    A collection of functions for writing clouds as ensight file content.
 
 SourceFiles
     ensightOutputCloud.C
@@ -45,14 +44,18 @@ SourceFiles
 
 namespace Foam
 {
+
 // Forward declarations
 class fvMesh;
 
-namespace ensightCloud
+namespace ensightOutput
 {
 
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
 //- Write cloud positions
-bool writePositions
+bool writeCloudPositions
 (
     const fvMesh& mesh,
     const word& cloudName,
@@ -84,7 +87,7 @@ bool writeCloudField
 );
 
 
-} // End namespace ensightCloud
+} // End namespace ensightOutput
 } // End namespace Foam
 
 
diff --git a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C
index aa0ead7b4f..0ff836ab98 100644
--- a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C
+++ b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016-2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -29,7 +29,7 @@ License
 // * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
 
 template<class Type>
-bool Foam::ensightCloud::writeCloudField
+bool Foam::ensightOutput::writeCloudField
 (
     const IOField<Type>& field,
     ensightFile& os,
@@ -113,7 +113,7 @@ bool Foam::ensightCloud::writeCloudField
 
 
 template<class Type>
-bool Foam::ensightCloud::writeCloudField
+bool Foam::ensightOutput::writeCloudField
 (
     const IOobject& io,
     const bool exists,
diff --git a/src/sampling/Make/options b/src/sampling/Make/options
index 2a3f639795..85fc47f432 100644
--- a/src/sampling/Make/options
+++ b/src/sampling/Make/options
@@ -3,13 +3,11 @@ EXE_INC = \
     -I$(LIB_SRC)/fileFormats/lnInclude \
     -I$(LIB_SRC)/surfMesh/lnInclude \
     -I$(LIB_SRC)/meshTools/lnInclude \
-    -I$(LIB_SRC)/conversion/lnInclude \
     -I$(LIB_SRC)/dynamicMesh/lnInclude \
     -I$(LIB_SRC)/lagrangian/basic/lnInclude
 
 LIB_LIBS = \
     -lfiniteVolume \
     -lmeshTools \
-    -lconversion \
     -ldynamicMesh \
     -llagrangian
diff --git a/src/sampling/sampledSurface/writers/ensight/ensightSurfaceWriterImpl.C b/src/sampling/sampledSurface/writers/ensight/ensightSurfaceWriterImpl.C
index cb040ff965..c4435c54b9 100644
--- a/src/sampling/sampledSurface/writers/ensight/ensightSurfaceWriterImpl.C
+++ b/src/sampling/sampledSurface/writers/ensight/ensightSurfaceWriterImpl.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2014 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015-2018 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -26,9 +26,10 @@ License
 #include "IOmanip.H"
 #include "Fstream.H"
 #include "OSspecific.H"
+
 #include "ensightCase.H"
 #include "ensightPartFaces.H"
-#include "ensightSerialOutput.H"
+#include "ensightOutput.H"
 #include "ensightPTraits.H"
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
@@ -140,13 +141,27 @@ Foam::fileName Foam::ensightSurfaceWriter::writeUncollated
 
     // Write field
     osField.writeKeyword(ensightPTraits<Type>::typeName);
-    ensightSerialOutput::writeField
-    (
-        values,
-        ensPart,
-        osField,
-        isNodeValues
-    );
+
+    if (isNodeValues)
+    {
+        ensightOutput::Serial::writePointField
+        (
+            values,
+            ensPart,
+            osField
+            // false // serial
+        );
+    }
+    else
+    {
+        ensightOutput::Detail::writeFaceField
+        (
+            values,
+            ensPart,
+            osField,
+            false // serial
+        );
+    }
 
     return osCase.name();
 }
@@ -436,13 +451,27 @@ Foam::fileName Foam::ensightSurfaceWriter::writeCollated
 
     // Write field
     osField.writeKeyword(ensightPTraits<Type>::typeName);
-    ensightSerialOutput::writeField
-    (
-        values,
-        ensPart,
-        osField,
-        isNodeValues
-    );
+
+    if (isNodeValues)
+    {
+        ensightOutput::Serial::writePointField
+        (
+            values,
+            ensPart,
+            osField
+            // serial
+        );
+    }
+    else
+    {
+        ensightOutput::Detail::writeFaceField
+        (
+            values,
+            ensPart,
+            osField,
+            false // serial
+        );
+    }
 
     // Place a timestamp in the directory for future reference
     {
-- 
GitLab