diff --git a/applications/test/foamToEnsight-check/Make/files b/applications/test/foamToEnsight-check/Make/files
new file mode 100644
index 0000000000..d5b94d1fe7
--- /dev/null
+++ b/applications/test/foamToEnsight-check/Make/files
@@ -0,0 +1,3 @@
+foamToEnsight-check.C
+
+EXE = $(FOAM_USER_APPBIN)/foamToEnsight-check
diff --git a/applications/test/foamToEnsight-check/Make/options b/applications/test/foamToEnsight-check/Make/options
new file mode 100644
index 0000000000..7fd9abdcb7
--- /dev/null
+++ b/applications/test/foamToEnsight-check/Make/options
@@ -0,0 +1,16 @@
+EXE_INC = \
+ -I$(LIB_SRC)/finiteVolume/lnInclude \
+ -I$(LIB_SRC)/finiteArea/lnInclude \
+ -I$(LIB_SRC)/fileFormats/lnInclude \
+ -I$(LIB_SRC)/meshTools/lnInclude \
+ -I$(LIB_SRC)/conversion/lnInclude \
+ -I$(LIB_SRC)/lagrangian/intermediate/lnInclude
+
+EXE_LIBS = \
+ -lfiniteVolume \
+ -lfiniteArea \
+ -lfileFormats \
+ -lmeshTools \
+ -lconversion \
+ -llagrangianIntermediate \
+ -lgenericPatchFields
diff --git a/applications/test/foamToEnsight-check/foamToEnsight-check.C b/applications/test/foamToEnsight-check/foamToEnsight-check.C
new file mode 100644
index 0000000000..8759fcf8db
--- /dev/null
+++ b/applications/test/foamToEnsight-check/foamToEnsight-check.C
@@ -0,0 +1,357 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | www.openfoam.com
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2022 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 .
+
+Application
+ foamToEnsight-check
+
+Description
+ Check data sizes for conversion to ensight format.
+
+\*---------------------------------------------------------------------------*/
+
+#include "argList.H"
+#include "timeSelector.H"
+#include "IOobjectList.H"
+#include "IOmanip.H"
+#include "OFstream.H"
+#include "Pstream.H"
+#include "HashOps.H"
+#include "regionProperties.H"
+
+#include "fvc.H"
+#include "faMesh.H"
+#include "fvMesh.H"
+
+// file-format/conversion
+#include "ensightFaMesh.H"
+#include "ensightMesh.H"
+
+using namespace Foam;
+
+
+void printStats(const FixedList& stats, const char *what = "")
+{
+ Info<< what << "max-comm: "<< stats[0] << nl
+ << what << "max-size: "<< stats[1] << nl
+ << what << "off-proc: "<< stats[2] << nl;
+}
+
+
+template
+FixedList printPartInfo
+(
+ const EnsightPartType& part,
+ int verbose = 0
+)
+{
+ Info<< "part: " << part.name().c_str() << nl
+ << " size: "
+ << (Pstream::parRun() ? part.total() : part.size())
+ << " (";
+
+ FixedList stats(Zero);
+
+ label& maxComm = stats[0];
+ label& maxSize = stats[1];
+ label& totNonLocalSize = stats[2];
+
+ for (int typei=0; typei < EnsightPartType::nTypes; ++typei)
+ {
+ const auto etype = typename EnsightPartType::elemType(typei);
+
+ if (typei) Info<< ' ';
+ Info<< EnsightPartType::elemNames[etype] << ": "
+ << (Pstream::parRun() ? part.total(etype) : part.size(etype));
+
+ label elemCount = part.size(etype);
+ label commCount = (Pstream::master() ? label(0) : elemCount);
+ label nonLocalCount = commCount;
+
+ if (Pstream::parRun())
+ {
+ reduce(elemCount, maxOp());
+ reduce(commCount, maxOp());
+
+ reduce(nonLocalCount, sumOp());
+ }
+
+ maxComm = max(maxComm, commCount);
+ maxSize = max(maxSize, elemCount);
+ totNonLocalSize = max(totNonLocalSize, nonLocalCount);
+ }
+ Info<< ")" << endl;
+
+ if (verbose && Pstream::parRun() && part.total())
+ {
+ for (int typei=0; typei < EnsightPartType::nTypes; ++typei)
+ {
+ const auto etype = typename EnsightPartType::elemType(typei);
+
+ label elemCount = part.size(etype);
+ label totCount = part.total(etype);
+
+ Info<< " "
+ << EnsightPartType::elemNames[etype] << ": "
+ << totCount;
+
+ if (totCount)
+ {
+ labelList sizes(UPstream::listGatherValues(elemCount));
+
+ Info<< " ";
+ sizes.writeList(Info);
+ }
+
+ Info<< endl;
+ }
+ }
+
+ printStats(stats, " ");
+
+ return stats;
+}
+
+
+void printInfo(const ensightMesh& mesh, int verbose = 0)
+{
+ FixedList cellStats(Zero);
+ FixedList faceStats(Zero);
+
+ for (const auto& iter : mesh.cellZoneParts().sorted())
+ {
+ FixedList stats = printPartInfo(iter.val(), verbose);
+
+ for (label i=0; i < 3; ++i)
+ {
+ cellStats[i] = max(cellStats[i], stats[i]);
+ }
+ }
+
+ for (const auto& iter : mesh.faceZoneParts().sorted())
+ {
+ FixedList stats = printPartInfo(iter.val(), verbose);
+
+ for (label i=0; i < 3; ++i)
+ {
+ faceStats[i] = max(faceStats[i], stats[i]);
+ }
+ }
+
+ for (const auto& iter : mesh.boundaryParts().sorted())
+ {
+ FixedList stats = printPartInfo(iter.val(), verbose);
+
+ for (label i=0; i < 3; ++i)
+ {
+ faceStats[i] = max(faceStats[i], stats[i]);
+ }
+ }
+
+ Info<< nl
+ << "===============" << nl;
+ printStats(cellStats, "cell ");
+
+ Info<< nl;
+ printStats(faceStats, "face ");
+
+ Info<< "===============" << endl;
+}
+
+
+void printInfo(const ensightFaMesh& mesh, int verbose = 0)
+{
+ printPartInfo(mesh.areaPart());
+}
+
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+int main(int argc, char *argv[])
+{
+ argList::addNote
+ (
+ "Check data sizes for conversion of OpenFOAM to Ensight format"
+ );
+ // timeSelector::addOptions();
+
+ // Less frequently used - reduce some clutter
+ argList::setAdvanced("decomposeParDict");
+
+ argList::addVerboseOption("Additional verbosity");
+
+ #include "addAllRegionOptions.H"
+
+ argList::addBoolOption
+ (
+ "no-boundary", // noPatches
+ "Suppress writing any patches"
+ );
+ argList::addBoolOption
+ (
+ "no-internal",
+ "Suppress writing the internal mesh"
+ );
+ argList::addBoolOption
+ (
+ "no-cellZones",
+ "Suppress writing any cellZones"
+ );
+ argList::addBoolOption
+ (
+ "no-finite-area",
+ "Suppress output of finite-area mesh/fields",
+ true // mark as an advanced option
+ );
+
+ #include "setRootCase.H"
+
+ // ------------------------------------------------------------------------
+ // Configuration
+
+ const int optVerbose = args.verbose();
+ const bool doBoundary = !args.found("no-boundary");
+ const bool doInternal = !args.found("no-internal");
+ const bool doCellZones = !args.found("no-cellZones");
+ const bool doFiniteArea = !args.found("no-finite-area");
+
+ ensightMesh::options writeOpts;
+ writeOpts.useBoundaryMesh(doBoundary);
+ writeOpts.useInternalMesh(doInternal);
+ writeOpts.useCellZones(doCellZones);
+
+ // ------------------------------------------------------------------------
+
+ #include "createTime.H"
+
+ instantList timeDirs = timeSelector::select0(runTime, args);
+
+ // Handle -allRegions, -regions, -region
+ #include "getAllRegionOptions.H"
+
+ // ------------------------------------------------------------------------
+
+ #include "createNamedMeshes.H"
+
+ // ------------------------------------------------------------------------
+ /// #include "createMeshAccounting.H"
+
+ PtrList ensightMeshes(regionNames.size());
+ PtrList meshesFa(regionNames.size());
+ PtrList ensightMeshesFa(regionNames.size());
+
+ forAll(regionNames, regioni)
+ {
+ const fvMesh& mesh = meshes[regioni];
+
+ ensightMeshes.set
+ (
+ regioni,
+ new ensightMesh(mesh, writeOpts)
+ );
+ ensightMeshes[regioni].verbose(optVerbose);
+
+
+ if (doFiniteArea)
+ {
+ autoPtr faMeshPtr(faMesh::TryNew(mesh));
+
+ if (faMeshPtr)
+ {
+ meshesFa.set(regioni, std::move(faMeshPtr));
+
+ ensightMeshesFa.set
+ (
+ regioni,
+ new ensightFaMesh(meshesFa[regioni])
+ );
+ ensightMeshesFa[regioni].verbose(optVerbose);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+
+ if (Pstream::master())
+ {
+ Info<< "Checking " << timeDirs.size() << " time steps" << nl;
+ }
+
+ forAll(timeDirs, timei)
+ {
+ runTime.setTime(timeDirs[timei], timei);
+
+ forAll(regionNames, regioni)
+ {
+ const word& regionName = regionNames[regioni];
+ // const word& regionDir = polyMesh::regionName(regionName);
+
+ auto& mesh = meshes[regioni];
+
+ polyMesh::readUpdateState meshState = mesh.readUpdate();
+ const bool moving = (meshState != polyMesh::UNCHANGED);
+
+ auto& ensMesh = ensightMeshes[regioni];
+
+ // Finite-area (can be missing)
+ auto* ensFaMeshPtr = ensightMeshesFa.get(regioni);
+
+ if (moving)
+ {
+ ensMesh.expire();
+ ensMesh.correct();
+
+ if (ensFaMeshPtr)
+ {
+ ensFaMeshPtr->expire();
+ ensFaMeshPtr->correct();
+ }
+ }
+
+ if (moving || timei == 0) // report
+ {
+ if (regionNames.size() > 1)
+ {
+ Info<< "region=" << regionName << nl;
+ }
+
+ printInfo(ensMesh, optVerbose);
+
+ if (ensFaMeshPtr)
+ {
+ printInfo(*ensFaMeshPtr, optVerbose);
+ }
+ }
+ }
+ }
+
+ Info<< "\nEnd"<< nl << endl;
+
+ return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H
index 45ee1ee64a..cff8b5cb05 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H
@@ -45,10 +45,10 @@ if (doLagrangian)
ensightOutput::writeCloudPositions
(
+ os.ref(),
mesh,
cloudName,
- cloudExists,
- os
+ cloudExists
);
Info<< " positions";
@@ -86,26 +86,34 @@ if (doLagrangian)
}
bool wrote = false;
- if (fieldType == scalarIOField::typeName)
+ do
{
- autoPtr os =
- ensCase.newCloudData(cloudName, fieldName);
+ #undef ensight_WRITE_CLOUD_FIELD
+ #define ensight_WRITE_CLOUD_FIELD(PrimitiveType) \
+ \
+ if (fieldType == IOField::typeName) \
+ { \
+ autoPtr os = \
+ ensCase.newCloudData \
+ ( \
+ cloudName, \
+ fieldName \
+ ); \
+ \
+ wrote = ensightOutput::readWriteCloudField \
+ ( \
+ os.ref(), \
+ fieldObject, \
+ fieldExists \
+ ); \
+ break; \
+ }
- wrote = ensightOutput::writeCloudField
- (
- fieldObject, fieldExists, os
- );
- }
- else if (fieldType == vectorIOField::typeName)
- {
- autoPtr os =
- ensCase.newCloudData(cloudName, fieldName);
+ ensight_WRITE_CLOUD_FIELD(scalar);
+ ensight_WRITE_CLOUD_FIELD(vector);
- wrote = ensightOutput::writeCloudField
- (
- fieldObject, fieldExists, os
- );
- }
+ #undef ensight_WRITE_CLOUD_FIELD
+ } while (false);
if (wrote)
{
diff --git a/etc/controlDict b/etc/controlDict
index 2a2b04713f..2cbd7bdec0 100644
--- a/etc/controlDict
+++ b/etc/controlDict
@@ -1,7 +1,7 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
-| \\ / O peration | Version: v2206 |
+| \\ / O peration | Version: v2212 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
@@ -118,7 +118,14 @@ OptimisationSwitches
// Default: 1e9
maxMasterFileBufferSize 1e9;
- commsType nonBlocking; //scheduled; //blocking;
+ // Upper limit when bundling off-processor field transfers (ensight).
+ // for component-wise transfer (uses float: 4 bytes)
+ // Eg, 5M for 50 ranks of 100k cells
+ ensight.maxChunk 5000000;
+
+
+ // Default communication type (nonBlocking | scheduled | blocking);
+ commsType nonBlocking;
floatTransfer 0;
nProcsSimpleSum 0;
@@ -136,6 +143,7 @@ OptimisationSwitches
// global reduction, even if multi-pass is not needed)
maxCommsSize 0;
+
// Trap floating point exception.
// Can override with FOAM_SIGFPE env variable (true|false)
trapFpe 1;
@@ -539,6 +547,7 @@ DebugSwitches
empty 0;
engineMesh 0;
enrichedPatch 0;
+ ensight 0;
epsilonWallFunction 0;
errorDrivenRefinement 0;
evaporationModel 0;
diff --git a/src/conversion/ensight/output/ensightOutputAreaField.H b/src/conversion/ensight/output/ensightOutputAreaField.H
index 37618cca6d..416c764ca3 100644
--- a/src/conversion/ensight/output/ensightOutputAreaField.H
+++ b/src/conversion/ensight/output/ensightOutputAreaField.H
@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2021 OpenCFD Ltd.
+ Copyright (C) 2021-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -31,8 +31,8 @@ Description
\*---------------------------------------------------------------------------*/
-#ifndef ensightOutputAreaField_H
-#define ensightOutputAreaField_H
+#ifndef Foam_ensightOutput_areaField_H
+#define Foam_ensightOutput_areaField_H
#include "ensightOutput.H"
#include "ensightFaces.H"
@@ -57,12 +57,39 @@ namespace ensightOutput
template
bool writeAreaField
(
+ //! Component scratch buffer
+ ensightOutput::floatBufferType& scratch,
+
+ //! Output file (must be valid on master)
ensightFile& os,
+
+ //! The field content to be written
const GeometricField& fld,
+
+ //! The addressing into the field
const ensightFaMesh& ensMesh
);
+//- Write finite-area field component-wise
+template
+bool writeAreaField
+(
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The field content to be written
+ const GeometricField& fld,
+
+ //! The addressing into the field
+ const ensightFaMesh& ensMesh
+)
+{
+ ensightOutput::floatBufferType scratch;
+ return ensightOutput::writeAreaField(scratch, os, fld, ensMesh);
+}
+
+
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace ensightOutput
diff --git a/src/conversion/ensight/output/ensightOutputAreaFieldTemplates.C b/src/conversion/ensight/output/ensightOutputAreaFieldTemplates.C
index aaccbd3cc2..4b7d2e84b1 100644
--- a/src/conversion/ensight/output/ensightOutputAreaFieldTemplates.C
+++ b/src/conversion/ensight/output/ensightOutputAreaFieldTemplates.C
@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2021 OpenCFD Ltd.
+ Copyright (C) 2021-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -34,6 +34,7 @@ License
template
bool Foam::ensightOutput::writeAreaField
(
+ ensightOutput::floatBufferType& scratch,
ensightFile& os,
const GeometricField& fld,
const ensightFaMesh& ensMesh
@@ -45,6 +46,7 @@ bool Foam::ensightOutput::writeAreaField
{
ensightOutput::Detail::writeFaceLocalField
(
+ scratch,
os,
fld,
ensMesh.areaPart(),
diff --git a/src/conversion/ensight/output/ensightOutputVolField.H b/src/conversion/ensight/output/ensightOutputVolField.H
index 7309103d4d..1c489e11c5 100644
--- a/src/conversion/ensight/output/ensightOutputVolField.H
+++ b/src/conversion/ensight/output/ensightOutputVolField.H
@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2016-2020 OpenCFD Ltd.
+ Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -31,8 +31,8 @@ Description
\*---------------------------------------------------------------------------*/
-#ifndef ensightOutputVolField_H
-#define ensightOutputVolField_H
+#ifndef Foam_ensightOutput_volField_H
+#define Foam_ensightOutput_volField_H
#include "ensightOutput.H"
#include "ensightFaces.H"
@@ -58,30 +58,115 @@ namespace ensightOutput
template
bool writeVolField
(
+ //! Component scratch buffer
+ ensightOutput::floatBufferType& scratch,
+
+ //! Output file (must be valid on master)
ensightFile& os,
+
+ //! The field content to be written
const GeometricField& vf,
+
+ //! The addressing (element-wise) into the field
const ensightMesh& ensMesh
);
+//- Write volume field component-wise
+template
+bool writeVolField
+(
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The field content to be written
+ const GeometricField& vf,
+
+ //! The addressing (element-wise) into the field
+ const ensightMesh& ensMesh
+)
+{
+ ensightOutput::floatBufferType scratch;
+ return ensightOutput::writeVolField(scratch, os, vf, ensMesh);
+}
//- Write volume field component-wise, optionally forcing interpolation
template
bool writeVolField
(
+ //! Component scratch buffer
+ ensightOutput::floatBufferType& scratch,
+
+ //! Output file (must be valid on master)
ensightFile& os,
+
+ //! The field content to be written
const GeometricField& vf,
+
+ //! The addressing (element-wise) into the field
const ensightMesh& ensMesh,
+
+ //! Interpolate values to points
const bool nodeValues
);
+//- Write volume field component-wise, optionally forcing interpolation
+template
+bool writeVolField
+(
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The field content to be written
+ const GeometricField& vf,
+
+ //! The addressing (element-wise) into the field
+ const ensightMesh& ensMesh,
+
+ //! Interpolate values to points
+ const bool nodeValues
+)
+{
+ ensightOutput::floatBufferType scratch;
+ return ensightOutput::writeVolField
+ (
+ scratch, os, vf, ensMesh, nodeValues
+ );
+}
+
+//- Write point field component-wise
+template
+bool writePointField
+(
+ //! Component scratch buffer
+ ensightOutput::floatBufferType& scratch,
+
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The field content to be written
+ const GeometricField& pf,
+
+ //! The addressing (element-wise) into the field
+ const ensightMesh& ensMesh
+);
+
//- Write point field component-wise
template
bool writePointField
(
+ //! Output file (must be valid on master)
ensightFile& os,
+
+ //! The field content to be written
const GeometricField& pf,
+
+ //! The addressing (element-wise) into the field
const ensightMesh& ensMesh
-);
+)
+{
+ ensightOutput::floatBufferType scratch;
+ return ensightOutput::writePointField(scratch, os, pf, ensMesh);
+}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/conversion/ensight/output/ensightOutputVolFieldTemplates.C b/src/conversion/ensight/output/ensightOutputVolFieldTemplates.C
index d7f07621ca..b940f11d23 100644
--- a/src/conversion/ensight/output/ensightOutputVolFieldTemplates.C
+++ b/src/conversion/ensight/output/ensightOutputVolFieldTemplates.C
@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2016-2021 OpenCFD Ltd.
+ Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -40,6 +40,7 @@ License
template
bool Foam::ensightOutput::writeVolField
(
+ ensightOutput::floatBufferType& scratch,
ensightFile& os,
const GeometricField& vf,
const ensightMesh& ensMesh
@@ -54,13 +55,12 @@ bool Foam::ensightOutput::writeVolField
const Map& faceZoneParts = ensMesh.faceZoneParts();
const Map& boundaryParts = ensMesh.boundaryParts();
-
// Write internalMesh and cellZones - sorted by index
for (const label zoneId : cellZoneParts.sortedToc())
{
const ensightCells& part = cellZoneParts[zoneId];
- ensightOutput::writeField(os, vf, part, parallel);
+ ensightOutput::writeField(scratch, os, vf, part, parallel);
}
@@ -88,6 +88,7 @@ bool Foam::ensightOutput::writeVolField
ensightOutput::writeField
(
+ scratch,
os,
vf.boundaryField()[patchId],
localPart,
@@ -170,7 +171,7 @@ bool Foam::ensightOutput::writeVolField
// - boundary faces use the corresponding patch value
// Local copy of the field
- values.resize(part.size());
+ values.resize_nocopy(part.size());
values = Zero;
auto valIter = values.begin();
@@ -189,7 +190,10 @@ bool Foam::ensightOutput::writeVolField
// The field is already in the proper element order
// - just need its corresponding sub-fields
- ensightOutput::Detail::writeFaceSubField(os, values, part, parallel);
+ ensightOutput::Detail::writeFaceSubField
+ (
+ scratch, os, values, part, parallel
+ );
}
return true;
@@ -199,6 +203,7 @@ bool Foam::ensightOutput::writeVolField
template
bool Foam::ensightOutput::writePointField
(
+ ensightOutput::floatBufferType& scratch,
ensightFile& os,
const GeometricField& pf,
const ensightMesh& ensMesh
@@ -219,16 +224,28 @@ bool Foam::ensightOutput::writePointField
{
const ensightCells& part = cellZoneParts[zoneId];
+ labelList uniquePointLabels;
+ part.uniqueMeshPoints(mesh, uniquePointLabels, parallel);
+
if (Pstream::master())
{
os.beginPart(part.index());
}
- labelList uniquePointLabels;
- part.uniqueMeshPoints(mesh, uniquePointLabels, parallel);
+ // Skip if empty
+ if
+ (
+ parallel
+ ? returnReduceAnd(uniquePointLabels.empty())
+ : uniquePointLabels.empty()
+ )
+ {
+ continue;
+ }
ensightOutput::Detail::writeFieldComponents
(
+ scratch,
os,
ensightFile::coordinates,
UIndirectList(pf.internalField(), uniquePointLabels),
@@ -244,13 +261,24 @@ bool Foam::ensightOutput::writePointField
{
const ensightFaces& part = boundaryParts[patchId];
+ labelList uniquePointLabels;
+ part.uniqueMeshPoints(mesh, uniquePointLabels, parallel);
+
if (Pstream::master())
{
os.beginPart(part.index());
}
- labelList uniquePointLabels;
- part.uniqueMeshPoints(mesh, uniquePointLabels, parallel);
+ // Skip if empty
+ if
+ (
+ parallel
+ ? returnReduceAnd(uniquePointLabels.empty())
+ : uniquePointLabels.empty()
+ )
+ {
+ continue;
+ }
const auto& bfld = pf.boundaryField()[patchId];
@@ -272,6 +300,7 @@ bool Foam::ensightOutput::writePointField
ensightOutput::Detail::writeFieldComponents
(
+ scratch,
os,
ensightFile::coordinates,
UIndirectList(*vpp, uniquePointLabels),
@@ -282,6 +311,7 @@ bool Foam::ensightOutput::writePointField
{
ensightOutput::Detail::writeFieldComponents
(
+ scratch,
os,
ensightFile::coordinates,
UIndirectList(pf.internalField(), uniquePointLabels),
@@ -297,26 +327,36 @@ bool Foam::ensightOutput::writePointField
{
const ensightFaces& part = faceZoneParts[zoneId];
+ labelList uniquePointLabels;
+ part.uniqueMeshPoints(mesh, uniquePointLabels, parallel);
+
if (Pstream::master())
{
os.beginPart(part.index());
}
+ // Skip if empty
+ if
+ (
+ parallel
+ ? returnReduceAnd(uniquePointLabels.empty())
+ : uniquePointLabels.empty()
+ )
+ {
+ continue;
+ }
+
// CAVEAT - does not properly handle valuePointPatchField,
// uses internalField only
- {
- labelList uniquePointLabels;
- part.uniqueMeshPoints(mesh, uniquePointLabels, parallel);
-
- ensightOutput::Detail::writeFieldComponents
- (
- os,
- ensightFile::coordinates,
- UIndirectList(pf.internalField(), uniquePointLabels),
- parallel
- );
- }
+ ensightOutput::Detail::writeFieldComponents
+ (
+ scratch,
+ os,
+ ensightFile::coordinates,
+ UIndirectList(pf.internalField(), uniquePointLabels),
+ parallel
+ );
}
return true;
@@ -328,6 +368,7 @@ bool Foam::ensightOutput::writePointField
template
bool Foam::ensightOutput::writeVolField
(
+ ensightOutput::floatBufferType& scratch,
ensightFile& os,
const GeometricField& vf,
const ensightMesh& ensMesh,
@@ -343,10 +384,10 @@ bool Foam::ensightOutput::writeVolField
pfld.ref().checkOut();
pfld.ref().rename(vf.name());
- return ensightOutput::writePointField(os, pfld, ensMesh);
+ return ensightOutput::writePointField(scratch, os, pfld, ensMesh);
}
- return ensightOutput::writeVolField(os, vf, ensMesh);
+ return ensightOutput::writeVolField(scratch, os, vf, ensMesh);
}
diff --git a/src/fileFormats/ensight/file/ensightFile.C b/src/fileFormats/ensight/file/ensightFile.C
index bd39b34b0a..19e9eb0b46 100644
--- a/src/fileFormats/ensight/file/ensightFile.C
+++ b/src/fileFormats/ensight/file/ensightFile.C
@@ -43,9 +43,23 @@ const char* const Foam::ensightFile::coordinates = "coordinates";
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
-bool Foam::ensightFile::hasUndef(const UList& field)
+bool Foam::ensightFile::hasUndef(const UList& field)
{
- for (const scalar& val : field)
+ for (const float val : field)
+ {
+ if (std::isnan(val))
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+
+bool Foam::ensightFile::hasUndef(const UList& field)
+{
+ for (const double val : field)
{
if (std::isnan(val))
{
@@ -354,15 +368,32 @@ void Foam::ensightFile::writeList(const UList& field)
{
for (const label val : field)
{
- write(scalar(val));
+ write(float(val));
newline();
}
}
-void Foam::ensightFile::writeList(const UList& field)
+void Foam::ensightFile::writeList(const UList& field)
{
- for (const scalar val : field)
+ for (const float val : field)
+ {
+ if (std::isnan(val))
+ {
+ writeUndef();
+ }
+ else
+ {
+ write(val);
+ }
+ newline();
+ }
+}
+
+
+void Foam::ensightFile::writeList(const UList& field)
+{
+ for (const double val : field)
{
if (std::isnan(val))
{
diff --git a/src/fileFormats/ensight/file/ensightFile.H b/src/fileFormats/ensight/file/ensightFile.H
index 6f63148fe2..b35dd97558 100644
--- a/src/fileFormats/ensight/file/ensightFile.H
+++ b/src/fileFormats/ensight/file/ensightFile.H
@@ -228,26 +228,42 @@ public:
// Adds newline after each value (ascii stream)
void writeList(const UList& field);
- //- Write a list of floating-point as "%12.5e" or as binary
- //- (double is narrowed to float).
+ //- Write a list of floats as "%12.5e" or as binary.
// Adds newline after each value (ascii stream)
- void writeList(const UList& field);
+ void writeList(const UList& field);
- //- Write an indirect list of scalars as "%12.5e" or as binary
+ //- Write a list of double as "%12.5e" or as binary.
+ //- (double is narrowed to float)
+ // Adds newline after each value (ascii stream)
+ void writeList(const UList& field);
+
+ //- Write an indirect list of float as "%12.5e" or as binary
+ // Adds newline after each value (ascii stream)
+ template
+ void writeList(const IndirectListBase& field);
+
+ //- Write an indirect list of double as "%12.5e" or as binary.
//- (double is narrowed to float)
// Adds newline after each value (ascii stream)
template
- void writeList(const IndirectListBase& field);
+ void writeList(const IndirectListBase& field);
// Other Methods
//- Check for any NaN in the field
- static bool hasUndef(const UList& field);
+ static bool hasUndef(const UList& field);
+
+ //- Check for any NaN in the field
+ static bool hasUndef(const UList& field);
//- Check for any NaN in the field
template
- static bool hasUndef(const IndirectListBase& field);
+ static bool hasUndef(const IndirectListBase& field);
+
+ //- Check for any NaN in the field
+ template
+ static bool hasUndef(const IndirectListBase& field);
};
diff --git a/src/fileFormats/ensight/file/ensightFileTemplates.C b/src/fileFormats/ensight/file/ensightFileTemplates.C
index 5603f95dcf..7ce8ff147e 100644
--- a/src/fileFormats/ensight/file/ensightFileTemplates.C
+++ b/src/fileFormats/ensight/file/ensightFileTemplates.C
@@ -28,9 +28,24 @@ License
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template
-bool Foam::ensightFile::hasUndef(const IndirectListBase& field)
+bool Foam::ensightFile::hasUndef(const IndirectListBase& field)
{
- for (const scalar val : field)
+ for (const float val : field)
+ {
+ if (std::isnan(val))
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+
+template
+bool Foam::ensightFile::hasUndef(const IndirectListBase& field)
+{
+ for (const double val : field)
{
if (std::isnan(val))
{
@@ -56,9 +71,27 @@ void Foam::ensightFile::writeLabels(const IndirectListBase& list)
template
-void Foam::ensightFile::writeList(const IndirectListBase& field)
+void Foam::ensightFile::writeList(const IndirectListBase& field)
{
- for (const scalar val : field)
+ for (const float val : field)
+ {
+ if (std::isnan(val))
+ {
+ writeUndef();
+ }
+ else
+ {
+ write(val);
+ }
+ newline();
+ }
+}
+
+
+template
+void Foam::ensightFile::writeList(const IndirectListBase& field)
+{
+ for (const double val : field)
{
if (std::isnan(val))
{
diff --git a/src/fileFormats/ensight/output/ensightOutput.C b/src/fileFormats/ensight/output/ensightOutput.C
index d2d8eb007a..80d73531bb 100644
--- a/src/fileFormats/ensight/output/ensightOutput.C
+++ b/src/fileFormats/ensight/output/ensightOutput.C
@@ -32,6 +32,23 @@ License
#include "polyMesh.H"
#include "ListOps.H"
#include "manifoldCellsMeshObject.H"
+#include "debug.H"
+#include "defineDebugSwitch.H"
+#include "registerSwitch.H"
+
+// * * * * * * * * * * * * * * * * Globals * * * * * * * * * * * * * * * * * //
+
+defineDebugSwitchWithName(Foam::ensightOutput, "ensight", 0);
+
+registerDebugSwitchWithName(Foam::ensightOutput, ensightOutput, "ensight");
+
+int Foam::ensightOutput::maxChunk_
+(
+ Foam::debug::optimisationSwitch("ensight.maxChunk", 0)
+);
+
+registerOptSwitch("ensight.maxChunk", int, Foam::ensightOutput::maxChunk_);
+
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/fileFormats/ensight/output/ensightOutput.H b/src/fileFormats/ensight/output/ensightOutput.H
index a9833d2de1..4c26ff69dc 100644
--- a/src/fileFormats/ensight/output/ensightOutput.H
+++ b/src/fileFormats/ensight/output/ensightOutput.H
@@ -38,6 +38,7 @@ SourceFiles
#ifndef Foam_ensightOutput_H
#define Foam_ensightOutput_H
+#include "ensightOutputFwd.H"
#include "ensightFile.H"
#include "ensightGeoFile.H"
#include "ensightCells.H"
@@ -186,7 +187,8 @@ void writeFaceConnectivity
const ensightFaces::elemType etype,
const label nTotal,
const UIndirectList& faces,
- bool parallel //!< Collective write?
+ //! Prefer collective write?
+ bool parallel
);
@@ -197,7 +199,8 @@ void writeFaceConnectivity
const ensightFaces::elemType etype,
const label nTotal,
const faceUList& faces,
- bool parallel //!< Collective write?
+ //! Prefer collective write?
+ bool parallel
);
@@ -207,7 +210,8 @@ void writeFaceConnectivity
ensightGeoFile& os,
const ensightFaces& part,
const faceUList& faces,
- bool parallel //!< Collective write?
+ //! Prefer collective write?
+ bool parallel
);
@@ -219,7 +223,8 @@ void writeFaceConnectivityPresorted
ensightGeoFile& os,
const ensightFaces& part,
const faceUList& faces,
- bool parallel //!< Collective write?
+ //! Prefer collective write?
+ bool parallel
);
@@ -232,10 +237,20 @@ void writeFaceConnectivityPresorted
template
bool writeField
(
+ //! Component scratch buffer
+ ensightOutput::floatBufferType& scratch,
+
+ //! Output file (must be valid on master)
ensightFile& os,
+
+ //! The field content to be written
const Field& fld,
+
+ //! The addressing (element-wise) into the field
const ensightCells& part,
- bool parallel //!< Collective write?
+
+ //! Prefer collective write?
+ bool parallel
);
//- Write a field of faces values as an indirect list,
@@ -243,13 +258,69 @@ bool writeField
template
bool writeField
(
+ //! Component scratch buffer
+ ensightOutput::floatBufferType& scratch,
+
+ //! Output file (must be valid on master)
ensightFile& os,
+
+ //! The field content to be written
const Field& fld,
+
+ //! The addressing (element-wise) into the field
const ensightFaces& part,
- bool parallel //!< Collective write?
+
+ //! Prefer collective write?
+ bool parallel
);
+//- Write a field of cell values as an indirect list,
+//- using the cell ids from ensightCells
+template
+bool writeField
+(
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The field content to be written
+ const Field& fld,
+
+ //! The addressing (element-wise) into the field
+ const ensightCells& part,
+
+ //! Prefer collective write?
+ bool parallel
+)
+{
+ ensightOutput::floatBufferType scratch;
+ return ensightOutput::writeField(scratch, os, fld, part, parallel);
+}
+
+
+//- Write a field of faces values as an indirect list,
+//- using the face ids from ensightFaces
+template
+bool writeField
+(
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The field content to be written
+ const Field& fld,
+
+ //! The addressing (element-wise) into the field
+ const ensightFaces& part,
+
+ //! Prefer collective write?
+ bool parallel
+)
+{
+ ensightOutput::floatBufferType scratch;
+ return ensightOutput::writeField(scratch, os, fld, part, parallel);
+}
+
+
/*---------------------------------------------------------------------------*\
Namespace ensightOutput::Detail
\*---------------------------------------------------------------------------*/
@@ -302,48 +373,109 @@ void writeLabelListList
);
-//- Copy specified field component into a scalar buffer
-//- works for various lists types. Must be adequately sized before calling
+//- Copy specified field component into a scalar buffer.
+//- Works for various lists types. Must be adequately sized before calling
template class FieldContainer, class Type>
void copyComponent
(
- List& cmptBuffer,
+ //! Input field data
const FieldContainer& input,
- const direction cmpt
+
+ //! Component to be extracted
+ const direction cmpt,
+
+ //! [out] Component scratch buffer
+ UList& cmptBuffer
);
-//- Write field content (component-wise)
-template class FieldContainer, class Type>
-void writeFieldContent
-(
- ensightFile& os,
- const FieldContainer& fld,
- bool parallel //!< Collective write?
-);
-
-
-//- Write coordinates (component-wise) for the given part
+//- Write coordinates (component-wise) for the given part.
+//
+// Has internal check for (nPoints != 0)
template class FieldContainer>
bool writeCoordinates
(
+ //! Output file (must be valid on master)
ensightGeoFile& os,
+
+ //! The ensight part id
const label partId,
+
+ //! The ensight part description
const word& partName,
+
+ //! The total number of points
const label nPoints,
+
+ //! The point field to be written
const FieldContainer& fld,
- bool parallel //!< Collective write?
+
+ //! Prefer collective write?
+ bool parallel
);
-//- Write field content (component-wise) for the given ensight element type
+//- Write field content (component-wise) for the given ensight element type.
template class FieldContainer, class Type>
-bool writeFieldComponents
+void writeFieldComponents
(
+ //! Component scratch buffer
+ ensightOutput::floatBufferType& scratch,
+
+ //! Output file (must be valid on master)
ensightFile& os,
+
+ //! The ensight element type (ignored if nullptr)
const char* key,
+
+ //! The field content to be written for this element type
const FieldContainer& fld,
- bool parallel //!< Collective write?
+
+ //! Prefer collective write?
+ bool parallel
+);
+
+//- Write field content (component-wise) for the given ensight element type.
+template class FieldContainer, class Type>
+void writeFieldComponents
+(
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The ensight element type (can be nullptr)
+ const char* key,
+
+ //! The field content to be written for this element type
+ const FieldContainer& fld,
+
+ //!< Prefer collective write?
+ bool parallel
+)
+{
+ ensightOutput::floatBufferType scratch;
+ Detail::writeFieldComponents(scratch, os, key, fld, parallel);
+}
+
+
+//- Write a sub-field of faces values as an indirect list,
+//- using the sub-list sizing information from ensightFaces
+template
+bool writeFaceSubField
+(
+ //! Component scratch buffer
+ ensightOutput::floatBufferType& scratch,
+
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The field content to be written
+ const Field& fld,
+
+ //! The addressing (element-wise) into the field
+ const ensightFaces& part,
+
+ //! Prefer collective write?
+ bool parallel
);
@@ -352,11 +484,22 @@ bool writeFieldComponents
template
bool writeFaceSubField
(
+ //! Output file (must be valid on master)
ensightFile& os,
+
+ //! The field content to be written
const Field& fld,
+
+ //! The addressing (element-wise) into the field
const ensightFaces& part,
- bool parallel //!< Collective write?
-);
+
+ //! Prefer collective write?
+ bool parallel
+)
+{
+ ensightOutput::floatBufferType scratch;
+ return Detail::writeFaceSubField(scratch, os, fld, part, parallel);
+}
//- Write a field of faces values as an indirect list,
@@ -364,12 +507,44 @@ bool writeFaceSubField
template
bool writeFaceLocalField
(
+ //! Component scratch buffer
+ ensightOutput::floatBufferType& scratch,
+
+ //! Output file (must be valid on master)
ensightFile& os,
+
+ //! The field content to be written
const Field& fld,
+
+ //! The addressing (element-wise) into the field
const ensightFaces& part,
- bool parallel //!< Collective write?
+
+ //! Prefer collective write?
+ bool parallel
);
+//- Write a field of faces values as an indirect list,
+//- using the face order from ensightFaces
+template
+bool writeFaceLocalField
+(
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The field content to be written
+ const Field& fld,
+
+ //! The addressing (element-wise) into the field
+ const ensightFaces& part,
+
+ //! Prefer collective write?
+ bool parallel
+)
+{
+ ensightOutput::floatBufferType scratch;
+ return Detail::writeFaceLocalField(scratch, os, fld, part, parallel);
+}
+
} // End namespace Detail
diff --git a/src/fileFormats/ensight/output/ensightOutputFwd.H b/src/fileFormats/ensight/output/ensightOutputFwd.H
new file mode 100644
index 0000000000..ac2e1c6432
--- /dev/null
+++ b/src/fileFormats/ensight/output/ensightOutputFwd.H
@@ -0,0 +1,78 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | www.openfoam.com
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2022 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 .
+
+Namespace
+ Foam::ensightOutput
+
+Description
+ A collection of functions for writing ensight file content.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef Foam_ensightOutputFwd_H
+#define Foam_ensightOutputFwd_H
+
+#include "DynamicList.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward Declarations
+class ensightFile;
+class ensightGeoFile;
+
+
+/*---------------------------------------------------------------------------*\
+ Namespace ensightOutput
+\*---------------------------------------------------------------------------*/
+
+namespace ensightOutput
+{
+
+//- The list type used for component-wise buffering.
+// Always has value_type = \c float (what ensight uses internally)
+typedef DynamicList floatBufferType;
+
+//- Static debugging option
+extern int debug;
+
+//- Upper limit on number of items for bundled off-processor field transfers.
+//- The component-wise transfer uses float (4 bytes).
+// Eg, 5M for 50 ranks of 100k cells each
+extern int maxChunk_;
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace ensightOutput
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/ensight/output/ensightOutputTemplates.C b/src/fileFormats/ensight/output/ensightOutputTemplates.C
index 13b15daaeb..b6470dd9b5 100644
--- a/src/fileFormats/ensight/output/ensightOutputTemplates.C
+++ b/src/fileFormats/ensight/output/ensightOutputTemplates.C
@@ -55,9 +55,9 @@ void Foam::ensightOutput::Detail::writeLabelListList
template class FieldContainer, class Type>
void Foam::ensightOutput::Detail::copyComponent
(
- List& cmptBuffer,
const FieldContainer& input,
- const direction cmpt
+ const direction cmpt,
+ UList& cmptBuffer
)
{
if (cmptBuffer.size() < input.size())
@@ -70,78 +70,178 @@ void Foam::ensightOutput::Detail::copyComponent
auto iter = cmptBuffer.begin();
- for (const Type& val : input)
+ if (std::is_same::cmptType>::value)
{
- *iter = component(val, cmpt);
- ++iter;
+ // Direct copy
+ for (const Type& val : input)
+ {
+ *iter = component(val, cmpt);
+ ++iter;
+ }
+ }
+ else
+ {
+ // Copy with narrowing
+ for (const Type& val : input)
+ {
+ *iter = narrowFloat(component(val, cmpt));
+ ++iter;
+ }
}
}
template class FieldContainer, class Type>
-void Foam::ensightOutput::Detail::writeFieldContent
+void Foam::ensightOutput::Detail::writeFieldComponents
(
+ ensightOutput::floatBufferType& scratch,
ensightFile& os,
+ const char* key,
const FieldContainer& fld,
bool parallel
)
{
- // already checked prior to calling, but extra safety
parallel = parallel && Pstream::parRun();
+ const label localSize = fld.size();
+
// Gather sizes (offsets irrelevant)
const globalIndex procAddr
(
parallel
- ? globalIndex(globalIndex::gatherOnly{}, fld.size())
- : globalIndex(globalIndex::gatherNone{}, fld.size())
+ ? globalIndex(globalIndex::gatherOnly{}, localSize)
+ : globalIndex(globalIndex::gatherNone{}, localSize)
);
+ if (Pstream::master() && key)
+ {
+ os.writeKeyword(key);
+ }
if (Pstream::master())
{
- DynamicList cmptBuffer(procAddr.maxSize());
+ // Buffer size needed for an individual rank
+ const label minSize(max(localSize, procAddr.maxSize()));
+
+ // Buffer size needed for all nonLocal ranks
+ const label nonLocalSize(procAddr.totalSize() - localSize);
+
+ // Maximum off-processor transfer size
+ const label maxTransfer =
+ (
+ (ensightOutput::maxChunk_ > 0)
+ ? min(static_cast(ensightOutput::maxChunk_), nonLocalSize)
+ : static_cast(0)
+ );
+
+ // Allocate at least enough to process a single rank, but potentially
+ // receive multiple ranks at a time before writing
+
+ scratch.resize_nocopy(max(minSize, maxTransfer));
+
+ if (Pstream::master() && debug > 1)
+ {
+ Info<< "ensight";
+ if (key)
+ {
+ Info<< " (" << key << ')';
+ }
+
+ Info<< " total-size:" << procAddr.totalSize()
+ << " buf-size:" << scratch.size() << "/" << scratch.capacity()
+ << " any-proc:" << minSize
+ << " off-proc:" << nonLocalSize << endl;
+
+ Info<< "proc-sends: (";
+
+ label nPending = localSize;
+
+ Info<< (localSize ? '0' : '_');
+
+ // Receive others, writing as needed
+ for (const label proci : procAddr.subProcs())
+ {
+ const label procSize = procAddr.localSize(proci);
+
+ if (procSize)
+ {
+ if (nPending + procSize > scratch.size())
+ {
+ // Flush buffer
+ nPending = 0;
+ Info<< ") (";
+ }
+ else
+ {
+ Info<< ' ';
+ }
+
+ Info<< proci;
+ nPending += procSize;
+ }
+ }
+
+ Info<< ')' << endl;
+ }
for (direction d=0; d < pTraits::nComponents; ++d)
{
const direction cmpt = ensightPTraits::componentOrder[d];
- // Write master data
- cmptBuffer.resize_nocopy(procAddr.localSize(0));
- copyComponent(cmptBuffer, fld, cmpt);
- os.writeList(cmptBuffer);
+ // Master
+ copyComponent(fld, cmpt, scratch);
+ label nPending = localSize;
- // Receive and write
+ // Receive others, writing as needed
for (const label proci : procAddr.subProcs())
{
- cmptBuffer.resize_nocopy(procAddr.localSize(proci));
- UIPstream::read
- (
- UPstream::commsTypes::scheduled,
- proci,
- cmptBuffer.data_bytes(),
- cmptBuffer.size_bytes()
- );
- os.writeList(cmptBuffer);
+ const label procSize = procAddr.localSize(proci);
+
+ if (procSize)
+ {
+ if (nPending + procSize > scratch.size())
+ {
+ // Flush buffer
+ os.writeList(SubList(scratch, nPending));
+ nPending = 0;
+ }
+
+ SubList slot(scratch, procSize, nPending);
+ nPending += procSize;
+
+ UIPstream::read
+ (
+ UPstream::commsTypes::scheduled,
+ proci,
+ slot.data_bytes(),
+ slot.size_bytes()
+ );
+ }
+ }
+
+ if (nPending)
+ {
+ // Flush buffer
+ os.writeList(SubList(scratch, nPending));
}
}
}
- else if (parallel)
+ else if (parallel && localSize)
{
- // Send
- List cmptBuffer(fld.size());
+ scratch.resize_nocopy(localSize);
for (direction d=0; d < pTraits::nComponents; ++d)
{
const direction cmpt = ensightPTraits::componentOrder[d];
- copyComponent(cmptBuffer, fld, cmpt);
+ copyComponent(fld, cmpt, scratch);
+
UOPstream::write
(
UPstream::commsTypes::scheduled,
UPstream::masterNo(),
- cmptBuffer.cdata_bytes(),
- cmptBuffer.size_bytes()
+ scratch.cdata_bytes(),
+ scratch.size_bytes()
);
}
}
@@ -159,45 +259,31 @@ bool Foam::ensightOutput::Detail::writeCoordinates
bool parallel
)
{
- parallel = parallel && Pstream::parRun();
-
if (Pstream::master())
{
os.beginPart(partId, partName);
os.beginCoordinates(nPoints);
}
- ensightOutput::Detail::writeFieldContent(os, fld, parallel);
-
- return true;
-}
-
-
-template class FieldContainer, class Type>
-bool Foam::ensightOutput::Detail::writeFieldComponents
-(
- ensightFile& os,
- const char* key,
- const FieldContainer& fld,
- bool parallel
-)
-{
- parallel = parallel && Pstream::parRun();
-
- // Preliminary checks
+ bool ok = (Pstream::master() && (nPoints > 0));
+ if (parallel)
{
- // No field
- if (parallel ? returnReduceAnd(fld.empty()) : fld.empty()) return false;
+ Pstream::broadcast(ok);
}
-
- if (Pstream::master())
+ if (ok)
{
- os.writeKeyword(key);
+ ensightOutput::floatBufferType scratch;
+ ensightOutput::Detail::writeFieldComponents
+ (
+ scratch,
+ os,
+ nullptr, // (no element type)
+ fld,
+ parallel
+ );
}
- ensightOutput::Detail::writeFieldContent(os, fld, parallel);
-
return true;
}
@@ -205,6 +291,7 @@ bool Foam::ensightOutput::Detail::writeFieldComponents
template
bool Foam::ensightOutput::Detail::writeFaceSubField
(
+ ensightOutput::floatBufferType& scratch,
ensightFile& os,
const Field& fld,
const ensightFaces& part,
@@ -213,13 +300,17 @@ bool Foam::ensightOutput::Detail::writeFaceSubField
{
parallel = parallel && Pstream::parRun();
- // Preliminary checks: total() contains pre-reduced information
- {
- // No geometry
- if (parallel ? !part.total() : !part.size()) return false;
+ // Need geometry and field. part.total() is already reduced
+ const bool good =
+ (
+ parallel
+ ? (part.total() && returnReduceOr(fld.size()))
+ : (part.size() && fld.size())
+ );
- // No field
- if (parallel ? returnReduceAnd(fld.empty()) : fld.empty()) return false;
+ if (!good)
+ {
+ return false;
}
@@ -232,13 +323,18 @@ bool Foam::ensightOutput::Detail::writeFaceSubField
{
const auto etype = ensightFaces::elemType(typei);
- ensightOutput::Detail::writeFieldComponents
- (
- os,
- ensightFaces::key(etype),
- SubField(fld, part.range(etype)),
- parallel
- );
+ // Write elements of this type
+ if (parallel ? part.total(etype) : part.size(etype))
+ {
+ ensightOutput::Detail::writeFieldComponents
+ (
+ scratch,
+ os,
+ ensightFaces::key(etype),
+ SubField(fld, part.range(etype)),
+ parallel
+ );
+ }
}
return true;
@@ -248,6 +344,7 @@ bool Foam::ensightOutput::Detail::writeFaceSubField
template
bool Foam::ensightOutput::Detail::writeFaceLocalField
(
+ ensightOutput::floatBufferType& scratch,
ensightFile& os,
const Field& fld,
const ensightFaces& part,
@@ -256,15 +353,20 @@ bool Foam::ensightOutput::Detail::writeFaceLocalField
{
parallel = parallel && Pstream::parRun();
- // Preliminary checks: total() contains pre-reduced information
- {
- // No geometry
- if (parallel ? !part.total() : !part.size()) return false;
+ // Need geometry and field. part.total() is already reduced
+ const bool good =
+ (
+ parallel
+ ? (part.total() && returnReduceOr(fld.size()))
+ : (part.size() && fld.size())
+ );
- // No field
- if (parallel ? returnReduceAnd(fld.empty()) : fld.empty()) return false;
+ if (!good)
+ {
+ return false;
}
+
bool validAddressing = (part.size() == part.faceOrder().size());
if (parallel)
@@ -289,13 +391,18 @@ bool Foam::ensightOutput::Detail::writeFaceLocalField
{
const auto etype = ensightFaces::elemType(typei);
- ensightOutput::Detail::writeFieldComponents
- (
- os,
- ensightFaces::key(etype),
- UIndirectList(fld, part.faceOrder(etype)),
- parallel
- );
+ // Write elements of this type
+ if (parallel ? part.total(etype) : part.size(etype))
+ {
+ ensightOutput::Detail::writeFieldComponents
+ (
+ scratch,
+ os,
+ ensightFaces::key(etype),
+ UIndirectList(fld, part.faceOrder(etype)),
+ parallel
+ );
+ }
}
return true;
@@ -307,6 +414,7 @@ bool Foam::ensightOutput::Detail::writeFaceLocalField
template
bool Foam::ensightOutput::writeField
(
+ ensightOutput::floatBufferType& scratch,
ensightFile& os,
const Field& fld,
const ensightCells& part,
@@ -315,13 +423,17 @@ bool Foam::ensightOutput::writeField
{
parallel = parallel && Pstream::parRun();
- // Preliminary checks: total() contains pre-reduced information
- {
- // No geometry
- if (parallel ? !part.total() : !part.size()) return false;
+ // Need geometry and field. part.total() is already reduced
+ const bool good =
+ (
+ parallel
+ ? (part.total() && returnReduceOr(fld.size()))
+ : (part.size() && fld.size())
+ );
- // No field
- if (parallel ? returnReduceAnd(fld.empty()) : fld.empty()) return false;
+ if (!good)
+ {
+ return false;
}
@@ -334,13 +446,18 @@ bool Foam::ensightOutput::writeField
{
const auto etype = ensightCells::elemType(typei);
- ensightOutput::Detail::writeFieldComponents
- (
- os,
- ensightCells::key(etype),
- UIndirectList(fld, part.cellIds(etype)),
- parallel
- );
+ // Write elements of this type
+ if (parallel ? part.total(etype) : part.size(etype))
+ {
+ ensightOutput::Detail::writeFieldComponents
+ (
+ scratch,
+ os,
+ ensightCells::key(etype),
+ UIndirectList(fld, part.cellIds(etype)),
+ parallel
+ );
+ }
}
return true;
@@ -350,6 +467,7 @@ bool Foam::ensightOutput::writeField
template
bool Foam::ensightOutput::writeField
(
+ ensightOutput::floatBufferType& scratch,
ensightFile& os,
const Field& fld,
const ensightFaces& part,
@@ -358,13 +476,17 @@ bool Foam::ensightOutput::writeField
{
parallel = parallel && Pstream::parRun();
- // Preliminary checks: total() contains pre-reduced information
- {
- // No geometry
- if (parallel ? !part.total() : !part.size()) return false;
+ // Need geometry and field. part.total() is already reduced
+ const bool good =
+ (
+ parallel
+ ? (part.total() && returnReduceOr(fld.size()))
+ : (part.size() && fld.size())
+ );
- // No field
- if (parallel ? returnReduceAnd(fld.empty()) : fld.empty()) return false;
+ if (!good)
+ {
+ return false;
}
@@ -377,13 +499,18 @@ bool Foam::ensightOutput::writeField
{
const auto etype = ensightFaces::elemType(typei);
- ensightOutput::Detail::writeFieldComponents
- (
- os,
- ensightFaces::key(etype),
- UIndirectList(fld, part.faceIds(etype)),
- parallel
- );
+ // Write elements of this type
+ if (parallel ? part.total(etype) : part.size(etype))
+ {
+ ensightOutput::Detail::writeFieldComponents
+ (
+ scratch,
+ os,
+ ensightFaces::key(etype),
+ UIndirectList(fld, part.faceIds(etype)),
+ parallel
+ );
+ }
}
return true;
diff --git a/src/fileFormats/ensight/part/cells/ensightCells.C b/src/fileFormats/ensight/part/cells/ensightCells.C
index a5e26b29c7..398ff131c3 100644
--- a/src/fileFormats/ensight/part/cells/ensightCells.C
+++ b/src/fileFormats/ensight/part/cells/ensightCells.C
@@ -99,7 +99,7 @@ Foam::FixedList Foam::ensightCells::sizes() const
{
FixedList count;
- forAll(count, typei)
+ for (int typei = 0; typei < nTypes; ++typei)
{
count[typei] = size(elemType(typei));
}
@@ -108,14 +108,14 @@ Foam::FixedList Foam::ensightCells::sizes() const
}
-Foam::label Foam::ensightCells::total() const
+Foam::label Foam::ensightCells::totalSize() const noexcept
{
- label nTotal = 0;
- forAll(sizes_, typei)
+ label count = 0;
+ for (label n : sizes_)
{
- nTotal += sizes_[typei];
+ count += n;
}
- return nTotal;
+ return count;
}
@@ -137,11 +137,10 @@ void Foam::ensightCells::clearOut()
void Foam::ensightCells::reduce()
{
- forAll(sizes_, typei)
+ for (int typei = 0; typei < nTypes; ++typei)
{
sizes_[typei] = size(elemType(typei));
}
- // Can reduce FixedList with sumOp in a single operation
Foam::reduce(sizes_, sumOp());
}
diff --git a/src/fileFormats/ensight/part/cells/ensightCells.H b/src/fileFormats/ensight/part/cells/ensightCells.H
index f2f7edce17..928399f45e 100644
--- a/src/fileFormats/ensight/part/cells/ensightCells.H
+++ b/src/fileFormats/ensight/part/cells/ensightCells.H
@@ -82,7 +82,7 @@ public:
// Static Functions
//- The ensight element name for the specified 'Cell' type
- inline static const char* key(const elemType etype);
+ inline static const char* key(const elemType etype) noexcept;
private:
@@ -183,7 +183,10 @@ public:
//- The global size of all element types.
// This value is only meaningful after a reduce operation.
- label total() const;
+ label totalSize() const noexcept;
+
+ //- Same as totalSize()
+ label total() const noexcept { return totalSize(); }
//- The global size of the specified element type.
// This value is only meaningful after a reduce operation.
diff --git a/src/fileFormats/ensight/part/cells/ensightCellsI.H b/src/fileFormats/ensight/part/cells/ensightCellsI.H
index 52515d0c14..956e2606b9 100644
--- a/src/fileFormats/ensight/part/cells/ensightCellsI.H
+++ b/src/fileFormats/ensight/part/cells/ensightCellsI.H
@@ -46,7 +46,7 @@ inline bool Foam::ensightCells::manifold() const noexcept
}
-inline const char* Foam::ensightCells::key(const elemType etype)
+inline const char* Foam::ensightCells::key(const elemType etype) noexcept
{
return elemNames[etype];
}
diff --git a/src/fileFormats/ensight/part/faces/ensightFaces.C b/src/fileFormats/ensight/part/faces/ensightFaces.C
index 22095fdeaf..404a4e3f34 100644
--- a/src/fileFormats/ensight/part/faces/ensightFaces.C
+++ b/src/fileFormats/ensight/part/faces/ensightFaces.C
@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2016-2021 OpenCFD Ltd.
+ Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -124,7 +124,7 @@ Foam::FixedList Foam::ensightFaces::sizes() const
{
FixedList count;
- forAll(count, typei)
+ for (int typei = 0; typei < nTypes; ++typei)
{
count[typei] = size(elemType(typei));
}
@@ -133,14 +133,14 @@ Foam::FixedList Foam::ensightFaces::sizes() const
}
-Foam::label Foam::ensightFaces::total() const
+Foam::label Foam::ensightFaces::totalSize() const noexcept
{
- label nTotal = 0;
- forAll(sizes_, typei)
+ label count = 0;
+ for (label n : sizes_)
{
- nTotal += sizes_[typei];
+ count += n;
}
- return nTotal;
+ return count;
}
@@ -163,11 +163,10 @@ void Foam::ensightFaces::clearOut()
void Foam::ensightFaces::reduce()
{
- forAll(sizes_, typei)
+ for (int typei = 0; typei < nTypes; ++typei)
{
sizes_[typei] = size(elemType(typei));
}
- // Can reduce FixedList with sumOp in a single operation
Foam::reduce(sizes_, sumOp());
}
diff --git a/src/fileFormats/ensight/part/faces/ensightFaces.H b/src/fileFormats/ensight/part/faces/ensightFaces.H
index 275fc3b1dd..8b4cff2819 100644
--- a/src/fileFormats/ensight/part/faces/ensightFaces.H
+++ b/src/fileFormats/ensight/part/faces/ensightFaces.H
@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2016-2021 OpenCFD Ltd.
+ Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -97,7 +97,7 @@ public:
// Static Functions
//- The ensight element name for the specified 'Face' type
- static inline const char* key(const elemType etype);
+ static inline const char* key(const elemType etype) noexcept;
private:
@@ -162,7 +162,10 @@ public:
//- The global size of all element types.
// This value is only meaningful after a reduce operation.
- label total() const;
+ label totalSize() const noexcept;
+
+ //- Same as totalSize
+ label total() const noexcept { return totalSize(); }
//- The global size of the specified element type.
// This value is only meaningful after a reduce operation.
diff --git a/src/fileFormats/ensight/part/faces/ensightFacesI.H b/src/fileFormats/ensight/part/faces/ensightFacesI.H
index 1560d87fb6..a188260172 100644
--- a/src/fileFormats/ensight/part/faces/ensightFacesI.H
+++ b/src/fileFormats/ensight/part/faces/ensightFacesI.H
@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2016-2021 OpenCFD Ltd.
+ Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -46,7 +46,7 @@ Foam::ensightFaces::add(const elemType etype, label id, bool flip)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
-inline const char* Foam::ensightFaces::key(const elemType etype)
+inline const char* Foam::ensightFaces::key(const elemType etype) noexcept
{
return elemNames[etype];
}
diff --git a/src/fileFormats/ensight/type/ensightPTraits.C b/src/fileFormats/ensight/type/ensightPTraits.C
index 9eaf9d30f6..aca6dfb4be 100644
--- a/src/fileFormats/ensight/type/ensightPTraits.C
+++ b/src/fileFormats/ensight/type/ensightPTraits.C
@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2015 OpenFOAM Foundation
- Copyright (C) 2019 OpenCFD Ltd.
+ Copyright (C) 2019-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -41,11 +41,20 @@ Foam::ensightPTraits::componentOrder[] = {0};
template<>
const char* const
-Foam::ensightPTraits::typeName = "scalar";
+Foam::ensightPTraits::typeName = "scalar";
template<>
const Foam::direction
-Foam::ensightPTraits::componentOrder[] = {0};
+Foam::ensightPTraits::componentOrder[] = {0};
+
+
+template<>
+const char* const
+Foam::ensightPTraits::typeName = "scalar";
+
+template<>
+const Foam::direction
+Foam::ensightPTraits::componentOrder[] = {0};
template<>
diff --git a/src/fileFormats/ensight/type/ensightPTraits.H b/src/fileFormats/ensight/type/ensightPTraits.H
index be7e40b48a..c2244655b4 100644
--- a/src/fileFormats/ensight/type/ensightPTraits.H
+++ b/src/fileFormats/ensight/type/ensightPTraits.H
@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2015 OpenFOAM Foundation
- Copyright (C) 2019-2021 OpenCFD Ltd.
+ Copyright (C) 2019-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -47,7 +47,7 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
- Class ensightPTraits Declaration
+ Class ensightPTraits Declaration
\*---------------------------------------------------------------------------*/
template
@@ -69,8 +69,11 @@ struct ensightPTraits
template<> const char* const ensightPTraits::typeName;
template<> const direction ensightPTraits::componentOrder[];
-template<> const char* const ensightPTraits::typeName;
-template<> const direction ensightPTraits::componentOrder[];
+template<> const char* const ensightPTraits::typeName;
+template<> const direction ensightPTraits::componentOrder[];
+
+template<> const char* const ensightPTraits::typeName;
+template<> const direction ensightPTraits::componentOrder[];
template<> const char* const ensightPTraits::typeName;
template<> const direction ensightPTraits::componentOrder[];
diff --git a/src/fileFormats/vtk/output/foamVtkOutput.C b/src/fileFormats/vtk/output/foamVtkOutput.C
index e4f33eb710..338f7b555f 100644
--- a/src/fileFormats/vtk/output/foamVtkOutput.C
+++ b/src/fileFormats/vtk/output/foamVtkOutput.C
@@ -130,7 +130,7 @@ void Foam::vtk::writeListParallel
)
{
// Gather sizes (offsets irrelevant)
- const globalIndex procAddr(values.size(), globalIndex::gatherOnly{});
+ const globalIndex procAddr(globalIndex::gatherOnly{}, values.size());
if (Pstream::master())
{
@@ -146,33 +146,40 @@ void Foam::vtk::writeListParallel
for (const label proci : procAddr.subProcs())
{
- recvData.resize_nocopy(procAddr.localSize(proci));
- UIPstream::read
- (
- UPstream::commsTypes::scheduled,
- proci,
- recvData.data_bytes(),
- recvData.size_bytes()
- );
+ const label procSize = procAddr.localSize(proci);
- // With value offset
- const label offsetId = procOffset.localStart(proci);
- for (const label val : recvData)
+ if (procSize)
{
- vtk::write(fmt, val + offsetId);
+ recvData.resize_nocopy(procSize);
+ UIPstream::read
+ (
+ UPstream::commsTypes::scheduled,
+ proci,
+ recvData.data_bytes(),
+ recvData.size_bytes()
+ );
+
+ // With value offset
+ const label offsetId = procOffset.localStart(proci);
+ for (const label val : recvData)
+ {
+ vtk::write(fmt, val + offsetId);
+ }
}
}
}
else
{
- // Send
- UOPstream::write
- (
- UPstream::commsTypes::scheduled,
- UPstream::masterNo(),
- values.cdata_bytes(),
- values.size_bytes()
- );
+ if (values.size())
+ {
+ UOPstream::write
+ (
+ UPstream::commsTypes::scheduled,
+ UPstream::masterNo(),
+ values.cdata_bytes(),
+ values.size_bytes()
+ );
+ }
}
}
diff --git a/src/fileFormats/vtk/output/foamVtkOutputTemplates.C b/src/fileFormats/vtk/output/foamVtkOutputTemplates.C
index ef8c9d11bc..552cf654bd 100644
--- a/src/fileFormats/vtk/output/foamVtkOutputTemplates.C
+++ b/src/fileFormats/vtk/output/foamVtkOutputTemplates.C
@@ -171,7 +171,7 @@ void Foam::vtk::writeListParallel
// Gather sizes (offsets irrelevant)
- const globalIndex procAddr(values.size(), globalIndex::gatherOnly{});
+ const globalIndex procAddr(globalIndex::gatherOnly{}, values.size());
if (Pstream::master())
@@ -184,27 +184,34 @@ void Foam::vtk::writeListParallel
for (const label proci : procAddr.subProcs())
{
- recvData.resize_nocopy(procAddr.localSize(proci));
- UIPstream::read
- (
- UPstream::commsTypes::scheduled,
- proci,
- recvData.data_bytes(),
- recvData.size_bytes()
- );
- vtk::writeList(fmt, recvData);
+ const label procSize = procAddr.localSize(proci);
+
+ if (procSize)
+ {
+ recvData.resize_nocopy(procSize);
+ UIPstream::read
+ (
+ UPstream::commsTypes::scheduled,
+ proci,
+ recvData.data_bytes(),
+ recvData.size_bytes()
+ );
+ vtk::writeList(fmt, recvData);
+ }
}
}
else
{
- // Send
- UOPstream::write
- (
- UPstream::commsTypes::scheduled,
- UPstream::masterNo(),
- values.cdata_bytes(),
- values.size_bytes()
- );
+ if (values.size())
+ {
+ UOPstream::write
+ (
+ UPstream::commsTypes::scheduled,
+ UPstream::masterNo(),
+ values.cdata_bytes(),
+ values.size_bytes()
+ );
+ }
}
}
@@ -233,7 +240,7 @@ void Foam::vtk::writeListParallel
}
// Gather sizes (offsets irrelevant)
- const globalIndex procAddr(sendData.size(), globalIndex::gatherOnly{});
+ const globalIndex procAddr(globalIndex::gatherOnly{}, sendData.size());
if (Pstream::master())
@@ -246,26 +253,34 @@ void Foam::vtk::writeListParallel
for (const label proci : procAddr.subProcs())
{
- recvData.resize_nocopy(procAddr.localSize(proci));
- UIPstream::read
- (
- UPstream::commsTypes::scheduled,
- proci,
- recvData.data_bytes(),
- recvData.size_bytes()
- );
- vtk::writeList(fmt, recvData);
+ const label procSize = procAddr.localSize(proci);
+
+ if (procSize)
+ {
+ recvData.resize_nocopy(procSize);
+ UIPstream::read
+ (
+ UPstream::commsTypes::scheduled,
+ proci,
+ recvData.data_bytes(),
+ recvData.size_bytes()
+ );
+ vtk::writeList(fmt, recvData);
+ }
}
}
else
{
- UOPstream::write
- (
- UPstream::commsTypes::scheduled,
- UPstream::masterNo(),
- sendData.cdata_bytes(),
- sendData.size_bytes()
- );
+ if (sendData.size())
+ {
+ UOPstream::write
+ (
+ UPstream::commsTypes::scheduled,
+ UPstream::masterNo(),
+ sendData.cdata_bytes(),
+ sendData.size_bytes()
+ );
+ }
}
}
@@ -294,7 +309,7 @@ void Foam::vtk::writeListParallel
}
// Gather sizes (offsets irrelevant)
- const globalIndex procAddr(sendData.size(), globalIndex::gatherOnly{});
+ const globalIndex procAddr(globalIndex::gatherOnly{}, sendData.size());
if (Pstream::master())
@@ -307,26 +322,35 @@ void Foam::vtk::writeListParallel
for (const label proci : procAddr.subProcs())
{
- recvData.resize_nocopy(procAddr.localSize(proci));
- UIPstream::read
- (
- UPstream::commsTypes::scheduled,
- proci,
- recvData.data_bytes(),
- recvData.size_bytes()
- );
- vtk::writeList(fmt, recvData);
+ const label procSize = procAddr.localSize(proci);
+
+ if (procSize)
+ {
+ recvData.resize_nocopy(procSize);
+
+ UIPstream::read
+ (
+ UPstream::commsTypes::scheduled,
+ proci,
+ recvData.data_bytes(),
+ recvData.size_bytes()
+ );
+ vtk::writeList(fmt, recvData);
+ }
}
}
else
{
- UOPstream::write
- (
- UPstream::commsTypes::scheduled,
- UPstream::masterNo(),
- sendData.cdata_bytes(),
- sendData.size_bytes()
- );
+ if (sendData.size())
+ {
+ UOPstream::write
+ (
+ UPstream::commsTypes::scheduled,
+ UPstream::masterNo(),
+ sendData.cdata_bytes(),
+ sendData.size_bytes()
+ );
+ }
}
}
@@ -349,8 +373,8 @@ void Foam::vtk::writeListsParallel
// Gather sizes (offsets irrelevant)
- const globalIndex procAddr1(values1.size(), globalIndex::gatherOnly{});
- const globalIndex procAddr2(values2.size(), globalIndex::gatherOnly{});
+ const globalIndex procAddr1(globalIndex::gatherOnly{}, values1.size());
+ const globalIndex procAddr2(globalIndex::gatherOnly{}, values2.size());
if (Pstream::master())
@@ -368,45 +392,61 @@ void Foam::vtk::writeListsParallel
for (const label proci : procAddr1.subProcs())
{
// values1
- recvData.resize_nocopy(procAddr1.localSize(proci));
- UIPstream::read
- (
- UPstream::commsTypes::scheduled,
- proci,
- recvData.data_bytes(),
- recvData.size_bytes()
- );
- vtk::writeList(fmt, recvData);
+ label procSize = procAddr1.localSize(proci);
+
+ if (procSize)
+ {
+ recvData.resize_nocopy(procSize);
+ UIPstream::read
+ (
+ UPstream::commsTypes::scheduled,
+ proci,
+ recvData.data_bytes(),
+ recvData.size_bytes()
+ );
+ vtk::writeList(fmt, recvData);
+ }
// values2
- recvData.resize_nocopy(procAddr2.localSize(proci));
- UIPstream::read
- (
- UPstream::commsTypes::scheduled,
- proci,
- recvData.data_bytes(),
- recvData.size_bytes()
- );
- vtk::writeList(fmt, recvData);
+ procSize = procAddr2.localSize(proci);
+
+ if (procSize)
+ {
+ recvData.resize_nocopy(procSize);
+ UIPstream::read
+ (
+ UPstream::commsTypes::scheduled,
+ proci,
+ recvData.data_bytes(),
+ recvData.size_bytes()
+ );
+ vtk::writeList(fmt, recvData);
+ }
}
}
else
{
- UOPstream::write
- (
- UPstream::commsTypes::scheduled,
- UPstream::masterNo(),
- values1.cdata_bytes(),
- values1.size_bytes()
- );
+ if (values1.size())
+ {
+ UOPstream::write
+ (
+ UPstream::commsTypes::scheduled,
+ UPstream::masterNo(),
+ values1.cdata_bytes(),
+ values1.size_bytes()
+ );
+ }
- UOPstream::write
- (
- UPstream::commsTypes::scheduled,
- UPstream::masterNo(),
- values2.cdata_bytes(),
- values2.size_bytes()
- );
+ if (values2.size())
+ {
+ UOPstream::write
+ (
+ UPstream::commsTypes::scheduled,
+ UPstream::masterNo(),
+ values2.cdata_bytes(),
+ values2.size_bytes()
+ );
+ }
}
}
@@ -437,8 +477,8 @@ void Foam::vtk::writeListsParallel
// Gather sizes (offsets irrelevant)
- const globalIndex procAddr1(values1.size(), globalIndex::gatherOnly{});
- const globalIndex procAddr2(sendData2.size(), globalIndex::gatherOnly{});
+ const globalIndex procAddr1(globalIndex::gatherOnly{}, values1.size());
+ const globalIndex procAddr2(globalIndex::gatherOnly{}, sendData2.size());
if (Pstream::master())
@@ -457,45 +497,61 @@ void Foam::vtk::writeListsParallel
for (const label proci : procAddr1.subProcs())
{
// values1
- recvData.resize_nocopy(procAddr1.localSize(proci));
- UIPstream::read
- (
- UPstream::commsTypes::scheduled,
- proci,
- recvData.data_bytes(),
- recvData.size_bytes()
- );
- vtk::writeList(fmt, recvData);
+ label procSize = procAddr1.localSize(proci);
+
+ if (procSize)
+ {
+ recvData.resize_nocopy(procSize);
+ UIPstream::read
+ (
+ UPstream::commsTypes::scheduled,
+ proci,
+ recvData.data_bytes(),
+ recvData.size_bytes()
+ );
+ vtk::writeList(fmt, recvData);
+ }
// values2
- recvData.resize_nocopy(procAddr2.localSize(proci));
- UIPstream::read
- (
- UPstream::commsTypes::scheduled,
- proci,
- recvData.data_bytes(),
- recvData.size_bytes()
- );
- vtk::writeList(fmt, recvData);
+ procSize = procAddr2.localSize(proci);
+
+ if (procSize)
+ {
+ recvData.resize_nocopy(procSize);
+ UIPstream::read
+ (
+ UPstream::commsTypes::scheduled,
+ proci,
+ recvData.data_bytes(),
+ recvData.size_bytes()
+ );
+ vtk::writeList(fmt, recvData);
+ }
}
}
else
{
- UOPstream::write
- (
- UPstream::commsTypes::scheduled,
- UPstream::masterNo(),
- values1.cdata_bytes(),
- values1.size_bytes()
- );
+ if (values1.size())
+ {
+ UOPstream::write
+ (
+ UPstream::commsTypes::scheduled,
+ UPstream::masterNo(),
+ values1.cdata_bytes(),
+ values1.size_bytes()
+ );
+ }
- UOPstream::write
- (
- UPstream::commsTypes::scheduled,
- UPstream::masterNo(),
- sendData2.cdata_bytes(),
- sendData2.size_bytes()
- );
+ if (sendData2.size())
+ {
+ UOPstream::write
+ (
+ UPstream::commsTypes::scheduled,
+ UPstream::masterNo(),
+ sendData2.cdata_bytes(),
+ sendData2.size_bytes()
+ );
+ }
}
}
diff --git a/src/functionObjects/utilities/ensightWrite/ensightWrite.C b/src/functionObjects/utilities/ensightWrite/ensightWrite.C
index 36a3b53d18..92f6575d89 100644
--- a/src/functionObjects/utilities/ensightWrite/ensightWrite.C
+++ b/src/functionObjects/utilities/ensightWrite/ensightWrite.C
@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2016-2020 OpenCFD Ltd.
+ Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -26,6 +26,7 @@ License
\*---------------------------------------------------------------------------*/
#include "ensightWrite.H"
+#include "ensightOutput.H"
#include "Time.H"
#include "polyMesh.H"
#include "addToRunTimeSelectionTable.H"
@@ -47,6 +48,9 @@ namespace functionObjects
}
}
+// Implementation
+#include "ensightWriteImpl.C"
+
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::label Foam::functionObjects::ensightWrite::writeAllVolFields
@@ -57,11 +61,26 @@ Foam::label Foam::functionObjects::ensightWrite::writeAllVolFields
{
label count = 0;
- count += writeVolFields(proxy, acceptField);
- count += writeVolFields(proxy, acceptField);
- count += writeVolFields(proxy, acceptField);
- count += writeVolFields(proxy, acceptField);
- count += writeVolFields(proxy, acceptField);
+ ensightOutput::floatBufferType scratch;
+
+ {
+ #undef doLocalCode
+ #define doLocalCode(PrimitiveType) \
+ count += writeVolFieldsImpl \
+ ( \
+ scratch, \
+ proxy, \
+ acceptField \
+ );
+
+ doLocalCode(scalar);
+ doLocalCode(vector);
+ doLocalCode(sphericalTensor);
+ doLocalCode(symmTensor);
+ doLocalCode(tensor);
+
+ #undef doLocalCode
+ }
return count;
}
@@ -215,6 +234,8 @@ bool Foam::functionObjects::ensightWrite::write()
ensMesh_().write(os);
}
+ // TBD: handle allow/deny filters
+
wordHashSet acceptField(mesh_.names(selectFields_));
// Prune restart fields
diff --git a/src/functionObjects/utilities/ensightWrite/ensightWrite.H b/src/functionObjects/utilities/ensightWrite/ensightWrite.H
index 7ad89894f6..9e049823cd 100644
--- a/src/functionObjects/utilities/ensightWrite/ensightWrite.H
+++ b/src/functionObjects/utilities/ensightWrite/ensightWrite.H
@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2016-2020 OpenCFD Ltd.
+ Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -127,16 +127,18 @@ See also
SourceFiles
ensightWrite.C
- ensightWriteTemplates.C
+ ensightWriteImpl.C
+ ensightWriteUpdate.C
\*---------------------------------------------------------------------------*/
-#ifndef functionObjects_ensightWrite_H
-#define functionObjects_ensightWrite_H
+#ifndef Foam_functionObjects_ensightWrite_H
+#define Foam_functionObjects_ensightWrite_H
#include "fvMeshFunctionObject.H"
#include "ensightCase.H"
#include "ensightMesh.H"
+#include "ensightOutputFwd.H"
#include "interpolation.H"
#include "volFields.H"
@@ -223,6 +225,15 @@ class ensightWrite
// Write
+ //- Write selected volume fields.
+ template
+ label writeVolFieldsImpl
+ (
+ ensightOutput::floatBufferType& scratch,
+ const fvMeshSubset& proxy,
+ const wordHashSet& acceptField
+ );
+
//- Write all volume fields
label writeAllVolFields
(
@@ -230,15 +241,6 @@ class ensightWrite
const wordHashSet& acceptField
);
- //- Write selected volume fields.
- template
- label writeVolFields
- (
- const fvMeshSubset& proxy,
- const wordHashSet& acceptField
- );
-
-
//- No copy construct
ensightWrite(const ensightWrite&) = delete;
@@ -296,12 +298,6 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-#ifdef NoRepository
- #include "ensightWriteTemplates.C"
-#endif
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
#endif
// ************************************************************************* //
diff --git a/src/functionObjects/utilities/ensightWrite/ensightWriteTemplates.C b/src/functionObjects/utilities/ensightWrite/ensightWriteImpl.C
similarity index 92%
rename from src/functionObjects/utilities/ensightWrite/ensightWriteTemplates.C
rename to src/functionObjects/utilities/ensightWrite/ensightWriteImpl.C
index 8156cd0acb..3fb5204b2e 100644
--- a/src/functionObjects/utilities/ensightWrite/ensightWriteTemplates.C
+++ b/src/functionObjects/utilities/ensightWrite/ensightWriteImpl.C
@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2016-2020 OpenCFD Ltd.
+ Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -30,8 +30,9 @@ License
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template
-Foam::label Foam::functionObjects::ensightWrite::writeVolFields
+Foam::label Foam::functionObjects::ensightWrite::writeVolFieldsImpl
(
+ ensightOutput::floatBufferType& scratch,
const fvMeshSubset& proxy,
const wordHashSet& acceptField
)
@@ -58,6 +59,7 @@ Foam::label Foam::functionObjects::ensightWrite::writeVolFields
ensightOutput::writeVolField
(
+ scratch,
os.ref(),
field,
ensMesh(),
diff --git a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C
index 0a2d6f7687..9d46d9bda2 100644
--- a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C
+++ b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C
@@ -35,40 +35,41 @@ License
namespace Foam
{
- //- Binary output
- static inline void writeMeasured_binary
- (
- ensightFile& os,
- const UList& points
- )
+
+//- Binary output
+static inline void writeMeasured_binary
+(
+ ensightFile& os,
+ const UList& points
+)
+{
+ for (const floatVector& p : points)
{
- for (const point& p : points)
- {
- os.write(p.x());
- os.write(p.y());
- os.write(p.z());
- }
+ os.write(p.x());
+ os.write(p.y());
+ os.write(p.z());
+ }
+}
+
+//- ASCII output. Id + position together
+static inline label writeMeasured_ascii
+(
+ ensightFile& os,
+ label pointId,
+ const UList& points
+)
+{
+ for (const floatVector& p : points)
+ {
+ os.write(++pointId, 8); // 1-index and an unusual width
+ os.write(p.x());
+ os.write(p.y());
+ os.write(p.z());
+ os.newline();
}
- //- ASCII output. Id + position together
- static inline label writeMeasured_ascii
- (
- ensightFile& os,
- label pointId,
- const UList& points
- )
- {
- for (const point& p : points)
- {
- os.write(++pointId, 8); // 1-index and an unusual width
- os.write(p.x());
- os.write(p.y());
- os.write(p.z());
- os.newline();
- }
-
- return pointId;
- }
+ return pointId;
+}
} // End namespace Foam
@@ -77,10 +78,10 @@ namespace Foam
bool Foam::ensightOutput::writeCloudPositions
(
+ ensightFile& os,
const fvMesh& mesh,
const word& cloudName,
- bool exists,
- autoPtr& output
+ bool exists
)
{
label nLocalParcels(0);
@@ -97,7 +98,6 @@ bool Foam::ensightOutput::writeCloudPositions
if (Pstream::master())
{
- ensightFile& os = output();
os.beginParticleCoordinates(nTotParcels);
}
@@ -111,10 +111,12 @@ bool Foam::ensightOutput::writeCloudPositions
const globalIndex procAddr(nLocalParcels, globalIndex::gatherOnly{});
- DynamicList positions;
+ DynamicList positions;
positions.reserve(Pstream::master() ? procAddr.maxSize() : nLocalParcels);
- // Extract positions
+ // Extract positions from parcel.
+ // Store as floatVector, since that is what Ensight will write anyhow
+
if (parcelsPtr)
{
const auto& parcels = *parcelsPtr;
@@ -123,10 +125,26 @@ bool Foam::ensightOutput::writeCloudPositions
auto outIter = positions.begin();
- for (const passiveParticle& p : parcels)
+ if (std::is_same::value)
{
- *outIter = p.position();
- ++outIter;
+ for (const passiveParticle& p : parcels)
+ {
+ *outIter = p.position();
+ ++outIter;
+ }
+ }
+ else
+ {
+ for (const passiveParticle& p : parcels)
+ {
+ vector pos(p.position());
+
+ (*outIter).x() = narrowFloat(pos.x());
+ (*outIter).y() = narrowFloat(pos.y());
+ (*outIter).z() = narrowFloat(pos.z());
+
+ ++outIter;
+ }
}
parcelsPtr.reset(nullptr);
@@ -134,7 +152,6 @@ bool Foam::ensightOutput::writeCloudPositions
if (Pstream::master())
{
- ensightFile& os = output();
const bool isBinaryOutput = (os.format() == IOstreamOption::BINARY);
label parcelId = 0;
@@ -164,35 +181,42 @@ bool Foam::ensightOutput::writeCloudPositions
// Receive and write
for (const label proci : procAddr.subProcs())
{
- positions.resize_nocopy(procAddr.localSize(proci));
- UIPstream::read
- (
- UPstream::commsTypes::scheduled,
- proci,
- positions.data_bytes(),
- positions.size_bytes()
- );
+ const label procSize = procAddr.localSize(proci);
- if (isBinaryOutput)
+ if (procSize)
{
- writeMeasured_binary(os, positions);
- }
- else
- {
- parcelId = writeMeasured_ascii(os, parcelId, positions);
+ positions.resize_nocopy(procSize);
+ UIPstream::read
+ (
+ UPstream::commsTypes::scheduled,
+ proci,
+ positions.data_bytes(),
+ positions.size_bytes()
+ );
+
+ if (isBinaryOutput)
+ {
+ writeMeasured_binary(os, positions);
+ }
+ else
+ {
+ parcelId = writeMeasured_ascii(os, parcelId, positions);
+ }
}
}
}
else
{
- // Send
- UOPstream::write
- (
- UPstream::commsTypes::scheduled,
- UPstream::masterNo(),
- positions.cdata_bytes(),
- positions.size_bytes()
- );
+ if (positions.size())
+ {
+ UOPstream::write
+ (
+ UPstream::commsTypes::scheduled,
+ UPstream::masterNo(),
+ positions.cdata_bytes(),
+ positions.size_bytes()
+ );
+ }
}
return true;
diff --git a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H
index 894a6aa21c..e83fbecec0 100644
--- a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H
+++ b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H
@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2016-2021 OpenCFD Ltd.
+ Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -35,11 +35,10 @@ SourceFiles
\*---------------------------------------------------------------------------*/
-#ifndef ensightOutputCloud_H
-#define ensightOutputCloud_H
+#ifndef Foam_ensightOutputCloud_H
+#define Foam_ensightOutputCloud_H
#include "ensightFile.H"
-#include "autoPtr.H"
#include "IOField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -59,10 +58,17 @@ namespace ensightOutput
//- Write cloud positions
bool writeCloudPositions
(
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The associated volume mesh
const fvMesh& mesh,
+
+ //! The name of the cloud
const word& cloudName,
- bool exists,
- autoPtr& output
+
+ //! The processor-local existence
+ bool exists
);
@@ -70,19 +76,27 @@ bool writeCloudPositions
template
bool writeCloudField
(
- const IOField& field,
- ensightFile& os
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The cloud field
+ const IOField& field
);
//- Read cloud field from IOobject (if exists == true) and write,
//- always returning true.
template
-bool writeCloudField
+bool readWriteCloudField
(
- const IOobject& io,
- bool exists,
- autoPtr& output
+ //! Output file (must be valid on master)
+ ensightFile& os,
+
+ //! The field object name/location for reading
+ const IOobject& fieldObject,
+
+ //! Exists anywhere? May still be missing on a local processor
+ bool existsAny
);
@@ -98,9 +112,13 @@ namespace Detail
template
label writeCloudFieldContent
(
+ //! Output file (must be valid on master)
ensightFile& os,
+
const UList& fld,
- label count = 0 //!< The current output count
+
+ //! The current output count
+ label count = 0
);
diff --git a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C
index 76e671640b..cc865cc7d3 100644
--- a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C
+++ b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C
@@ -69,8 +69,8 @@ Foam::label Foam::ensightOutput::Detail::writeCloudFieldContent
template
bool Foam::ensightOutput::writeCloudField
(
- const IOField& field,
- ensightFile& os
+ ensightFile& os,
+ const IOField& field
)
{
if (returnReduceAnd(field.empty()))
@@ -79,7 +79,7 @@ bool Foam::ensightOutput::writeCloudField
}
// Gather sizes (offsets irrelevant)
- const globalIndex procAddr(field.size(), globalIndex::gatherOnly{});
+ const globalIndex procAddr(globalIndex::gatherOnly{}, field.size());
if (Pstream::master())
{
@@ -99,21 +99,27 @@ bool Foam::ensightOutput::writeCloudField
for (const label proci : procAddr.subProcs())
{
- recvData.resize_nocopy(procAddr.localSize(proci));
- UIPstream::read
- (
- UPstream::commsTypes::scheduled,
- proci,
- recvData.data_bytes(),
- recvData.size_bytes()
- );
+ const label procSize = procAddr.localSize(proci);
- count = ensightOutput::Detail::writeCloudFieldContent
- (
- os,
- recvData,
- count
- );
+ if (procSize)
+ {
+ recvData.resize_nocopy(procSize);
+
+ UIPstream::read
+ (
+ UPstream::commsTypes::scheduled,
+ proci,
+ recvData.data_bytes(),
+ recvData.size_bytes()
+ );
+
+ count = ensightOutput::Detail::writeCloudFieldContent
+ (
+ os,
+ recvData,
+ count
+ );
+ }
}
// Add final newline if required
@@ -124,14 +130,16 @@ bool Foam::ensightOutput::writeCloudField
}
else
{
- // Send
- UOPstream::write
- (
- UPstream::commsTypes::scheduled,
- UPstream::masterNo(),
- field.cdata_bytes(),
- field.size_bytes()
- );
+ if (field.size())
+ {
+ UOPstream::write
+ (
+ UPstream::commsTypes::scheduled,
+ UPstream::masterNo(),
+ field.cdata_bytes(),
+ field.size_bytes()
+ );
+ }
}
return true;
@@ -139,25 +147,25 @@ bool Foam::ensightOutput::writeCloudField
template
-bool Foam::ensightOutput::writeCloudField
+bool Foam::ensightOutput::readWriteCloudField
(
- const IOobject& io,
- const bool exists,
- autoPtr& output
+ ensightFile& os,
+ const IOobject& fieldObject,
+ const bool existsAny
)
{
- if (exists)
+ if (existsAny)
{
- // When exists == true, it exists globally,
+ // When exists == true, it exists somewhere globally,
// but can still be missing on the local processor.
// Handle this by READ_IF_PRESENT instead.
- IOobject fieldObj(io);
- fieldObj.readOpt(IOobject::READ_IF_PRESENT);
+ IOobject io(fieldObject);
+ io.readOpt(IOobject::READ_IF_PRESENT);
- IOField field(fieldObj);
+ IOField field(io);
- writeCloudField(field, output.ref());
+ writeCloudField(os, field);
}
return true;
diff --git a/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.C b/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.C
index 3a2dcf0bec..91b20276d3 100644
--- a/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.C
+++ b/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.C
@@ -67,14 +67,22 @@ static void writeTrackField
forAll(fieldPtrs, tracki)
{
- // Write as point data
+ const Field& fld = fieldPtrs[tracki];
os.beginPart(tracki); // Part index (0-based)
+
+ // Skip if empty. This check is probably redundant
+ if (fld.empty())
+ {
+ continue;
+ }
+
+ // Write as coordinates data
ensightOutput::Detail::writeFieldComponents
(
os,
ensightFile::coordinates,
- fieldPtrs[tracki],
+ fld,
false /* serial only! */
);
}