From 8652b28c4eb957c109c81ea91fe10df66db1b79e Mon Sep 17 00:00:00 2001
From: Andrew Heather <>
Date: Tue, 21 Nov 2017 16:33:33 +0000
Subject: [PATCH] ENH: Added finiteArea support to foamToVTK

---
 .../foamToEnsight/foamToEnsight.C             |  21 +---
 .../dataConversion/foamToVTK/Make/options     |   2 +
 .../dataConversion/foamToVTK/foamToVTK.C      | 114 +++++++++++++++++
 .../dataConversion/foamToVTK/readFields.C     |  32 +++++
 src/conversion/Make/options                   |   2 +
 .../vtk/output/foamVtkSurfaceMeshWriter.H     |  18 +++
 .../foamVtkSurfaceMeshWriterTemplates.C       |  49 +++++++-
 src/functionObjects/utilities/Make/options    |   2 +
 .../utilities/vtkWrite/vtkWrite.C             | 117 +++++++++---------
 .../utilities/vtkWrite/vtkWrite.H             |  12 +-
 .../utilities/vtkWrite/vtkWriteTemplates.C    |  25 ++++
 .../cylinder/system/controlDict               |   2 +-
 .../sphereTransport/system/controlDict        |   2 +-
 .../planeTransport/system/controlDict         |   2 +-
 14 files changed, 314 insertions(+), 86 deletions(-)

diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C
index e95296e1b5..737b3e5b64 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C
@@ -97,25 +97,6 @@ using namespace Foam;
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-// file-scope helper
-static bool inFileNameList
-(
-    const fileNameList& nameList,
-    const word& name
-)
-{
-    forAll(nameList, i)
-    {
-        if (nameList[i] == name)
-        {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-
 int main(int argc, char *argv[])
 {
     timeSelector::addOptions();
@@ -641,7 +622,7 @@ int main(int argc, char *argv[])
 
             Info<< "Write " << cloudName << " (";
 
-            bool cloudExists = inFileNameList(currentCloudDirs, cloudName);
+            bool cloudExists = currentCloudDirs.found(cloudName);
             reduce(cloudExists, orOp<bool>());
 
             {
diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/Make/options b/applications/utilities/postProcessing/dataConversion/foamToVTK/Make/options
index 541ffa86ae..27111f09d4 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToVTK/Make/options
+++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/Make/options
@@ -3,11 +3,13 @@ EXE_INC = \
     -I$(LIB_SRC)/conversion/lnInclude \
     -I$(LIB_SRC)/lagrangian/basic/lnInclude \
     -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/finiteArea/lnInclude \
     -I$(LIB_SRC)/dynamicMesh/lnInclude \
     -I$(LIB_SRC)/meshTools/lnInclude
 
 EXE_LIBS = \
     -lconversion \
     -ldynamicMesh \
+    -lfiniteArea \
     -llagrangian \
     -lgenericPatchFields
diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C
index eb6b3b6ddd..c51ccefdf9 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C
+++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C
@@ -155,6 +155,7 @@ Note
 #include "Cloud.H"
 #include "passiveParticle.H"
 #include "stringOps.H"
+#include "areaFields.H"
 
 #include "meshSubsetHelper.H"
 #include "readFields.H"
@@ -862,6 +863,119 @@ int main(int argc, char *argv[])
         );
 
 
+        // Finite-area mesh and fields - need not exist
+
+        autoPtr<faMesh> aMeshPtr;
+        {
+            const bool throwing = FatalError.throwExceptions();
+            try
+            {
+                aMeshPtr.reset(new faMesh(meshRef.baseMesh()));
+            }
+            catch (Foam::error& err)
+            {
+                aMeshPtr.clear();
+            }
+            FatalError.throwExceptions(throwing);
+        }
+
+        if (aMeshPtr.valid())
+        {
+            // Construct the area fields
+
+            PtrList<const areaScalarField> aScalarFld;
+            PtrList<const areaVectorField> aVectorFld;
+            PtrList<const areaSphericalTensorField> aSphTensorf;
+            PtrList<const areaSymmTensorField> aSymTensorFld;
+            PtrList<const areaTensorField> aTensorFld;
+
+            const faMesh& aMesh = aMeshPtr();
+
+            if (!specifiedFields || selectedFields.size())
+            {
+                readFields
+                (
+                    aMesh,
+                    objects,
+                    selectedFields,
+                    aScalarFld
+                );
+                print("    areaScalar           :", Info, aScalarFld);
+
+                readFields
+                (
+                    aMesh,
+                    objects,
+                    selectedFields,
+                    aVectorFld
+                );
+                print("    areaVector           :", Info, aVectorFld);
+
+                readFields
+                (
+                    aMesh,
+                    objects,
+                    selectedFields,
+                    aSphTensorf
+                );
+                print("    areaSphericalTensor   :", Info, aSphTensorf);
+
+                readFields
+                (
+                    aMesh,
+                    objects,
+                    selectedFields,
+                    aSymTensorFld
+                );
+                print("    areaSymmTensor        :", Info, aSymTensorFld);
+
+                readFields
+                (
+                    aMesh,
+                    objects,
+                    selectedFields,
+                    aTensorFld
+                );
+                print("    areaTensor            :", Info, aTensorFld);
+            }
+
+            const label nAreaFields =
+            (
+                aScalarFld.size()
+              + aVectorFld.size()
+              + aSphTensorf.size()
+              + aSymTensorFld.size()
+              + aTensorFld.size()
+            );
+
+            fileName outputName(fvPath/"finiteArea");
+
+            mkDir(outputName);
+
+            const auto& pp = aMesh.patch();
+
+            vtk::surfaceMeshWriter writer
+            (
+                pp,
+                aMesh.name(),
+                outputName/"finiteArea" + "_" + timeDesc,
+                fmtType
+            );
+
+            // Number of fields
+            writer.beginCellData(nAreaFields);
+
+            writer.write(aScalarFld);
+            writer.write(aVectorFld);
+            writer.write(aSphTensorf);
+            writer.write(aSymTensorFld);
+            writer.write(aTensorFld);
+
+            writer.endCellData();
+
+            writer.writeFooter();
+        }
+
         PtrList<const pointScalarField> pScalarFld;
         PtrList<const pointVectorField> pVectorFld;
         PtrList<const pointSphericalTensorField> pSphTensorFld;
diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.C
index 1db40528a1..6547f11d38 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.C
+++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.C
@@ -72,6 +72,38 @@ label readFields
 }
 
 
+template<class GeoField>
+void readFields
+(
+    const typename GeoField::Mesh& mesh,
+    const IOobjectList& objects,
+    const HashSet<word>& selectedFields,
+    PtrList<const GeoField>& fields
+)
+{
+    // Search list of objects for fields of type GeomField
+    IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName));
+
+    // Construct the fields
+    fields.setSize(fieldObjects.size());
+    label nFields = 0;
+
+    forAllIters(fieldObjects, iter)
+    {
+        if (selectedFields.empty() || selectedFields.found(iter()->name()))
+        {
+            fields.set
+            (
+                nFields++,
+                new GeoField(*iter(), mesh)
+            );
+        }
+    }
+
+    fields.setSize(nFields);
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 } // End namespace Foam
diff --git a/src/conversion/Make/options b/src/conversion/Make/options
index 22e6c0f6f1..0e0829fd61 100644
--- a/src/conversion/Make/options
+++ b/src/conversion/Make/options
@@ -1,8 +1,10 @@
 EXE_INC = \
     -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/finiteArea/lnInclude \
     -I$(LIB_SRC)/fileFormats/lnInclude \
     -I$(LIB_SRC)/meshTools/lnInclude
 
 LIB_LIBS = \
     -lfiniteVolume \
+    -lfiniteArea \
     -lmeshTools
diff --git a/src/conversion/vtk/output/foamVtkSurfaceMeshWriter.H b/src/conversion/vtk/output/foamVtkSurfaceMeshWriter.H
index bf5de51327..ea463c41c2 100644
--- a/src/conversion/vtk/output/foamVtkSurfaceMeshWriter.H
+++ b/src/conversion/vtk/output/foamVtkSurfaceMeshWriter.H
@@ -40,6 +40,7 @@ SourceFiles
 #include "OFstream.H"
 #include "volFields.H"
 #include "surfaceFields.H"
+#include "areaFields.H"
 #include "indirectPrimitivePatch.H"
 #include "foamVtkOutputOptions.H"
 
@@ -152,6 +153,13 @@ public:
             const GeometricField<Type, fvsPatchField, surfaceMesh>& field
         );
 
+        //- Write surface field
+        template<class Type>
+        void write
+        (
+            const GeometricField<Type, faPatchField, areaMesh>& field
+        );
+
 
       // Write fields (collectively)
 
@@ -164,6 +172,16 @@ public:
                 const GeometricField<Type, fvsPatchField, surfaceMesh>
             >& sflds
         );
+
+        //- Write surface fields
+        template<class Type>
+        void write
+        (
+            const UPtrList
+            <
+                const GeometricField<Type, faPatchField, areaMesh>
+            >& sflds
+        );
 };
 
 
diff --git a/src/conversion/vtk/output/foamVtkSurfaceMeshWriterTemplates.C b/src/conversion/vtk/output/foamVtkSurfaceMeshWriterTemplates.C
index 1b459b3bd9..8b52dfc02f 100644
--- a/src/conversion/vtk/output/foamVtkSurfaceMeshWriterTemplates.C
+++ b/src/conversion/vtk/output/foamVtkSurfaceMeshWriterTemplates.C
@@ -74,8 +74,7 @@ void Foam::vtk::surfaceMeshWriter::write
     }
     else
     {
-        format().openDataArray<float, nCmpt>(field.name())
-            .closeTag();
+        format().openDataArray<float, nCmpt>(field.name()).closeTag();
     }
 
     format().writeSize(payLoad);
@@ -90,6 +89,36 @@ void Foam::vtk::surfaceMeshWriter::write
 }
 
 
+template<class Type>
+void Foam::vtk::surfaceMeshWriter::write
+(
+    const GeometricField<Type, faPatchField, areaMesh>& field
+)
+{
+    const int nCmpt(pTraits<Type>::nComponents);
+    const uint64_t payLoad(pp_.size() * nCmpt * sizeof(float));
+
+    if (legacy_)
+    {
+        legacy::floatField(os(), field.name(), nCmpt, pp_.size());
+    }
+    else
+    {
+        format().openDataArray<float, nCmpt>(field.name()).closeTag();
+    }
+
+    format().writeSize(payLoad);
+    vtk::writeList(format(), field.primitiveField());
+
+    format().flush();
+
+    if (!legacy_)
+    {
+        format().endDataArray();
+    }
+}
+
+
 template<class Type>
 void Foam::vtk::surfaceMeshWriter::write
 (
@@ -106,4 +135,20 @@ void Foam::vtk::surfaceMeshWriter::write
 }
 
 
+template<class Type>
+void Foam::vtk::surfaceMeshWriter::write
+(
+    const UPtrList
+    <
+        const GeometricField<Type, faPatchField, areaMesh>
+    >& sflds
+)
+{
+    for (const auto& field : sflds)
+    {
+        write(field);
+    }
+}
+
+
 // ************************************************************************* //
diff --git a/src/functionObjects/utilities/Make/options b/src/functionObjects/utilities/Make/options
index 9e14e74355..a9844b6d0e 100644
--- a/src/functionObjects/utilities/Make/options
+++ b/src/functionObjects/utilities/Make/options
@@ -1,5 +1,6 @@
 EXE_INC = \
     -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/finiteArea/lnInclude \
     -I$(LIB_SRC)/fileFormats/lnInclude \
     -I$(LIB_SRC)/conversion/lnInclude \
     -I$(LIB_SRC)/sampling/lnInclude \
@@ -9,6 +10,7 @@ EXE_INC = \
 
 LIB_LIBS = \
     -lfiniteVolume \
+    -lfiniteArea \
     -lconversion \
     -lsampling \
     -lfluidThermophysicalModels \
diff --git a/src/functionObjects/utilities/vtkWrite/vtkWrite.C b/src/functionObjects/utilities/vtkWrite/vtkWrite.C
index af55e3f82e..3006e253d4 100644
--- a/src/functionObjects/utilities/vtkWrite/vtkWrite.C
+++ b/src/functionObjects/utilities/vtkWrite/vtkWrite.C
@@ -26,6 +26,7 @@ License
 #include "vtkWrite.H"
 #include "dictionary.H"
 #include "Time.H"
+#include "areaFields.H"
 #include "foamVtkInternalWriter.H"
 #include "addToRunTimeSelectionTable.H"
 
@@ -59,12 +60,6 @@ Foam::functionObjects::vtkWrite::vtkWrite
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::functionObjects::vtkWrite::~vtkWrite()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 bool Foam::functionObjects::vtkWrite::read(const dictionary& dict)
@@ -125,21 +120,6 @@ bool Foam::functionObjects::vtkWrite::execute()
 
 bool Foam::functionObjects::vtkWrite::write()
 {
-    // Count number of fields to be written: only needed for legacy vtk format
-    label nFields = 0;
-    if (writeOpts_.legacy())
-    {
-        nFields =
-        (
-            (writeIds_ ? 1 : 0)
-          + countFields<volScalarField>()
-          + countFields<volVectorField>()
-          + countFields<volSphericalTensorField>()
-          + countFields<volSymmTensorField>()
-          + countFields<volTensorField>()
-        );
-    }
-
     // const word timeDesc =
     //     useTimeName ? time_.timeName() : Foam::name(time_.timeIndex());
 
@@ -165,55 +145,72 @@ bool Foam::functionObjects::vtkWrite::write()
         }
     }
 
-    // Create file and write header
-    const fileName outputName
-    (
-        vtkDir/vtkName
-      + "_"
-      + timeDesc
-    );
+    // internal mesh
+    {
+        const fileName outputName
+        (
+            vtkDir/vtkName
+          + "_"
+          + timeDesc
+        );
 
-    Info<< name() << " output Time: " << time_.timeName() << nl
-        << "    Internal  : " << outputName << endl;
+        Info<< name() << " output Time: " << time_.timeName() << nl
+            << "    Internal  : " << outputName << endl;
 
-    vtk::vtuCells vtuMeshCells
-    (
-        mesh_,
-        writeOpts_,
-        true  // decompose
-    );
+        // Number of fields to be written: only needed for legacy vtk format
+        label nVolFields = 0;
+        if (writeOpts_.legacy())
+        {
+            nVolFields =
+            (
+                (writeIds_ ? 1 : 0)
+              + countFields<volScalarField>()
+              + countFields<volVectorField>()
+              + countFields<volSphericalTensorField>()
+              + countFields<volSymmTensorField>()
+              + countFields<volTensorField>()
+            );
+        }
 
-    // Write mesh
-    vtk::internalWriter writer
-    (
-        mesh_,
-        vtuMeshCells,
-        outputName,
-        writeOpts_
-    );
+        vtk::vtuCells vtuMeshCells
+        (
+            mesh_,
+            writeOpts_,
+            true  // decompose
+        );
 
-    // CellData
-    {
-        writer.beginCellData(nFields);
+        // Write mesh
+        vtk::internalWriter writer
+        (
+            mesh_,
+            vtuMeshCells,
+            outputName,
+            writeOpts_
+        );
 
-        // Write cellID field
-        if (writeIds_)
+        // CellData
         {
-            writer.writeCellIDs();
+            writer.beginCellData(nVolFields);
+
+            // Write cellID field
+            if (writeIds_)
+            {
+                writer.writeCellIDs();
+            }
+
+            // Write volFields
+            writeFields<volScalarField>(writer);
+            writeFields<volVectorField>(writer);
+            writeFields<volSphericalTensorField>(writer);
+            writeFields<volSymmTensorField>(writer);
+            writeFields<volTensorField>(writer);
+
+            writer.endCellData();
         }
 
-        // Write volFields
-        writeFields<volScalarField>(writer);
-        writeFields<volVectorField>(writer);
-        writeFields<volSphericalTensorField>(writer);
-        writeFields<volSymmTensorField>(writer);
-        writeFields<volTensorField>(writer);
-
-        writer.endCellData();
+        writer.writeFooter();
     }
 
-    writer.writeFooter();
-
     return true;
 }
 
diff --git a/src/functionObjects/utilities/vtkWrite/vtkWrite.H b/src/functionObjects/utilities/vtkWrite/vtkWrite.H
index 2ea05fb3cf..2dcff3f426 100644
--- a/src/functionObjects/utilities/vtkWrite/vtkWrite.H
+++ b/src/functionObjects/utilities/vtkWrite/vtkWrite.H
@@ -77,6 +77,7 @@ SourceFiles
 
 #include "fvMeshFunctionObject.H"
 #include "foamVtkInternalWriter.H"
+#include "foamVtkSurfaceMeshWriter.H"
 #include "wordRes.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -121,6 +122,15 @@ class vtkWrite
         label writeFields(vtk::internalWriter& writer, bool verbose=true) const;
 
 
+        //- Write selected fields for GeoField type.
+        template<class GeoField>
+        label writeFields
+        (
+            vtk::surfaceMeshWriter& writer,
+            bool verbose=true
+        ) const;
+
+
         //- Disallow default bitwise copy construct
         vtkWrite(const vtkWrite&) = delete;
 
@@ -146,7 +156,7 @@ public:
 
 
     //- Destructor
-    virtual ~vtkWrite();
+    virtual ~vtkWrite() = default;
 
 
     // Member Functions
diff --git a/src/functionObjects/utilities/vtkWrite/vtkWriteTemplates.C b/src/functionObjects/utilities/vtkWrite/vtkWriteTemplates.C
index 1cdce49cd1..74ac9392a0 100644
--- a/src/functionObjects/utilities/vtkWrite/vtkWriteTemplates.C
+++ b/src/functionObjects/utilities/vtkWrite/vtkWriteTemplates.C
@@ -58,4 +58,29 @@ Foam::functionObjects::vtkWrite::writeFields
 }
 
 
+template<class GeoField>
+Foam::label
+Foam::functionObjects::vtkWrite::writeFields
+(
+    vtk::surfaceMeshWriter& writer,
+    bool verbose
+) const
+{
+    const wordList names = obr_.sortedNames<GeoField>(selectFields_);
+
+    if (verbose && names.size())
+    {
+        Info<< "    " << GeoField::typeName
+            << " " << flatOutput(names) << endl;
+    }
+
+    for (const word& fieldName : names)
+    {
+        writer.write(obr_.lookupObject<GeoField>(fieldName));
+    }
+
+    return names.size();
+}
+
+
 // ************************************************************************* //
diff --git a/tutorials/finiteArea/liquidFilmFoam/cylinder/system/controlDict b/tutorials/finiteArea/liquidFilmFoam/cylinder/system/controlDict
index 25ff91cb56..eab803f167 100644
--- a/tutorials/finiteArea/liquidFilmFoam/cylinder/system/controlDict
+++ b/tutorials/finiteArea/liquidFilmFoam/cylinder/system/controlDict
@@ -37,7 +37,7 @@ writeFormat     ascii;
 
 writePrecision  6;
 
-writeCompression uncompressed;
+writeCompression off;
 
 timeFormat      general;
 
diff --git a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/controlDict b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/controlDict
index ea3a12f8b0..e4b39188a9 100644
--- a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/controlDict
+++ b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/controlDict
@@ -35,7 +35,7 @@ purgeWrite          0;
 
 writeFormat         ascii;
 
-writeCompression    uncompressed;
+writeCompression    off;
 
 timeFormat          general;
 
diff --git a/tutorials/finiteArea/surfactantFoam/planeTransport/system/controlDict b/tutorials/finiteArea/surfactantFoam/planeTransport/system/controlDict
index 99317e670a..509179d129 100644
--- a/tutorials/finiteArea/surfactantFoam/planeTransport/system/controlDict
+++ b/tutorials/finiteArea/surfactantFoam/planeTransport/system/controlDict
@@ -35,7 +35,7 @@ purgeWrite          0;
 
 writeFormat         ascii;
 
-writeCompression    uncompressed;
+writeCompression    off;
 
 timeFormat          general;
 
-- 
GitLab