diff --git a/applications/utilities/mesh/manipulation/setSet/setSet.C b/applications/utilities/mesh/manipulation/setSet/setSet.C index fa48186c90c275c9e013fa709c0ea2831858e110..e37212d160578fe821e037ec40a71726711ab33b 100644 --- a/applications/utilities/mesh/manipulation/setSet/setSet.C +++ b/applications/utilities/mesh/manipulation/setSet/setSet.C @@ -43,9 +43,7 @@ Description #include "topoSetSource.H" #include "Fstream.H" #include "demandDrivenData.H" -#include "foamVtkWriteCellSetFaces.H" -#include "foamVtkWriteFaceSet.H" -#include "foamVtkWritePointSet.H" +#include "foamVtkWriteTopoSet.H" #include "IOobjectList.H" #include "cellZoneSet.H" #include "faceZoneSet.H" @@ -70,47 +68,26 @@ using namespace Foam; void writeVTK ( const polyMesh& mesh, - const topoSet& currentSet, - const fileName& vtkBaseName + const topoSet& currSet, + const fileName& outputName ) { - if (isA<faceSet>(currentSet)) - { - // Faces of set with OpenFOAM faceID as value - vtk::writeFaceSet - ( - mesh, - dynamicCast<const faceSet&>(currentSet), - mesh.time().path()/vtkBaseName, - vtk::formatType::LEGACY_BINARY - ); - } - else if (isA<cellSet>(currentSet)) - { - // External faces of cellset with OpenFOAM cellID as value - vtk::writeCellSetFaces - ( - mesh, - dynamicCast<const cellSet&>(currentSet), - mesh.time().path()/vtkBaseName, - vtk::formatType::LEGACY_BINARY - ); - } - else if (isA<pointSet>(currentSet)) - { - vtk::writePointSet + if + ( + !vtk::writeTopoSet ( mesh, - dynamicCast<const pointSet&>(currentSet), - mesh.time().path()/vtkBaseName, - vtk::formatType::LEGACY_BINARY - ); - } - else + currSet, + vtk::formatType::INLINE_BASE64, // XML-binary + // vtk::formatType::LEGACY_BINARY, + outputName, + false // Not parallel + ) + ) { WarningInFunction - << "Don't know how to handle set of type " << currentSet.type() - << endl; + << "Don't know how to handle set of type " + << currSet.type() << nl; } } @@ -502,35 +479,35 @@ bool doCommand if (!noSync) currentSet.sync(mesh); // Write + Info<< " Writing " << currentSet.name() + << " (size " + << returnReduce(currentSet.size(), sumOp<label>()) + << ") to " + << ( + currentSet.instance()/currentSet.local() + / currentSet.name() + ); + + if (writeVTKFile) { - mkDir(mesh.time().path()/"VTK"/currentSet.name()); - - fileName vtkName + fileName outputName ( - "VTK"/currentSet.name()/currentSet.name() - + "_" - + name(mesh.time().timeIndex()) + mesh.time().path()/"VTK"/currentSet.name() + / currentSet.name() + "_" + + Foam::name(mesh.time().timeIndex()) ); + mkDir(outputName.path()); - Info<< " Writing " << currentSet.name() - << " (size " - << returnReduce(currentSet.size(), sumOp<label>()) - << ") to " - << currentSet.instance()/currentSet.local() - /currentSet.name() - << " and to vtk file " << vtkName << endl << endl; + Info<< " and to vtk file " + << outputName.relative(mesh.time().path()) + << nl << nl; - writeVTK(mesh, currentSet, vtkName); + writeVTK(mesh, currentSet, outputName); } else { - Info<< " Writing " << currentSet.name() - << " (size " - << returnReduce(currentSet.size(), sumOp<label>()) - << ") to " - << currentSet.instance()/currentSet.local() - /currentSet.name() << endl << endl; + Info<< nl << nl; } if (writeCurrentTime) diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C index e253be1f19e0d9bf89fe9ce0d156b23eb6b3bdde..3fdb93d05c1ac9f63e8150032be040173373a136 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C @@ -168,8 +168,7 @@ Note #include "foamVtkPatchWriter.H" #include "foamVtkSurfaceMeshWriter.H" #include "foamVtkLagrangianWriter.H" -#include "foamVtkWriteFaceSet.H" -#include "foamVtkWritePointSet.H" +#include "foamVtkWriteTopoSet.H" #include "foamVtkWriteSurfFields.H" #include "memInfo.H" @@ -629,21 +628,25 @@ int main(int argc, char *argv[]) vtuMeshCells.clear(); } + + // Attempt topoSets first + bool shortCircuit = false; + // If faceSet: write faceSet only (as polydata) if (faceSetName.size()) { - // Load the faceSet + // Load faceSet set(mesh, faceSetName); // Filename as if patch with same name. - mkDir(fvPath/set.name()); - - fileName outputName + const fileName outputName ( - fvPath/set.name()/set.name() - + "_" - + timeDesc + fvPath/set.name() + / set.name() + "_" + timeDesc ); + + mkDir(outputName.path()); + Info<< " faceSet : " << outputName.relative(runTime.path()) << nl; @@ -651,27 +654,29 @@ int main(int argc, char *argv[]) ( meshProxy.mesh(), set, + fmtType, outputName, - fmtType + false // In parallel (later) ); - continue; + + shortCircuit = true; } // If pointSet: write pointSet only (as polydata) if (pointSetName.size()) { - // Load the pointSet + // Load pointSet set(mesh, pointSetName); // Filename as if patch with same name. - mkDir(fvPath/set.name()); - - fileName outputName + const fileName outputName ( - fvPath/set.name()/set.name() - + "_" - + timeDesc + fvPath/set.name() + / set.name() + "_" + timeDesc ); + + mkDir(outputName.path()); + Info<< " pointSet : " << outputName.relative(runTime.path()) << nl; @@ -679,9 +684,16 @@ int main(int argc, char *argv[]) ( meshProxy.mesh(), set, + fmtType, outputName, - fmtType + false // In parallel (later) ); + + shortCircuit = true; + } + + if (shortCircuit) + { continue; } diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files index cf53f0e9268186df2c64ee81fa206d68c03436ad..e89cf987fcd7d0731407fbde47354ad260ebff63 100644 --- a/src/meshTools/Make/files +++ b/src/meshTools/Make/files @@ -297,6 +297,8 @@ meshStructure/meshStructure.C meshStructure/topoDistanceData.C meshStructure/pointTopoDistanceData.C +output/foamVtkIndPatchWriter.C +output/foamVtkWriteTopoSet.C output/foamVtkWriteFaceSet.C output/foamVtkWritePointSet.C output/foamVtkWriteCellSetFaces.C diff --git a/src/meshTools/output/foamVtkIndPatchWriter.C b/src/meshTools/output/foamVtkIndPatchWriter.C new file mode 100644 index 0000000000000000000000000000000000000000..bf8adcf9fcc4a191145c36a333e86a68301d8e42 --- /dev/null +++ b/src/meshTools/output/foamVtkIndPatchWriter.C @@ -0,0 +1,449 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkIndPatchWriter.H" +#include "foamVtkOutput.H" +#include "globalIndex.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::vtk::indirectPatchWriter::beginPiece() +{ + // Basic sizes + nLocalPoints_ = pp_.nPoints(); + nLocalFaces_ = pp_.size(); + nLocalVerts_ = 0; + + for (const face& f : pp_) + { + nLocalVerts_ += f.size(); + } + + numberOfPoints_ = nLocalPoints_; + numberOfCells_ = nLocalFaces_; + + if (parallel_) + { + reduce(numberOfPoints_, sumOp<label>()); + reduce(numberOfCells_, sumOp<label>()); + } + + + // Nothing else to do for legacy + if (legacy()) return; + + if (format_) + { + format().tag + ( + vtk::fileTag::PIECE, + vtk::fileAttr::NUMBER_OF_POINTS, numberOfPoints_, + vtk::fileAttr::NUMBER_OF_POLYS, numberOfCells_ + ); + } +} + + +void Foam::vtk::indirectPatchWriter::writePoints() +{ + if (format_) + { + if (legacy()) + { + legacy::beginPoints(os_, numberOfPoints_); + } + else + { + const uint64_t payLoad = vtk::sizeofData<float, 3>(numberOfPoints_); + + format() + .tag(vtk::fileTag::POINTS) + .beginDataArray<float,3>(vtk::dataArrayAttr::POINTS); + + format().writeSize(payLoad); + } + } + + + if (parallel_ ? Pstream::master() : true) + { + { + vtk::writeList(format(), pp_.localPoints()); + } + } + + + if (parallel_) + { + if (Pstream::master()) + { + pointField recv; + + // Receive each point field and write + for + ( + int slave=Pstream::firstSlave(); + slave<=Pstream::lastSlave(); + ++slave + ) + { + IPstream fromSlave(Pstream::commsTypes::blocking, slave); + + { + fromSlave >> recv; + + vtk::writeList(format(), recv); + } + } + } + else + { + // Send to master + OPstream toMaster + ( + Pstream::commsTypes::blocking, + Pstream::masterNo() + ); + + { + toMaster << pp_.localPoints(); + } + } + } + + + if (format_) + { + format().flush(); + format().endDataArray(); + + if (!legacy()) + { + format() + .endTag(vtk::fileTag::POINTS); + } + } +} + + +void Foam::vtk::indirectPatchWriter::writePolysLegacy +( + const globalIndex& pointOffsets +) +{ + // Connectivity count without additional storage (done internally) + + label nFaces = nLocalFaces_; + label nVerts = nLocalVerts_; + + if (parallel_) + { + reduce(nFaces, sumOp<label>()); + reduce(nVerts, sumOp<label>()); + } + + if (nFaces != numberOfCells_) + { + FatalErrorInFunction + << "Expecting " << numberOfCells_ + << " faces, but found " << nFaces + << exit(FatalError); + } + + legacy::beginPolys(os_, nFaces, nVerts); + + labelList vertLabels(nLocalFaces_ + nLocalVerts_); + + { + // Legacy: size + connectivity together + // [nPts, id1, id2, ..., nPts, id1, id2, ...] + + auto iter = vertLabels.begin(); + + label off = pointOffsets.localStart(); + + { + for (const face& f : pp_.localFaces()) + { + *iter = f.size(); // The size prefix + ++iter; + + for (const label pfi : f) + { + *iter = pfi + off; // Face vertex label + ++iter; + } + } + off += pp_.nPoints(); + } + } + + + if (parallel_) + { + vtk::writeListParallel(format_.ref(), vertLabels); + } + else + { + vtk::writeList(format(), vertLabels); + } + + if (format_) + { + format().flush(); + } +} + + +void Foam::vtk::indirectPatchWriter::writePolys +( + const globalIndex& pointOffsets +) +{ + if (format_) + { + format().tag(vtk::fileTag::POLYS); + } + + // + // 'connectivity' + // + { + labelList vertLabels(nLocalVerts_); + + label nVerts = nLocalVerts_; + + if (parallel_) + { + reduce(nVerts, sumOp<label>()); + } + + if (format_) + { + const uint64_t payLoad = vtk::sizeofData<label>(nVerts); + + format().beginDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY); + format().writeSize(payLoad * sizeof(label)); + } + + { + // XML: connectivity only + // [id1, id2, ..., id1, id2, ...] + + auto iter = vertLabels.begin(); + + label off = pointOffsets.localStart(); + + { + for (const face& f : pp_.localFaces()) + { + for (const label pfi : f) + { + *iter = pfi + off; // Face vertex label + ++iter; + } + } + off += pp_.nPoints(); + } + } + + + if (parallel_) + { + vtk::writeListParallel(format_.ref(), vertLabels); + } + else + { + vtk::writeList(format(), vertLabels); + } + + if (format_) + { + format().flush(); + format().endDataArray(); + } + } + + + // + // 'offsets' (connectivity offsets) + // + { + labelList vertOffsets(nLocalFaces_); + label nOffs = vertOffsets.size(); + + // global connectivity offsets + const globalIndex procOffset(nLocalVerts_); + + if (parallel_) + { + reduce(nOffs, sumOp<label>()); + } + + if (format_) + { + const uint64_t payLoad = vtk::sizeofData<label>(nOffs); + + format().beginDataArray<label>(vtk::dataArrayAttr::OFFSETS); + format().writeSize(payLoad); + } + + + label off = procOffset.localStart(); + + auto iter = vertOffsets.begin(); + + { + for (const face& f : pp_) + { + off += f.size(); // End offset + *iter = off; + ++iter; + } + } + + + if (parallel_) + { + vtk::writeListParallel(format_.ref(), vertOffsets); + } + else + { + vtk::writeList(format_.ref(), vertOffsets); + } + + + if (format_) + { + format().flush(); + format().endDataArray(); + } + } + + if (format_) + { + format().endTag(vtk::fileTag::POLYS); + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::vtk::indirectPatchWriter::indirectPatchWriter +( + const indirectPrimitivePatch& pp, + const vtk::outputOptions opts +) +: + vtk::fileWriter(vtk::fileTag::POLY_DATA, opts), + pp_(pp), + numberOfPoints_(0), + numberOfCells_(0), + nLocalPoints_(0), + nLocalFaces_(0), + nLocalVerts_(0) +{ + // We do not currently support append mode + opts_.append(false); +} + + +Foam::vtk::indirectPatchWriter::indirectPatchWriter +( + const indirectPrimitivePatch& pp, + const fileName& file, + bool parallel +) +: + indirectPatchWriter(pp) +{ + open(file, parallel); +} + + +Foam::vtk::indirectPatchWriter::indirectPatchWriter +( + const indirectPrimitivePatch& pp, + const vtk::outputOptions opts, + const fileName& file, + bool parallel +) +: + indirectPatchWriter(pp, opts) +{ + open(file, parallel); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::vtk::indirectPatchWriter::beginFile(std::string title) +{ + if (title.size()) + { + return vtk::fileWriter::beginFile(title); + } + + // Provide default title + return vtk::fileWriter::beginFile("surfaces"); +} + + +bool Foam::vtk::indirectPatchWriter::writeGeometry() +{ + enter_Piece(); + + beginPiece(); + + writePoints(); + + const globalIndex globalPointOffset(nLocalPoints_); + + if (legacy()) + { + writePolysLegacy(globalPointOffset); + } + else + { + writePolys(globalPointOffset); + } + + return true; +} + + +bool Foam::vtk::indirectPatchWriter::beginCellData(label nFields) +{ + return enter_CellData(numberOfCells_, nFields); +} + + +bool Foam::vtk::indirectPatchWriter::beginPointData(label nFields) +{ + return enter_PointData(numberOfPoints_, nFields); +} + + +// ************************************************************************* // diff --git a/src/meshTools/output/foamVtkIndPatchWriter.H b/src/meshTools/output/foamVtkIndPatchWriter.H new file mode 100644 index 0000000000000000000000000000000000000000..c0e989dbf080ac07db65f5a609f746f5e23ce520 --- /dev/null +++ b/src/meshTools/output/foamVtkIndPatchWriter.H @@ -0,0 +1,222 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::vtk::indirectPatchWriter + +Description + Write indirectPrimitivePatch faces/points (optionally with fields) + as a vtp file or a legacy vtk file. + + The file output states are managed by the Foam::vtk::fileWriter class. + FieldData (eg, TimeValue) must appear before any geometry pieces. + +Note + Parallel output is combined into a single Piece without point merging, + which is similar to using multi-piece data sets, but allows more + convenient creation as a streaming process. + In the future, the duplicate points at processor connections + may be addressed using ghost points. + +SourceFiles + foamVtkIndPatchWriter.C + foamVtkIndPatchWriterTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkIndPatchWriter_H +#define foamVtkIndPatchWriter_H + +#include "foamVtkFileWriter.H" +#include "indirectPrimitivePatch.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declarations +class globalIndex; + +namespace vtk +{ + +/*---------------------------------------------------------------------------*\ + Class vtk::indirectPatchWriter Declaration +\*---------------------------------------------------------------------------*/ + +class indirectPatchWriter +: + public vtk::fileWriter +{ + // Private Member Data + + //- Reference to the faces as an indirect patch + const indirectPrimitivePatch& pp_; + + //- The numer of field points for the current Piece + label numberOfPoints_; + + //- The numer of field cells (faces) for the current Piece + label numberOfCells_; + + //- Local number of points + label nLocalPoints_; + + //- Local number of faces + label nLocalFaces_; + + //- Local face vertices (connectivity) count. Sum of face sizes. + label nLocalVerts_; + + + // Private Member Functions + + //- Determing sizes (nLocalPoints_, nLocalFaces_, nLocalVerts_), + //- and begin piece + void beginPiece(); + + //- Write patch points + void writePoints(); + + //- Write patch faces, legacy format + void writePolysLegacy(const globalIndex& pointOffsets); + + //- Write patch faces + void writePolys(const globalIndex& pointOffsets); + + + //- No copy construct + indirectPatchWriter(const indirectPatchWriter&) = delete; + + //- No copy assignment + void operator=(const indirectPatchWriter&) = delete; + + +public: + + // Constructors + + //- Construct from patch (default output INLINE_BASE64) + indirectPatchWriter + ( + const indirectPrimitivePatch& pp, + const vtk::outputOptions opts = vtk::formatType::INLINE_BASE64 + ); + + //- Construct from components (default output INLINE_BASE64), + // and open the file for writing. + // The file name is with/without an extension. + indirectPatchWriter + ( + const indirectPrimitivePatch& pp, + const fileName& file, + bool parallel = Pstream::parRun() + ); + + //- Construct from components and open the file for writing. + // The file name is with/without an extension. + indirectPatchWriter + ( + const indirectPrimitivePatch& pp, + const vtk::outputOptions opts, + const fileName& file, + bool parallel = Pstream::parRun() + ); + + + //- Destructor + virtual ~indirectPatchWriter() = default; + + + // Member Functions + + //- File extension for current format type. + using vtk::fileWriter::ext; + + //- File extension for given output type + inline static word ext(vtk::outputOptions opts) + { + return opts.ext(vtk::fileTag::POLY_DATA); + } + + //- Reference to the indirect patch + inline const indirectPrimitivePatch& patch() const + { + return pp_; + } + + + //- Write file header (non-collective) + // \note Expected calling states: (OPENED). + virtual bool beginFile(std::string title = ""); + + //- Write patch topology + // Also writes the file header if not previously written. + // \note Must be called prior to writing CellData or PointData + virtual bool writeGeometry(); + + //- Begin CellData output section for specified number of fields. + // Must be called prior to writing any cell data fields. + // \param nFields is for legacy format only. + // When nFields=0, this a no-op for legacy format. + // \note Expected calling states: (PIECE | POINT_DATA). + // + // \return True if the state changed + virtual bool beginCellData(label nFields = 0); + + //- Begin PointData for specified number of fields. + // Must be called prior to writing any point data fields. + // \param nFields is for legacy format only. + // When nFields=0, this a no-op for legacy format. + // \note Expected calling states: (PIECE | CELL_DATA). + // + // \return True if the state changed + virtual bool beginPointData(label nFields = 0); + + + // Write + + //- Write a list of Cell (Face) or Point values + template<class Type> + void write(const word& fieldName, const UList<Type>& field); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace vtk +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "foamVtkIndPatchWriterTemplates.C" +#endif + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/meshTools/output/foamVtkIndPatchWriterTemplates.C b/src/meshTools/output/foamVtkIndPatchWriterTemplates.C new file mode 100644 index 0000000000000000000000000000000000000000..b0819afc183c969c484d0f040de85587b4a0eb47 --- /dev/null +++ b/src/meshTools/output/foamVtkIndPatchWriterTemplates.C @@ -0,0 +1,130 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class Type> +void Foam::vtk::indirectPatchWriter::write +( + const word& fieldName, + const UList<Type>& field +) +{ + if (isState(outputState::CELL_DATA)) + { + ++nCellData_; + } + else if (isState(outputState::POINT_DATA)) + { + ++nPointData_; + } + else + { + FatalErrorInFunction + << "Bad writer state (" << stateNames[state_] + << ") - should be (" << stateNames[outputState::CELL_DATA] + << ") or (" << stateNames[outputState::POINT_DATA] + << ") for field " << fieldName << nl << endl + << exit(FatalError); + } + + static_assert + ( + ( + std::is_same<typename pTraits<Type>::cmptType,label>::value + || std::is_floating_point<typename pTraits<Type>::cmptType>::value + ), + "Label and Floating-point vector space only" + ); + + const bool isLabel = + std::is_same<typename pTraits<Type>::cmptType(), label>::value; + + + const direction nCmpt(pTraits<Type>::nComponents); + + label nValues = field.size(); + + // Could check sizes: + // nValues == nLocalFaces (CELL_DATA) + // nValues == nLocalPoints (POINT_DATA) + + if (parallel_) + { + reduce(nValues, sumOp<label>()); + } + + if (format_) + { + if (isLabel) + { + if (legacy()) + { + legacy::intField<nCmpt>(format(), fieldName, nValues); + } + else + { + const uint64_t payLoad = vtk::sizeofData<label, nCmpt>(nValues); + + format().beginDataArray<label, nCmpt>(fieldName); + format().writeSize(payLoad); + } + } + else + { + if (legacy()) + { + legacy::floatField<nCmpt>(format(), fieldName, nValues); + } + else + { + const uint64_t payLoad = vtk::sizeofData<float, nCmpt>(nValues); + + format().beginDataArray<float, nCmpt>(fieldName); + format().writeSize(payLoad); + } + } + } + + + if (parallel_) + { + vtk::writeListParallel(format_.ref(), field); + } + else + { + vtk::writeList(format(), field); + } + + + if (format_) + { + format().flush(); + format().endDataArray(); + } +} + + +// ************************************************************************* // diff --git a/src/meshTools/output/foamVtkWriteCellSetFaces.C b/src/meshTools/output/foamVtkWriteCellSetFaces.C index 38bc7d107d0a6e127637bbfd5036f842d1265a1e..09227deb246c9ec26ca037a03772064bec2eef4a 100644 --- a/src/meshTools/output/foamVtkWriteCellSetFaces.C +++ b/src/meshTools/output/foamVtkWriteCellSetFaces.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd. + \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -23,36 +23,34 @@ License \*---------------------------------------------------------------------------*/ -#include "foamVtkWriteCellSetFaces.H" -#include "foamVtkOutputOptions.H" -#include "OFstream.H" -#include "primitiveMesh.H" +#include "foamVtkWriteTopoSet.H" +#include "foamVtkIndPatchWriter.H" +#include "polyMesh.H" #include "cellSet.H" -#include "uindirectPrimitivePatch.H" +#include "globalIndex.H" // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // -void Foam::vtk::writeCellSetFaces +bool Foam::vtk::writeCellSetFaces ( - const primitiveMesh& mesh, + const polyMesh& mesh, const cellSet& set, - const fileName& baseName, - const vtk::outputOptions outOpts + const vtk::outputOptions opts, + const fileName& file, + bool parallel ) { - outputOptions opts(outOpts); - opts.legacy(true); // Legacy only, no xml, no append + typedef IndirectList<face> FaceListType; - const bool legacy_(opts.legacy()); + const globalIndex cellIdOffset(mesh.nCells()); - std::ofstream os(baseName + (legacy_ ? ".vtk" : ".vtp")); - - autoPtr<vtk::formatter> format = opts.newFormatter(os); + indirectPrimitivePatch pp + ( + FaceListType(mesh.faces(), labelList()), + mesh.points() + ); + FaceListType& faces = pp; - if (legacy_) - { - legacy::fileHeader(format(), set.name(), vtk::fileTag::POLY_DATA); - } //------------------------------------------------------------------------- @@ -87,57 +85,48 @@ void Foam::vtk::writeCellSetFaces } } - const labelList faceLabels(cellFaces.sortedToc()); - labelList faceValues(cellFaces.size()); + // Use these faces + faces.resetAddressing(cellFaces.sortedToc()); - forAll(faceLabels, facei) + // For each face, the corresponding cellID + + labelList faceValues(faces.size()); + + // Cell ID { - faceValues[facei] = cellFaces[faceLabels[facei]]; // Cell ID - } + const labelList& faceIds = faces.addressing(); - uindirectPrimitivePatch pp - ( - UIndirectList<face>(mesh.faces(), faceLabels), - mesh.points() - ); + const label off = cellIdOffset.localStart(); + + forAll(faceValues, facei) + { + faceValues[facei] = cellFaces[faceIds[facei]] + off; + } + } //------------------------------------------------------------------------- - // Write points and faces as polygons - legacy::beginPoints(os, pp.nPoints()); + indirectPatchWriter writer(pp, opts); - vtk::writeList(format(), pp.localPoints()); - format().flush(); + writer.open(file, parallel); - // connectivity count without additional storage (done internally) - uint64_t nConnectivity = 0; - forAll(pp, facei) - { - nConnectivity += pp[facei].size(); - } - - legacy::beginPolys(os, pp.size(), nConnectivity); + writer.beginFile(set.name()); + writer.writeGeometry(); + //------------------------------------------------------------------------- - // legacy: size + connectivity together - // [nPts, id1, id2, ..., nPts, id1, id2, ...] - forAll(pp, facei) + // CellData - cellID only { - const face& f = pp.localFaces()[facei]; + writer.beginCellData(1); - format().write(f.size()); // The size prefix - vtk::writeList(format(), f); - } - format().flush(); + writer.write("faceID", faceValues); + // End CellData/PointData is implicit + } - // Write data - faceId/cellId - legacy::beginCellData(format(), pp.size(), 1); - - os << "cellID 1 " << pp.size() << " int" << nl; + writer.close(); - vtk::writeList(format(), faceValues); - format().flush(); + return true; } diff --git a/src/meshTools/output/foamVtkWriteFaceSet.C b/src/meshTools/output/foamVtkWriteFaceSet.C index cfe8a5e895dd3744d32a88f8d3db6569538b86ba..28003c9be23712b3a89784e546e19134f3c1451b 100644 --- a/src/meshTools/output/foamVtkWriteFaceSet.C +++ b/src/meshTools/output/foamVtkWriteFaceSet.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd. + \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -23,85 +23,62 @@ License \*---------------------------------------------------------------------------*/ -#include "foamVtkWriteFaceSet.H" -#include "foamVtkOutputOptions.H" -#include "OFstream.H" -#include "primitiveMesh.H" +#include "foamVtkWriteTopoSet.H" +#include "foamVtkIndPatchWriter.H" +#include "polyMesh.H" #include "faceSet.H" -#include "uindirectPrimitivePatch.H" +#include "globalIndex.H" // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // -void Foam::vtk::writeFaceSet +bool Foam::vtk::writeFaceSet ( - const primitiveMesh& mesh, + const polyMesh& mesh, const faceSet& set, - const fileName& baseName, - const vtk::outputOptions outOpts + const vtk::outputOptions opts, + const fileName& file, + bool parallel ) { - outputOptions opts(outOpts); - opts.legacy(true); // Legacy only, no xml, no append + typedef IndirectList<face> FaceListType; - const bool legacy_(opts.legacy()); + const globalIndex faceIdOffset(mesh.nFaces()); - std::ofstream os(baseName + (legacy_ ? ".vtk" : ".vtp")); - - autoPtr<vtk::formatter> format = opts.newFormatter(os); - - if (legacy_) - { - legacy::fileHeader(format(), set.name(), vtk::fileTag::POLY_DATA); - } - - //------------------------------------------------------------------------- - - // Faces of set with OpenFOAM faceID as value - const labelList faceLabels(set.sortedToc()); - - uindirectPrimitivePatch pp + indirectPrimitivePatch pp ( - UIndirectList<face>(mesh.faces(), faceLabels), + FaceListType(mesh.faces(), labelList()), mesh.points() ); + FaceListType& faces = pp; + + // Use the faces from faceSet + faces.resetAddressing(set.sortedToc()); //------------------------------------------------------------------------- - // Write points and faces as polygons - legacy::beginPoints(os, pp.nPoints()); + indirectPatchWriter writer(pp, opts); - vtk::writeList(format(), pp.localPoints()); - format().flush(); + writer.open(file, parallel); - // connectivity count without additional storage (done internally) - uint64_t nConnectivity = 0; - forAll(pp, facei) - { - nConnectivity += pp[facei].size(); - } - legacy::beginPolys(os, pp.size(), nConnectivity); + writer.beginFile(set.name()); + writer.writeGeometry(); - // legacy: size + connectivity together - // [nPts, id1, id2, ..., nPts, id1, id2, ...] - forAll(pp, facei) + // CellData - faceID only { - const face& f = pp.localFaces()[facei]; - - format().write(f.size()); // The size prefix - vtk::writeList(format(), f); - } - format().flush(); + writer.beginCellData(1); + labelField faceValues(faces.addressing()); + faceValues += faceIdOffset.localStart(); - // Write data - faceId/cellId + writer.write("faceID", faceValues); - legacy::beginCellData(format(), pp.size(), 1); + // End CellData/PointData is implicit + } - os << "faceID 1 " << pp.size() << " int" << nl; + writer.close(); - vtk::writeList(format(), faceLabels); - format().flush(); + return true; } diff --git a/src/meshTools/output/foamVtkWritePointSet.C b/src/meshTools/output/foamVtkWritePointSet.C index e228359946280463e44af830e7d077cb74eeb1b2..1952c3a2fc4b058cd69d43921c88566da0a54c2f 100644 --- a/src/meshTools/output/foamVtkWritePointSet.C +++ b/src/meshTools/output/foamVtkWritePointSet.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd. + \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -23,53 +23,209 @@ License \*---------------------------------------------------------------------------*/ -#include "foamVtkWritePointSet.H" -#include "foamVtkOutputOptions.H" -#include "OFstream.H" -#include "primitiveMesh.H" +#include <fstream> +#include "foamVtkWriteTopoSet.H" +#include "polyMesh.H" #include "pointSet.H" +#include "globalIndex.H" +#include "OSspecific.H" // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // -void Foam::vtk::writePointSet +bool Foam::vtk::writePointSet ( - const primitiveMesh& mesh, + const polyMesh& mesh, const pointSet& set, - const fileName& baseName, - const vtk::outputOptions outOpts + const vtk::outputOptions opts, + const fileName& file, + bool parallel ) { - outputOptions opts(outOpts); - opts.legacy(true); // Legacy only, no xml, no append + vtk::outputOptions opts_(opts); + opts_.append(false); // Do not support append - const bool legacy_(opts.legacy()); + const bool legacy = opts_.legacy(); - std::ofstream os(baseName + (legacy_ ? ".vtk" : ".vtp")); + // Only allow parallel if really is a parallel run. + parallel = parallel && Pstream::parRun(); - autoPtr<vtk::formatter> format = opts.newFormatter(os); - if (legacy_) + std::ofstream os_; + autoPtr<vtk::formatter> format; + + // Open a file and attach a formatter + // - on master (always) + // - on slave if not parallel + // + // This means we can always check if format_ is defined to know if output + // is desired on any particular process. + + if (Pstream::master() || !parallel) + { + mkDir(file.path()); + + // Extension is inappropriate. Legacy instead of xml, or vice versa. + const word ext = vtk::fileExtension[vtk::fileTag::POLY_DATA]; + + if (file.hasExt(ext)) + { + // Extension is correct + os_.open(file); + } + else if + ( + legacy + ? file.hasExt(ext) + : file.hasExt(vtk::legacy::fileExtension) + ) + { + // Extension is inappropriate. Legacy instead of xml, or vice versa. + os_.open(file.lessExt() + "." + ext); + } + else + { + // Extension added automatically + os_.open(file + "." + ext); + } + + format = opts_.newFormatter(os_); + } + + + //------------------------------------------------------------------------- + + const globalIndex pointIdOffset(mesh.nPoints()); + + labelField pointLabels(set.sortedToc()); + + label numberOfPoints = pointLabels.size(); + + if (parallel) { - legacy::fileHeader(format(), set.name(), vtk::fileTag::POLY_DATA); + reduce(numberOfPoints, sumOp<label>()); + } + + if (format) + { + const auto& title = set.name(); + + if (legacy) + { + // beginFile: + + legacy::fileHeader<vtk::fileTag::POLY_DATA>(format(), title); + + // beginPoints: + + legacy::beginPoints(os_, numberOfPoints); + } + else + { + // XML (inline) + + // beginFile: + + format() + .xmlHeader() + .xmlComment(title) + .beginVTKFile<vtk::fileTag::POLY_DATA>(); + + // beginPiece: + format() + .tag + ( + vtk::fileTag::PIECE, + vtk::fileAttr::NUMBER_OF_POINTS, numberOfPoints + ); + + // beginPoints: + const uint64_t payLoad = vtk::sizeofData<float,3>(numberOfPoints); + + format() + .tag(vtk::fileTag::POINTS) + .beginDataArray<float,3>(vtk::dataArrayAttr::POINTS); + format().writeSize(payLoad); + } } + //------------------------------------------------------------------------- - const labelList pointLabels(set.sortedToc()); + // pointLabels are the addressing for an indirect list - // Write points - legacy::beginPoints(os, pointLabels.size()); + if (parallel) + { + vtk::writeListParallel(format(), mesh.points(), pointLabels); + } + else + { + vtk::writeList(format(), mesh.points(), pointLabels); + } - vtk::writeList(format(), mesh.points(), pointLabels); - format().flush(); + if (format) + { + format().flush(); + format().endDataArray(); + + if (!legacy) + { + format() + .endTag(vtk::fileTag::POINTS); + } + + + // beginPointData: + if (legacy) + { + legacy::beginPointData(format(), numberOfPoints, 1); // 1 field + } + else + { + format().beginPointData(); + } + } - // Write data - pointID - legacy::beginPointData(format(), pointLabels.size(), 1); + if (format) + { + // pointID + + if (legacy) + { + // 1 component + legacy::intField<1>(format(), "pointID", numberOfPoints); + } + else + { + const uint64_t payLoad = vtk::sizeofData<label>(numberOfPoints); + + format().beginDataArray<label>("pointID"); + format().writeSize(payLoad); + } + } - os << "pointID 1 " << pointLabels.size() << " int" << nl; - vtk::writeList(format(), pointLabels); - format().flush(); + if (parallel) + { + vtk::writeListParallel(format.ref(), pointLabels, pointIdOffset); + } + else + { + vtk::writeList(format(), pointLabels); + } + + + if (format) + { + format().flush(); + format().endDataArray(); + format().endPointData(); + format().endPiece(); + + format().endTag(vtk::fileTag::POLY_DATA) + .endVTKFile(); + } + + return true; } diff --git a/src/meshTools/output/foamVtkWritePointSet.H b/src/meshTools/output/foamVtkWritePointSet.H deleted file mode 100644 index 576f2ccb4d186eb7f8e5843dca0f254a07ae772d..0000000000000000000000000000000000000000 --- a/src/meshTools/output/foamVtkWritePointSet.H +++ /dev/null @@ -1,73 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -InNamespace - Foam::vtk - -Description - Write pointSet to vtk polydata file. - The data are the original point ids. - -SourceFiles - foamVtkWritePointSet.C - -\*---------------------------------------------------------------------------*/ - -#ifndef foamVtkWritePointSet_H -#define foamVtkWritePointSet_H - -#include "foamVtkOutputOptions.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -// Forward declarations -class primitiveMesh; -class pointSet; -class fileName; - -namespace vtk -{ - -//- Write pointSet to vtk polydata file. -// The data are the original point ids. -void writePointSet -( - const primitiveMesh& mesh, - const pointSet& set, - const fileName& baseName, - const vtk::outputOptions outOpts -); - - -} // End namespace vtk -} // End namespace Foam - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#endif - -// ************************************************************************* // diff --git a/src/meshTools/output/foamVtkWriteFaceSet.H b/src/meshTools/output/foamVtkWriteTopoSet.C similarity index 51% rename from src/meshTools/output/foamVtkWriteFaceSet.H rename to src/meshTools/output/foamVtkWriteTopoSet.C index d556c91bdb741697d3870f8ffe77ee09cf415df1..b4f433d148f86d18dd2006f9b8600483ed735a23 100644 --- a/src/meshTools/output/foamVtkWriteFaceSet.H +++ b/src/meshTools/output/foamVtkWriteTopoSet.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -21,53 +21,65 @@ License You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. -InNamespace - Foam::vtk - -Description - Write faceSet to vtk polydata file. - The data are the mesh face ids. - -SourceFiles - foamVtkWritePointSet.C - \*---------------------------------------------------------------------------*/ -#ifndef foamVtkWriteFaceSet_H -#define foamVtkWriteFaceSet_H - -#include "foamVtkOutputOptions.H" +#include "foamVtkWriteTopoSet.H" +#include "polyMesh.H" +#include "topoSet.H" +#include "faceSet.H" +#include "cellSet.H" +#include "pointSet.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -namespace Foam -{ - -// Forward declarations -class primitiveMesh; -class faceSet; -class fileName; - -namespace vtk -{ - -//- Write faceSet to vtk polydata file. -// Only one data which is original pointID. -void writeFaceSet +bool Foam::vtk::writeTopoSet ( - const primitiveMesh& mesh, - const faceSet& set, - const fileName& baseName, - const vtk::outputOptions outOpts -); - - -} // End namespace vtk -} // End namespace Foam - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + const polyMesh& mesh, + const topoSet& set, + const vtk::outputOptions opts, + const fileName& file, + bool parallel +) +{ + if (isA<pointSet>(set)) + { + return vtk::writePointSet + ( + mesh, + dynamicCast<const pointSet&>(set), + opts, + file, + parallel + ); + } + else if (isA<faceSet>(set)) + { + return vtk::writeFaceSet + ( + mesh, + dynamicCast<const faceSet&>(set), + opts, + file, + parallel + ); + } + else if (isA<cellSet>(set)) + { + return vtk::writeCellSetFaces + ( + mesh, + dynamicCast<const cellSet&>(set), + opts, + file, + parallel + ); + } + + WarningInFunction + << "No VTK writer for '" << set.type() << "' topoSet" << nl << endl; + + return false; +} -#endif // ************************************************************************* // diff --git a/src/meshTools/output/foamVtkWriteCellSetFaces.H b/src/meshTools/output/foamVtkWriteTopoSet.H similarity index 52% rename from src/meshTools/output/foamVtkWriteCellSetFaces.H rename to src/meshTools/output/foamVtkWriteTopoSet.H index e4d15efc9e2ca9c09379a84354e05862aaaf9a66..0e4c07a09ae31a205d834f0027454c2b6ab5fdaf 100644 --- a/src/meshTools/output/foamVtkWriteCellSetFaces.H +++ b/src/meshTools/output/foamVtkWriteTopoSet.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 @@ -25,20 +25,21 @@ InNamespace Foam::vtk Description - Write faces of cellSet to vtk polydata file. - - The data are the original cell ids + Write topoSet in VTK format SourceFiles + foamVtkWriteTopoSet.C foamVtkWriteCellSetFaces.C + foamVtkWriteFaceSet.C + foamVtkWritePointSet.C \*---------------------------------------------------------------------------*/ #ifndef foamVtkWriteCellSetFaces_H #define foamVtkWriteCellSetFaces_H -#include "primitiveMesh.H" -#include "uindirectPrimitivePatch.H" +#include "fileName.H" +#include "UPstream.H" #include "foamVtkOutputOptions.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -47,27 +48,74 @@ namespace Foam { // Forward declarations -class primitiveMesh; +class polyMesh; +class topoSet; +class faceSet; class cellSet; -class fileName; +class pointSet; namespace vtk { +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//- Dispatch to vtk::writeCellSetFaces, vtk::writeFaceSet, vtk::writePointSet +// The file name is with/without an extension. +// \return True on successful dispatch +bool writeTopoSet +( + const polyMesh& mesh, + const topoSet& set, + const vtk::outputOptions opts, + const fileName& file, + bool parallel = Pstream::parRun() +); + + +//- Write faceSet as VTK polydata file. +// Only one CELL_DATA, which is the original faceID +// The file name is with/without an extension. +bool writeFaceSet +( + const polyMesh& mesh, + const faceSet& set, + const vtk::outputOptions opts, + const fileName& file, + bool parallel = Pstream::parRun() +); + + //- Write perimeter faces of cellset to vtk polydata file. // The data are the original cell ids -void writeCellSetFaces +// The file name is with/without an extension. +bool writeCellSetFaces ( - const primitiveMesh& mesh, + const polyMesh& mesh, const cellSet& set, - const fileName& baseName, - const vtk::outputOptions outOpts + const vtk::outputOptions opts, + const fileName& file, + bool parallel = Pstream::parRun() +); + + +//- Write pointSet to VTK polydata file. +// Only one CELL_DATA, which is the original pointID +// The file name is with/without an extension. +bool writePointSet +( + const polyMesh& mesh, + const pointSet& set, + const vtk::outputOptions opts, + const fileName& file, + bool parallel = Pstream::parRun() ); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + } // End namespace vtk } // End namespace Foam - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #endif