From 0454f4a04021ac69c8ceabeb33d97a1a95acf075 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Fri, 17 Sep 2021 18:46:30 +0200 Subject: [PATCH] ENH: robustness and functionality improvements for VTK output - PstreamBuffers for parallel VTK output. - avoids MPI overflows for larger meshes - new vtk::lineWriter for writing edges - vtk::fileWriter::writeUniform now also supports processor-specific uniform values instead of assuming that they are identical everywhere. --- .../vtk/output/foamVtkPatchWriterTemplates.C | 2 +- src/fileFormats/Make/files | 1 + src/fileFormats/vtk/base/foamVtkCore.C | 24 +- src/fileFormats/vtk/base/foamVtkCore.H | 10 +- src/fileFormats/vtk/file/foamVtkFileWriter.C | 67 ++- src/fileFormats/vtk/file/foamVtkFileWriter.H | 62 +-- src/fileFormats/vtk/file/foamVtkFileWriterI.H | 6 +- .../vtk/file/foamVtkFileWriterTemplates.C | 19 +- src/fileFormats/vtk/output/foamVtkOutput.C | 83 ++-- src/fileFormats/vtk/output/foamVtkOutput.H | 26 +- src/fileFormats/vtk/output/foamVtkOutputI.H | 28 +- .../vtk/output/foamVtkOutputTemplates.C | 352 ++++++++++++---- src/fileFormats/vtk/write/foamVtkLineWriter.C | 138 ++++++ src/fileFormats/vtk/write/foamVtkLineWriter.H | 180 ++++++++ src/fileFormats/vtk/write/foamVtkPolyWriter.C | 392 +++++++++++++++--- src/fileFormats/vtk/write/foamVtkPolyWriter.H | 52 ++- .../vtk/write/foamVtkPolyWriterTemplates.C | 28 +- .../vtk/write/foamVtkSurfaceWriter.C | 8 +- .../vtk/write/foamVtkSurfaceWriter.H | 15 +- .../edgeMeshFormats/vtk/VTKedgeFormat.C | 85 ++-- .../edgeMeshFormats/vtk/VTKedgeFormat.H | 35 +- .../vtk/mesh/foamVtkInternalMeshWriter.C | 58 +-- .../vtk/mesh/foamVtkInternalMeshWriter.H | 4 + .../mesh/foamVtkInternalMeshWriterTemplates.C | 46 +- .../output/vtk/patch/foamVtkPatchMeshWriter.C | 104 +---- .../output/vtk/patch/foamVtkPatchMeshWriter.H | 10 +- .../patch/foamVtkPatchMeshWriterTemplates.C | 22 +- 27 files changed, 1347 insertions(+), 510 deletions(-) create mode 100644 src/fileFormats/vtk/write/foamVtkLineWriter.C create mode 100644 src/fileFormats/vtk/write/foamVtkLineWriter.H diff --git a/src/conversion/vtk/output/foamVtkPatchWriterTemplates.C b/src/conversion/vtk/output/foamVtkPatchWriterTemplates.C index 9dc41948e46..0219a3b835c 100644 --- a/src/conversion/vtk/output/foamVtkPatchWriterTemplates.C +++ b/src/conversion/vtk/output/foamVtkPatchWriterTemplates.C @@ -149,7 +149,7 @@ void Foam::vtk::patchWriter::write << exit(FatalError); } - label nFaces = nLocalFaces_; + label nFaces = nLocalPolys_; if (parallel_) { diff --git a/src/fileFormats/Make/files b/src/fileFormats/Make/files index 2686cefc430..f7fd57b8538 100644 --- a/src/fileFormats/Make/files +++ b/src/fileFormats/Make/files @@ -59,6 +59,7 @@ vtk/part/foamVtuCells.C vtk/part/foamVtuSizing.C vtk/read/vtkUnstructuredReader.C +vtk/write/foamVtkLineWriter.C vtk/write/foamVtkPolyWriter.C vtk/write/foamVtkSurfaceWriter.C diff --git a/src/fileFormats/vtk/base/foamVtkCore.C b/src/fileFormats/vtk/base/foamVtkCore.C index 14f832fec6e..b9488e8824a 100644 --- a/src/fileFormats/vtk/base/foamVtkCore.C +++ b/src/fileFormats/vtk/base/foamVtkCore.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2017-2018 OpenCFD Ltd. + Copyright (C) 2017-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -113,6 +113,8 @@ Foam::vtk::dataArrayAttrNames }); +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + // Legacy const Foam::word Foam::vtk::legacy::fileExtension("vtk"); @@ -132,11 +134,27 @@ const Foam::Enum < Foam::vtk::fileTag > -Foam::vtk::legacy::dataTypeNames +Foam::vtk::legacy::fileTagNames ({ - { vtk::fileTag::CELL_DATA, "CELL_DATA" }, + { vtk::fileTag::POINTS, "POINTS" }, + { vtk::fileTag::CELLS, "CELLS" }, + { vtk::fileTag::POLYS, "POLYGONS" }, + { vtk::fileTag::VERTS, "VERTICES" }, + { vtk::fileTag::LINES, "LINES" }, + { vtk::fileTag::CELL_DATA, "CELL_DATA" }, { vtk::fileTag::POINT_DATA, "POINT_DATA" }, }); +const Foam::Enum +< + Foam::vtk::dataArrayAttr +> +Foam::vtk::legacy::dataArrayAttrNames +({ + { vtk::dataArrayAttr::OFFSETS, "OFFSETS" }, + { vtk::dataArrayAttr::CONNECTIVITY, "CONNECTIVITY" }, +}); + + // ************************************************************************* // diff --git a/src/fileFormats/vtk/base/foamVtkCore.H b/src/fileFormats/vtk/base/foamVtkCore.H index 2524964a0af..08615850ecb 100644 --- a/src/fileFormats/vtk/base/foamVtkCore.H +++ b/src/fileFormats/vtk/base/foamVtkCore.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2018 OpenCFD Ltd. + Copyright (C) 2016-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -183,8 +183,12 @@ namespace legacy //- Legacy content names (POLYDATA, UNSTRUCTURED_GRID) extern const Foam::Enum<vtk::fileTag> contentNames; - //- Legacy data type names (CELL_DATA, POINT_DATA) - extern const Foam::Enum<vtk::fileTag> dataTypeNames; + //- Legacy file tags (eg, LINES, CELL_DATA, POINT_DATA, ...) + extern const Foam::Enum<vtk::fileTag> fileTagNames; + + //- Legacy attributes (eg, OFFSETS) + extern const Foam::Enum<dataArrayAttr> dataArrayAttrNames; + } // End namespace legacy diff --git a/src/fileFormats/vtk/file/foamVtkFileWriter.C b/src/fileFormats/vtk/file/foamVtkFileWriter.C index aff45b90177..3cc8b7e72a5 100644 --- a/src/fileFormats/vtk/file/foamVtkFileWriter.C +++ b/src/fileFormats/vtk/file/foamVtkFileWriter.C @@ -26,6 +26,7 @@ License \*---------------------------------------------------------------------------*/ #include "foamVtkFileWriter.H" +#include "globalIndex.H" #include "OSspecific.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -342,7 +343,7 @@ bool Foam::vtk::fileWriter::open(const fileName& file, bool parallel) // Open a file and attach a formatter // - on master (always) - // - on slave if not parallel + // - on subproc (if not parallel) // // This means we can always check if format_ is defined to know if output // is desired on any particular process. @@ -515,7 +516,7 @@ void Foam::vtk::fileWriter::writeTimeValue(scalar timeValue) << exit(FatalError); } - // No collectives - can skip on slave processors + // No collectives - can skip on sub-procs if (!format_) return; if (legacy()) @@ -529,4 +530,66 @@ void Foam::vtk::fileWriter::writeTimeValue(scalar timeValue) } +bool Foam::vtk::fileWriter::writeProcIDs(const label nValues) +{ + // Write procIDs whenever running in parallel + + if (!Pstream::parRun()) + { + return false; // Non-parallel: skip + } + + if (isState(outputState::CELL_DATA)) + { + ++nCellData_; + } + else + { + reportBadState(FatalErrorInFunction, outputState::CELL_DATA) + << " for procID field" << nl << endl + << exit(FatalError); + + return false; + } + + + const globalIndex procSizes + ( + parallel_ + ? globalIndex(nValues) + : globalIndex() + ); + + const label totalCount = (parallel_ ? procSizes.size() : nValues); + + this->beginDataArray<label>("procID", totalCount); + + bool good = false; + + if (parallel_) + { + if (Pstream::master()) + { + // Per-processor ids + for (const int proci : Pstream::allProcs()) + { + vtk::write(format(), label(proci), procSizes.localSize(proci)); + } + good = true; + } + } + else + { + vtk::write(format(), label(Pstream::myProcNo()), totalCount); + good = true; + } + + + this->endDataArray(); + + // MPI barrier + return parallel_ ? returnReduce(good, orOp<bool>()) : good; +} + + // ************************************************************************* // diff --git a/src/fileFormats/vtk/file/foamVtkFileWriter.H b/src/fileFormats/vtk/file/foamVtkFileWriter.H index 19a1d4e1500..ea25b303232 100644 --- a/src/fileFormats/vtk/file/foamVtkFileWriter.H +++ b/src/fileFormats/vtk/file/foamVtkFileWriter.H @@ -107,10 +107,10 @@ protected: //- The output file name fileName outputFile_; - //- The VTK formatter in use (master process) + //- The VTK formatter in use (only valid on master process) autoPtr<vtk::formatter> format_; - //- The backend ostream in use (master process) + //- The backend ostream in use (only opened on master process) std::ofstream os_; @@ -123,16 +123,16 @@ protected: Ostream& reportBadState(Ostream&, outputState, outputState) const; //- The backend ostream in use - inline std::ofstream& os(); + inline std::ofstream& os() noexcept; //- The VTK formatter in use inline vtk::formatter& format(); - //- True if the output state corresponds to the test state. - inline bool isState(outputState test) const; + //- True if output state corresponds to the test state. + inline bool isState(outputState test) const noexcept; - //- True if the output state does not correspond to the test state. - inline bool notState(outputState test) const; + //- True if output state does not correspond to the test state. + inline bool notState(outputState test) const noexcept; //- Start of a field or DataArray output (legacy or non-legacy). template<class Type> @@ -151,26 +151,6 @@ protected: //- End of a POINTS DataArray void endPoints(); - - //- Write uniform field content. - // No context checking (eg, file-open, CellData, PointData, etc) - template<class Type> - void writeUniform - ( - const word& fieldName, - const Type& val, - const label nValues - ); - - //- Write basic (primitive) field content - // No context checking (eg, file-open, CellData, PointData, etc) - template<class Type> - void writeBasicField - ( - const word& fieldName, - const UList<Type>& field - ); - //- Trigger change state to Piece. Resets nCellData_, nPointData_. bool enter_Piece(); @@ -194,6 +174,34 @@ protected: bool exit_File(); + // Field writing + + //- Write uniform field content. + // No context checking (eg, file-open, CellData, PointData, etc) + // The value and count can be different on each processor + template<class Type> + void writeUniform + ( + const word& fieldName, + const Type& val, + const label nValues + ); + + //- Write basic (primitive) field content + // No context checking (eg, file-open, CellData, PointData, etc) + template<class Type> + void writeBasicField + ( + const word& fieldName, + const UList<Type>& field + ); + + //- Write nValues of processor ids as CellData (no-op in serial) + bool writeProcIDs(const label nValues); + + + // Other + //- No copy construct fileWriter(const fileWriter&) = delete; diff --git a/src/fileFormats/vtk/file/foamVtkFileWriterI.H b/src/fileFormats/vtk/file/foamVtkFileWriterI.H index 62c7d86600e..192eac45a75 100644 --- a/src/fileFormats/vtk/file/foamVtkFileWriterI.H +++ b/src/fileFormats/vtk/file/foamVtkFileWriterI.H @@ -27,7 +27,7 @@ License // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // -inline std::ofstream& Foam::vtk::fileWriter::os() +inline std::ofstream& Foam::vtk::fileWriter::os() noexcept { return os_; } @@ -39,13 +39,13 @@ inline Foam::vtk::formatter& Foam::vtk::fileWriter::format() } -inline bool Foam::vtk::fileWriter::isState(outputState test) const +inline bool Foam::vtk::fileWriter::isState(outputState test) const noexcept { return (test == state_); } -inline bool Foam::vtk::fileWriter::notState(outputState test) const +inline bool Foam::vtk::fileWriter::notState(outputState test) const noexcept { return (test != state_); } diff --git a/src/fileFormats/vtk/file/foamVtkFileWriterTemplates.C b/src/fileFormats/vtk/file/foamVtkFileWriterTemplates.C index 79a774fce91..21ec488823f 100644 --- a/src/fileFormats/vtk/file/foamVtkFileWriterTemplates.C +++ b/src/fileFormats/vtk/file/foamVtkFileWriterTemplates.C @@ -89,14 +89,25 @@ void Foam::vtk::fileWriter::writeUniform ( const word& fieldName, const Type& val, - const label nValues + const label nLocalValues ) { - this->beginDataArray<Type>(fieldName, nValues); + label nTotal = nLocalValues; - if (format_) + if (parallel_) + { + reduce(nTotal, sumOp<label>()); + } + + this->beginDataArray<Type>(fieldName, nTotal); + + if (parallel_) + { + vtk::writeValueParallel(format_.ref(), val, nLocalValues); + } + else { - vtk::write(format(), val, nValues); + vtk::write(format(), val, nLocalValues); } this->endDataArray(); diff --git a/src/fileFormats/vtk/output/foamVtkOutput.C b/src/fileFormats/vtk/output/foamVtkOutput.C index 7e32b87dcf0..08a00cf6e40 100644 --- a/src/fileFormats/vtk/output/foamVtkOutput.C +++ b/src/fileFormats/vtk/output/foamVtkOutput.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2020 OpenCFD Ltd. + Copyright (C) 2016-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -39,7 +39,7 @@ License #include "globalIndex.H" #include "instant.H" #include "Fstream.H" -#include "Pstream.H" +#include "PstreamBuffers.H" #include "OSspecific.H" // * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * // @@ -99,7 +99,7 @@ void Foam::vtk::writeIdentity label start ) { - // No nComponents for label, so use fmt.write() directly + // No nComponents for label, can use fmt.write() directly for (label i=0; i < len; ++i) { fmt.write(start); @@ -114,7 +114,7 @@ void Foam::vtk::writeList const UList<uint8_t>& values ) { - // No nComponents for char, so use fmt.write() directly + // No nComponents for char, can use fmt.write() directly for (const uint8_t val : values) { fmt.write(val); @@ -125,85 +125,59 @@ void Foam::vtk::writeList void Foam::vtk::writeListParallel ( vtk::formatter& fmt, - const UList<uint8_t>& values + const labelUList& values, + const globalIndex& procOffset ) { - if (Pstream::master()) - { - vtk::writeList(fmt, values); - - List<uint8_t> recv; - - // Receive and write - for (const int slave : Pstream::subProcs()) - { - IPstream fromSlave(Pstream::commsTypes::blocking, slave); + // List sizes + const globalIndex sizes(values.size()); - fromSlave >> recv; + PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking); - vtk::writeList(fmt, recv); - } - } - else + // Send to master + if (!Pstream::master()) { - // Send to master - OPstream toMaster + UOPstream os(Pstream::masterNo(), pBufs); + os.write ( - Pstream::commsTypes::blocking, - Pstream::masterNo() + reinterpret_cast<const char*>(values.cdata()), + values.size_bytes() ); - - toMaster << values; } -} + pBufs.finishedSends(); -void Foam::vtk::writeListParallel -( - vtk::formatter& fmt, - const labelUList& values, - const globalIndex& procOffset -) -{ if (Pstream::master()) { + // Master data + // Write with offset const label offsetId = procOffset.offset(0); - for (const label val : values) { vtk::write(fmt, val + offsetId); } - labelList recv; - // Receive and write - for (const int slave : Pstream::subProcs()) + for (const int proci : Pstream::subProcs()) { - IPstream fromSlave(Pstream::commsTypes::blocking, slave); + List<label> recv(sizes.localSize(proci)); - fromSlave >> recv; - - const label offsetId = procOffset.offset(slave); + UIPstream is(proci, pBufs); + is.read + ( + reinterpret_cast<char*>(recv.data()), + recv.size_bytes() + ); // Write with offset + const label offsetId = procOffset.offset(proci); for (const label val : recv) { vtk::write(fmt, val + offsetId); } } } - else - { - // Send to master - OPstream toMaster - ( - Pstream::commsTypes::blocking, - Pstream::masterNo() - ); - - toMaster << values; - } } @@ -219,6 +193,9 @@ void Foam::vtk::legacy::fileHeader // Line 1: os << "# vtk DataFile Version 2.0" << nl; + // OR + // os << "# vtk DataFile Version 5.1" << nl; + // Line 2: title const auto truncate = title.find('\n'); diff --git a/src/fileFormats/vtk/output/foamVtkOutput.H b/src/fileFormats/vtk/output/foamVtkOutput.H index ac8c3b68520..ad7d6bf7747 100644 --- a/src/fileFormats/vtk/output/foamVtkOutput.H +++ b/src/fileFormats/vtk/output/foamVtkOutput.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2019 OpenCFD Ltd. + Copyright (C) 2016-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -59,7 +59,7 @@ SourceFiles namespace Foam { -// Forward declarations +// Forward Declarations class instant; class globalIndex; @@ -94,14 +94,20 @@ namespace vtk // The output does not include the payload size. void writeList(vtk::formatter& fmt, const UList<uint8_t>& values); - //- Write a list of uint8_t values. - // The output does not include the payload size. - void writeListParallel(vtk::formatter& fmt, const UList<uint8_t>& values); - //- Component-wise write of a value (N times) template<class Type> inline void write(vtk::formatter& fmt, const Type& val, const label n=1); + //- Component-wise write of a value (N times) in parallel + // The value and count may differ on each processor + template<class Type> + inline void writeValueParallel + ( + vtk::formatter& fmt, + const Type& val, + const label count=1 + ); + //- Write a list of values. // The output does not include the payload size. @@ -215,7 +221,7 @@ namespace legacy // Functions - //- Emit header for legacy file. + //- Emit header for legacy file (vtk DataFile Version 2.0) // Writes "ASCII" or "BINARY" depending on specified type. void fileHeader(std::ostream& os, const std::string& title, bool binary); @@ -248,6 +254,12 @@ namespace legacy //- Emit header for POINTS (with trailing newline). inline void beginPoints(std::ostream& os, label nPoints); + //- Emit header for LINES (with trailing newline). + // The nConnectivity is the sum of all connectivity points used, + // but \b without additional space for the size prefixes. + // The additional prefix sizes are added internally. + inline void beginLines(std::ostream& os, label nLines, label nConnectivity); + //- Emit header for POLYGONS (with trailing newline). // The nConnectivity is the sum of all connectivity points used, // but \b without additional space for the size prefixes. diff --git a/src/fileFormats/vtk/output/foamVtkOutputI.H b/src/fileFormats/vtk/output/foamVtkOutputI.H index 036432e3c09..9789eecc41f 100644 --- a/src/fileFormats/vtk/output/foamVtkOutputI.H +++ b/src/fileFormats/vtk/output/foamVtkOutputI.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2017-2019 OpenCFD Ltd. + Copyright (C) 2017-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -113,7 +113,23 @@ inline void Foam::vtk::legacy::fileHeader inline void Foam::vtk::legacy::beginPoints(std::ostream& os, label nPoints) { os << nl - << "POINTS " << nPoints << " float" << nl; + << legacy::fileTagNames[vtk::fileTag::POINTS] + << ' ' << nPoints + << " float" << nl; +} + + +inline void Foam::vtk::legacy::beginLines +( + std::ostream& os, + label nLines, + label nConnectivity +) +{ + os << nl + << legacy::fileTagNames[vtk::fileTag::LINES] + << ' ' << nLines + << ' ' << (nLines + nConnectivity) << nl; } @@ -125,7 +141,9 @@ inline void Foam::vtk::legacy::beginPolys ) { os << nl - << "POLYGONS " << nPolys << ' ' << (nPolys + nConnectivity) << nl; + << legacy::fileTagNames[vtk::fileTag::POLYS] + << ' ' << nPolys + << ' ' << (nPolys + nConnectivity) << nl; } @@ -159,7 +177,7 @@ inline void Foam::vtk::legacy::beginCellData { fmt.os() << nl - << legacy::dataTypeNames[vtk::fileTag::CELL_DATA] + << legacy::fileTagNames[vtk::fileTag::CELL_DATA] << ' ' << nCells << nl; legacy::fieldData(fmt, nFields); } @@ -174,7 +192,7 @@ inline void Foam::vtk::legacy::beginPointData { fmt.os() << nl - << legacy::dataTypeNames[vtk::fileTag::POINT_DATA] + << legacy::fileTagNames[vtk::fileTag::POINT_DATA] << ' ' << nPoints << nl; legacy::fieldData(fmt, nFields); } diff --git a/src/fileFormats/vtk/output/foamVtkOutputTemplates.C b/src/fileFormats/vtk/output/foamVtkOutputTemplates.C index e296a2b2b56..59bdb0e88fe 100644 --- a/src/fileFormats/vtk/output/foamVtkOutputTemplates.C +++ b/src/fileFormats/vtk/output/foamVtkOutputTemplates.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2020 OpenCFD Ltd. + Copyright (C) 2016-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -25,7 +25,8 @@ License \*---------------------------------------------------------------------------*/ -#include "Pstream.H" +#include "globalIndex.H" +#include "PstreamBuffers.H" #include "ListOps.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -123,38 +124,39 @@ void Foam::vtk::writeLists template<class Type> -void Foam::vtk::writeListParallel +void Foam::vtk::writeValueParallel ( vtk::formatter& fmt, - const UList<Type>& values + const Type& val, + const label count ) { if (Pstream::master()) { - vtk::writeList(fmt, values); + vtk::write(fmt, val, count); - List<Type> recv; + label subCount; + Type subValue; - // Receive and write - for (const int slave : Pstream::subProcs()) + // Receive each [size, value] tuple + for (const int proci : Pstream::subProcs()) { - IPstream fromSlave(Pstream::commsTypes::blocking, slave); - - fromSlave >> recv; + IPstream is(Pstream::commsTypes::blocking, proci); + is >> subCount >> subValue; - vtk::writeList(fmt, recv); + vtk::write(fmt, subValue, subCount); } } else { - // Send to master - OPstream toMaster + OPstream os ( Pstream::commsTypes::blocking, Pstream::masterNo() ); - toMaster << values; + // Send [size, value] tuple + os << count << val; } } @@ -163,36 +165,106 @@ template<class Type> void Foam::vtk::writeListParallel ( vtk::formatter& fmt, - const UList<Type>& values, - const labelUList& addressing + const UList<Type>& values ) { - if (Pstream::master()) + // List sizes + const globalIndex sizes(values.size()); + + PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking); + + // Send to master + if (!Pstream::master()) { - vtk::writeList(fmt, values, addressing); + UOPstream os(Pstream::masterNo(), pBufs); + if (is_contiguous<Type>::value) + { + os.write + ( + reinterpret_cast<const char*>(values.cdata()), + values.size_bytes() + ); + } + else + { + os << values; + } + } - List<Type> recv; + pBufs.finishedSends(); + + if (Pstream::master()) + { + // Write master data + vtk::writeList(fmt, values); // Receive and write - for (const int slave : Pstream::subProcs()) + for (const int proci : Pstream::subProcs()) { - IPstream fromSlave(Pstream::commsTypes::blocking, slave); + UIPstream is(proci, pBufs); + + { + List<Type> recv(sizes.localSize(proci)); + + if (is_contiguous<Type>::value) + { + is.read + ( + reinterpret_cast<char*>(recv.data()), + recv.size_bytes() + ); + } + else + { + is >> recv; + } + vtk::writeList(fmt, recv); + } + } + } +} - fromSlave >> recv; - vtk::writeList(fmt, recv); - } +template<class Type> +void Foam::vtk::writeListParallel +( + vtk::formatter& fmt, + const UList<Type>& values, + const labelUList& addressing +) +{ + UIndirectList<Type> send(values, addressing); + + // List sizes + const globalIndex sizes(send.size()); + + PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking); + + // Send to master + if (!Pstream::master()) + { + UOPstream os(Pstream::masterNo(), pBufs); + os << send; } - else + + pBufs.finishedSends(); + + if (Pstream::master()) { - // Send to master - OPstream toMaster - ( - Pstream::commsTypes::blocking, - Pstream::masterNo() - ); + // Write master data + vtk::writeList(fmt, values, addressing); + + // Receive and write + for (const int proci : Pstream::subProcs()) + { + UIPstream is(proci, pBufs); - toMaster << List<Type>(values, addressing); + { + List<Type> recv; + is >> recv; + vtk::writeList(fmt, recv); + } + } } } @@ -205,32 +277,66 @@ void Foam::vtk::writeListParallel const bitSet& selected ) { - if (Pstream::master()) + List<Type> send; + if (!Pstream::master()) { - vtk::writeList(fmt, values, selected); - - List<Type> recv; + send = subset(selected, values); + } - // Receive and write - for (const int slave : Pstream::subProcs()) - { - IPstream fromSlave(Pstream::commsTypes::blocking, slave); + // List sizes. + // NOTE okay to skip proc0 since we only need sizes (not offsets) + const globalIndex sizes(send.size()); - fromSlave >> recv; + PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking); - vtk::writeList(fmt, recv); + // Send to master + if (!Pstream::master()) + { + UOPstream os(Pstream::masterNo(), pBufs); + if (is_contiguous<Type>::value) + { + os.write + ( + reinterpret_cast<const char*>(send.cdata()), + send.size_bytes() + ); + } + else + { + os << send; } } - else + + pBufs.finishedSends(); + + if (Pstream::master()) { - // Send to master - OPstream toMaster - ( - Pstream::commsTypes::blocking, - Pstream::masterNo() - ); + // Write master data + vtk::writeList(fmt, values, selected); - toMaster << subset(selected, values); + // Receive and write + for (const int proci : Pstream::subProcs()) + { + UIPstream is(proci, pBufs); + + { + List<Type> recv(sizes.localSize(proci)); + + if (is_contiguous<Type>::value) + { + is.read + ( + reinterpret_cast<char*>(recv.data()), + recv.size_bytes() + ); + } + else + { + is >> recv; + } + vtk::writeList(fmt, recv); + } + } } } @@ -243,34 +349,90 @@ void Foam::vtk::writeListsParallel const UList<Type>& values2 ) { - if (Pstream::master()) - { - vtk::writeList(fmt, values1); - vtk::writeList(fmt, values2); + // List sizes + const globalIndex sizes1(values1.size()); + const globalIndex sizes2(values2.size()); - List<Type> recv1, recv2; + PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking); - // Receive and write - for (const int slave : Pstream::subProcs()) + // Send to master + if (!Pstream::master()) + { + UOPstream os(Pstream::masterNo(), pBufs); + if (is_contiguous<Type>::value) { - IPstream fromSlave(Pstream::commsTypes::blocking, slave); - - fromSlave >> recv1 >> recv2; - - vtk::writeList(fmt, recv1); - vtk::writeList(fmt, recv2); + os.write + ( + reinterpret_cast<const char*>(values1.cdata()), + values1.size_bytes() + ); + os.write + ( + reinterpret_cast<const char*>(values2.cdata()), + values2.size_bytes() + ); + } + else + { + os << values1 << values2; } } - else + + pBufs.finishedSends(); + + if (Pstream::master()) { - // Send to master - OPstream toMaster + // Write master data + vtk::writeList(fmt, values1); + vtk::writeList(fmt, values2); + + // Reserve max receive size + DynamicList<Type> recv ( - Pstream::commsTypes::blocking, - Pstream::masterNo() + max(sizes1.maxNonLocalSize(), sizes2.maxNonLocalSize()) ); - toMaster << values1 << values2; + // Receive and write + for (const int proci : Pstream::subProcs()) + { + UIPstream is(proci, pBufs); + + // values1 + { + List<Type> recv(sizes1.localSize(proci)); + if (is_contiguous<Type>::value) + { + is.read + ( + reinterpret_cast<char*>(recv.data()), + recv.size_bytes() + ); + } + else + { + is >> recv; + } + vtk::writeList(fmt, recv); + } + + // values2 + { + List<Type> recv(sizes2.localSize(proci)); + if (is_contiguous<Type>::value) + { + is.read + ( + reinterpret_cast<char*>(recv.data()), + recv.size_bytes() + ); + } + else + { + is >> recv; + } + vtk::writeList(fmt, recv); + } + } } } @@ -284,35 +446,45 @@ void Foam::vtk::writeListsParallel const labelUList& addressing ) { + UIndirectList<Type> send2(values2, addressing); + + PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking); + + // Send to master + if (!Pstream::master()) + { + UOPstream os(Pstream::masterNo(), pBufs); + os << values1 << send2; + } + + pBufs.finishedSends(); + if (Pstream::master()) { + // Write master data vtk::writeList(fmt, values1); vtk::writeList(fmt, values2, addressing); - List<Type> recv1, recv2; - // Receive and write - for (const int slave : Pstream::subProcs()) + for (const int proci : Pstream::subProcs()) { - IPstream fromSlave(Pstream::commsTypes::blocking, slave); - - fromSlave >> recv1 >> recv2; - - vtk::writeList(fmt, recv1); - vtk::writeList(fmt, recv2); + UIPstream is(proci, pBufs); + + // values1 + { + List<Type> recv; + is >> recv; + vtk::writeList(fmt, recv); + } + + // values2 (send2) + { + List<Type> recv; + is >> recv; + vtk::writeList(fmt, recv); + } } } - else - { - // Send to master - OPstream toMaster - ( - Pstream::commsTypes::blocking, - Pstream::masterNo() - ); - - toMaster << values1 << List<Type>(values2, addressing); - } } diff --git a/src/fileFormats/vtk/write/foamVtkLineWriter.C b/src/fileFormats/vtk/write/foamVtkLineWriter.C new file mode 100644 index 00000000000..a5f42b5ad98 --- /dev/null +++ b/src/fileFormats/vtk/write/foamVtkLineWriter.C @@ -0,0 +1,138 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkLineWriter.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::vtk::lineWriter::lineWriter +( + const pointField& points, + const edgeList& edges, + const vtk::outputOptions opts +) +: + vtk::polyWriter(opts), + + points_(std::cref<pointField>(points)), + edges_(std::cref<edgeList>(edges)), + instant_() +{} + + +Foam::vtk::lineWriter::lineWriter +( + const pointField& points, + const edgeList& edges, + const fileName& file, + bool parallel +) +: + lineWriter(points, edges) +{ + open(file, parallel); +} + + +Foam::vtk::lineWriter::lineWriter +( + const pointField& points, + const edgeList& edges, + const vtk::outputOptions opts, + const fileName& file, + bool parallel +) +: + lineWriter(points, edges, opts) +{ + open(file, parallel); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::vtk::lineWriter::setTime(const instant& inst) +{ + instant_ = inst; +} + + +bool Foam::vtk::lineWriter::beginFile(std::string title) +{ + if (title.size()) + { + return vtk::fileWriter::beginFile(title); + } + + if (!instant_.name().empty()) + { + return vtk::fileWriter::beginFile + ( + "time='" + instant_.name() + "'" + ); + } + + // Provide default title + return vtk::fileWriter::beginFile("edges"); +} + + +bool Foam::vtk::lineWriter::writeGeometry() +{ + return writeLineGeometry(points_.get(), edges_.get()); +} + + +void Foam::vtk::lineWriter::writeTimeValue() +{ + if (!instant_.name().empty()) + { + vtk::fileWriter::writeTimeValue(instant_.value()); + } +} + + +void Foam::vtk::lineWriter::piece +( + const pointField& points, + const edgeList& edges +) +{ + endPiece(); + + points_ = std::cref<pointField>(points); + edges_ = std::cref<edgeList>(edges); +} + + +bool Foam::vtk::lineWriter::writeProcIDs() +{ + return vtk::fileWriter::writeProcIDs(nLocalLines_); +} + + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/write/foamVtkLineWriter.H b/src/fileFormats/vtk/write/foamVtkLineWriter.H new file mode 100644 index 00000000000..36245558f23 --- /dev/null +++ b/src/fileFormats/vtk/write/foamVtkLineWriter.H @@ -0,0 +1,180 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::vtk::lineWriter + +Description + Write edge/points (optionally with fields) + as a vtp file or a legacy vtk file. + + The file output states are managed by the Foam::vtk::fileWriter class. + FieldData (eg, TimeValue) must appear before any geometry pieces. + +Note + Parallel output is combined into a single Piece without point merging, + which is similar to using multi-piece data sets, but allows more + convenient creation as a streaming process. + In the future, the duplicate points at processor connections + may be addressed using ghost points. + +SourceFiles + foamVtkLineWriter.C + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_vtk_lineWriter_H +#define Foam_vtk_lineWriter_H + +#include "foamVtkPolyWriter.H" +#include "instant.H" +#include <functional> + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace vtk +{ + +/*---------------------------------------------------------------------------*\ + Class vtk::lineWriter Declaration +\*---------------------------------------------------------------------------*/ + +class lineWriter +: + public vtk::polyWriter +{ + // Private Member Data + + //- Reference to the points + std::reference_wrapper<const pointField> points_; + + //- Reference to the edges + std::reference_wrapper<const edgeList> edges_; + + //- Time name/value + instant instant_; + + + // Private Member Functions + + //- No copy construct + lineWriter(const lineWriter&) = delete; + + //- No copy assignment + void operator=(const lineWriter&) = delete; + + +public: + + // Constructors + + //- Construct from components (default format INLINE_BASE64) + lineWriter + ( + const pointField& pts, + const edgeList& edges, + const vtk::outputOptions opts = vtk::formatType::INLINE_BASE64 + ); + + //- Construct from components (default format INLINE_BASE64), + //- and open the file for writing. + // The file name is with/without an extension. + lineWriter + ( + const pointField& pts, + const edgeList& edges, + const fileName& file, + bool parallel = Pstream::parRun() + ); + + //- Construct from components and open the file for writing. + // The file name is with/without an extension. + lineWriter + ( + const pointField& pts, + const edgeList& edges, + const vtk::outputOptions opts, + const fileName& file, + bool parallel = Pstream::parRun() + ); + + + //- Destructor + virtual ~lineWriter() = default; + + + // Member Functions + + //- Define a time name/value for the output + virtual void setTime(const instant& inst); + + //- Write file header (non-collective) + // \note Expected calling states: (OPENED). + virtual bool beginFile(std::string title = ""); + + //- Write patch topology + // Also writes the file header if not previously written. + // \note Must be called prior to writing CellData or PointData + virtual bool writeGeometry(); + + //- Write "TimeValue" FieldData (name as per Catalyst output) + // Must be called within the FIELD_DATA state. + // \note As a convenience this can also be called from + // (OPENED | DECLARED) states, in which case it invokes + // beginFieldData(1) internally. + using vtk::fileWriter::writeTimeValue; + + //- Write the currently set time as "TimeValue" FieldData + void writeTimeValue(); + + //- Reset point/edge references to begin a new piece + void piece(const pointField& points, const edgeList& edges); + + + //- Write processor ids for each line as CellData + //- (no-op in serial) + bool writeProcIDs(); + + //- Write a uniform field of Cell (Line) or Point values + template<class Type> + void writeUniform(const word& fieldName, const Type& val) + { + polyWriter::writeUniformValue<Type>(nLocalLines_, fieldName, val); + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace vtk +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/write/foamVtkPolyWriter.C b/src/fileFormats/vtk/write/foamVtkPolyWriter.C index f11894a554d..28de456d9c5 100644 --- a/src/fileFormats/vtk/write/foamVtkPolyWriter.C +++ b/src/fileFormats/vtk/write/foamVtkPolyWriter.C @@ -29,26 +29,86 @@ License #include "foamVtkOutput.H" #include "globalIndex.H" +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// The connectivity count for a list of edges +static inline label countConnectivity(const edgeList& edges) +{ + return 2 * edges.size(); // An edge always has two ends +} + + +// The connectivity count for a list of faces +static label countConnectivity(const faceList& faces) +{ + label nConnectivity = 0; + + for (const face& f : faces) + { + nConnectivity += f.size(); + } + + return nConnectivity; +} + +} // End namespace Foam + + // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::vtk::polyWriter::beginPiece ( const pointField& points, - const faceList& faces + const edgeList& edges ) { // Basic sizes nLocalPoints_ = points.size(); - nLocalFaces_ = faces.size(); - nLocalVerts_ = 0; + nLocalLines_ = edges.size(); + nLocalPolys_ = 0; - for (const face& f : faces) + numberOfPoints_ = nLocalPoints_; + numberOfCells_ = nLocalLines_; + + if (parallel_) + { + reduce(numberOfPoints_, sumOp<label>()); + reduce(numberOfCells_, sumOp<label>()); + } + + + // Nothing else to do for legacy + if (legacy()) return; + + if (format_) { - nLocalVerts_ += f.size(); + format().tag + ( + vtk::fileTag::PIECE, + vtk::fileAttr::NUMBER_OF_POINTS, numberOfPoints_, + vtk::fileAttr::NUMBER_OF_LINES, numberOfCells_ + // AND: vtk::fileAttr::NUMBER_OF_POLYS, 0 + ); } +} + + +void Foam::vtk::polyWriter::beginPiece +( + const pointField& points, + const faceList& faces +) +{ + // Basic sizes + nLocalPoints_ = points.size(); + nLocalLines_ = 0; + nLocalPolys_ = faces.size(); numberOfPoints_ = nLocalPoints_; - numberOfCells_ = nLocalFaces_; + numberOfCells_ = nLocalPolys_; if (parallel_) { @@ -67,6 +127,7 @@ void Foam::vtk::polyWriter::beginPiece vtk::fileTag::PIECE, vtk::fileAttr::NUMBER_OF_POINTS, numberOfPoints_, vtk::fileAttr::NUMBER_OF_POLYS, numberOfCells_ + // AND: vtk::fileAttr::NUMBER_OF_LINES, 0 ); } } @@ -79,48 +140,219 @@ void Foam::vtk::polyWriter::writePoints { this->beginPoints(numberOfPoints_); - if (parallel_ ? Pstream::master() : true) + if (parallel_) + { + vtk::writeListParallel(format_.ref(), points); + } + else { + vtk::writeList(format(), points); + + } + + this->endPoints(); +} + + +void Foam::vtk::polyWriter::writeLinesLegacy +( + const edgeList& edges, + const label pointOffset +) +{ + // Connectivity count without additional storage (done internally) + const label nLocalConns = countConnectivity(edges); + + label nLines = nLocalLines_; + label nConns = nLocalConns; + + if (parallel_) + { + reduce(nLines, sumOp<label>()); + reduce(nConns, sumOp<label>()); + } + + if (nLines != numberOfCells_) + { + FatalErrorInFunction + << "Expecting " << numberOfCells_ + << " edges, but found " << nLines + << exit(FatalError); + } + + legacy::beginLines(os_, nLines, nConns); + + labelList vertLabels(nLocalLines_ + nLocalConns); + + { + // Legacy: size + connectivity together + // [nPts, id1, id2, ..., nPts, id1, id2, ...] + + auto iter = vertLabels.begin(); + + const label off = pointOffset; + + for (const edge& e : edges) { - vtk::writeList(format(), points); + *iter = e.size(); // The size prefix (always 2 for an edge) + ++iter; + + *iter = off + e.first(); // Vertex labels + ++iter; + + *iter = off + e.second(); + ++iter; } } + if (parallel_) { - if (Pstream::master()) + vtk::writeListParallel(format_.ref(), vertLabels); + } + else + { + vtk::writeList(format(), vertLabels); + } + + if (format_) + { + format().flush(); + } +} + + +void Foam::vtk::polyWriter::writeLines +( + const edgeList& edges, + const label pointOffset +) +{ + // Connectivity count without additional storage (done internally) + const label nLocalConns = countConnectivity(edges); + + if (format_) + { + format().tag(vtk::fileTag::LINES); + } + + // + // 'connectivity' + // + { + labelList vertLabels(nLocalConns); + + label nConns = nLocalConns; + + if (parallel_) { - pointField recv; + reduce(nConns, sumOp<label>()); + } - // Receive each point field and write - for (const int subproci : Pstream::subProcs()) - { - IPstream fromProc(Pstream::commsTypes::blocking, subproci); + if (format_) + { + const uint64_t payLoad = vtk::sizeofData<label>(nConns); - { - fromProc >> recv; + format().beginDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY); + format().writeSize(payLoad * sizeof(label)); + } - vtk::writeList(format(), recv); - } + { + // XML: connectivity only + // [id1, id2, ..., id1, id2, ...] + + auto iter = vertLabels.begin(); + + const label off = pointOffset; + + for (const edge& e : edges) + { + // Edge vertex labels + *iter = off + e.first(); + ++iter; + + *iter = off + e.second(); + ++iter; } } + + + if (parallel_) + { + vtk::writeListParallel(format_.ref(), vertLabels); + } else { - // Send - OPstream toProc - ( - Pstream::commsTypes::blocking, - Pstream::masterNo() - ); + vtk::writeList(format(), vertLabels); + } - { - toProc << points; - } + if (format_) + { + format().flush(); + format().endDataArray(); } } - this->endPoints(); + // + // 'offsets' (connectivity offsets) + // + { + labelList vertOffsets(nLocalLines_); + label nOffs = vertOffsets.size(); + + if (parallel_) + { + reduce(nOffs, sumOp<label>()); + } + + if (format_) + { + const uint64_t payLoad = vtk::sizeofData<label>(nOffs); + + format().beginDataArray<label>(vtk::dataArrayAttr::OFFSETS); + format().writeSize(payLoad); + } + + + // processor-local connectivity offsets + label off = + ( + parallel_ ? globalIndex(nLocalConns).localStart() : 0 + ); + + + auto iter = vertOffsets.begin(); + + for (const edge& e : edges) + { + off += e.size(); // End offset + *iter = off; + ++iter; + } + + + if (parallel_) + { + vtk::writeListParallel(format_.ref(), vertOffsets); + } + else + { + vtk::writeList(format_.ref(), vertOffsets); + } + + + if (format_) + { + format().flush(); + format().endDataArray(); + } + } + + if (format_) + { + format().endTag(vtk::fileTag::LINES); + } } @@ -131,27 +363,28 @@ void Foam::vtk::polyWriter::writePolysLegacy ) { // Connectivity count without additional storage (done internally) + const label nLocalConns = countConnectivity(faces); - label nFaces = nLocalFaces_; - label nVerts = nLocalVerts_; + label nPolys = nLocalPolys_; + label nConns = nLocalConns; if (parallel_) { - reduce(nFaces, sumOp<label>()); - reduce(nVerts, sumOp<label>()); + reduce(nPolys, sumOp<label>()); + reduce(nConns, sumOp<label>()); } - if (nFaces != numberOfCells_) + if (nPolys != numberOfCells_) { FatalErrorInFunction << "Expecting " << numberOfCells_ - << " faces, but found " << nFaces + << " faces, but found " << nPolys << exit(FatalError); } - legacy::beginPolys(os_, nFaces, nVerts); + legacy::beginPolys(os_, nPolys, nConns); - labelList vertLabels(nLocalFaces_ + nLocalVerts_); + labelList vertLabels(nLocalPolys_ + nLocalConns); { // Legacy: size + connectivity together @@ -159,21 +392,18 @@ void Foam::vtk::polyWriter::writePolysLegacy auto iter = vertLabels.begin(); - label off = pointOffset; + const label off = pointOffset; + for (const face& f : faces) { - for (const face& f : faces) + *iter = f.size(); // The size prefix + ++iter; + + for (const label id : f) { - *iter = f.size(); // The size prefix + *iter = id + off; // Vertex label ++iter; - - for (const label pfi : f) - { - *iter = pfi + off; // Face vertex label - ++iter; - } } - // off += points.size(); } } @@ -200,6 +430,9 @@ void Foam::vtk::polyWriter::writePolys const label pointOffset ) { + // Connectivity count without additional storage (done internally) + const label nLocalConns = countConnectivity(faces); + if (format_) { format().tag(vtk::fileTag::POLYS); @@ -209,18 +442,18 @@ void Foam::vtk::polyWriter::writePolys // 'connectivity' // { - labelList vertLabels(nLocalVerts_); + labelList vertLabels(nLocalConns); - label nVerts = nLocalVerts_; + label nConns = nLocalConns; if (parallel_) { - reduce(nVerts, sumOp<label>()); + reduce(nConns, sumOp<label>()); } if (format_) { - const uint64_t payLoad = vtk::sizeofData<label>(nVerts); + const uint64_t payLoad = vtk::sizeofData<label>(nConns); format().beginDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY); format().writeSize(payLoad * sizeof(label)); @@ -234,16 +467,13 @@ void Foam::vtk::polyWriter::writePolys label off = pointOffset; + for (const face& f : faces) { - for (const face& f : faces) + for (const label id : f) { - for (const label pfi : f) - { - *iter = pfi + off; // Face vertex label - ++iter; - } + *iter = id + off; // Face vertex label + ++iter; } - // off += points.size(); } } @@ -269,7 +499,7 @@ void Foam::vtk::polyWriter::writePolys // 'offsets' (connectivity offsets) // { - labelList vertOffsets(nLocalFaces_); + labelList vertOffsets(nLocalPolys_); label nOffs = vertOffsets.size(); if (parallel_) @@ -289,19 +519,17 @@ void Foam::vtk::polyWriter::writePolys // processor-local connectivity offsets label off = ( - parallel_ ? globalIndex(nLocalVerts_).localStart() : 0 + parallel_ ? globalIndex(nLocalConns).localStart() : 0 ); auto iter = vertOffsets.begin(); + for (const face& f : faces) { - for (const face& f : faces) - { - off += f.size(); // End offset - *iter = off; - ++iter; - } + off += f.size(); // End offset + *iter = off; + ++iter; } @@ -340,8 +568,8 @@ Foam::vtk::polyWriter::polyWriter numberOfPoints_(0), numberOfCells_(0), nLocalPoints_(0), - nLocalFaces_(0), - nLocalVerts_(0) + nLocalLines_(0), + nLocalPolys_(0) { // We do not currently support append mode opts_.append(false); @@ -387,6 +615,36 @@ bool Foam::vtk::polyWriter::writeGeometry() } +bool Foam::vtk::polyWriter::writeLineGeometry +( + const pointField& points, + const edgeList& edges +) +{ + enter_Piece(); + + beginPiece(points, edges); + + writePoints(points); + + const label pointOffset = + ( + parallel_ ? globalIndex(nLocalPoints_).localStart() : 0 + ); + + if (legacy()) + { + writeLinesLegacy(edges, pointOffset); + } + else + { + writeLines(edges, pointOffset); + } + + return true; +} + + bool Foam::vtk::polyWriter::writePolyGeometry ( const pointField& points, diff --git a/src/fileFormats/vtk/write/foamVtkPolyWriter.H b/src/fileFormats/vtk/write/foamVtkPolyWriter.H index 8dadb17f754..4c10b0f2bf5 100644 --- a/src/fileFormats/vtk/write/foamVtkPolyWriter.H +++ b/src/fileFormats/vtk/write/foamVtkPolyWriter.H @@ -51,6 +51,7 @@ SourceFiles #include "foamVtkFileWriter.H" #include "pointField.H" +#include "edgeList.H" #include "faceList.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -75,30 +76,53 @@ protected: //- The number of field points for the current Piece label numberOfPoints_; - //- The number of field cells (faces) for the current Piece + //- The number of field cells (edges or faces) for the current Piece label numberOfCells_; //- Local number of points label nLocalPoints_; - //- Local number of faces - label nLocalFaces_; + //- Local number of lines (edges) + label nLocalLines_; - //- Local face vertices (connectivity) count. Sum of face sizes. - label nLocalVerts_; + //- Local number of polys (faces) + label nLocalPolys_; + // Protected Member Functions + + //- Write a uniform field of Cell (Poly or Line) or Point values + template<class Type> + void writeUniformValue + ( + const label nCellValues, // Could be Poly or Line! + const word& fieldName, + const Type& val + ); + private: // Private Member Functions - //- Determine sizes (nLocalPoints_, nLocalFaces_, nLocalVerts_), + //- Determine sizes (nLocalPoints_, nLocalLines_), + //- and begin piece + void beginPiece(const pointField& points, const edgeList& edges); + + //- Determine sizes (nLocalPoints_, nLocalPolys_), //- and begin piece void beginPiece(const pointField& points, const faceList& faces); //- Write points void writePoints(const pointField& points); + //- Write lines, legacy format + // \param pointOffset processor-local point offset + void writeLinesLegacy(const edgeList& edges, const label pointOffset); + + //- Write lines + // \param pointOffset processor-local point offset + void writeLines(const edgeList& edges, const label pointOffset); + //- Write faces, legacy format // \param pointOffset processor-local point offset void writePolysLegacy(const faceList& faces, const label pointOffset); @@ -163,6 +187,16 @@ public: // their own geomety, but use writePolyGeometry() directly virtual bool writeGeometry(); + //- Low-level write edge/point topology. + //- Normally used by writeGeometry() in a derived class + // Also writes the file header if not previously written. + // \note Must be called prior to writing CellData or PointData + bool writeLineGeometry + ( + const pointField& points, + const edgeList& edges + ); + //- Low-level write face/point topology. //- Normally used by writeGeometry() in a derived class // Also writes the file header if not previously written. @@ -194,11 +228,7 @@ public: // Write - //- Write a uniform field of Cell (Face) or Point values - template<class Type> - void writeUniform(const word& fieldName, const Type& val); - - //- Write a list of Cell (Face) or Point values + //- Write a list of Cell (Poly or Line) or Point values template<class Type> void write(const word& fieldName, const UList<Type>& field); }; diff --git a/src/fileFormats/vtk/write/foamVtkPolyWriterTemplates.C b/src/fileFormats/vtk/write/foamVtkPolyWriterTemplates.C index b0db6d1cfec..319836b4637 100644 --- a/src/fileFormats/vtk/write/foamVtkPolyWriterTemplates.C +++ b/src/fileFormats/vtk/write/foamVtkPolyWriterTemplates.C @@ -25,24 +25,27 @@ License \*---------------------------------------------------------------------------*/ -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // template<class Type> -void Foam::vtk::polyWriter::writeUniform +void Foam::vtk::polyWriter::writeUniformValue ( + const label nCellValues, const word& fieldName, const Type& val ) { + label nValues(0); + if (isState(outputState::CELL_DATA)) { ++nCellData_; - vtk::fileWriter::writeUniform<Type>(fieldName, val, numberOfCells_); + nValues = nCellValues; } else if (isState(outputState::POINT_DATA)) { ++nPointData_; - vtk::fileWriter::writeUniform<Type>(fieldName, val, numberOfPoints_); + nValues = nLocalPoints_; } else { @@ -54,10 +57,16 @@ void Foam::vtk::polyWriter::writeUniform ) << " for uniform field " << fieldName << nl << endl << exit(FatalError); + + return; } + + vtk::fileWriter::writeUniform<Type>(fieldName, val, nValues); } +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + template<class Type> void Foam::vtk::polyWriter::write ( @@ -66,18 +75,18 @@ void Foam::vtk::polyWriter::write ) { // Could check sizes: - // nValues == nLocalFaces (CELL_DATA) - // nValues == nLocalPoints (POINT_DATA) + // CELL_DATA: nValues == (nLocalPolys | nLocalLines) + // POINT_DATA: nValues == nLocalPoints + + // const label nValues = field.size(); if (isState(outputState::CELL_DATA)) { ++nCellData_; - vtk::fileWriter::writeBasicField<Type>(fieldName, field); } else if (isState(outputState::POINT_DATA)) { ++nPointData_; - vtk::fileWriter::writeBasicField<Type>(fieldName, field); } else { @@ -89,7 +98,10 @@ void Foam::vtk::polyWriter::write ) << " for field " << fieldName << nl << endl << exit(FatalError); + return; } + + vtk::fileWriter::writeBasicField<Type>(fieldName, field); } diff --git a/src/fileFormats/vtk/write/foamVtkSurfaceWriter.C b/src/fileFormats/vtk/write/foamVtkSurfaceWriter.C index 9ee9709d861..7b07cace360 100644 --- a/src/fileFormats/vtk/write/foamVtkSurfaceWriter.C +++ b/src/fileFormats/vtk/write/foamVtkSurfaceWriter.C @@ -88,7 +88,7 @@ bool Foam::vtk::surfaceWriter::beginFile(std::string title) return vtk::fileWriter::beginFile(title); } - if (instant_.name().size()) + if (!instant_.name().empty()) { return vtk::fileWriter::beginFile ( @@ -129,4 +129,10 @@ void Foam::vtk::surfaceWriter::piece } +bool Foam::vtk::surfaceWriter::writeProcIDs() +{ + return vtk::fileWriter::writeProcIDs(nLocalPolys_); +} + + // ************************************************************************* // diff --git a/src/fileFormats/vtk/write/foamVtkSurfaceWriter.H b/src/fileFormats/vtk/write/foamVtkSurfaceWriter.H index 830ee6132d2..0a9d2ccdf36 100644 --- a/src/fileFormats/vtk/write/foamVtkSurfaceWriter.H +++ b/src/fileFormats/vtk/write/foamVtkSurfaceWriter.H @@ -42,7 +42,6 @@ Note SourceFiles foamVtkSurfaceWriter.C - foamVtkSurfaceWriterTemplates.C \*---------------------------------------------------------------------------*/ @@ -152,8 +151,20 @@ public: //- Write the currently set time as "TimeValue" FieldData void writeTimeValue(); - //- Reset point, face references to begin a new piece + //- Reset point/face references to begin a new piece void piece(const pointField& points, const faceList& faces); + + + //- Write processor ids for each poly as CellData + //- (no-op in serial) + bool writeProcIDs(); + + //- Write a uniform field of Cell (Poly) or Point values + template<class Type> + void writeUniform(const word& fieldName, const Type& val) + { + polyWriter::writeUniformValue<Type>(nLocalPolys_, fieldName, val); + } }; diff --git a/src/meshTools/edgeMesh/edgeMeshFormats/vtk/VTKedgeFormat.C b/src/meshTools/edgeMesh/edgeMeshFormats/vtk/VTKedgeFormat.C index 7f1951a9711..782ce50b0ea 100644 --- a/src/meshTools/edgeMesh/edgeMeshFormats/vtk/VTKedgeFormat.C +++ b/src/meshTools/edgeMesh/edgeMeshFormats/vtk/VTKedgeFormat.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -28,50 +28,9 @@ License #include "VTKedgeFormat.H" #include "Fstream.H" -#include "clock.H" -#include "vtkUnstructuredReader.H" #include "Time.H" - -// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // - -void Foam::fileFormats::VTKedgeFormat::writeHeader -( - Ostream& os, - const pointField& pointLst -) -{ - // Write header - os << "# vtk DataFile Version 2.0" << nl - << "featureEdgeMesh written " << clock::dateTime().c_str() << nl - << "ASCII" << nl - << nl - << "DATASET POLYDATA" << nl; - - // Write vertex coords - os << "POINTS " << pointLst.size() << " double" << nl; - for (const point& pt : pointLst) - { - os << float(pt.x()) << ' ' - << float(pt.y()) << ' ' - << float(pt.z()) << nl; - } -} - - -void Foam::fileFormats::VTKedgeFormat::writeEdges -( - Ostream& os, - const UList<edge>& edgeLst -) -{ - os << "LINES " << edgeLst.size() << ' ' << 3*edgeLst.size() << nl; - - for (const edge& e : edgeLst) - { - os << "2 " << e[0] << ' ' << e[1] << nl; - } -} - +#include "foamVtkLineWriter.H" +#include "vtkUnstructuredReader.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -122,19 +81,21 @@ bool Foam::fileFormats::VTKedgeFormat::read storedPoints().transfer(reader.points()); label nEdges = 0; - forAll(reader.lines(), lineI) + for (const auto& lineVerts : reader.lines()) { - nEdges += reader.lines()[lineI].size()-1; + if (lineVerts.size() > 1) + { + nEdges += (lineVerts.size()-1); + } } - storedEdges().setSize(nEdges); + storedEdges().resize(nEdges); nEdges = 0; - forAll(reader.lines(), lineI) + for (const auto& lineVerts : reader.lines()) { - const labelList& verts = reader.lines()[lineI]; - for (label i = 1; i < verts.size(); i++) + for (label i = 1; i < lineVerts.size(); ++i) { - storedEdges()[nEdges++] = edge(verts[i-1], verts[i]); + storedEdges()[nEdges++] = edge(lineVerts[i-1], lineVerts[i]); } } @@ -148,16 +109,20 @@ void Foam::fileFormats::VTKedgeFormat::write const edgeMesh& eMesh ) { - OFstream os(filename); - if (!os.good()) - { - FatalErrorInFunction - << "Cannot open file for writing " << filename - << exit(FatalError); - } + // NB: restrict output to legacy ascii so that we are still able + // to read it with vtkUnstructuredReader + + vtk::lineWriter writer + ( + eMesh.points(), + eMesh.edges(), + vtk::formatType::LEGACY_ASCII, + filename, + false // non-parallel write (edgeMesh already serialized) + ); - writeHeader(os, eMesh.points()); - writeEdges(os, eMesh.edges()); + writer.beginFile("OpenFOAM edgeMesh"); + writer.writeGeometry(); } diff --git a/src/meshTools/edgeMesh/edgeMeshFormats/vtk/VTKedgeFormat.H b/src/meshTools/edgeMesh/edgeMeshFormats/vtk/VTKedgeFormat.H index ac88e0bc8db..084828d639c 100644 --- a/src/meshTools/edgeMesh/edgeMeshFormats/vtk/VTKedgeFormat.H +++ b/src/meshTools/edgeMesh/edgeMeshFormats/vtk/VTKedgeFormat.H @@ -54,37 +54,12 @@ class VTKedgeFormat : public edgeMesh { - // Private Member Functions - - //- No copy construct - VTKedgeFormat(const VTKedgeFormat&) = delete; - - //- No copy assignment - void operator=(const VTKedgeFormat&) = delete; - - -protected: - - // Protected Member Functions - - //- Write header information with points - static void writeHeader - ( - Ostream&, - const pointField& - ); - - //- Write edges - static void writeEdges(Ostream&, const UList<edge>&); - - public: - // Constructors - //- Construct from file name - VTKedgeFormat(const fileName&); + //- Read construct from file name + explicit VTKedgeFormat(const fileName& filename); // Selectors @@ -103,12 +78,12 @@ public: // Member Functions //- Write surface mesh components by proxy - static void write(const fileName&, const edgeMesh&); + static void write(const fileName& name, const edgeMesh&); //- Read from file - virtual bool read(const fileName&); + virtual bool read(const fileName& name); - //- Write object file + //- Write object to file virtual void write(const fileName& name) const { write(name, *this); diff --git a/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriter.C b/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriter.C index be2bf99fa49..a5ee5abd525 100644 --- a/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriter.C +++ b/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriter.C @@ -45,16 +45,24 @@ void Foam::vtk::internalMeshWriter::beginPiece() if (parallel_) { + if (debug > 1) + { + PoutInFunction + << ": nPoints=" << numberOfPoints_ + << " nCells=" << numberOfCells_ << nl; + } + reduce(numberOfPoints_, sumOp<label>()); reduce(numberOfCells_, sumOp<label>()); } + DebugInFunction + << "nPoints=" << numberOfPoints_ + << " nCells=" << numberOfCells_ << nl; + // Nothing else to do for legacy if (legacy()) return; - DebugInFunction - << "nPoints=" << numberOfPoints_ << " nCells=" << numberOfCells_ << nl; - if (format_) { format() @@ -178,7 +186,10 @@ void Foam::vtk::internalMeshWriter::writeCellsLegacy(const label pointOffset) } -void Foam::vtk::internalMeshWriter::writeCellsConnectivity(const label pointOffset) +void Foam::vtk::internalMeshWriter::writeCellsConnectivity +( + const label pointOffset +) { // // 'connectivity' @@ -316,7 +327,10 @@ void Foam::vtk::internalMeshWriter::writeCellsConnectivity(const label pointOffs } -void Foam::vtk::internalMeshWriter::writeCellsFaces(const label pointOffset) +void Foam::vtk::internalMeshWriter::writeCellsFaces +( + const label pointOffset +) { label nFaceLabels = vtuCells_.faceLabels().size(); @@ -628,39 +642,7 @@ bool Foam::vtk::internalMeshWriter::writeProcIDs() return false; } - if (isState(outputState::CELL_DATA)) - { - ++nCellData_; - } - else - { - reportBadState(FatalErrorInFunction, outputState::CELL_DATA) - << " for procID field" << nl << endl - << exit(FatalError); - } - - const globalIndex procMaps(vtuCells_.nFieldCells()); - - this->beginDataArray<label>("procID", procMaps.size()); - - bool good = false; - - if (Pstream::master()) - { - // Per-processor ids - for (const int proci : Pstream::allProcs()) - { - vtk::write(format(), label(proci), procMaps.localSize(proci)); - } - - good = true; - } - - this->endDataArray(); - - - // MPI barrier - return returnReduce(good, orOp<bool>()); + return vtk::fileWriter::writeProcIDs(vtuCells_.nFieldCells()); } diff --git a/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriter.H b/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriter.H index 17c69893038..00da9739a7a 100644 --- a/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriter.H +++ b/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriter.H @@ -225,6 +225,10 @@ public: //- Write primitive field of CellData template<class Type> void writeCellData(const word& fieldName, const UList<Type>& field); + + //- Write primitive field of PointData + template<class Type> + void writePointData(const word& fieldName, const UList<Type>& field); }; diff --git a/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriterTemplates.C b/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriterTemplates.C index 866117286a7..ecf419c903e 100644 --- a/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriterTemplates.C +++ b/src/meshTools/output/vtk/mesh/foamVtkInternalMeshWriterTemplates.C @@ -37,15 +37,17 @@ void Foam::vtk::internalMeshWriter::writeUniform const Type& val ) { + label nValues(0); + if (isState(outputState::CELL_DATA)) { ++nCellData_; - vtk::fileWriter::writeUniform<Type>(fieldName, val, numberOfCells_); + nValues = vtuCells_.nFieldCells(); } else if (isState(outputState::POINT_DATA)) { ++nPointData_; - vtk::fileWriter::writeUniform<Type>(fieldName, val, numberOfPoints_); + nValues = vtuCells_.nFieldPoints(); } else { @@ -54,9 +56,14 @@ void Foam::vtk::internalMeshWriter::writeUniform FatalErrorInFunction, outputState::CELL_DATA, outputState::POINT_DATA - ) << " for field " << fieldName << nl << endl + ) + << " for uniform field " << fieldName << nl << endl << exit(FatalError); + + return; } + + vtk::fileWriter::writeUniform<Type>(fieldName, val, nValues); } @@ -95,4 +102,37 @@ void Foam::vtk::internalMeshWriter::writeCellData } +template<class Type> +void Foam::vtk::internalMeshWriter::writePointData +( + const word& fieldName, + const UList<Type>& field +) +{ + if (isState(outputState::POINT_DATA)) + { + ++nPointData_; + } + else + { + reportBadState(FatalErrorInFunction, outputState::POINT_DATA) + << " for field " << fieldName << nl << endl + << exit(FatalError); + } + + this->beginDataArray<Type>(fieldName, numberOfPoints_); + + if (parallel_) + { + vtk::writeListParallel(format_.ref(), field); + } + else + { + vtk::writeList(format(), field); + } + + this->endDataArray(); +} + + // ************************************************************************* // diff --git a/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriter.C b/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriter.C index acec853d6b3..63f85246a6d 100644 --- a/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriter.C +++ b/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriter.C @@ -38,14 +38,15 @@ void Foam::vtk::patchMeshWriter::beginPiece() // Basic sizes const polyBoundaryMesh& patches = mesh_.boundaryMesh(); - nLocalPoints_ = nLocalFaces_ = nLocalVerts_ = 0; + nLocalPoints_ = nLocalPolys_ = 0; + nLocalVerts_ = 0; for (const label patchId : patchIDs_) { const polyPatch& pp = patches[patchId]; nLocalPoints_ += pp.nPoints(); - nLocalFaces_ += pp.size(); + nLocalPolys_ += pp.size(); for (const face& f : pp) { @@ -54,7 +55,7 @@ void Foam::vtk::patchMeshWriter::beginPiece() } numberOfPoints_ = nLocalPoints_; - numberOfCells_ = nLocalFaces_; + numberOfCells_ = nLocalPolys_; if (parallel_) { @@ -148,26 +149,26 @@ void Foam::vtk::patchMeshWriter::writePolysLegacy(const label pointOffset) // Connectivity count without additional storage (done internally) - label nFaces = nLocalFaces_; + label nPolys = nLocalPolys_; label nVerts = nLocalVerts_; if (parallel_) { - reduce(nFaces, sumOp<label>()); + reduce(nPolys, sumOp<label>()); reduce(nVerts, sumOp<label>()); } - if (nFaces != numberOfCells_) + if (nPolys != numberOfCells_) { FatalErrorInFunction << "Expecting " << numberOfCells_ - << " faces, but found " << nFaces + << " faces, but found " << nPolys << exit(FatalError); } - legacy::beginPolys(os_, nFaces, nVerts); + legacy::beginPolys(os_, nPolys, nVerts); - labelList vertLabels(nLocalFaces_ + nLocalVerts_); + labelList vertLabels(nLocalPolys_ + nLocalVerts_); { // Legacy: size + connectivity together @@ -186,9 +187,9 @@ void Foam::vtk::patchMeshWriter::writePolysLegacy(const label pointOffset) *iter = f.size(); // The size prefix ++iter; - for (const label pfi : f) + for (const label id : f) { - *iter = pfi + off; // Face vertex label + *iter = id + off; // Face vertex label ++iter; } } @@ -258,9 +259,9 @@ void Foam::vtk::patchMeshWriter::writePolys(const label pointOffset) for (const face& f : pp.localFaces()) { - for (const label pfi : f) + for (const label id : f) { - *iter = pfi + off; // Face vertex label + *iter = id + off; // Face vertex label ++iter; } } @@ -290,7 +291,7 @@ void Foam::vtk::patchMeshWriter::writePolys(const label pointOffset) // 'offsets' (connectivity offsets) // { - labelList vertOffsets(nLocalFaces_); + labelList vertOffsets(nLocalPolys_); label nOffs = vertOffsets.size(); if (parallel_) @@ -367,7 +368,7 @@ Foam::vtk::patchMeshWriter::patchMeshWriter numberOfPoints_(0), numberOfCells_(0), nLocalPoints_(0), - nLocalFaces_(0), + nLocalPolys_(0), nLocalVerts_(0), mesh_(mesh), @@ -512,15 +513,15 @@ void Foam::vtk::patchMeshWriter::writePatchIDs() const polyBoundaryMesh& patches = mesh_.boundaryMesh(); - label nFaces = nLocalFaces_; + label nPolys = nLocalPolys_; if (parallel_) { - reduce(nFaces, sumOp<label>()); + reduce(nPolys, sumOp<label>()); } - this->beginDataArray<label>("patchID", nFaces); + this->beginDataArray<label>("patchID", nPolys); if (parallel_ ? Pstream::master() : true) { @@ -584,66 +585,7 @@ void Foam::vtk::patchMeshWriter::writePatchIDs() bool Foam::vtk::patchMeshWriter::writeProcIDs() { - // This is different than for internalWriter. - // Here we allow procIDs whenever running in parallel, even if the - // output is serial. This allow diagnosis of processor patches. - - if (!Pstream::parRun()) - { - // Skip in non-parallel - return false; - } - - if (isState(outputState::CELL_DATA)) - { - ++nCellData_; - } - else - { - reportBadState(FatalErrorInFunction, outputState::CELL_DATA) - << " for patchID field" << nl << endl - << exit(FatalError); - } - - label nFaces = nLocalFaces_; - - if (parallel_) - { - reduce(nFaces, sumOp<label>()); - } - - - this->beginDataArray<label>("procID", nFaces); - - bool good = false; - - if (parallel_) - { - globalIndex procSizes(nLocalFaces_); - - if (Pstream::master()) - { - // Per-processor ids - for (const int proci : Pstream::allProcs()) - { - vtk::write(format(), label(proci), procSizes.localSize(proci)); - } - - good = true; - } - } - else - { - vtk::write(format(), label(Pstream::myProcNo()), nLocalFaces_); - - good = true; - } - - - this->endDataArray(); - - // MPI barrier - return parallel_ ? returnReduce(good, orOp<bool>()) : good; + return vtk::fileWriter::writeProcIDs(nLocalPolys_); } @@ -668,15 +610,15 @@ bool Foam::vtk::patchMeshWriter::writeNeighIDs() const polyBoundaryMesh& patches = mesh_.boundaryMesh(); - label nFaces = nLocalFaces_; + label nPolys = nLocalPolys_; if (parallel_) { - reduce(nFaces, sumOp<label>()); + reduce(nPolys, sumOp<label>()); } - this->beginDataArray<label>("neighID", nFaces); + this->beginDataArray<label>("neighID", nPolys); bool good = false; diff --git a/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriter.H b/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriter.H index 2a26482be14..0622d66d802 100644 --- a/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriter.H +++ b/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriter.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2019 OpenCFD Ltd. + Copyright (C) 2016-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -82,8 +82,8 @@ protected: //- Local number of points label nLocalPoints_; - //- Local number of faces - label nLocalFaces_; + //- Local number of polys (faces) + label nLocalPolys_; //- Local face vertices (connectivity) count. Sum of face sizes. label nLocalVerts_; @@ -97,7 +97,7 @@ protected: // Private Member Functions - //- Determine sizes (nLocalPoints_, nLocalFaces_, nLocalVerts_), + //- Determine sizes (nLocalPoints_, nLocalPolys_), //- and begin piece. void beginPiece(); @@ -172,7 +172,7 @@ public: } //- The patch IDs - inline const labelList& patchIDs() const + const labelList& patchIDs() const noexcept { return patchIDs_; } diff --git a/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriterTemplates.C b/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriterTemplates.C index ef81dcb7822..349a6b28fcd 100644 --- a/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriterTemplates.C +++ b/src/meshTools/output/vtk/patch/foamVtkPatchMeshWriterTemplates.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2020 OpenCFD Ltd. + Copyright (C) 2016-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,23 +37,33 @@ void Foam::vtk::patchMeshWriter::writeUniform const Type& val ) { + label nValues(0); + if (isState(outputState::CELL_DATA)) { ++nCellData_; - vtk::fileWriter::writeUniform<Type>(fieldName, val, numberOfCells_); + nValues = nLocalPolys_; } else if (isState(outputState::POINT_DATA)) { ++nPointData_; - vtk::fileWriter::writeUniform<Type>(fieldName, val, numberOfPoints_); + nValues = nLocalPoints_; } else { - WarningInFunction - << "Ignore bad writer state (" << stateNames[state_] - << ") for field " << fieldName << nl << endl + reportBadState + ( + FatalErrorInFunction, + outputState::CELL_DATA, + outputState::POINT_DATA + ) + << " for uniform field " << fieldName << nl << endl << exit(FatalError); + + return; } + + vtk::fileWriter::writeUniform<Type>(fieldName, val, nValues); } -- GitLab