From 05427217a02d7f7c22ceba2af7847c2328741330 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Mon, 17 Sep 2018 08:59:03 +0200 Subject: [PATCH] ENH: improvements for foamVtkOutput, foamVtkFormatter (issue #926) - parallel list output for foamVtkOutput - simplified '.series' file output - beginDataArray() method instead of openDataArray() + closeTag() since this seems to be the most common use anyhow. With an optional argument for leaving the tag open, this works the same as openDataArray() which may be deprecated in the future. - begin/end methods for CellData, PointData, FieldData (commonly used) - templating parameters for file headers, content version, legacy fields. This improves coding robustness and convenience of use. - use formatter and higher-level methods for legacy output - attribute quoting character now part of the formatter itself instead of as an argument for xmlAttr(). Toggle with quoting() method. - pair-wise processing of xml attributes, which also allows them to be passed as optional entries when creating an xml tag. - xmlComment with multiple arguments --- .../foamToVTK/foamVtkLagrangianWriter.C | 44 +- .../foamVtkLagrangianWriterTemplates.C | 4 +- .../vtk/output/foamVtkInternalWriter.C | 21 +- .../output/foamVtkInternalWriterTemplates.C | 8 +- .../vtk/output/foamVtkOutputFieldsTemplates.C | 10 +- .../vtk/output/foamVtkPatchWriter.C | 26 +- .../vtk/output/foamVtkPatchWriterTemplates.C | 6 +- .../vtk/output/foamVtkSurfaceMeshWriter.C | 6 +- .../foamVtkSurfaceMeshWriterTemplates.C | 4 +- .../vtk/output/foamVtkWriteSurfFields.C | 7 +- src/fileFormats/vtk/core/foamVtkCore.C | 56 +++ src/fileFormats/vtk/core/foamVtkCore.H | 70 +++- src/fileFormats/vtk/core/foamVtkPTraits.C | 6 +- src/fileFormats/vtk/core/foamVtkPTraits.H | 13 +- .../vtk/format/foamVtkAppendBase64Formatter.C | 17 +- .../vtk/format/foamVtkAppendBase64Formatter.H | 13 +- .../vtk/format/foamVtkAppendRawFormatter.C | 20 +- .../vtk/format/foamVtkAppendRawFormatter.H | 16 +- .../vtk/format/foamVtkAsciiFormatter.C | 9 +- .../vtk/format/foamVtkAsciiFormatter.H | 8 +- .../vtk/format/foamVtkBase64Formatter.H | 2 +- .../vtk/format/foamVtkBase64Layer.C | 10 +- .../vtk/format/foamVtkBase64Layer.H | 6 +- src/fileFormats/vtk/format/foamVtkFormatter.C | 231 ++++++---- src/fileFormats/vtk/format/foamVtkFormatter.H | 380 +++++++++++++---- .../vtk/format/foamVtkFormatterI.H | 396 +++++++++++++++--- .../vtk/format/foamVtkFormatterTemplates.C | 77 ++-- .../vtk/format/foamVtkLegacyAsciiFormatter.H | 15 +- .../vtk/format/foamVtkLegacyRawFormatter.C | 9 +- .../vtk/format/foamVtkLegacyRawFormatter.H | 18 +- src/fileFormats/vtk/output/foamVtkOutput.C | 266 +++++++++--- src/fileFormats/vtk/output/foamVtkOutput.H | 243 ++++++++--- src/fileFormats/vtk/output/foamVtkOutputI.H | 132 ++++-- .../vtk/output/foamVtkOutputOptions.H | 3 + .../vtk/output/foamVtkOutputOptionsI.H | 15 +- .../vtk/output/foamVtkOutputTemplates.C | 269 +++++++++++- .../lagrangian/vtkCloud/vtkCloud.C | 16 +- .../output/foamVtkWriteCellSetFaces.C | 2 +- src/meshTools/output/foamVtkWriteFaceSet.C | 2 +- src/meshTools/output/foamVtkWritePointSet.C | 2 +- .../surfaceFormats/vtk/VTKsurfaceFormatCore.C | 34 +- 41 files changed, 1923 insertions(+), 569 deletions(-) diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamVtkLagrangianWriter.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamVtkLagrangianWriter.C index 60511094043..cbe2d515bc7 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamVtkLagrangianWriter.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamVtkLagrangianWriter.C @@ -226,20 +226,27 @@ void Foam::vtk::lagrangianWriter::beginParcelData(label nFields) { if (!nParcels_) return; // Skip if there are no parcels - const vtk::fileTag dataType = - ( - useVerts_ - ? vtk::fileTag::CELL_DATA - : vtk::fileTag::POINT_DATA - ); - - if (legacy_) + if (useVerts_) { - legacy::dataHeader(os_, dataType, nParcels_, nFields); + if (legacy_) + { + legacy::beginCellData(format(), nParcels_, nFields); + } + else + { + format().beginCellData(); + } } else { - format().tag(dataType); + if (legacy_) + { + legacy::beginPointData(format(), nParcels_, nFields); + } + else + { + format().beginPointData(); + } } } @@ -248,16 +255,17 @@ void Foam::vtk::lagrangianWriter::endParcelData() { if (!nParcels_) return; // Skip if there are no parcels - const vtk::fileTag dataType = - ( - useVerts_ - ? vtk::fileTag::CELL_DATA - : vtk::fileTag::POINT_DATA - ); - if (!legacy_) { - format().endTag(dataType); + + if (useVerts_) + { + format().endCellData(); + } + else + { + format().endPointData(); + } } } diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamVtkLagrangianWriterTemplates.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamVtkLagrangianWriterTemplates.C index 5b4181f55f7..bd0e7202ead 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamVtkLagrangianWriterTemplates.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamVtkLagrangianWriterTemplates.C @@ -78,7 +78,7 @@ void Foam::vtk::lagrangianWriter::writeIOField(const wordList& fieldNames) if (legacy_) { - legacy::intField(os(), fldName, nCmpt, fld.size()); + legacy::intField<nCmpt>(format(), fldName, fld.size()); } else { @@ -103,7 +103,7 @@ void Foam::vtk::lagrangianWriter::writeIOField(const wordList& fieldNames) if (legacy_) { - legacy::floatField(os(), fldName, nCmpt, fld.size()); + legacy::floatField<nCmpt>(format(), fldName, fld.size()); } else { diff --git a/src/conversion/vtk/output/foamVtkInternalWriter.C b/src/conversion/vtk/output/foamVtkInternalWriter.C index 49bf062e827..4972f98ca12 100644 --- a/src/conversion/vtk/output/foamVtkInternalWriter.C +++ b/src/conversion/vtk/output/foamVtkInternalWriter.C @@ -284,17 +284,11 @@ void Foam::vtk::internalWriter::beginCellData(label nFields) { if (legacy_) { - legacy::dataHeader - ( - os(), - vtk::fileTag::CELL_DATA, - vtuCells_.nFieldCells(), - nFields - ); + legacy::beginCellData(format(), vtuCells_.nFieldCells(), nFields); } else { - format().tag(vtk::fileTag::CELL_DATA); + format().beginCellData(); } } @@ -303,7 +297,7 @@ void Foam::vtk::internalWriter::endCellData() { if (!legacy_) { - format().endTag(vtk::fileTag::CELL_DATA); + format().endCellData(); } } @@ -312,17 +306,16 @@ void Foam::vtk::internalWriter::beginPointData(label nFields) { if (legacy_) { - legacy::dataHeader + legacy::beginPointData ( - os(), - vtk::fileTag::POINT_DATA, + format(), vtuCells_.nFieldPoints(), nFields ); } else { - format().tag(vtk::fileTag::POINT_DATA); + format().beginPointData(); } } @@ -331,7 +324,7 @@ void Foam::vtk::internalWriter::endPointData() { if (!legacy_) { - format().endTag(vtk::fileTag::POINT_DATA); + format().endPointData(); } } diff --git a/src/conversion/vtk/output/foamVtkInternalWriterTemplates.C b/src/conversion/vtk/output/foamVtkInternalWriterTemplates.C index 77689e5ec7b..b0177ade71f 100644 --- a/src/conversion/vtk/output/foamVtkInternalWriterTemplates.C +++ b/src/conversion/vtk/output/foamVtkInternalWriterTemplates.C @@ -43,7 +43,7 @@ void Foam::vtk::internalWriter::write if (legacy_) { - legacy::floatField(os(), field.name(), nCmpt, cellMap.size()); + legacy::floatField<nCmpt>(format(), field.name(), cellMap.size()); } else { @@ -87,7 +87,7 @@ void Foam::vtk::internalWriter::write if (legacy_) { - legacy::floatField(os(), field.name(), nCmpt, nVals); + legacy::floatField<nCmpt>(format(), field.name(), nVals); } else { @@ -136,7 +136,7 @@ void Foam::vtk::internalWriter::write if (legacy_) { - legacy::floatField(os(), vfield.name(), nCmpt, nVals); + legacy::floatField<nCmpt>(format(), vfield.name(), nVals); } else { @@ -179,7 +179,7 @@ void Foam::vtk::internalWriter::write if (legacy_) { - legacy::floatField(os(), vfield.name(), nCmpt, nVals); + legacy::floatField<nCmpt>(format(), vfield.name(), nVals); } else { diff --git a/src/conversion/vtk/output/foamVtkOutputFieldsTemplates.C b/src/conversion/vtk/output/foamVtkOutputFieldsTemplates.C index 74cb846a1b4..5136eb0bf51 100644 --- a/src/conversion/vtk/output/foamVtkOutputFieldsTemplates.C +++ b/src/conversion/vtk/output/foamVtkOutputFieldsTemplates.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -39,7 +39,7 @@ void Foam::vtk::writeField ); fmt.writeSize(payLoad); - writeList(fmt, fld); + vtk::writeList(fmt, fld); fmt.flush(); } @@ -59,7 +59,7 @@ void Foam::vtk::writeField ); fmt.writeSize(payLoad); - writeList(fmt, fld, cellMap); + vtk::writeList(fmt, fld, cellMap); fmt.flush(); } @@ -78,7 +78,7 @@ void Foam::vtk::writeField ); fmt.writeSize(payLoad); - writeList(fmt, fld.internalField()); + vtk::writeList(fmt, fld.internalField()); fmt.flush(); } @@ -98,7 +98,7 @@ void Foam::vtk::writeField ); fmt.writeSize(payLoad); - writeList(fmt, fld.internalField(), cellMap); + vtk::writeList(fmt, fld.internalField(), cellMap); fmt.flush(); } diff --git a/src/conversion/vtk/output/foamVtkPatchWriter.C b/src/conversion/vtk/output/foamVtkPatchWriter.C index 18764148cd6..3ca9500a84f 100644 --- a/src/conversion/vtk/output/foamVtkPatchWriter.C +++ b/src/conversion/vtk/output/foamVtkPatchWriter.C @@ -301,17 +301,11 @@ void Foam::vtk::patchWriter::beginCellData(label nFields) { if (legacy_) { - legacy::dataHeader - ( - os(), - vtk::fileTag::CELL_DATA, - nFaces_, - nFields - ); + legacy::beginCellData(format(), nFaces_, nFields); } else { - format().tag(vtk::fileTag::CELL_DATA); + format().beginCellData(); } } @@ -320,7 +314,7 @@ void Foam::vtk::patchWriter::endCellData() { if (!legacy_) { - format().endTag(vtk::fileTag::CELL_DATA); + format().endCellData(); } } @@ -329,17 +323,11 @@ void Foam::vtk::patchWriter::beginPointData(label nFields) { if (legacy_) { - legacy::dataHeader - ( - os(), - vtk::fileTag::POINT_DATA, - nPoints_, - nFields - ); + legacy::beginPointData(format(), nPoints_, nFields); } else { - format().tag(vtk::fileTag::POINT_DATA); + format().beginPointData(); } } @@ -348,7 +336,7 @@ void Foam::vtk::patchWriter::endPointData() { if (!legacy_) { - format().endTag(vtk::fileTag::POINT_DATA); + format().endPointData(); } } @@ -373,7 +361,7 @@ void Foam::vtk::patchWriter::writePatchIDs() if (legacy_) { - legacy::intField(os_, "patchID", 1, nFaces_); + legacy::intField<1>(format(), "patchID", nFaces_); // 1 component } else { diff --git a/src/conversion/vtk/output/foamVtkPatchWriterTemplates.C b/src/conversion/vtk/output/foamVtkPatchWriterTemplates.C index 9c77912499f..0bc96023904 100644 --- a/src/conversion/vtk/output/foamVtkPatchWriterTemplates.C +++ b/src/conversion/vtk/output/foamVtkPatchWriterTemplates.C @@ -39,7 +39,7 @@ void Foam::vtk::patchWriter::write if (legacy_) { - legacy::floatField(os_, field.name(), nCmpt, nFaces_); + legacy::floatField<nCmpt>(format(), field.name(), nFaces_); } else { @@ -83,7 +83,7 @@ void Foam::vtk::patchWriter::write if (legacy_) { - legacy::floatField(os_, field.name(), nCmpt, nPoints_); + legacy::floatField<nCmpt>(format(), field.name(), nPoints_); } else { @@ -121,7 +121,7 @@ void Foam::vtk::patchWriter::write if (legacy_) { - legacy::floatField(os_, field.name(), nCmpt, nPoints_); + legacy::floatField<nCmpt>(format(), field.name(), nPoints_); } else { diff --git a/src/conversion/vtk/output/foamVtkSurfaceMeshWriter.C b/src/conversion/vtk/output/foamVtkSurfaceMeshWriter.C index f5ba90efc17..96b62ed9c78 100644 --- a/src/conversion/vtk/output/foamVtkSurfaceMeshWriter.C +++ b/src/conversion/vtk/output/foamVtkSurfaceMeshWriter.C @@ -230,11 +230,11 @@ void Foam::vtk::surfaceMeshWriter::beginCellData(label nFields) { if (legacy_) { - legacy::dataHeader(os(), vtk::fileTag::CELL_DATA, pp_.size(), nFields); + legacy::beginCellData(format(), pp_.size(), nFields); } else { - format().tag(vtk::fileTag::CELL_DATA); + format().beginCellData(); } } @@ -243,7 +243,7 @@ void Foam::vtk::surfaceMeshWriter::endCellData() { if (!legacy_) { - format().endTag(vtk::fileTag::CELL_DATA); + format().endCellData(); } } diff --git a/src/conversion/vtk/output/foamVtkSurfaceMeshWriterTemplates.C b/src/conversion/vtk/output/foamVtkSurfaceMeshWriterTemplates.C index 8b52dfc02f4..c54d53f3dd0 100644 --- a/src/conversion/vtk/output/foamVtkSurfaceMeshWriterTemplates.C +++ b/src/conversion/vtk/output/foamVtkSurfaceMeshWriterTemplates.C @@ -70,7 +70,7 @@ void Foam::vtk::surfaceMeshWriter::write if (legacy_) { - legacy::floatField(os(), field.name(), nCmpt, pp_.size()); + legacy::floatField<nCmpt>(format(), field.name(), pp_.size()); } else { @@ -100,7 +100,7 @@ void Foam::vtk::surfaceMeshWriter::write if (legacy_) { - legacy::floatField(os(), field.name(), nCmpt, pp_.size()); + legacy::floatField<nCmpt>(format(), field.name(), pp_.size()); } else { diff --git a/src/conversion/vtk/output/foamVtkWriteSurfFields.C b/src/conversion/vtk/output/foamVtkWriteSurfFields.C index bfe1f350381..1742470dbf8 100644 --- a/src/conversion/vtk/output/foamVtkWriteSurfFields.C +++ b/src/conversion/vtk/output/foamVtkWriteSurfFields.C @@ -94,10 +94,9 @@ void Foam::vtk::writeSurfFields // Fields if (legacy_) { - legacy::dataHeader + legacy::beginPointData ( - os, - vtk::fileTag::POINT_DATA, + format(), mesh.nFaces(), surfVectorFields.size() ); @@ -114,7 +113,7 @@ void Foam::vtk::writeSurfFields if (legacy_) { - legacy::floatField(os, fld.name(), nCmpt, mesh.nFaces()); + legacy::floatField<nCmpt>(format(), fld.name(), mesh.nFaces()); } else { diff --git a/src/fileFormats/vtk/core/foamVtkCore.C b/src/fileFormats/vtk/core/foamVtkCore.C index 7a61ccb0345..c8b41b924c2 100644 --- a/src/fileFormats/vtk/core/foamVtkCore.C +++ b/src/fileFormats/vtk/core/foamVtkCore.C @@ -27,6 +27,32 @@ License // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +const Foam::Enum +< + Foam::vtk::fileTag +> +Foam::vtk::fileExtension +{ + { fileTag::POLY_DATA, "vtp" }, + { fileTag::UNSTRUCTURED_GRID, "vtu" }, + { fileTag::MULTI_BLOCK, "vtm" }, + // { fileTag::COLLECTION, "pvd" }, +}; + + +const Foam::Enum +< + Foam::vtk::fileTag +> +Foam::vtk::fileContentVersions +{ + { fileTag::POLY_DATA, "0.1" }, + { fileTag::UNSTRUCTURED_GRID, "0.1" }, + { fileTag::MULTI_BLOCK, "1.0" }, + // { fileTag::COLLECTION, "0.1" }, +}; + + const Foam::Enum < Foam::vtk::fileTag @@ -35,6 +61,7 @@ Foam::vtk::fileTagNames ({ { fileTag::VTK_FILE, "VTKFile" }, { fileTag::DATA_ARRAY, "DataArray" }, + { fileTag::BLOCK, "Block" }, { fileTag::PIECE, "Piece" }, { fileTag::DATA_SET, "DataSet" }, { fileTag::POINTS, "Points" }, @@ -44,9 +71,11 @@ Foam::vtk::fileTagNames { fileTag::LINES, "Lines" }, { fileTag::CELL_DATA, "CellData" }, { fileTag::POINT_DATA, "PointData" }, + { fileTag::FIELD_DATA, "FieldData" }, { fileTag::POLY_DATA, "PolyData" }, { fileTag::UNSTRUCTURED_GRID, "UnstructuredGrid" }, { fileTag::MULTI_BLOCK, "vtkMultiBlockDataSet" }, + // { fileTag::COLLECTION, "Collection" }, }); @@ -58,6 +87,7 @@ Foam::vtk::fileAttrNames ({ { fileAttr::OFFSET, "offset" }, { fileAttr::NUMBER_OF_COMPONENTS, "NumberOfComponents" }, + { fileAttr::NUMBER_OF_TUPLES, "NumberOfTuples" }, { fileAttr::NUMBER_OF_POINTS, "NumberOfPoints" }, { fileAttr::NUMBER_OF_CELLS, "NumberOfCells" }, { fileAttr::NUMBER_OF_POLYS, "NumberOfPolys" }, @@ -81,4 +111,30 @@ Foam::vtk::dataArrayAttrNames }); +// Legacy + +const Foam::word Foam::vtk::legacy::fileExtension("vtk"); + +const Foam::Enum +< + Foam::vtk::fileTag +> +Foam::vtk::legacy::contentNames +({ + { vtk::fileTag::POLY_DATA, "POLYDATA" }, + { vtk::fileTag::UNSTRUCTURED_GRID, "UNSTRUCTURED_GRID" }, +}); + + +const Foam::Enum +< + Foam::vtk::fileTag +> +Foam::vtk::legacy::dataTypeNames +({ + { vtk::fileTag::CELL_DATA, "CELL_DATA" }, + { vtk::fileTag::POINT_DATA, "POINT_DATA" }, +}); + + // ************************************************************************* // diff --git a/src/fileFormats/vtk/core/foamVtkCore.H b/src/fileFormats/vtk/core/foamVtkCore.H index 8584c9672ce..88620ebc5c3 100644 --- a/src/fileFormats/vtk/core/foamVtkCore.H +++ b/src/fileFormats/vtk/core/foamVtkCore.H @@ -35,6 +35,7 @@ SourceFiles #ifndef foamVtkCore_H #define foamVtkCore_H +#include <cstdint> #include "Enum.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -59,22 +60,29 @@ namespace vtk //- The output format type for file contents. // Upper bits for output type, lower bits for the format itself. - enum class formatType + enum class formatType : uint8_t { - /** XML inline ASCII, using the asciiFormatter */ - INLINE_ASCII = 0, - /** XML inline base64, using the base64Formatter */ - INLINE_BASE64 = 0x01, - /** XML append base64, using the appendBase64Formatter */ - APPEND_BASE64 = 0x11, - /** XML append raw binary, using the appendRawFormatter */ - APPEND_BINARY = 0x12, - /** Legacy ASCII, using the legacyAsciiFormatter */ - LEGACY_ASCII = 0x20, - /** Legacy raw binary, using the legacyRawFormatter */ - LEGACY_BINARY = 0x22, + INLINE_ASCII = 0, //!< XML inline ASCII, asciiFormatter + INLINE_BASE64 = 0x01, //!< XML inline base64, base64Formatter + APPEND_BASE64 = 0x11, //!< XML append base64, appendBase64Formatter + APPEND_BINARY = 0x12, //!< XML append raw binary, appendRawFormatter + LEGACY_ASCII = 0x20, //!< Legacy ASCII, legacyAsciiFormatter + LEGACY_BINARY = 0x22, //!< Legacy raw binary, legacyRawFormatter }; + //- Test for XML append format + inline bool isAppend(enum formatType fmt) + { + return (uint8_t(fmt) & 0x10); + } + + //- Test for vtk legacy format + inline bool isLegacy(enum formatType fmt) + { + return (uint8_t(fmt) & 0x20); + } + + //- Equivalent to enumeration in "vtkCellType.h" enum cellType { @@ -104,6 +112,7 @@ namespace vtk { VTK_FILE, //!< "VTKFile" DATA_ARRAY, //!< "DataArray" + BLOCK, //!< "Block" PIECE, //!< "Piece" DATA_SET, //!< "DataSet" POINTS, //!< "Points" @@ -113,12 +122,19 @@ namespace vtk LINES, //!< "Lines" CELL_DATA, //!< "CellData" POINT_DATA, //!< "PointData" + FIELD_DATA, //!< "FieldData" POLY_DATA, //!< "PolyData" UNSTRUCTURED_GRID, //!< "UnstructuredGrid" MULTI_BLOCK, //!< "vtkMultiBlockDataSet" }; - //- Strings corresponding to the vtk xml tags + //- File extension (without ".") for some vtk XML file content types + extern const Foam::Enum<fileTag> fileExtension; + + //- Version string for some vtk XML file content types + extern const Foam::Enum<fileTag> fileContentVersions; + + //- Strings corresponding to the vtk XML tags extern const Foam::Enum<fileTag> fileTagNames; //- Some common XML attributes for vtk files @@ -126,6 +142,7 @@ namespace vtk { OFFSET, //!< "offset" NUMBER_OF_COMPONENTS, //!< "NumberOfComponents" + NUMBER_OF_TUPLES, //!< "NumberOfTuples" NUMBER_OF_POINTS, //!< "NumberOfPoints" NUMBER_OF_CELLS, //!< "NumberOfCells" NUMBER_OF_POLYS, //!< "NumberOfPolys" @@ -133,10 +150,10 @@ namespace vtk NUMBER_OF_LINES, //!< "NumberOfLines" }; - //- Strings corresponding to the vtk xml attributes + //- Strings corresponding to the vtk XML attributes extern const Foam::Enum<fileAttr> fileAttrNames; - //- Some common names for XML data arrays + //- Some common names for XML DataArray entries enum class dataArrayAttr { POINTS, //!< "Points" @@ -147,10 +164,29 @@ namespace vtk FACEOFFSETS, //!< "faceoffsets" }; - //- Strings corresponding to the vtk xml attributes + //- Strings corresponding to the vtk XML DataArray attributes extern const Foam::Enum<dataArrayAttr> dataArrayAttrNames; +/*---------------------------------------------------------------------------*\ + Namespace legacy +\*---------------------------------------------------------------------------*/ + +namespace legacy +{ + + //- Legacy file extension ("vtk") + extern const word fileExtension; + + //- 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; + +} // End namespace legacy + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace vtk diff --git a/src/fileFormats/vtk/core/foamVtkPTraits.C b/src/fileFormats/vtk/core/foamVtkPTraits.C index 0cc5ca04e49..7a542257c8b 100644 --- a/src/fileFormats/vtk/core/foamVtkPTraits.C +++ b/src/fileFormats/vtk/core/foamVtkPTraits.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -66,5 +66,9 @@ const char* const Foam::vtkPTraits<Foam::endian>::typeName = "BigEndian"; #endif +template<> +const char* const +Foam::vtkPTraits<std::string>::typeName = "String"; + // ************************************************************************* // diff --git a/src/fileFormats/vtk/core/foamVtkPTraits.H b/src/fileFormats/vtk/core/foamVtkPTraits.H index ac8df066465..b40375f1fb2 100644 --- a/src/fileFormats/vtk/core/foamVtkPTraits.H +++ b/src/fileFormats/vtk/core/foamVtkPTraits.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -33,6 +33,7 @@ Description #define foamVtkPTraits_H #include <cstdint> +#include <string> // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -47,13 +48,10 @@ class endian; \*---------------------------------------------------------------------------*/ template<class PrimitiveType> -class vtkPTraits +struct vtkPTraits { -public: - // Static data members - - static const char* const typeName; + static const char* const typeName; }; @@ -81,6 +79,9 @@ const char* const vtkPTraits<double>::typeName; // Float64 template<> const char* const vtkPTraits<Foam::endian>::typeName; // (Big|Little)Endian +template<> +const char* const vtkPTraits<std::string>::typeName; // String + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.C b/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.C index 5527e5c35ae..334241b2f18 100644 --- a/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.C +++ b/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -41,7 +41,8 @@ Foam::vtk::appendBase64Formatter::appendBase64Formatter std::ostream& os ) : - foamVtkBase64Layer(os) + foamVtkBase64Layer(os), + offset_(0) {} @@ -68,4 +69,16 @@ const char* Foam::vtk::appendBase64Formatter::name() const } +uint64_t Foam::vtk::appendBase64Formatter::offset(const uint64_t numbytes) +{ + uint64_t prev = offset_; + + if (formatter::npos != numbytes) + { + offset_ += this->encodedLength(sizeof(uint64_t) + numbytes); + } + return prev; +} + + // ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.H b/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.H index 2384289f679..6f3814a22ac 100644 --- a/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.H +++ b/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -46,7 +46,7 @@ namespace vtk { /*---------------------------------------------------------------------------*\ - Class appendBase64Formatter Declaration + Class vtk::appendBase64Formatter Declaration \*---------------------------------------------------------------------------*/ class appendBase64Formatter @@ -58,6 +58,9 @@ class appendBase64Formatter static const char* name_; static const outputOptions opts_; + //- The current offset for append data. + uint64_t offset_; + // Private Member Functions @@ -88,6 +91,12 @@ public: //- Output name for XML type ("append") virtual const char* name() const; + //- Increase the append data offset by numbytes and sizeof(uint64_t). + // The additional (uint64_t) size information is consistent with + // writeSize(). + // + // \return The previous data offset + virtual uint64_t offset(const uint64_t numbytes); }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.C b/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.C index f8b7bcf29fd..c7e2783c5e6 100644 --- a/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.C +++ b/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.C @@ -52,7 +52,8 @@ void Foam::vtk::appendRawFormatter::write Foam::vtk::appendRawFormatter::appendRawFormatter(std::ostream& os) : - formatter(os) + formatter(os), + offset_(0) {} @@ -77,9 +78,22 @@ const char* Foam::vtk::appendRawFormatter::encoding() const } -void Foam::vtk::appendRawFormatter::writeSize(const uint64_t nBytes) +uint64_t Foam::vtk::appendRawFormatter::offset(const uint64_t numbytes) { - write(reinterpret_cast<const char*>(&nBytes), sizeof(uint64_t)); + uint64_t prev = offset_; + + if (formatter::npos != numbytes) + { + offset_ += this->encodedLength(sizeof(uint64_t) + numbytes); + } + return prev; +} + + +bool Foam::vtk::appendRawFormatter::writeSize(const uint64_t numbytes) +{ + write(reinterpret_cast<const char*>(&numbytes), sizeof(uint64_t)); + return true; } diff --git a/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.H b/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.H index dbbcf0788ae..fc05f9249c4 100644 --- a/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.H +++ b/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -45,7 +45,7 @@ namespace vtk { /*---------------------------------------------------------------------------*\ - Class appendRawFormatter Declaration + Class vtk::appendRawFormatter Declaration \*---------------------------------------------------------------------------*/ class appendRawFormatter @@ -58,6 +58,9 @@ class appendRawFormatter static const char* encoding_; static const outputOptions opts_; + //- The current offset for append data. + uint64_t offset_; + // Private Member Functions @@ -99,9 +102,16 @@ public: //- Output name for append encoding type ("raw") virtual const char* encoding() const; + //- Increase the append data offset by numbytes and sizeof(uint64_t). + // The additional (uint64_t) size information is consistent with + // writeSize() + // + // \return The previous data offset + virtual uint64_t offset(const uint64_t numbytes); //- Write leading size for binary output - virtual void writeSize(const uint64_t nBytes); + // \return True - format uses this information + virtual bool writeSize(const uint64_t numbytes); virtual void write(const uint8_t val); virtual void write(const label val); diff --git a/src/fileFormats/vtk/format/foamVtkAsciiFormatter.C b/src/fileFormats/vtk/format/foamVtkAsciiFormatter.C index d220627ab71..fa549ff24a2 100644 --- a/src/fileFormats/vtk/format/foamVtkAsciiFormatter.C +++ b/src/fileFormats/vtk/format/foamVtkAsciiFormatter.C @@ -113,8 +113,10 @@ const char* Foam::vtk::asciiFormatter::encoding() const } -void Foam::vtk::asciiFormatter::writeSize(const uint64_t ignored) -{/*nop*/} +bool Foam::vtk::asciiFormatter::writeSize(const uint64_t) +{ + return false; +} void Foam::vtk::asciiFormatter::write(const uint8_t val) @@ -163,8 +165,7 @@ void Foam::vtk::asciiFormatter::flush() } -std::size_t -Foam::vtk::asciiFormatter::encodedLength(std::size_t ignored) const +std::size_t Foam::vtk::asciiFormatter::encodedLength(std::size_t) const { return 0; } diff --git a/src/fileFormats/vtk/format/foamVtkAsciiFormatter.H b/src/fileFormats/vtk/format/foamVtkAsciiFormatter.H index b050d6573c3..25d7fc7f380 100644 --- a/src/fileFormats/vtk/format/foamVtkAsciiFormatter.H +++ b/src/fileFormats/vtk/format/foamVtkAsciiFormatter.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -47,7 +47,7 @@ namespace vtk { /*---------------------------------------------------------------------------*\ - Class asciiFormatter Declaration + Class vtk::asciiFormatter Declaration \*---------------------------------------------------------------------------*/ class asciiFormatter @@ -108,7 +108,8 @@ public: //- Write leading size - this is a no-op for ascii output - virtual void writeSize(const uint64_t ignored); + // \return False - never used by this format + virtual bool writeSize(const uint64_t ignored); virtual void write(const uint8_t val); virtual void write(const label val); @@ -119,6 +120,7 @@ public: virtual void flush(); //- The encoded length for ascii output is not applicable. + // \return 0 virtual std::size_t encodedLength(std::size_t ignored) const; }; diff --git a/src/fileFormats/vtk/format/foamVtkBase64Formatter.H b/src/fileFormats/vtk/format/foamVtkBase64Formatter.H index cd733e643e5..9b96c1ac719 100644 --- a/src/fileFormats/vtk/format/foamVtkBase64Formatter.H +++ b/src/fileFormats/vtk/format/foamVtkBase64Formatter.H @@ -44,7 +44,7 @@ namespace vtk { /*---------------------------------------------------------------------------*\ - Class base64Formatter Declaration + Class vtk::base64Formatter Declaration \*---------------------------------------------------------------------------*/ class base64Formatter diff --git a/src/fileFormats/vtk/format/foamVtkBase64Layer.C b/src/fileFormats/vtk/format/foamVtkBase64Layer.C index fbdc7ad5257..8cbfbc2c01f 100644 --- a/src/fileFormats/vtk/format/foamVtkBase64Layer.C +++ b/src/fileFormats/vtk/format/foamVtkBase64Layer.C @@ -68,9 +68,10 @@ const char* Foam::vtk::foamVtkBase64Layer::encoding() const } -void Foam::vtk::foamVtkBase64Layer::writeSize(const uint64_t nBytes) +bool Foam::vtk::foamVtkBase64Layer::writeSize(const uint64_t numbytes) { - write(reinterpret_cast<const char*>(&nBytes), sizeof(uint64_t)); + write(reinterpret_cast<const char*>(&numbytes), sizeof(uint64_t)); + return true; } @@ -121,10 +122,7 @@ void Foam::vtk::foamVtkBase64Layer::flush() } -std::size_t Foam::vtk::foamVtkBase64Layer::encodedLength -( - std::size_t n -) const +std::size_t Foam::vtk::foamVtkBase64Layer::encodedLength(std::size_t n) const { return base64Layer::encodedLength(n); } diff --git a/src/fileFormats/vtk/format/foamVtkBase64Layer.H b/src/fileFormats/vtk/format/foamVtkBase64Layer.H index d965c6348dd..3805a57747a 100644 --- a/src/fileFormats/vtk/format/foamVtkBase64Layer.H +++ b/src/fileFormats/vtk/format/foamVtkBase64Layer.H @@ -43,7 +43,7 @@ namespace vtk { /*---------------------------------------------------------------------------*\ - Class foamVtkBase64Layer Declaration + Class vtk::foamVtkBase64Layer Declaration \*---------------------------------------------------------------------------*/ class foamVtkBase64Layer @@ -89,9 +89,9 @@ public: //- Name for the XML append encoding ("base64"). virtual const char* encoding() const; - //- Write leading size for binary output - virtual void writeSize(const uint64_t nBytes); + // \return True - format uses this information + virtual bool writeSize(const uint64_t numbytes); virtual void write(const uint8_t val); virtual void write(const label val); diff --git a/src/fileFormats/vtk/format/foamVtkFormatter.C b/src/fileFormats/vtk/format/foamVtkFormatter.C index 711bcdecd24..c6b2a4e56f7 100644 --- a/src/fileFormats/vtk/format/foamVtkFormatter.C +++ b/src/fileFormats/vtk/format/foamVtkFormatter.C @@ -24,104 +24,103 @@ License #include "foamVtkFormatter.H" -// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // - -std::size_t Foam::vtk::formatter::encodedLength(std::size_t n) const -{ - return n; -} +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // - -void Foam::vtk::formatter::indent() +bool Foam::vtk::formatter::canWriteAttr(const word& k) const { - label n = xmlTags_.size() * 2; - while (n--) + if (!inTag_) { - os_ << ' '; + WarningInFunction + << "xml attribute '" << k << "' but not inside a tag!" << endl; } + + return inTag_; } -Foam::vtk::formatter& -Foam::vtk::formatter::xmlHeader() +bool Foam::vtk::formatter::canWriteToplevel(const char* what) const { if (inTag_) { WarningInFunction - << "xml header, but already within a tag!" + << "Cannot add " << what << " inside a tag!" << endl; } - os_ << "<?xml version='1.0'?>" << nl; + return !inTag_; +} - return *this; + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void Foam::vtk::formatter::quoting(const quoteChar quote) +{ + quote_ = quote; } -Foam::vtk::formatter& -Foam::vtk::formatter::xmlComment(const std::string& comment) +uint64_t Foam::vtk::formatter::offset(const uint64_t) { - if (inTag_) - { - WarningInFunction - << "adding xml comment inside a tag??" - << endl; - } + return formatter::npos; +} - indent(); - os_ << "<!-- " << comment << " -->" << nl; - return *this; +std::size_t Foam::vtk::formatter::encodedLength(std::size_t n) const +{ + return n; } -Foam::vtk::formatter& -Foam::vtk::formatter::openTag(const word& tagName) +bool Foam::vtk::formatter::openTagImpl(const word& tagName) { if (inTag_) { WarningInFunction - << "open XML tag '" << tagName - << "', but already within a tag!" + << "open xml tag '" << tagName << "', but already within a tag!" << endl; + + return false; } + // Emit, before changing the stack or the state. indent(); os_ << '<' << tagName; + // Add to the stack and change the state. xmlTags_.append(tagName); inTag_ = true; - return *this; + return true; } -Foam::vtk::formatter& -Foam::vtk::formatter::closeTag(const bool isEmpty) +Foam::vtk::formatter& Foam::vtk::formatter::closeTag(const bool isEmpty) { if (!inTag_) { WarningInFunction - << "close XML tag, but not within a tag!" + << "attempt to close xml tag, but not within a tag!" << endl; } - - if (isEmpty) + else { - // eg, <tag ... /> - xmlTags_.remove(); - os_ << " /"; + // Change the state + inTag_ = false; + + if (isEmpty) + { + // Eg, <tag ... /> + xmlTags_.remove(); + os_ << " /"; + } + os_ << '>' << nl; } - os_ << '>' << nl; - - inTag_ = false; return *this; } -Foam::vtk::formatter& -Foam::vtk::formatter::endTag(const word& tagName) +Foam::vtk::formatter& Foam::vtk::formatter::endTag(const word& tagName) { const word curr(xmlTags_.remove()); indent(); @@ -129,16 +128,18 @@ Foam::vtk::formatter::endTag(const word& tagName) if (inTag_) { WarningInFunction - << "adding XML endTag '" << curr + << "adding xml endTag '" << curr << "' but already in another tag!" << endl; + + // Also suppress further output, or not? } - // verify expected end tag + // Verify expected end tag if (!tagName.empty() && tagName != curr) { WarningInFunction - << "expecting to end xml-tag '" << tagName + << "expecting to end xml tag '" << tagName << "' but found '" << curr << "' instead" << endl; } @@ -151,8 +152,7 @@ Foam::vtk::formatter::endTag(const word& tagName) } -Foam::vtk::formatter& -Foam::vtk::formatter::beginVTKFile +Foam::vtk::formatter& Foam::vtk::formatter::beginVTKFile ( const word& contentType, const word& contentVersion, @@ -176,15 +176,7 @@ Foam::vtk::formatter::beginVTKFile } -Foam::vtk::formatter& -Foam::vtk::formatter::endVTKFile() -{ - return endTag(vtk::fileTag::VTK_FILE); -} - - -Foam::vtk::formatter& -Foam::vtk::formatter::beginAppendedData() +Foam::vtk::formatter& Foam::vtk::formatter::beginAppendedData() { openTag("AppendedData"); xmlAttr("encoding", encoding()); @@ -195,31 +187,124 @@ Foam::vtk::formatter::beginAppendedData() } -Foam::vtk::formatter& -Foam::vtk::formatter::endAppendedData() +Foam::vtk::formatter& Foam::vtk::formatter::endAppendedData() { - flush(); // flush any pending encoded content - os_ << nl; // ensure clear separation from content. + flush(); // Flush any pending encoded content + os_ << nl; // Ensure clear separation from content return endTag("AppendedData"); } -Foam::vtk::formatter& -Foam::vtk::formatter::xmlAttr +Foam::vtk::formatter& Foam::vtk::formatter::beginBlock ( - const word& k, - const std::string& v, - const char quote + label index, + std::string name ) { - if (!inTag_) + openTag(vtk::fileTag::BLOCK); + if (index >= 0) { - WarningInFunction - << "xml attribute '" << k << "' but not within a tag!" - << endl; + xmlAttr("index", index); + } + if (name.size()) + { + xmlAttr("name", name); } + closeTag(); + + return *this; +} + + +Foam::vtk::formatter& Foam::vtk::formatter::beginPiece +( + label index, + std::string name +) +{ + openTag(vtk::fileTag::PIECE); + if (index >= 0) + { + xmlAttr("index", index); + } + if (name.size()) + { + xmlAttr("name", name); + } + closeTag(); + + return *this; +} + + +Foam::vtk::formatter& Foam::vtk::formatter::DataSet +( + label index, + std::string file, + bool autoName +) +{ + openTag(vtk::fileTag::DATA_SET); + + if (index >= 0) + { + xmlAttr("index", index); + } + if (file.size()) + { + if (autoName) + { + xmlAttr("name", fileName::nameLessExt(file)); + } + xmlAttr("file", file); + } + closeTag(true); // Empty tag. ie, <DataSet ... /> + + return *this; +} + + +Foam::vtk::formatter& Foam::vtk::formatter::DataSet +( + label index, + std::string file, + std::string name +) +{ + openTag(vtk::fileTag::DATA_SET); + + if (index >= 0) + { + xmlAttr("index", index); + } + if (name.size()) + { + xmlAttr("name", name); + } + if (file.size()) + { + xmlAttr("file", file); + } + closeTag(true); // Empty tag. ie, <DataSet ... /> + + return *this; +} + + +Foam::vtk::formatter& Foam::vtk::formatter::writeTimeValue(scalar timeValue) +{ + // Emit "TimeValue" as FieldData + // NumberOfTuples="1" (required!) + + uint64_t payLoad = vtk::sizeofData<float>(1); + + beginDataArray<float,1,1>("TimeValue"); + writeSize(payLoad); + + write(timeValue); + flush(); - os_ << ' ' << k << '=' << quote << v.c_str() << quote; + endDataArray(); return *this; } diff --git a/src/fileFormats/vtk/format/foamVtkFormatter.H b/src/fileFormats/vtk/format/foamVtkFormatter.H index c3e9c916386..ef423c10cc2 100644 --- a/src/fileFormats/vtk/format/foamVtkFormatter.H +++ b/src/fileFormats/vtk/format/foamVtkFormatter.H @@ -27,7 +27,8 @@ Class Description Abstract class for a VTK output stream formatter. - Includes very simple support for writing XML elements. + Includes simple support for writing XML elements. + By default uses single-quoting for XML attributes. SourceFiles foamVtkFormatter.C @@ -39,8 +40,9 @@ SourceFiles #define foamVtkFormatter_H #include "int.H" -#include "uint64.H" #include "label.H" +#include "uint64.H" +#include "direction.H" #include "word.H" #include "UList.H" #include "DynamicList.H" @@ -59,11 +61,23 @@ namespace vtk class outputOptions; /*---------------------------------------------------------------------------*\ - Class formatter Declaration + Class vtk::formatter Declaration \*---------------------------------------------------------------------------*/ class formatter { +public: + + //- Quoting for XML attributes + enum quoteChar : char + { + DOUBLE_QUOTE = '\"', //!< Double-quote XML attributes + SINGLE_QUOTE = '\'', //!< Single-quote XML attributes + }; + + +protected: + // Private Data //- The output stream for the formatter @@ -75,33 +89,60 @@ class formatter //- Tag open/closed/ended state mutable bool inTag_; + //- Quoting character for XML attributes + char quote_; + - // Private Member Functions +protected: + + // Protected Member Functions - //- Write XML attribute key/value pair + //- Can write XML key/value attribute pair when inside a tag. + //- Emit warning and return false if this condition is not met. + bool canWriteAttr(const word& k) const; + + //- Can write tag-like top-level content (eg, comment, ...) + //- when not already inside a tag. + //- Emit warning and return false if this condition is not met. + bool canWriteToplevel(const char* what) const; + + //- Write XML key/value attribute pair (implementation). template<class Type> - formatter& writeAttribute - ( - const word& k, - const Type& v, - const char quote = '\'' - ); + inline void writeAttr(const word& k, const Type& v); + //- No-op write XML attribute (for templating code). + // \return formatter for chaining + inline formatter& xmlAttr(); -protected: + //- No-op XML comment loop (for templating code). + inline void xmlCommentLoop(); - // Protected Member Functions + //- Loop/output XML comments + template<class... Args> + inline void xmlCommentLoop(const std::string& text, Args&&... args); + + //- Open XML tag (implementation), checking if not already inside + //- another tag. + //- Emit warning and return false if this condition is not met. + bool openTagImpl(const word& tagName); + + + // Constructors //- Construct and attach to an output stream inline formatter(std::ostream& os); + public: // Public typedefs - //- Use UInt64 for header data + //- The header data is vtk UInt64 typedef uint64_t headerType; + //- Out of range position or size. + static constexpr uint64_t npos = uint64_t(-1); + //- Destructor virtual ~formatter() = default; @@ -123,9 +164,23 @@ public: //- Name for the XML append encoding virtual const char* encoding() const = 0; + //- Change quoting char for XML attributes (default: SINGLE_QUOTE) + void quoting(const quoteChar quote); + + //- Increase the append data offset by numbytes and sizeof(uint64_t). + // The additional (uint64_t) size information is consistent with + // writeSize() + // + // \return The previous data offset or formatter::npos for formats + // that do not support appending data. + virtual uint64_t offset(const uint64_t numbytes); + + //- The encoded length for binary output is pass-through. + virtual std::size_t encodedLength(std::size_t n) const; //- Write leading size for binary output - virtual void writeSize(const uint64_t nBytes) = 0; + // \return True if used by the formatter. + virtual bool writeSize(const uint64_t numbytes) = 0; virtual void write(const uint8_t val) = 0; virtual void write(const label val) = 0; @@ -135,61 +190,65 @@ public: //- Flush encoding, write newline etc. virtual void flush() = 0; - //- The encoded length for binary output. - // The default is pass-through. - virtual std::size_t encodedLength(std::size_t n) const; - - // Member Functions + // General Output - // Output + //- Add indenting according to the current XML tag depth + // Two spaces per depth. + inline void indent(); - //- Indent according to the currently nested XML tags - void indent(); + //- Add indenting of n spaces. + inline void indent(label n); //- Write XML header // \return formatter for chaining - formatter& xmlHeader(); + inline formatter& xmlHeader(); //- Write XML comment (at the current indentation level) // \return formatter for chaining - formatter& xmlComment(const std::string& comment); + template<class... Args> + inline formatter& xmlComment(const std::string& text, Args&&... args); - //- Open XML tag + //- Start an XML tag, optionally with attributes // \return formatter for chaining - formatter& openTag(const word& tagName); + template<class... Args> + inline formatter& openTag(const word& tagName, Args&&... args); - //- Open XML tag + //- Start an XML tag, optionally with attributes // \return formatter for chaining - inline formatter& openTag(const vtk::fileTag& tagEnum); + template<class... Args> + inline formatter& openTag(vtk::fileTag t, Args&&... args); - //- Close XML tag, optional as an empty container. + //- Finish an XML tag, optional as an empty container. // Always adds a trailing newline. // \return formatter for chaining formatter& closeTag(const bool isEmpty = false); - //- End XML tag, optional with sanity check + //- An end XML tag, optional with sanity check // Always adds a trailing newline. // \return formatter for chaining formatter& endTag(const word& tagName = word::null); - //- End XML tag with sanity check + //- An end XML tag with sanity check // Always adds a trailing newline. // \return formatter for chaining - inline formatter& endTag(const vtk::fileTag& tagEnum); + inline virtual formatter& endTag(vtk::fileTag t); //- Write XML tag without any attributes. Combines openTag/closeTag. // \return formatter for chaining - inline formatter& tag(const word& tagName); + template<class... Args> + inline formatter& tag(const word& t, Args&&... args); //- Write XML tag without any attributes. Combines openTag/closeTag. // \return formatter for chaining - inline formatter& tag(const vtk::fileTag& tagEnum); + template<class... Args> + inline formatter& tag(vtk::fileTag t, Args&&... args); + //- Add a "VTKFile" XML tag for contentType, followed by a tag for - // the contentType itself. Optionally leave the contentType tag - // open for adding additional attributes. + //- the contentType itself. + // \param leaveOpen Leave tag open for additional attributes. // \return formatter for chaining formatter& beginVTKFile ( @@ -199,127 +258,300 @@ public: ); //- Add a "VTKFile" XML tag for contentType, followed by a tag for - // the contentType itself. Optionally leave the contentType tag - // open for adding additional attributes. + //- the contentType itself. + // \param leaveOpen Leave tag open for additional attributes. // \return formatter for chaining inline formatter& beginVTKFile ( - const vtk::fileTag& contentType, + vtk::fileTag contentType, const word& contentVersion, const bool leaveOpen = false ); + //- Add a "VTKFile" XML tag for contentType, followed by a tag for + //- the contentType itself. + // \param leaveOpen Leave tag open for additional attributes. + // \return formatter for chaining + inline formatter& beginVTKFile + ( + vtk::fileTag contentType, + const bool leaveOpen = false + ); + + //- Add a "VTKFile" XML tag for contentType, followed by a tag for + //- the contentType itself. + // \param leaveOpen Leave tag open for additional attributes. + // \return formatter for chaining + template<vtk::fileTag ContentType> + inline formatter& beginVTKFile(bool leaveOpen = false); + //- Add a "AppendedData" XML tag with the current encoding and output - // the requisite '_' prefix. + //- the requisite '_' prefix. // \return formatter for chaining formatter& beginAppendedData(); + //- Begin "Block" XML section. + // \param index The index of the block + // \param name The name of the block (ignored if empty) + // \return formatter for chaining + formatter& beginBlock(label index, std::string name = ""); + + //- End "Block" XML section. + // \return formatter for chaining + inline formatter& endBlock(); + + //- Begin "Piece" XML section. + // \param index The index of the piece + // \param name The name of the piece (ignored if empty) + // \return formatter for chaining + formatter& beginPiece(label index, std::string name = ""); + + //- End "Piece" XML section. + // \return formatter for chaining + inline virtual formatter& endPiece(); - //- Open "DataArray" XML tag + //- Insert a single "DataSet" XML entry tag. + // \param index The index of the DataSet + // \param file The file name for the data (ignored if empty) + // \param autoName The name for the data extracted from the file name + // (without extension) // \return formatter for chaining - template<class Type, int nComp=0> - formatter& openDataArray(const word& dataName); + formatter& DataSet + ( + label index, + std::string file = "", + bool autoName = true + ); - //- Open "DataArray" XML tag + //- Insert a single "DataSet" XML entry tag. + // \param index The index of the DataSet + // \param file The file name for the data (ignored if empty) + // \param name The name for the dataset // \return formatter for chaining - template<class Type, int nComp=0> - formatter& openDataArray(const vtk::dataArrayAttr& attrEnum); + formatter& DataSet + ( + label index, + std::string file, + std::string name + ); + //- Begin "DataArray" XML section. + // + // \param dataName The name of the DataArray + // \param payLoad Additional payLoad information to increment + // the offset for an append formatter and add the "offset" + // attribute accordingly. + // \param leaveOpen Leave tag open for additional attributes. + // + // \return formatter for chaining + template<class Type, direction nComp=1, int nTuple=0> + formatter& beginDataArray + ( + const word& dataName, + uint64_t payLoad = npos, + bool leaveOpen = false + ); + + //- Begin "DataArray" XML section. + // + // \param dataName The name of the DataArray as an enumeration + // \param payLoad Additional payLoad information to increment + // the offset for an append formatter and add the "offset" + // attribute accordingly. + // \param leaveOpen Leave tag open for additional attributes. + // + // \return formatter for chaining + template<class Type, direction nComp=1, int nTuple=0> + inline formatter& beginDataArray + ( + const vtk::dataArrayAttr& dataName, + uint64_t payLoad = npos, + bool leaveOpen = false + ); + + //- End "DataArray" XML section + // \return formatter for chaining + inline virtual formatter& endDataArray(); //- Insert a single "PDataArray" XML entry tag. // For some entries, the name is optional. // \return formatter for chaining - template<class Type, int nComp=0> + template<class Type, direction nComp=1, int nTuple=0> formatter& PDataArray(const word& dataName); - //- End "DataArray" XML tag - // \return formatter for chaining - inline formatter& endDataArray(); + //- Begin "FieldData" XML section. + inline formatter& beginFieldData(); + + //- Begin "CellData" XML section. + inline formatter& beginCellData(); + + //- Begin "PointData" XML section. + inline formatter& beginPointData(); + + //- End "FieldData" XML section. + inline virtual formatter& endFieldData(); + + //- End "CellData" XML section. + inline virtual formatter& endCellData(); + + //- End "PointData" XML section. + inline virtual formatter& endPointData(); + - //- End "AppendedData" XML tag + //- End "AppendedData" XML section // \return formatter for chaining formatter& endAppendedData(); - //- End "VTKFile" XML tag + //- End "VTKFile" XML section. // \return formatter for chaining - formatter& endVTKFile(); + inline virtual formatter& endVTKFile(); - //- Write XML attribute + //- Emit "TimeValue" for FieldData (name as per Catalyst output) + formatter& writeTimeValue(scalar timeValue); + + + // XML Attributes + + //- Pair-wise write of XML key/value attributes // \return formatter for chaining - formatter& xmlAttr + template<class... Args> + inline formatter& xmlAttr ( const word& k, const std::string& v, - const char quote = '\'' + Args&&... args ); - //- Write XML attribute + //- Pair-wise write of XML key/value attributes // \return formatter for chaining + template<class... Args> inline formatter& xmlAttr ( const word& k, const int32_t v, - const char quote = '\'' + Args&&... args ); - //- Write XML attribute + //- Pair-wise write of XML key/value attributes // \return formatter for chaining + template<class... Args> inline formatter& xmlAttr ( const word& k, const int64_t v, - const char quote = '\'' + Args&&... args ); - //- Write XML attribute + //- Pair-wise write of XML key/value attributes // \return formatter for chaining + template<class... Args> inline formatter& xmlAttr ( const word& k, const uint64_t v, - const char quote = '\'' + Args&&... args ); - //- Write XML attribute + //- Pair-wise write of XML key/value attributes // \return formatter for chaining + template<class... Args> inline formatter& xmlAttr ( const word& k, const scalar v, - const char quote = '\'' + Args&&... args + ); + + //- Pair-wise write of XML key/value attributes + // \return formatter for chaining + template<class... Args> + inline formatter& xmlAttr + ( + const vtk::fileAttr& k, + const std::string& v, + Args&&... args ); - //- Write XML attribute + //- Pair-wise write of XML key/value attributes // \return formatter for chaining + template<class... Args> inline formatter& xmlAttr ( - const vtk::fileAttr& attrEnum, + const vtk::fileAttr& k, const int32_t v, - const char quote = '\'' + Args&&... args ); - //- Write XML attribute + //- Pair-wise write of XML key/value attributes // \return formatter for chaining + template<class... Args> inline formatter& xmlAttr ( - const vtk::fileAttr& attrEnum, + const vtk::fileAttr& k, const int64_t v, - const char quote = '\'' + Args&&... args ); - //- Write XML attribute + //- Pair-wise write of XML key/value attributes // \return formatter for chaining + template<class... Args> inline formatter& xmlAttr ( - const vtk::fileAttr& attrEnum, + const vtk::fileAttr& k, const uint64_t v, - const char quote = '\'' + Args&&... args ); + + //- Pair-wise write of XML key/value attributes + // \return formatter for chaining + template<class... Args> + inline formatter& xmlAttr + ( + const vtk::fileAttr& k, + const scalar v, + Args&&... args + ); + + + // Housekeeping + + //- Open "DataArray" XML tag and leave open (requires a closeTag). + // \deprecated Use beginDataArray instead (SEPT-2018) + template<class Type, direction nComp=1, int nTuple=0> + formatter& openDataArray(const word& dataName) + { + return beginDataArray<Type, nComp, nTuple> + ( + dataName, formatter::npos, true + ); + } + + //- Open "DataArray" XML tag and leave open (requires a closeTag). + // \deprecated Use beginDataArray instead (SEPT-2018) + template<class Type, direction nComp=1, int nTuple=0> + formatter& openDataArray(const vtk::dataArrayAttr& dataName) + { + return beginDataArray<Type, nComp, nTuple> + ( + dataName, formatter::npos, true + ); + } + }; +// Global Functions + +//- Commonly used calculation for header and payload sizes +template<class Type, direction nComp=1> +inline uint64_t sizeofData(label count) +{ + return (count * nComp * sizeof(Type)); +} + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace vtk diff --git a/src/fileFormats/vtk/format/foamVtkFormatterI.H b/src/fileFormats/vtk/format/foamVtkFormatterI.H index 58e050bf542..bf3204c388a 100644 --- a/src/fileFormats/vtk/format/foamVtkFormatterI.H +++ b/src/fileFormats/vtk/format/foamVtkFormatterI.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -23,13 +23,43 @@ License \*---------------------------------------------------------------------------*/ +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlAttr() +{ + return *this; +} + + +inline void Foam::vtk::formatter::xmlCommentLoop() +{} + + +template<class... Args> +inline void Foam::vtk::formatter::xmlCommentLoop +( + const std::string& text, + Args&&... args +) +{ + if (text.length()) + { + indent(); indent(4); + os_ << text << nl; + } + + xmlCommentLoop(std::forward<Args>(args)...); +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // inline Foam::vtk::formatter::formatter(std::ostream& os) : os_(os), xmlTags_(), - inTag_(false) + inTag_(false), + quote_(SINGLE_QUOTE) {} @@ -41,43 +71,124 @@ inline std::ostream& Foam::vtk::formatter::os() } -inline Foam::vtk::formatter& -Foam::vtk::formatter::openTag(const vtk::fileTag& tagEnum) +inline void Foam::vtk::formatter::indent() { - return openTag(vtk::fileTagNames[tagEnum]); + indent(2*xmlTags_.size()); } -inline Foam::vtk::formatter& -Foam::vtk::formatter::endTag(const vtk::fileTag& tagEnum) +inline void Foam::vtk::formatter::indent(label n) { - return endTag(vtk::fileTagNames[tagEnum]); + while (n-- > 0) + { + os_ << ' '; + } } -inline Foam::vtk::formatter& -Foam::vtk::formatter::tag(const word& tagName) +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlHeader() { - openTag(tagName); + if (canWriteToplevel("xml header")) + { + os_ << "<?xml version='1.0'?>" << nl; + } + + return *this; +} + + +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlComment +( + const std::string& text, + Args&&... args +) +{ + if (canWriteToplevel("xml comment")) + { + indent(); + os_ << "<!--"; + + if (sizeof...(Args)) + { + os_ << nl; + + xmlCommentLoop(text, std::forward<Args>(args)...); + + indent(); indent(2); + } + else + { + os_ << ' ' << text << ' '; + } + + os_ << "-->" << nl; + } + + return *this; +} + + +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::openTag +( + const word& tagName, + Args&&... args +) +{ + if (openTagImpl(tagName)) + { + xmlAttr(std::forward<Args>(args)...); + } + + return *this; +} + + +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::openTag +( + vtk::fileTag t, + Args&&... args +) +{ + return openTag(vtk::fileTagNames[t], std::forward<Args>(args)...); +} + + +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::tag +( + const word& t, + Args&&... args +) +{ + openTagImpl(t); + xmlAttr(std::forward<Args>(args)...); closeTag(); return *this; } -inline Foam::vtk::formatter& -Foam::vtk::formatter::tag(const vtk::fileTag& tagEnum) +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::tag +( + vtk::fileTag t, + Args&&... args +) { - return tag(vtk::fileTagNames[tagEnum]); + return tag(vtk::fileTagNames[t], std::forward<Args>(args)...); } -inline Foam::vtk::formatter& -Foam::vtk::formatter::beginVTKFile +// Begin tags + +inline Foam::vtk::formatter& Foam::vtk::formatter::beginVTKFile ( - const vtk::fileTag& contentType, + vtk::fileTag contentType, const word& contentVersion, - const bool leaveOpen + bool leaveOpen ) { return beginVTKFile @@ -89,94 +200,275 @@ Foam::vtk::formatter::beginVTKFile } -inline Foam::vtk::formatter& -Foam::vtk::formatter::endDataArray() +inline Foam::vtk::formatter& Foam::vtk::formatter::beginVTKFile +( + vtk::fileTag contentType, + bool leaveOpen +) +{ + return beginVTKFile + ( + vtk::fileTagNames[contentType], + vtk::fileContentVersions[contentType], + leaveOpen + ); +} + + +template<Foam::vtk::fileTag ContentType> +inline Foam::vtk::formatter& Foam::vtk::formatter::beginVTKFile(bool leaveOpen) +{ + return beginVTKFile + ( + vtk::fileTagNames[ContentType], + vtk::fileContentVersions[ContentType], + leaveOpen + ); +} + + +template<class Type, Foam::direction nComp, int nTuple> +inline Foam::vtk::formatter& Foam::vtk::formatter::beginDataArray +( + const vtk::dataArrayAttr& dataName, + uint64_t payLoad, + bool leaveOpen +) +{ + return + beginDataArray<Type, nComp, nTuple> + ( + vtk::dataArrayAttrNames[dataName], + payLoad, + leaveOpen + ); +} + + +inline Foam::vtk::formatter& Foam::vtk::formatter::beginCellData() +{ + return tag(vtk::fileTag::CELL_DATA); +} + + +inline Foam::vtk::formatter& Foam::vtk::formatter::beginPointData() +{ + return tag(vtk::fileTag::POINT_DATA); +} + + +inline Foam::vtk::formatter& Foam::vtk::formatter::beginFieldData() +{ + return tag(vtk::fileTag::FIELD_DATA); +} + + +// End tags + +inline Foam::vtk::formatter& Foam::vtk::formatter::endTag(vtk::fileTag t) +{ + return endTag(vtk::fileTagNames[t]); +} + + +inline Foam::vtk::formatter& Foam::vtk::formatter::endCellData() { - return endTag("DataArray"); + return endTag(vtk::fileTag::CELL_DATA); } -inline Foam::vtk::formatter& -Foam::vtk::formatter::xmlAttr +inline Foam::vtk::formatter& Foam::vtk::formatter::endPointData() +{ + return endTag(vtk::fileTag::POINT_DATA); +} + + +inline Foam::vtk::formatter& Foam::vtk::formatter::endFieldData() +{ + return endTag(vtk::fileTag::FIELD_DATA); +} + + +inline Foam::vtk::formatter& Foam::vtk::formatter::endDataArray() +{ + return endTag(vtk::fileTag::DATA_ARRAY); +} + + +inline Foam::vtk::formatter& Foam::vtk::formatter::endBlock() +{ + return endTag(vtk::fileTag::BLOCK); +} + + +inline Foam::vtk::formatter& Foam::vtk::formatter::endPiece() +{ + return endTag(vtk::fileTag::PIECE); +} + + +inline Foam::vtk::formatter& Foam::vtk::formatter::endVTKFile() +{ + return endTag(vtk::fileTag::VTK_FILE); +} + + +// Attributes + +template<class Type> +inline void Foam::vtk::formatter::writeAttr(const word& k, const Type& v) +{ + os_ << ' ' << k << '=' << quote_ << v << quote_; +} + + +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlAttr +( + const word& k, + const std::string& v, + Args&&... args +) +{ + if (!canWriteAttr(k)) return *this; + + writeAttr(k, v.c_str()); + return xmlAttr(std::forward<Args>(args)...); +} + + +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlAttr ( const word& k, const int32_t v, - const char quote + Args&&... args ) { - return writeAttribute(k, v, quote); + if (!canWriteAttr(k)) return *this; + + writeAttr(k, v); + return xmlAttr(std::forward<Args>(args)...); } -inline Foam::vtk::formatter& -Foam::vtk::formatter::xmlAttr +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlAttr ( const word& k, const int64_t v, - const char quote + Args&&... args ) { - return writeAttribute(k, v, quote); + if (!canWriteAttr(k)) return *this; + + writeAttr(k, v); + return xmlAttr(std::forward<Args>(args)...); } -inline Foam::vtk::formatter& -Foam::vtk::formatter::xmlAttr +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlAttr ( const word& k, const uint64_t v, - const char quote + Args&&... args ) { - return writeAttribute(k, v, quote); + if (!canWriteAttr(k)) return *this; + + writeAttr(k, v); + return xmlAttr(std::forward<Args>(args)...); } -inline Foam::vtk::formatter& -Foam::vtk::formatter::xmlAttr +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlAttr ( const word& k, const scalar v, - const char quote + Args&&... args ) { - return writeAttribute(k, v, quote); + if (!canWriteAttr(k)) return *this; + + writeAttr(k, v); + return xmlAttr(std::forward<Args>(args)...); +} + + +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlAttr +( + const vtk::fileAttr& k, + const std::string& v, + Args&&... args +) +{ + if (!canWriteAttr(vtk::fileAttrNames[k])) return *this; + + writeAttr(vtk::fileAttrNames[k], v.c_str()); + return xmlAttr(std::forward<Args>(args)...); } -inline Foam::vtk::formatter& -Foam::vtk::formatter::xmlAttr +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlAttr ( - const vtk::fileAttr& attrEnum, + const vtk::fileAttr& k, const int32_t v, - const char quote + Args&&... args ) { - return xmlAttr(vtk::fileAttrNames[attrEnum], v, quote); + if (!canWriteAttr(vtk::fileAttrNames[k])) return *this; + + writeAttr(vtk::fileAttrNames[k], v); + return xmlAttr(std::forward<Args>(args)...); } -inline Foam::vtk::formatter& -Foam::vtk::formatter::xmlAttr +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlAttr ( - const vtk::fileAttr& attrEnum, + const vtk::fileAttr& k, const int64_t v, - const char quote + Args&&... args ) { - return xmlAttr(vtk::fileAttrNames[attrEnum], v, quote); + if (!canWriteAttr(vtk::fileAttrNames[k])) return *this; + + writeAttr(vtk::fileAttrNames[k], v); + return xmlAttr(std::forward<Args>(args)...); } -inline Foam::vtk::formatter& -Foam::vtk::formatter::xmlAttr +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlAttr ( - const vtk::fileAttr& attrEnum, + const vtk::fileAttr& k, const uint64_t v, - const char quote + Args&&... args ) { - return xmlAttr(vtk::fileAttrNames[attrEnum], v, quote); + if (!canWriteAttr(vtk::fileAttrNames[k])) return *this; + + writeAttr(vtk::fileAttrNames[k], v); + return xmlAttr(std::forward<Args>(args)...); +} + + +template<class... Args> +inline Foam::vtk::formatter& Foam::vtk::formatter::xmlAttr +( + const vtk::fileAttr& k, + const scalar v, + Args&&... args +) +{ + if (!canWriteAttr(vtk::fileAttrNames[k])) return *this; + + writeAttr(vtk::fileAttrNames[k], v); + return xmlAttr(std::forward<Args>(args)...); } diff --git a/src/fileFormats/vtk/format/foamVtkFormatterTemplates.C b/src/fileFormats/vtk/format/foamVtkFormatterTemplates.C index 87f4f9131b5..215d8bcb7d9 100644 --- a/src/fileFormats/vtk/format/foamVtkFormatterTemplates.C +++ b/src/fileFormats/vtk/format/foamVtkFormatterTemplates.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -26,75 +26,66 @@ License // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -template<class Type> -Foam::vtk::formatter& -Foam::vtk::formatter::writeAttribute +template<class Type, Foam::direction nComp, int nTuple> +Foam::vtk::formatter& Foam::vtk::formatter::beginDataArray ( - const word& k, - const Type& v, - const char quote + const word& dataName, + uint64_t payLoad, + bool leaveOpen ) { - if (!inTag_) - { - WarningInFunction - << "xml attribute '" << k << "' but not within a tag!" - << endl; - } - - os_ << ' ' << k << '=' << quote << v << quote; - - return *this; -} - - -template<class Type, int nComp> -Foam::vtk::formatter& -Foam::vtk::formatter::openDataArray -( - const word& dataName -) -{ - openTag("DataArray"); + openTag(vtk::fileTag::DATA_ARRAY); xmlAttr("type", vtkPTraits<Type>::typeName); xmlAttr("Name", dataName); + if (nComp > 1) { - xmlAttr(fileAttr::NUMBER_OF_COMPONENTS, nComp); + xmlAttr(fileAttr::NUMBER_OF_COMPONENTS, int(nComp)); + } + if (nTuple > 0) + { + xmlAttr(fileAttr::NUMBER_OF_TUPLES, nTuple); } xmlAttr("format", name()); - return *this; -} + if (formatter::npos != payLoad) + { + uint64_t off = offset(payLoad); + if (formatter::npos != off) + { + xmlAttr("offset", off); + } + } + if (!leaveOpen) + { + closeTag(); + } -template<class Type, int nComp> -Foam::vtk::formatter& -Foam::vtk::formatter::openDataArray -( - const vtk::dataArrayAttr& attrEnum -) -{ - return openDataArray<Type, nComp>(vtk::dataArrayAttrNames[attrEnum]); + return *this; } -template<class Type, int nComp> -Foam::vtk::formatter& -Foam::vtk::formatter::PDataArray +template<class Type, Foam::direction nComp, int nTuple> +Foam::vtk::formatter& Foam::vtk::formatter::PDataArray ( const word& dataName ) { openTag("PDataArray"); xmlAttr("type", vtkPTraits<Type>::typeName); + if (dataName.size()) { xmlAttr("Name", dataName); } if (nComp > 1) { - xmlAttr(fileAttr::NUMBER_OF_COMPONENTS, nComp); + xmlAttr(fileAttr::NUMBER_OF_COMPONENTS, int(nComp)); + } + if (nTuple > 0) + { + xmlAttr(fileAttr::NUMBER_OF_TUPLES, nTuple); } closeTag(true); diff --git a/src/fileFormats/vtk/format/foamVtkLegacyAsciiFormatter.H b/src/fileFormats/vtk/format/foamVtkLegacyAsciiFormatter.H index e191d1eb937..9bfec2594cb 100644 --- a/src/fileFormats/vtk/format/foamVtkLegacyAsciiFormatter.H +++ b/src/fileFormats/vtk/format/foamVtkLegacyAsciiFormatter.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -46,7 +46,7 @@ namespace vtk { /*---------------------------------------------------------------------------*\ - Class legacyAsciiFormatter Declaration + Class vtk::legacyAsciiFormatter Declaration \*---------------------------------------------------------------------------*/ class legacyAsciiFormatter @@ -95,6 +95,17 @@ public: // Currently identical to name(), but do not rely on this. virtual const char* encoding() const; + + // Disable some XML-only methods + + inline virtual formatter& endTag(vtk::fileTag) { return *this; } + inline virtual formatter& endDataArray() { return *this; } + inline virtual formatter& endFieldData() { return *this; } + inline virtual formatter& endCellData() { return *this; } + inline virtual formatter& endPointData() { return *this; } + inline virtual formatter& endPiece() { return *this; } + inline virtual formatter& endVTKFile() { return *this; } + }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/fileFormats/vtk/format/foamVtkLegacyRawFormatter.C b/src/fileFormats/vtk/format/foamVtkLegacyRawFormatter.C index 18f6890404c..85a78e91c8a 100644 --- a/src/fileFormats/vtk/format/foamVtkLegacyRawFormatter.C +++ b/src/fileFormats/vtk/format/foamVtkLegacyRawFormatter.C @@ -80,11 +80,10 @@ const char* Foam::vtk::legacyRawFormatter::encoding() const } -void Foam::vtk::legacyRawFormatter::writeSize -( - const uint64_t ignored -) -{/*nop*/} +bool Foam::vtk::legacyRawFormatter::writeSize(const uint64_t) +{ + return false; +} void Foam::vtk::legacyRawFormatter::write diff --git a/src/fileFormats/vtk/format/foamVtkLegacyRawFormatter.H b/src/fileFormats/vtk/format/foamVtkLegacyRawFormatter.H index ae88684b052..d37624c581f 100644 --- a/src/fileFormats/vtk/format/foamVtkLegacyRawFormatter.H +++ b/src/fileFormats/vtk/format/foamVtkLegacyRawFormatter.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -48,7 +48,7 @@ namespace vtk { /*---------------------------------------------------------------------------*\ - Class legacyRawFormatter Declaration + Class vtk::legacyRawFormatter Declaration \*---------------------------------------------------------------------------*/ class legacyRawFormatter @@ -104,7 +104,8 @@ public: //- Write leading size - a no-op for legacy binary output - virtual void writeSize(const uint64_t ignored); + // \return False - never used by this format + virtual bool writeSize(const uint64_t ignored); virtual void write(const uint8_t val); virtual void write(const label val); @@ -114,6 +115,17 @@ public: //- Write a newline to the output virtual void flush(); + + // Disable some XML-only methods + + inline virtual formatter& endTag(vtk::fileTag) { return *this; } + inline virtual formatter& endDataArray() { return *this; } + inline virtual formatter& endFieldData() { return *this; } + inline virtual formatter& endCellData() { return *this; } + inline virtual formatter& endPointData() { return *this; } + inline virtual formatter& endPiece() { return *this; } + inline virtual formatter& endVTKFile() { return *this; } + }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/fileFormats/vtk/output/foamVtkOutput.C b/src/fileFormats/vtk/output/foamVtkOutput.C index 589537fd286..ea5f533cb67 100644 --- a/src/fileFormats/vtk/output/foamVtkOutput.C +++ b/src/fileFormats/vtk/output/foamVtkOutput.C @@ -33,33 +33,20 @@ License #include "foamVtkLegacyAsciiFormatter.H" #include "foamVtkLegacyRawFormatter.H" #include "typeInfo.H" +#include "globalIndex.H" #include "instant.H" +#include "Fstream.H" +#include "Pstream.H" +#include "OSspecific.H" -// * * * * * * * * * * * * * * * Static Data * * * * * * * * * * * * * * * * // - -const Foam::Enum -< - Foam::vtk::fileTag -> -Foam::vtk::legacy::contentNames -({ - { vtk::fileTag::POLY_DATA, "POLYDATA" }, - { vtk::fileTag::UNSTRUCTURED_GRID, "UNSTRUCTURED_GRID" }, -}); - - -const Foam::Enum -< - Foam::vtk::fileTag -> -Foam::vtk::legacy::dataTypeNames -({ - { vtk::fileTag::CELL_DATA, "CELL_DATA" }, - { vtk::fileTag::POINT_DATA, "POINT_DATA" } -}); +// * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * // +Foam::autoPtr<Foam::vtk::formatter> +Foam::vtk::newFormatter(std::ostream& os, unsigned prec) +{ + return autoPtr<vtk::formatter>::NewFrom<vtk::asciiFormatter>(os, prec); +} -// * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * // Foam::autoPtr<Foam::vtk::formatter> Foam::vtk::newFormatter @@ -102,14 +89,24 @@ Foam::vtk::newFormatter } -void Foam::vtk::writeSeries +void Foam::vtk::seriesInfo ( Ostream& os, - const word& prefix, - const word& suffix, - const UList<instant>& series + const fileName& base, + const UList<instant>& series, + const char sep ) { + // Split the base into (stem, ext) components + // + // base = "path/file.vtm" + // + // stem = "file" + // ext = ".vtm" + + const word stem = base.nameLessExt(); + const word ext = "." + base.ext(); + // Begin file-series (JSON) os << "{\n \"file-series-version\" : \"1.0\",\n \"files\" : [\n"; @@ -118,12 +115,12 @@ void Foam::vtk::writeSeries label nremain = series.size(); // Each entry - // { "name" : "<prefix>name<suffix>", "time" : value } + // { "name" : "<stem><sep>name<ext>", "time" : value } for (const instant& inst : series) { os << " { \"name\" : \"" - << prefix << inst.name() << suffix + << stem << sep << inst.name() << ext << "\", \"time\" : " << inst.value() << " }"; if (--nremain) @@ -137,34 +134,207 @@ void Foam::vtk::writeSeries } -Foam::label Foam::vtk::writeVtmFile +void Foam::vtk::seriesWrite ( - std::ostream& os, - const UList<fileName>& files + const fileName& base, + const UList<instant>& series, + const char sep ) { - asciiFormatter vtmFile(os); + mkDir(base.path()); - vtmFile - .xmlHeader() - .beginVTKFile(fileTagNames[vtk::fileTag::MULTI_BLOCK], "1.0"); + autoPtr<OFstream> osPtr = + ( + base.hasExt("series") + ? autoPtr<OFstream>::New(base) + : autoPtr<OFstream>::New(base + ".series") + ); - forAll(files, i) + seriesInfo(*osPtr, base, series, sep); +} + + +Foam::fileName Foam::vtk::seriesBase +( + const fileName& outputName, + const char sep +) +{ + const auto dash = outputName.rfind(sep); + + // No separator? Or separator in path() instead of name()? + if + ( + std::string::npos == dash + || std::string::npos != outputName.find('/', dash) + ) { - vtmFile - .openTag(vtk::fileTag::DATA_SET) - .xmlAttr("index", i) - .xmlAttr("file", files[i]) - .closeTag(true); + // Warn? + return outputName; } - vtmFile.endTag(fileTagNames[vtk::fileTag::MULTI_BLOCK]).endVTKFile(); + const auto dot = outputName.find('.', dash); - return files.size(); + if (std::string::npos == dot) + { + return outputName.substr(0, dash); + } + + return outputName.substr(0, dash) + outputName.substr(dot); } -std::ostream& Foam::vtk::legacy::fileHeader +void Foam::vtk::writeList +( + vtk::formatter& fmt, + const UList<uint8_t>& values +) +{ + // No nComponents for char, so use fmt.write() directly + for (const uint8_t val : values) + { + fmt.write(val); + } +} + + +void Foam::vtk::writeListParallel +( + vtk::formatter& fmt, + const UList<uint8_t>& values +) +{ + if (Pstream::master()) + { + vtk::writeList(fmt, values); + + List<uint8_t> recv; + + // Receive and write + for + ( + int slave=Pstream::firstSlave(); + slave<=Pstream::lastSlave(); + ++slave + ) + { + IPstream fromSlave(Pstream::commsTypes::blocking, slave); + + fromSlave >> recv; + + vtk::writeList(fmt, recv); + } + } + else + { + // Send to master + OPstream toMaster + ( + Pstream::commsTypes::blocking, + Pstream::masterNo() + ); + + toMaster << values; + } +} + + +void Foam::vtk::writeListParallel +( + vtk::formatter& fmt, + const labelUList& values, + const globalIndex& procOffset +) +{ + if (Pstream::master()) + { + // 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 + ( + int slave=Pstream::firstSlave(); + slave<=Pstream::lastSlave(); + ++slave + ) + { + IPstream fromSlave(Pstream::commsTypes::blocking, slave); + + fromSlave >> recv; + + const label offsetId = procOffset.offset(slave); + + // Write with offset + for (const label val : recv) + { + vtk::write(fmt, val + offsetId); + } + } + } + else + { + // Send to master + OPstream toMaster + ( + Pstream::commsTypes::blocking, + Pstream::masterNo() + ); + + toMaster << values; + } +} + + +// * * * * * * * * * * * * * * Legacy Functions * * * * * * * * * * * * * * // + + +void Foam::vtk::legacy::fileHeader +( + std::ostream& os, + const std::string& title, + bool binary +) +{ + // Line 1: + os << "# vtk DataFile Version 2.0" << nl; + + // Line 2: title + + const auto truncate = title.find('\n'); + + if (title.empty() || 0 == truncate) + { + // Avoid an empty title + + os << "File generated by OpenFOAM"; + #if OPENFOAM + os << ' ' << OPENFOAM; + #endif + os << nl; + } + else if (std::string::npos == truncate) + { + os << title << nl; + } + else + { + os << title.substr(0, truncate) << nl; + } + + // Line 3: format + os << (binary ? "BINARY" : "ASCII") << nl; +} + + +void Foam::vtk::legacy::fileHeader ( vtk::formatter& fmt, const std::string& title, @@ -173,13 +343,11 @@ std::ostream& Foam::vtk::legacy::fileHeader { std::ostream& os = fmt.os(); - fileHeader(os, title, isType<legacyRawFormatter>(fmt)); - if (!contentType.empty()) + legacy::fileHeader(os, title, isType<legacyRawFormatter>(fmt)); + if (contentType.size()) { os << "DATASET " << contentType.c_str() << nl; } - - return os; } diff --git a/src/fileFormats/vtk/output/foamVtkOutput.H b/src/fileFormats/vtk/output/foamVtkOutput.H index 2f4a0d2f7af..9cd5434847a 100644 --- a/src/fileFormats/vtk/output/foamVtkOutput.H +++ b/src/fileFormats/vtk/output/foamVtkOutput.H @@ -44,6 +44,7 @@ SourceFiles #define foamVtkOutput_H #include "autoPtr.H" +#include "bitSet.H" #include "Enum.H" #include "foamVtkCore.H" #include "foamVtkFormatter.H" @@ -55,8 +56,10 @@ SourceFiles namespace Foam { + // Forward declarations class instant; +class globalIndex; namespace vtk { @@ -66,7 +69,11 @@ namespace vtk // General Functions //- Return a default asciiFormatter - autoPtr<vtk::formatter> newFormatter(std::ostream& os); + autoPtr<vtk::formatter> newFormatter + ( + std::ostream& os, + unsigned prec = IOstream::defaultPrecision() + ); //- Return a new formatter based on the specified format type autoPtr<vtk::formatter> newFormatter @@ -77,23 +84,56 @@ namespace vtk ); - //- Write file series (JSON format) for specified time instances + //- Print file series (JSON format) for specified time instances // - // \param prefix before the \c instant.name() - // \param suffix after the \c instant.name() - // \param series the list of name/value entries - void writeSeries + // \param os The output stream + // \param base The name for the series (eg, "path/file.vtm") + // \param series The list of suffix/value entries + // \param sep The separator used between file stem and suffix. + void seriesInfo ( Ostream& os, - const word& prefix, - const word& suffix, - const UList<instant>& series + const fileName& base, + const UList<instant>& series, + const char sep = '_' ); - //- Write vtm datasets for specified files - label writeVtmFile(std::ostream& os, const UList<fileName>& files); + //- Write file series (JSON format) to disk, for specified time instances + // + // \param base The name for the series (eg, "path/file.vtm") + // \param series The list of suffix/value entries + // \param sep The separator used between file stem and suffix. + void seriesWrite + ( + const fileName& base, + const UList<instant>& series, + const char sep = '_' + ); + + //- Extract the base name for a file series + // + // \param outputName The name of the data output file + // Eg, "somefile_0001.vtm" would extract to "somefile.vtm" + // \param sep The separator used between file stem and suffix. + fileName seriesBase(const fileName& outputName, const char sep = '_'); + //- Write a list of uint8_t values. + // 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 + ); + //- Write a value component-wise. template<class Type> inline void write @@ -109,7 +149,7 @@ namespace vtk void writeList ( vtk::formatter& fmt, - const UList<Type>& list + const UList<Type>& values ); //- Write a list of values. @@ -118,7 +158,7 @@ namespace vtk void writeList ( vtk::formatter& fmt, - const FixedList<Type, Size>& list + const FixedList<Type, Size>& values ); @@ -128,7 +168,88 @@ namespace vtk void writeList ( vtk::formatter& fmt, - const UList<Type>& list, + const UList<Type>& values, + const labelUList& addressing + ); + + //- Write a list of values via indirect addressing. + // The output does not include the payload size. + template<class Type> + void writeList + ( + vtk::formatter& fmt, + const UList<Type>& values, + const bitSet& selected + ); + + //- Write a list of values and a list of values via indirect addressing. + // The output does not include the payload size. + template<class Type> + void writeLists + ( + vtk::formatter& fmt, + const UList<Type>& values1, + const UList<Type>& values2, + const labelUList& addressing + ); + + + //- Write a list of values. + // The output does not include the payload size. + template<class Type> + void writeListParallel + ( + vtk::formatter& fmt, + const UList<Type>& values + ); + + //- Write a list of values, with constant per-processor offset + // The output does not include the payload size. + void writeListParallel + ( + vtk::formatter& fmt, + const UList<label>& values, + const globalIndex& procOffset + ); + + //- Write a list of values via indirect addressing. + // The output does not include the payload size. + template<class Type> + void writeListParallel + ( + vtk::formatter& fmt, + const UList<Type>& values, + const labelUList& addressing + ); + + //- Write a list of values via indirect addressing. + // The output does not include the payload size. + template<class Type> + void writeListParallel + ( + vtk::formatter& fmt, + const UList<Type>& values, + const bitSet& selected + ); + + //- Write a list of values and another list of values. + // The output does not include the payload size. + template<class Type> + void writeListsParallel + ( + vtk::formatter& fmt, + const UList<Type>& values1, + const UList<Type>& values2 + ); + + //- Write a list of values and a list of values via indirect addressing. + // The output does not include the payload size. + template<class Type> + void writeListsParallel + ( + vtk::formatter& fmt, + const UList<Type>& values1, + const UList<Type>& values2, const labelUList& addressing ); @@ -137,93 +258,101 @@ namespace vtk Namespace legacy \*---------------------------------------------------------------------------*/ -//- Some minimal additional support for writing legacy files namespace legacy { -// Constants - - //- Strings corresponding to the (POLYDATA, UNSTRUCTURED_GRID) elements - extern const Foam::Enum<vtk::fileTag> contentNames; - - //- Strings corresponding to the (CELL_DATA, POINT_DATA) elements - extern const Foam::Enum<vtk::fileTag> dataTypeNames; - - // Functions //- Emit header for legacy file. // Writes "ASCII" or "BINARY" depending on specified type. - inline std::ostream& fileHeader - ( - std::ostream& os, - const std::string& title, - const bool binary - ); + void fileHeader(std::ostream& os, const std::string& title, bool binary); //- Emit header for legacy file, with "ASCII" or "BINARY" depending on - // the formatter type. - // Includes "DATASET" with the specified dataset type. - inline void fileHeader + //- the formatter type. + // If the contentType is non-empty, it is used for "DATASET" line. + void fileHeader ( vtk::formatter& fmt, const std::string& title, - const vtk::fileTag& contentTypeTag + const std::string& contentType ); //- Emit header for legacy file, with "ASCII" or "BINARY" depending on - // the formatter type. - // If the contentType is non-empty, it is used for "DATASET" line. - std::ostream& fileHeader + //- the formatter type. + // Includes "DATASET" with the specified dataset type. + inline void fileHeader ( vtk::formatter& fmt, const std::string& title, - const std::string& contentType + vtk::fileTag contentType ); + //- Emit header for legacy file, with "ASCII" or "BINARY" depending on + //- the formatter type. + // Includes "DATASET" of the templated dataset type. + template<vtk::fileTag ContentType> + inline void fileHeader(vtk::formatter& fmt, const std::string& title); //- Emit header for POINTS (with trailing newline). - inline void beginPoints(std::ostream& os, const label nPoints); + inline void beginPoints(std::ostream& os, label nPoints); //- 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. // The additional prefix sizes are added internally. - inline void beginPolys + inline void beginPolys(std::ostream& os, label nPolys, label nConnectivity); + + + //- Emit "FIELD FieldData <n>" + inline void fieldData(vtk::formatter& fmt, label nFields); + + //- Emit legacy FIELD FieldData nFields. + inline void beginFieldData(vtk::formatter& fmt, label nFields); + + //- Emit legacy CELL_DATA nCells, FIELD FieldData nFields. + inline void beginCellData ( - std::ostream& os, - const label nPolys, - const label nConnectivity + vtk::formatter& fmt, + label nCells, + label nFields ); - - //- Use the enumerations vtk::fileTag::CELL_DATA, vtk::fileTag::POINT_DATA, - // to emit a legacy CELL_DATA, POINT_DATA element. - // The nEntries corresponds similarly to the number of cells or points, - // respectively. - inline void dataHeader + //- Emit legacy POINT_DATA nPoints, FIELD FieldData nFields. + inline void beginPointData ( - std::ostream& os, - const vtk::fileTag& dataTypeTag, - const label nEntries, - const label nFields + vtk::formatter& fmt, + label nPoints, + label nFields ); + + //- Emit "TimeValue" for a FIELD entry (name as per Catalyst output) + inline void writeTimeValue(vtk::formatter& fmt, scalar timeValue); + //- Start output of float field with the specified name. + template<direction nComp> inline void floatField ( - std::ostream& os, + vtk::formatter& fmt, + const word& name, + const label nEntries + ); + + //- Start output of double field with the specified name. + template<direction nComp> + inline void doubleField + ( + vtk::formatter& fmt, const word& name, - const int nCmpt, const label nEntries ); //- Start output of int field with the specified name. + template<direction nComp> inline void intField ( - std::ostream& os, + vtk::formatter& fmt, const word& name, - const int nCmpt, const label nEntries ); diff --git a/src/fileFormats/vtk/output/foamVtkOutputI.H b/src/fileFormats/vtk/output/foamVtkOutputI.H index b7717ea66d3..40b5275737a 100644 --- a/src/fileFormats/vtk/output/foamVtkOutputI.H +++ b/src/fileFormats/vtk/output/foamVtkOutputI.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -59,87 +59,149 @@ inline void write<double>(vtk::formatter& fmt, const double& val) // * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * // -inline std::ostream& Foam::vtk::legacy::fileHeader +inline void Foam::vtk::legacy::fileHeader ( - std::ostream& os, + vtk::formatter& fmt, const std::string& title, - const bool binary + vtk::fileTag contentType ) { - os << "# vtk DataFile Version 2.0" << nl - << title << nl - << (binary ? "BINARY" : "ASCII") << nl; - - return os; + legacy::fileHeader(fmt, title, legacy::contentNames[contentType]); } +template<Foam::vtk::fileTag ContentType> inline void Foam::vtk::legacy::fileHeader ( vtk::formatter& fmt, - const std::string& title, - const vtk::fileTag& contentTypeTag + const std::string& title ) { - fileHeader(fmt, title, contentNames[contentTypeTag]); + legacy::fileHeader(fmt, title, legacy::contentNames[ContentType]); +} + + +inline void Foam::vtk::legacy::beginPoints(std::ostream& os, label nPoints) +{ + os << nl + << "POINTS " << nPoints << " float" << nl; } -inline void Foam::vtk::legacy::beginPoints +inline void Foam::vtk::legacy::beginPolys ( std::ostream& os, - const label nPoints + label nPolys, + label nConnectivity ) { - os << "POINTS " << nPoints << " float" << nl; + os << nl + << "POLYGONS " << nPolys << ' ' << (nPolys + nConnectivity) << nl; } -inline void Foam::vtk::legacy::beginPolys +inline void Foam::vtk::legacy::fieldData ( - std::ostream& os, - const label nPolys, - const label nConnectivity + vtk::formatter& fmt, + label nFields ) { - os << "POLYGONS " << nPolys << ' ' << (nPolys + nConnectivity) << nl; + fmt.os() + << "FIELD FieldData " << nFields << nl; } -inline void Foam::vtk::legacy::dataHeader +inline void Foam::vtk::legacy::beginFieldData ( - std::ostream& os, - const vtk::fileTag& dataTypeTag, - const label nEntries, - const label nFields + vtk::formatter& fmt, + label nFields +) +{ + legacy::fieldData(fmt, nFields); +} + + +inline void Foam::vtk::legacy::beginCellData +( + vtk::formatter& fmt, + label nCells, + label nFields +) +{ + fmt.os() + << nl + << legacy::dataTypeNames[vtk::fileTag::CELL_DATA] + << ' ' << nCells << nl; + legacy::fieldData(fmt, nFields); +} + + +inline void Foam::vtk::legacy::beginPointData +( + vtk::formatter& fmt, + label nPoints, + label nFields +) +{ + fmt.os() + << nl + << legacy::dataTypeNames[vtk::fileTag::POINT_DATA] + << ' ' << nPoints << nl; + legacy::fieldData(fmt, nFields); +} + + +inline void Foam::vtk::legacy::writeTimeValue +( + vtk::formatter& fmt, + scalar timeValue ) { - os << dataTypeNames[dataTypeTag] << ' ' << nEntries << nl - << "FIELD attributes " << nFields << nl; + legacy::floatField<1>(fmt, "TimeValue", 1); + fmt.write(timeValue); + fmt.flush(); } +template<Foam::direction nComp> +inline void Foam::vtk::legacy::doubleField +( + vtk::formatter& fmt, + const word& fieldName, + label nEntries +) +{ + fmt.os() + << fieldName << ' ' + << int(nComp) << ' ' << nEntries << " double" << nl; +} + + +template<Foam::direction nComp> inline void Foam::vtk::legacy::floatField ( - std::ostream& os, + vtk::formatter& fmt, const word& fieldName, - const int nCmpt, - const label nEntries + label nEntries ) { - os << fieldName << ' ' << nCmpt << ' ' << nEntries << " float" << nl; + fmt.os() + << fieldName << ' ' + << int(nComp) << ' ' << nEntries << " float" << nl; } +template<Foam::direction nComp> inline void Foam::vtk::legacy::intField ( - std::ostream& os, + vtk::formatter& fmt, const word& fieldName, - const int nCmpt, - const label nEntries + label nEntries ) { - os << fieldName << ' ' << nCmpt << ' ' << nEntries << " int" << nl; + fmt.os() + << fieldName << ' ' + << int(nComp) << ' ' << nEntries << " int" << nl; } diff --git a/src/fileFormats/vtk/output/foamVtkOutputOptions.H b/src/fileFormats/vtk/output/foamVtkOutputOptions.H index fb15f9dd00d..976c5413b71 100644 --- a/src/fileFormats/vtk/output/foamVtkOutputOptions.H +++ b/src/fileFormats/vtk/output/foamVtkOutputOptions.H @@ -97,6 +97,9 @@ public: //- The output format type inline formatType fmt() const; + //- The file extension (legacy or xml) for the given content-type + inline word ext(vtk::fileTag contentType) const; + //- True if writer uses legacy file format inline bool legacy() const; diff --git a/src/fileFormats/vtk/output/foamVtkOutputOptionsI.H b/src/fileFormats/vtk/output/foamVtkOutputOptionsI.H index c8802c3da8b..36a0a3c7b21 100644 --- a/src/fileFormats/vtk/output/foamVtkOutputOptionsI.H +++ b/src/fileFormats/vtk/output/foamVtkOutputOptionsI.H @@ -25,7 +25,6 @@ License #include "foamVtkOutput.H" - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // inline Foam::vtk::outputOptions::outputOptions() @@ -56,13 +55,23 @@ Foam::vtk::outputOptions::newFormatter(std::ostream& os) const // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // -inline Foam::vtk::formatType -Foam::vtk::outputOptions::fmt() const +inline Foam::vtk::formatType Foam::vtk::outputOptions::fmt() const { return fmtType_; } +inline Foam::word Foam::vtk::outputOptions::ext(vtk::fileTag contentType) const +{ + return + ( + legacy() + ? vtk::legacy::fileExtension + : vtk::fileExtension[contentType] + ); +} + + inline bool Foam::vtk::outputOptions::legacy() const { return diff --git a/src/fileFormats/vtk/output/foamVtkOutputTemplates.C b/src/fileFormats/vtk/output/foamVtkOutputTemplates.C index 7a398f8d9d0..917aaa75d66 100644 --- a/src/fileFormats/vtk/output/foamVtkOutputTemplates.C +++ b/src/fileFormats/vtk/output/foamVtkOutputTemplates.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -23,6 +23,9 @@ License \*---------------------------------------------------------------------------*/ +#include "Pstream.H" +#include "ListOps.H" + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // template<class Type> @@ -44,12 +47,12 @@ template<class Type> void Foam::vtk::writeList ( vtk::formatter& fmt, - const UList<Type>& list + const UList<Type>& values ) { - for (const Type& val : list) + for (const Type& val : values) { - write(fmt, val); + vtk::write(fmt, val); } } @@ -58,12 +61,12 @@ template<class Type, unsigned Size> void Foam::vtk::writeList ( vtk::formatter& fmt, - const FixedList<Type, Size>& list + const FixedList<Type, Size>& values ) { - for (const Type& val : list) + for (const Type& val : values) { - write(fmt, val); + vtk::write(fmt, val); } } @@ -72,13 +75,261 @@ template<class Type> void Foam::vtk::writeList ( vtk::formatter& fmt, - const UList<Type>& list, + const UList<Type>& values, const labelUList& addressing ) { for (const label idx : addressing) { - write(fmt, list[idx]); + vtk::write(fmt, values[idx]); + } +} + + +template<class Type> +void Foam::vtk::writeList +( + vtk::formatter& fmt, + const UList<Type>& values, + const bitSet& selected +) +{ + for (const label idx : selected) + { + vtk::write(fmt, values[idx]); + } +} + + +template<class Type> +void Foam::vtk::writeLists +( + vtk::formatter& fmt, + const UList<Type>& values, + const UList<Type>& indirect, + const labelUList& addressing +) +{ + vtk::writeList(fmt, values); + vtk::writeList(fmt, indirect, addressing); +} + + +template<class Type> +void Foam::vtk::writeListParallel +( + vtk::formatter& fmt, + const UList<Type>& values +) +{ + if (Pstream::master()) + { + vtk::writeList(fmt, values); + + List<Type> recv; + + // Receive and write + for + ( + int slave=Pstream::firstSlave(); + slave<=Pstream::lastSlave(); + ++slave + ) + { + IPstream fromSlave(Pstream::commsTypes::blocking, slave); + + fromSlave >> recv; + + vtk::writeList(fmt, recv); + } + } + else + { + // Send to master + OPstream toMaster + ( + Pstream::commsTypes::blocking, + Pstream::masterNo() + ); + + toMaster << values; + } +} + + +template<class Type> +void Foam::vtk::writeListParallel +( + vtk::formatter& fmt, + const UList<Type>& values, + const labelUList& addressing +) +{ + if (Pstream::master()) + { + vtk::writeList(fmt, values, addressing); + + List<Type> recv; + + // Receive and write + for + ( + int slave=Pstream::firstSlave(); + slave<=Pstream::lastSlave(); + ++slave + ) + { + IPstream fromSlave(Pstream::commsTypes::blocking, slave); + + fromSlave >> recv; + + vtk::writeList(fmt, recv); + } + } + else + { + // Send to master + OPstream toMaster + ( + Pstream::commsTypes::blocking, + Pstream::masterNo() + ); + + toMaster << List<Type>(values, addressing); + } +} + + +template<class Type> +void Foam::vtk::writeListParallel +( + vtk::formatter& fmt, + const UList<Type>& values, + const bitSet& selected +) +{ + if (Pstream::master()) + { + vtk::writeList(fmt, values, selected); + + List<Type> recv; + + // Receive and write + for + ( + int slave=Pstream::firstSlave(); + slave<=Pstream::lastSlave(); + ++slave + ) + { + IPstream fromSlave(Pstream::commsTypes::blocking, slave); + + fromSlave >> recv; + + vtk::writeList(fmt, recv); + } + } + else + { + // Send to master + OPstream toMaster + ( + Pstream::commsTypes::blocking, + Pstream::masterNo() + ); + + toMaster << subset(selected, values); + } +} + + +template<class Type> +void Foam::vtk::writeListsParallel +( + vtk::formatter& fmt, + const UList<Type>& values1, + const UList<Type>& values2 +) +{ + if (Pstream::master()) + { + vtk::writeList(fmt, values1); + vtk::writeList(fmt, values2); + + List<Type> recv1, recv2; + + // Receive and write + for + ( + int slave=Pstream::firstSlave(); + slave<=Pstream::lastSlave(); + ++slave + ) + { + IPstream fromSlave(Pstream::commsTypes::blocking, slave); + + fromSlave >> recv1 >> recv2; + + vtk::writeList(fmt, recv1); + vtk::writeList(fmt, recv2); + } + } + else + { + // Send to master + OPstream toMaster + ( + Pstream::commsTypes::blocking, + Pstream::masterNo() + ); + + toMaster << values1 << values2; + } +} + + +template<class Type> +void Foam::vtk::writeListsParallel +( + vtk::formatter& fmt, + const UList<Type>& values1, + const UList<Type>& values2, + const labelUList& addressing +) +{ + if (Pstream::master()) + { + vtk::writeList(fmt, values1); + vtk::writeList(fmt, values2, addressing); + + List<Type> recv1, recv2; +; + // Receive and write + for + ( + int slave=Pstream::firstSlave(); + slave<=Pstream::lastSlave(); + ++slave + ) + { + IPstream fromSlave(Pstream::commsTypes::blocking, slave); + + fromSlave >> recv1 >> recv2; + + vtk::writeList(fmt, recv1); + vtk::writeList(fmt, recv2); + } + } + else + { + // Send to master + OPstream toMaster + ( + Pstream::commsTypes::blocking, + Pstream::masterNo() + ); + + toMaster << values1 << List<Type>(values2, addressing); } } diff --git a/src/functionObjects/lagrangian/vtkCloud/vtkCloud.C b/src/functionObjects/lagrangian/vtkCloud/vtkCloud.C index 07500761acd..c99faa34ce0 100644 --- a/src/functionObjects/lagrangian/vtkCloud/vtkCloud.C +++ b/src/functionObjects/lagrangian/vtkCloud/vtkCloud.C @@ -466,10 +466,12 @@ bool Foam::functionObjects::vtkCloud::write() // Each cloud separately for (const word& cloudName : cloudNames) { - const word prefix(cloudName + "_"); - const word suffix(".vtp"); // No legacy supported + // Legacy is not to be supported - const fileName outputName(vtkDir/prefix + timeDesc + suffix); + const fileName outputName + ( + vtkDir/cloudName + "_" + timeDesc + ".vtp" + ); if (writeCloud(outputName, cloudName)) { @@ -483,9 +485,11 @@ bool Foam::functionObjects::vtkCloud::write() series_(cloudName).append({time_.value(), timeDesc}); - OFstream os(vtkDir/cloudName + ".vtp.series", IOstream::ASCII); - - vtk::writeSeries(os, prefix, suffix, series_[cloudName]); + vtk::seriesWrite + ( + vtkDir/cloudName + ".vtp", + series_[cloudName] + ); } } } diff --git a/src/meshTools/output/foamVtkWriteCellSetFaces.C b/src/meshTools/output/foamVtkWriteCellSetFaces.C index 9a10c37e72d..38bc7d107d0 100644 --- a/src/meshTools/output/foamVtkWriteCellSetFaces.C +++ b/src/meshTools/output/foamVtkWriteCellSetFaces.C @@ -132,7 +132,7 @@ void Foam::vtk::writeCellSetFaces // Write data - faceId/cellId - legacy::dataHeader(os, vtk::fileTag::CELL_DATA, pp.size(), 1); + legacy::beginCellData(format(), pp.size(), 1); os << "cellID 1 " << pp.size() << " int" << nl; diff --git a/src/meshTools/output/foamVtkWriteFaceSet.C b/src/meshTools/output/foamVtkWriteFaceSet.C index f0f2a215211..cfe8a5e895d 100644 --- a/src/meshTools/output/foamVtkWriteFaceSet.C +++ b/src/meshTools/output/foamVtkWriteFaceSet.C @@ -96,7 +96,7 @@ void Foam::vtk::writeFaceSet // Write data - faceId/cellId - legacy::dataHeader(os, vtk::fileTag::CELL_DATA, pp.size(), 1); + legacy::beginCellData(format(), pp.size(), 1); os << "faceID 1 " << pp.size() << " int" << nl; diff --git a/src/meshTools/output/foamVtkWritePointSet.C b/src/meshTools/output/foamVtkWritePointSet.C index 64c88f0350a..e2283599462 100644 --- a/src/meshTools/output/foamVtkWritePointSet.C +++ b/src/meshTools/output/foamVtkWritePointSet.C @@ -64,7 +64,7 @@ void Foam::vtk::writePointSet format().flush(); // Write data - pointID - legacy::dataHeader(os, vtk::fileTag::POINT_DATA, pointLabels.size(), 1); + legacy::beginPointData(format(), pointLabels.size(), 1); os << "pointID 1 " << pointLabels.size() << " int" << nl; diff --git a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.C b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.C index 9de55aae6fa..9d921f48ff6 100644 --- a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.C +++ b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.C @@ -92,21 +92,8 @@ void Foam::fileFormats::VTKsurfaceFormatCore::writeCellData nFaces += z.size(); } - vtk::legacy::dataHeader - ( - format.os(), - vtk::fileTag::CELL_DATA, - nFaces, - 1 // Only one field - ); - - vtk::legacy::intField - ( - format.os(), - "region", - 1, // nComponent - nFaces - ); + vtk::legacy::beginCellData(format, nFaces, 1); // 1 field + vtk::legacy::intField<1>(format, "region", nFaces); // 1 component label zoneId = 0; for (const surfZone& zone : zones) @@ -132,21 +119,8 @@ void Foam::fileFormats::VTKsurfaceFormatCore::writeCellData // Number of faces const label nFaces = zoneIds.size(); - vtk::legacy::dataHeader - ( - format.os(), - vtk::fileTag::CELL_DATA, - nFaces, - 1 // Only one field - ); - - vtk::legacy::intField - ( - format.os(), - "region", - 1, // nComponent - nFaces - ); + vtk::legacy::beginCellData(format, nFaces, 1); // 1 field + vtk::legacy::intField<1>(format, "region", nFaces); // 1 component vtk::writeList(format, zoneIds); format.flush(); -- GitLab