ENH: parallel output for vtk::surfaceMeshWriter (#926)

This commit is contained in:
Mark Olesen
2018-09-13 13:48:14 +02:00
parent 1adac97150
commit c214d30473
5 changed files with 101 additions and 455 deletions

View File

@ -26,7 +26,6 @@ polyDualMesh/polyDualMesh.C
vtk/output/foamVtkInternalWriter.H vtk/output/foamVtkInternalWriter.H
vtk/output/foamVtkPatchWriter.H vtk/output/foamVtkPatchWriter.H
vtk/output/foamVtkSurfaceMeshWriter.C
vtk/output/foamVtkWriteSurfFields.C vtk/output/foamVtkWriteSurfFields.C
LIB = $(FOAM_LIBBIN)/libconversion LIB = $(FOAM_LIBBIN)/libconversion

View File

@ -1,264 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 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/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkSurfaceMeshWriter.H"
#include "foamVtkOutput.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::vtk::surfaceMeshWriter::beginPiece()
{
if (!legacy_)
{
format()
.openTag(vtk::fileTag::PIECE)
.xmlAttr(vtk::fileAttr::NUMBER_OF_POINTS, pp_.nPoints())
.xmlAttr(vtk::fileAttr::NUMBER_OF_POLYS, pp_.size())
.closeTag();
}
}
void Foam::vtk::surfaceMeshWriter::writePoints()
{
const uint64_t payLoad = (pp_.nPoints()*3*sizeof(float));
if (legacy_)
{
legacy::beginPoints(os_, pp_.nPoints());
}
else
{
format().tag(vtk::fileTag::POINTS)
.openDataArray<float, 3>(vtk::dataArrayAttr::POINTS)
.closeTag();
}
format().writeSize(payLoad);
vtk::writeList(format(), pp_.localPoints());
format().flush();
if (!legacy_)
{
format()
.endDataArray()
.endTag(vtk::fileTag::POINTS);
}
}
void Foam::vtk::surfaceMeshWriter::writePolysLegacy()
{
// connectivity count without additional storage (done internally)
uint64_t nConnectivity = 0;
forAll(pp_, facei)
{
nConnectivity += pp_[facei].size();
}
legacy::beginPolys(os_, pp_.size(), nConnectivity);
// legacy: size + connectivity together
// [nPts, id1, id2, ..., nPts, id1, id2, ...]
forAll(pp_, facei)
{
const face& f = pp_.localFaces()[facei];
format().write(f.size()); // The size prefix
vtk::writeList(format(), f);
}
format().flush();
}
void Foam::vtk::surfaceMeshWriter::writePolys()
{
//
// 'connectivity'
//
format().tag(vtk::fileTag::POLYS);
//
// 'connectivity'
//
{
// payload count
uint64_t payLoad = 0;
forAll(pp_, facei)
{
payLoad += pp_[facei].size();
}
format().openDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY)
.closeTag();
// payload size
format().writeSize(payLoad * sizeof(label));
forAll(pp_, facei)
{
const face& f = pp_.localFaces()[facei];
vtk::writeList(format(), f);
}
format().flush();
format()
.endDataArray();
}
//
// 'offsets' (connectivity offsets)
//
{
format()
.openDataArray<label>(vtk::dataArrayAttr::OFFSETS)
.closeTag();
// payload size
format().writeSize(pp_.size() * sizeof(label));
label off = 0;
forAll(pp_, facei)
{
off += pp_[facei].size();
format().write(off);
}
format().flush();
format().endDataArray();
}
format().endTag(vtk::fileTag::POLYS);
}
void Foam::vtk::surfaceMeshWriter::writeMesh()
{
writePoints();
if (legacy_)
{
writePolysLegacy();
}
else
{
writePolys();
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::vtk::surfaceMeshWriter::surfaceMeshWriter
(
const indirectPrimitivePatch& pp,
const word& name,
const fileName& baseName,
const vtk::outputOptions outOpts
)
:
pp_(pp),
legacy_(outOpts.legacy()),
format_(),
os_()
{
outputOptions opts(outOpts);
opts.append(false); // No append supported
os_.open((baseName + (legacy_ ? ".vtk" : ".vtp")).c_str());
format_ = opts.newFormatter(os_);
if (legacy_)
{
legacy::fileHeader(format(), name, vtk::fileTag::POLY_DATA);
}
else
{
// XML (inline)
format()
.xmlHeader()
.xmlComment(name)
.beginVTKFile(vtk::fileTag::POLY_DATA, "0.1");
}
beginPiece();
writeMesh();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::vtk::surfaceMeshWriter::~surfaceMeshWriter()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtk::surfaceMeshWriter::beginCellData(label nFields)
{
if (legacy_)
{
legacy::beginCellData(format(), pp_.size(), nFields);
}
else
{
format().beginCellData();
}
}
void Foam::vtk::surfaceMeshWriter::endCellData()
{
if (!legacy_)
{
format().endCellData();
}
}
void Foam::vtk::surfaceMeshWriter::writeFooter()
{
if (!legacy_)
{
// slight cheat. </Piece> too
format().endTag(vtk::fileTag::PIECE);
format().endTag(vtk::fileTag::POLY_DATA)
.endVTKFile();
}
}
// ************************************************************************* //

View File

@ -25,10 +25,19 @@ Class
Foam::vtk::surfaceMeshWriter Foam::vtk::surfaceMeshWriter
Description Description
Write faces with fields Write faces (eg face-zones or face-sets) with fields.
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 SourceFiles
foamVtkSurfaceMeshWriter.C
foamVtkSurfaceMeshWriterTemplates.C foamVtkSurfaceMeshWriterTemplates.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -36,106 +45,28 @@ SourceFiles
#ifndef foamVtkSurfaceMeshWriter_H #ifndef foamVtkSurfaceMeshWriter_H
#define foamVtkSurfaceMeshWriter_H #define foamVtkSurfaceMeshWriter_H
#include "pointMesh.H" #include <fstream>
#include "OFstream.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "areaFields.H" #include "areaFields.H"
#include "indirectPrimitivePatch.H" #include "surfaceFields.H"
#include "foamVtkOutputOptions.H" #include "foamVtkIndPatchWriter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
class volPointInterpolation;
namespace vtk namespace vtk
{ {
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class surfaceMeshWriter Declaration Class vtk::surfaceMeshWriter Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
class surfaceMeshWriter class surfaceMeshWriter
:
public vtk::indirectPatchWriter
{ {
// Private Member Data
const indirectPrimitivePatch& pp_;
//- Commonly used query
const bool legacy_;
autoPtr<vtk::formatter> format_;
std::ofstream os_;
// Private Member Functions // Private Member Functions
//- Begin piece
void beginPiece();
//- Write patch points
void writePoints();
//- Write patch faces
void writePolysLegacy();
//- Write patch faces
void writePolys();
//- Write mesh topology
void writeMesh();
//- No copy construct
surfaceMeshWriter(const surfaceMeshWriter&) = delete;
//- No copy assignment
void operator=(const surfaceMeshWriter&) = delete;
public:
// Constructors
//- Construct from components
surfaceMeshWriter
(
const indirectPrimitivePatch& pp,
const word& name,
const fileName& baseName,
const vtk::outputOptions outOpts
);
//- Destructor
~surfaceMeshWriter();
// Member Functions
inline std::ofstream& os()
{
return os_;
}
inline vtk::formatter& format()
{
return *format_;
}
//- Open write for CellData of count fields.
// The parameters are only used for the legacy format.
void beginCellData(label nFields);
//- Close write for CellData
void endCellData();
//- Write file footer
void writeFooter();
//- Get face field (internal face or boundary face) //- Get face field (internal face or boundary face)
template<class Type> template<class Type>
tmp<Field<Type>> getFaceField tmp<Field<Type>> getFaceField
@ -144,44 +75,73 @@ public:
) const; ) const;
// Write fields (individually) //- No copy construct
surfaceMeshWriter(const surfaceMeshWriter&) = delete;
//- Write surface field //- No copy assignment
void operator=(const surfaceMeshWriter&) = delete;
public:
// Constructors
//- Construct from patch (default format INLINE_BASE64)
surfaceMeshWriter
(
const indirectPrimitivePatch& pp,
const vtk::outputOptions opts = vtk::formatType::INLINE_BASE64
)
:
vtk::indirectPatchWriter(pp, opts)
{}
//- Construct from patch (default format INLINE_BASE64),
//- and open the file for writing.
// The file name is with/without an extension.
surfaceMeshWriter
(
const indirectPrimitivePatch& pp,
const fileName& file,
bool parallel = Pstream::parRun()
)
:
vtk::indirectPatchWriter(pp, file, parallel)
{}
//- Construct from patch and open the file for writing.
// The file name is with/without an extension.
surfaceMeshWriter
(
const indirectPrimitivePatch& pp,
const vtk::outputOptions opts,
const fileName& file,
bool parallel = Pstream::parRun()
)
:
vtk::indirectPatchWriter(pp, opts, file, parallel)
{}
//- Destructor
virtual ~surfaceMeshWriter() = default;
// Member Functions
//- Write surface field (CellData)
template<class Type> template<class Type>
void write void write
( (
const GeometricField<Type, fvsPatchField, surfaceMesh>& field const GeometricField<Type, fvsPatchField, surfaceMesh>& field
); );
//- Write surface field //- Write surface field (CellData)
template<class Type> template<class Type>
void write void write
( (
const GeometricField<Type, faPatchField, areaMesh>& field const GeometricField<Type, faPatchField, areaMesh>& field
); );
// Write fields (collectively)
//- Write surface fields
template<class Type>
void write
(
const UPtrList
<
const GeometricField<Type, fvsPatchField, surfaceMesh>
>& sflds
);
//- Write surface fields
template<class Type>
void write
(
const UPtrList
<
const GeometricField<Type, faPatchField, areaMesh>
>& sflds
);
}; };

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. \\/ M anipulation | Copyright (C) 2016-2018 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -23,9 +23,7 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "foamVtkSurfaceMeshWriter.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type> template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::tmp<Foam::Field<Type>>
@ -36,56 +34,50 @@ Foam::vtk::surfaceMeshWriter::getFaceField
{ {
const polyBoundaryMesh& patches = sfld.mesh().boundaryMesh(); const polyBoundaryMesh& patches = sfld.mesh().boundaryMesh();
tmp<Field<Type>> tfld(new Field<Type>(pp_.size())); const labelList& faceAddr = this->patch().addressing();
Field<Type>& fld = tfld.ref();
forAll(pp_.addressing(), i) auto tfld = tmp<Field<Type>>::New(faceAddr.size());
auto iter = tfld.ref().begin();
for (const label facei : faceAddr)
{ {
const label facei = pp_.addressing()[i];
const label patchi = patches.whichPatch(facei); const label patchi = patches.whichPatch(facei);
if (patchi == -1) if (patchi == -1)
{ {
fld[i] = sfld[facei]; *iter = sfld[facei];
} }
else else
{ {
const label localFacei = facei - patches[patchi].start(); const label localFacei = facei - patches[patchi].start();
fld[i] = sfld.boundaryField()[patchi][localFacei]; *iter = sfld.boundaryField()[patchi][localFacei];
} }
++iter;
} }
return tfld; return tfld;
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type> template<class Type>
void Foam::vtk::surfaceMeshWriter::write void Foam::vtk::surfaceMeshWriter::write
( (
const GeometricField<Type, fvsPatchField, surfaceMesh>& field const GeometricField<Type, fvsPatchField, surfaceMesh>& field
) )
{ {
const int nCmpt(pTraits<Type>::nComponents); if (notState(outputState::CELL_DATA))
const uint64_t payLoad(pp_.size() * nCmpt * sizeof(float));
if (legacy_)
{ {
legacy::floatField<nCmpt>(format(), field.name(), pp_.size()); FatalErrorInFunction
} << "Bad writer state (" << stateNames[state_]
else << ") - should be (" << stateNames[outputState::CELL_DATA]
{ << ") for field " << field.name() << nl << endl
format().openDataArray<float, nCmpt>(field.name()).closeTag(); << exit(FatalError);
} }
format().writeSize(payLoad); this->indirectPatchWriter::write(field.name(), getFaceField(field)());
vtk::writeList(format(), getFaceField(field)());
format().flush();
if (!legacy_)
{
format().endDataArray();
}
} }
@ -95,59 +87,16 @@ void Foam::vtk::surfaceMeshWriter::write
const GeometricField<Type, faPatchField, areaMesh>& field const GeometricField<Type, faPatchField, areaMesh>& field
) )
{ {
const int nCmpt(pTraits<Type>::nComponents); if (notState(outputState::CELL_DATA))
const uint64_t payLoad(pp_.size() * nCmpt * sizeof(float));
if (legacy_)
{ {
legacy::floatField<nCmpt>(format(), field.name(), pp_.size()); FatalErrorInFunction
} << "Bad writer state (" << stateNames[state_]
else << ") - should be (" << stateNames[outputState::CELL_DATA]
{ << ") for field " << field.name() << nl << endl
format().openDataArray<float, nCmpt>(field.name()).closeTag(); << exit(FatalError);
} }
format().writeSize(payLoad); this->indirectPatchWriter::write(field.name(), field.primitiveField());
vtk::writeList(format(), field.primitiveField());
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
template<class Type>
void Foam::vtk::surfaceMeshWriter::write
(
const UPtrList
<
const GeometricField<Type, fvsPatchField, surfaceMesh>
>& sflds
)
{
for (const auto& field : sflds)
{
write(field);
}
}
template<class Type>
void Foam::vtk::surfaceMeshWriter::write
(
const UPtrList
<
const GeometricField<Type, faPatchField, areaMesh>
>& sflds
)
{
for (const auto& field : sflds)
{
write(field);
}
} }

View File

@ -2,6 +2,7 @@ EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/finiteArea/lnInclude \ -I$(LIB_SRC)/finiteArea/lnInclude \
-I$(LIB_SRC)/fileFormats/lnInclude \ -I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/conversion/lnInclude \ -I$(LIB_SRC)/conversion/lnInclude \
-I$(LIB_SRC)/sampling/lnInclude \ -I$(LIB_SRC)/sampling/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \ -I$(LIB_SRC)/dynamicMesh/lnInclude \
@ -12,6 +13,7 @@ EXE_INC = \
LIB_LIBS = \ LIB_LIBS = \
-lfiniteVolume \ -lfiniteVolume \
-lfiniteArea \ -lfiniteArea \
-lmeshTools \
-lconversion \ -lconversion \
-lsampling \ -lsampling \
-ldynamicMesh \ -ldynamicMesh \