From ed62ed1b19b01a3df7d159b59087d6ef5074c623 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Thu, 27 Sep 2018 13:38:31 +0200 Subject: [PATCH] ENH: parallel and xml output for surface vector fields (issue #926) - implemented as vtk::surfaceFieldWriter, which replaces the vtk::writeSurfFields function. --- src/conversion/Make/files | 2 +- .../vtk/output/foamVtkSurfaceFieldWriter.C | 300 ++++++++++++++++++ .../vtk/output/foamVtkSurfaceFieldWriter.H | 186 +++++++++++ .../vtk/output/foamVtkWriteSurfFields.C | 171 ---------- .../vtk/output/foamVtkWriteSurfFields.H | 67 ---- 5 files changed, 487 insertions(+), 239 deletions(-) create mode 100644 src/conversion/vtk/output/foamVtkSurfaceFieldWriter.C create mode 100644 src/conversion/vtk/output/foamVtkSurfaceFieldWriter.H delete mode 100644 src/conversion/vtk/output/foamVtkWriteSurfFields.C delete mode 100644 src/conversion/vtk/output/foamVtkWriteSurfFields.H diff --git a/src/conversion/Make/files b/src/conversion/Make/files index 5d6233a1c61..eb9ac5e43c1 100644 --- a/src/conversion/Make/files +++ b/src/conversion/Make/files @@ -26,6 +26,6 @@ polyDualMesh/polyDualMesh.C vtk/output/foamVtkInternalWriter.H vtk/output/foamVtkPatchWriter.H -vtk/output/foamVtkWriteSurfFields.C +vtk/output/foamVtkSurfaceFieldWriter.C LIB = $(FOAM_LIBBIN)/libconversion diff --git a/src/conversion/vtk/output/foamVtkSurfaceFieldWriter.C b/src/conversion/vtk/output/foamVtkSurfaceFieldWriter.C new file mode 100644 index 00000000000..7b439e8c5f8 --- /dev/null +++ b/src/conversion/vtk/output/foamVtkSurfaceFieldWriter.C @@ -0,0 +1,300 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016-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 "foamVtkSurfaceFieldWriter.H" +#include "emptyFvsPatchFields.H" +#include "fvsPatchFields.H" +#include "surfaceFields.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::List<Foam::vector> Foam::vtk::surfaceFieldWriter::flattenBoundary +( + const surfaceVectorField& field +) const +{ + // Boundary field - flatten + + List<vector> flat(mesh_.nBoundaryFaces(), Zero); + + forAll(field.boundaryField(), patchi) + { + const polyPatch& pp = mesh_.boundaryMesh()[patchi]; + const auto& pfld = field.boundaryField()[patchi]; + + if (!isA<emptyFvsPatchVectorField>(pfld)) + { + SubList<vector>(flat, pp.size(), pp.offset()) = pfld; + } + } + + return flat; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::vtk::surfaceFieldWriter::surfaceFieldWriter +( + const fvMesh& mesh, + const vtk::outputOptions opts +) +: + vtk::fileWriter(vtk::fileTag::POLY_DATA, opts), + mesh_(mesh), + numberOfPoints_(0) +{ + opts_.append(false); // No append mode (horrible for streaming) + opts_.legacy(false); // Disallow legacy (inconvenient) +} + + +Foam::vtk::surfaceFieldWriter::surfaceFieldWriter +( + const fvMesh& mesh, + const fileName& file, + bool parallel +) +: + surfaceFieldWriter(mesh) +{ + open(file, parallel); +} + + +Foam::vtk::surfaceFieldWriter::surfaceFieldWriter +( + const fvMesh& mesh, + const vtk::outputOptions opts, + const fileName& file, + bool parallel +) +: + surfaceFieldWriter(mesh, opts) +{ + open(file, parallel); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::vtk::surfaceFieldWriter::beginFile(std::string title) +{ + if (title.size()) + { + return vtk::fileWriter::beginFile(title); + } + + + // Provide Default title + + if (legacy()) + { + return vtk::fileWriter::beginFile("surfaceFields"); + } + + + // XML (inline) + + return vtk::fileWriter::beginFile + ( + "surfaceFields " + "case='" + mesh_.time().globalCaseName() + + "' region='" + mesh_.name() + + "' time='" + mesh_.time().timeName() + + "' index='" + Foam::name(mesh_.time().timeIndex()) + + "'" + ); +} + + +bool Foam::vtk::surfaceFieldWriter::writeGeometry() +{ + enter_Piece(); + + // Output + + const pointField& centres = mesh_.faceCentres(); + + // PointData for each face. + numberOfPoints_ = centres.size(); + + if (parallel_) + { + reduce(numberOfPoints_, sumOp<label>()); + } + + // <Piece> + if (format_) + { + format() + .tag + ( + vtk::fileTag::PIECE, + fileAttr::NUMBER_OF_POINTS, numberOfPoints_ + ); + } + + + // <Point> + if (format_) + { + 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_) + { + // Internal faces + vtk::writeListParallel + ( + format_.ref(), + SubList<point>(centres, mesh_.nInternalFaces()) + ); + + // Boundary faces + vtk::writeListParallel + ( + format_.ref(), + SubList<point>(centres, mesh_.boundaryMesh().range()) + ); + } + else + { + // Non-parallel: use a normal write + + vtk::writeList(format(), centres); + } + + if (format_) + { + format().flush(); + + // Non-legacy + format() + .endDataArray() + .endTag(vtk::fileTag::POINTS); + } + + return true; +} + + +bool Foam::vtk::surfaceFieldWriter::beginCellData(label nFields) +{ + // No legacy, no CellData + return enter_CellData(0, 0); +} + + +bool Foam::vtk::surfaceFieldWriter::beginPointData(label nFields) +{ + // No legacy + return enter_PointData(numberOfPoints_, 0); +} + + +void Foam::vtk::surfaceFieldWriter::write(const surfaceVectorField& field) +{ + if (isState(outputState::POINT_DATA)) + { + ++nPointData_; + } + else + { + FatalErrorInFunction + << "Bad writer state (" << stateNames[state_] + << ") - should be (" << stateNames[outputState::POINT_DATA] + << ") for field " << field.name() << nl << endl + << exit(FatalError); + } + + label nFaces = field.mesh().nFaces(); + + if (parallel_) + { + reduce(nFaces, sumOp<label>()); + } + + if (nFaces != numberOfPoints_) + { + FatalErrorInFunction + << "Expecting " << numberOfPoints_ + << " faces, but found " << nFaces + << exit(FatalError); + } + + if (format_) + { + // Non-legacy + const uint64_t payLoad = + vtk::sizeofData<float, 3>(nFaces); + + format().beginDataArray<float, 3>(field.name()); + format().writeSize(payLoad); + } + + + // Internal field + const SubList<vector> internal(field, mesh_.nInternalFaces()); + + // Boundary field (flattened) + auto boundary(flattenBoundary(field)); + + + if (parallel_) + { + // Internal field + vtk::writeListParallel(format_.ref(), internal); + + // Boundary field + vtk::writeListParallel(format_.ref(), boundary); + } + else + { + // Non-parallel + + // Internal field + vtk::writeList(format_.ref(), internal); + + // Boundary field + vtk::writeList(format_.ref(), boundary); + } + + + if (format_) + { + format().flush(); + format().endDataArray(); + } +} + + +// ************************************************************************* // diff --git a/src/conversion/vtk/output/foamVtkSurfaceFieldWriter.H b/src/conversion/vtk/output/foamVtkSurfaceFieldWriter.H new file mode 100644 index 00000000000..4238ec2a555 --- /dev/null +++ b/src/conversion/vtk/output/foamVtkSurfaceFieldWriter.H @@ -0,0 +1,186 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2016-2018 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::vtk::surfaceFieldWriter + +Description + Write surfaces fields (as PointData) in VTP format. + Legacy VTK format is intentionally not supported. + + The file output is structured as HEAD, FIELD_DATA, PIECE followed by any + CELL_DATA or POINT_DATA. These states are tracked internally to help + detect logic errors. + + The FieldData element is to be placed prior to writing any geometry + Piece. This moves the information to the front of the output file + for visibility and simplifies the logic. + +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 + surfaceFieldWriter.C + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkSurfaceFieldWriter_H +#define foamVtkSurfaceFieldWriter_H + +#include "foamVtkFileWriter.H" +#include "fvMesh.H" +#include "pointField.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace vtk +{ + +/*---------------------------------------------------------------------------*\ + Class vtk::surfaceFieldWriter Declaration +\*---------------------------------------------------------------------------*/ + +class surfaceFieldWriter +: + public vtk::fileWriter +{ + // Private Member Data + + //- Reference to the OpenFOAM mesh (or subset) + const fvMesh& mesh_; + + //- The numer of field points for the current Piece + label numberOfPoints_; + + + // Private Member Functions + + //- Flatten boundary field values into a contiguous list + List<vector> flattenBoundary(const surfaceVectorField& field) const; + + + //- No copy construct + surfaceFieldWriter(const surfaceFieldWriter&) = delete; + + //- No copy assignment + void operator=(const surfaceFieldWriter&) = delete; + + +public: + + // Constructors + + //- Construct from mesh (default format INLINE_BASE64) + surfaceFieldWriter + ( + const fvMesh& mesh, + const vtk::outputOptions opts = vtk::formatType::INLINE_BASE64 + ); + + //- Construct from mesh (default format INLINE_BASE64), + //- and open the file for writing. + // The file name is with/without an extension. + surfaceFieldWriter + ( + const fvMesh& mesh, + const fileName& file, + bool parallel = Pstream::parRun() + ); + + //- Construct from mesh and open the file for writing. + // The file name is with/without an extension. + surfaceFieldWriter + ( + const fvMesh& mesh, + const vtk::outputOptions opts, + const fileName& file, + bool parallel = Pstream::parRun() + ); + + + //- Destructor + virtual ~surfaceFieldWriter() = 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) + { + // No legacy + return vtk::fileExtension[vtk::fileTag::POLY_DATA]; + } + + + //- Write file header (non-collective) + // \note Expected calling states: (OPENED). + virtual bool beginFile(std::string title = ""); + + //- Write cloud positions + // 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 the number of fields, which is required for + // legacy format. + // \note Expected calling states: (PIECE | POINT_DATA). + // + // \return True if the state changed + virtual bool beginCellData(label nFields=0); + + //- Begin PointData output section + // Must be called prior to writing data fields. + // \note Expected calling states: (PIECE). + // + // \return True if the state changed + virtual bool beginPointData(label nFields=0); + + + // Write + + //- Write field + void write(const surfaceVectorField& field); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace vtk +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/vtk/output/foamVtkWriteSurfFields.C b/src/conversion/vtk/output/foamVtkWriteSurfFields.C deleted file mode 100644 index 1742470dbf8..00000000000 --- a/src/conversion/vtk/output/foamVtkWriteSurfFields.C +++ /dev/null @@ -1,171 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2016-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/>. - -\*---------------------------------------------------------------------------*/ - -#include "foamVtkWriteSurfFields.H" -#include "OFstream.H" -#include "emptyFvsPatchFields.H" -#include "fvsPatchFields.H" -#include "surfaceFields.H" -#include "foamVtkOutput.H" - -// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // - -void Foam::vtk::writeSurfFields -( - const fvMesh& mesh, - const fileName& baseName, - const vtk::outputOptions outOpts, - const UPtrList<const surfaceVectorField>& surfVectorFields -) -{ - outputOptions opts(outOpts); - opts.append(false); // No append supported - - const bool legacy_(opts.legacy()); - - std::ofstream os(baseName + (legacy_ ? ".vtk" : ".vtp")); - autoPtr<vtk::formatter> format = opts.newFormatter(os); - - // Same payload size for points and vector fields! - const int nCmpt(3); // vector - const uint64_t payLoad(mesh.nFaces() * 3 * sizeof(float)); - - if (legacy_) - { - legacy::fileHeader(format(), "surfaceFields", vtk::fileTag::POLY_DATA); - legacy::beginPoints(os, mesh.nFaces()); - } - else - { - // XML (inline) - - format() - .xmlHeader() - .xmlComment("surfaceFields") - .beginVTKFile(vtk::fileTag::POLY_DATA, "0.1"); - - // Tricky - hide in beginPiece() - format() - .openTag(vtk::fileTag::PIECE) - .xmlAttr(vtk::fileAttr::NUMBER_OF_POINTS, mesh.nFaces()) - .closeTag(); - - format().tag(vtk::fileTag::POINTS) - .openDataArray<float,3>(vtk::dataArrayAttr::POINTS) - .closeTag(); - } - - const pointField& fc = mesh.faceCentres(); - - format().writeSize(payLoad); - vtk::writeList(format(), fc); - format().flush(); - - if (!legacy_) - { - format() - .endDataArray() - .endTag(vtk::fileTag::POINTS); - } - - - // Fields - if (legacy_) - { - legacy::beginPointData - ( - format(), - mesh.nFaces(), - surfVectorFields.size() - ); - } - else - { - format().tag(vtk::fileTag::POINT_DATA); - } - - // surfVectorFields - forAll(surfVectorFields, fieldi) - { - const auto& fld = surfVectorFields[fieldi]; - - if (legacy_) - { - legacy::floatField<nCmpt>(format(), fld.name(), mesh.nFaces()); - } - else - { - format().openDataArray<float, nCmpt>(fld.name()) - .closeTag(); - } - - format().writeSize(payLoad); - - for (label facei=0; facei < mesh.nInternalFaces(); ++facei) - { - vtk::write(format(), fld[facei]); - } - - forAll(fld.boundaryField(), patchi) - { - const fvPatch& pp = mesh.boundary()[patchi]; - const auto& pf = fld.boundaryField()[patchi]; - - if (isA<emptyFvsPatchVectorField>(pf)) - { - // Note: loop over polypatch size, not fvpatch size. - forAll(pp.patch(), i) - { - vtk::write(format(), vector::zero); - } - } - else - { - vtk::writeList(format(), pf); - } - } - - format().flush(); - - if (!legacy_) - { - format().endDataArray(); - } - } - - if (!legacy_) - { - format().endTag(vtk::fileTag::POINT_DATA); - - // slight cheat. </Piece> too - format().endTag(vtk::fileTag::PIECE); - - format().endTag(vtk::fileTag::POLY_DATA) - .endVTKFile(); - } -} - - -// ************************************************************************* // diff --git a/src/conversion/vtk/output/foamVtkWriteSurfFields.H b/src/conversion/vtk/output/foamVtkWriteSurfFields.H deleted file mode 100644 index ff7e77b00fd..00000000000 --- a/src/conversion/vtk/output/foamVtkWriteSurfFields.H +++ /dev/null @@ -1,67 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ 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/>. - -InNamespace - Foam::vtk - -Description - Write surface fields as vectors - -SourceFiles - foamVtkWriteSurfFields.C - -\*---------------------------------------------------------------------------*/ - -#ifndef foamVtkWriteSurfFields_H -#define foamVtkWriteSurfFields_H - -#include "fvMesh.H" -#include "surfaceMesh.H" -#include "surfaceFieldsFwd.H" -#include "foamVtkOutputOptions.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ -namespace vtk -{ - -//- Write surface vector fields -void writeSurfFields -( - const fvMesh& mesh, - const fileName& baseName, - const vtk::outputOptions outOpts, - const UPtrList<const surfaceVectorField>& surfVectorFields -); - -} // End namespace vtk -} // End namespace Foam - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#endif - -// ************************************************************************* // -- GitLab