ENH: parallel and xml output for vtk topoSet writers (issue #926)

- introduce lower-level vtk::indirectPatchWriter class
This commit is contained in:
Mark Olesen
2018-09-17 15:41:58 +02:00
parent 0e47b0717d
commit 0d2dbaf61b
12 changed files with 1251 additions and 350 deletions

View File

@ -43,9 +43,7 @@ Description
#include "topoSetSource.H" #include "topoSetSource.H"
#include "Fstream.H" #include "Fstream.H"
#include "demandDrivenData.H" #include "demandDrivenData.H"
#include "foamVtkWriteCellSetFaces.H" #include "foamVtkWriteTopoSet.H"
#include "foamVtkWriteFaceSet.H"
#include "foamVtkWritePointSet.H"
#include "IOobjectList.H" #include "IOobjectList.H"
#include "cellZoneSet.H" #include "cellZoneSet.H"
#include "faceZoneSet.H" #include "faceZoneSet.H"
@ -70,47 +68,26 @@ using namespace Foam;
void writeVTK void writeVTK
( (
const polyMesh& mesh, const polyMesh& mesh,
const topoSet& currentSet, const topoSet& currSet,
const fileName& vtkBaseName const fileName& outputName
) )
{ {
if (isA<faceSet>(currentSet)) if
{ (
// Faces of set with OpenFOAM faceID as value !vtk::writeTopoSet
vtk::writeFaceSet
( (
mesh, mesh,
dynamicCast<const faceSet&>(currentSet), currSet,
mesh.time().path()/vtkBaseName, vtk::formatType::INLINE_BASE64, // XML-binary
vtk::formatType::LEGACY_BINARY // vtk::formatType::LEGACY_BINARY,
); outputName,
} false // Not parallel
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
(
mesh,
dynamicCast<const pointSet&>(currentSet),
mesh.time().path()/vtkBaseName,
vtk::formatType::LEGACY_BINARY
);
}
else
{ {
WarningInFunction WarningInFunction
<< "Don't know how to handle set of type " << currentSet.type() << "Don't know how to handle set of type "
<< endl; << currSet.type() << nl;
} }
} }
@ -502,35 +479,35 @@ bool doCommand
if (!noSync) currentSet.sync(mesh); if (!noSync) currentSet.sync(mesh);
// Write // Write
Info<< " Writing " << currentSet.name()
<< " (size "
<< returnReduce(currentSet.size(), sumOp<label>())
<< ") to "
<< (
currentSet.instance()/currentSet.local()
/ currentSet.name()
);
if (writeVTKFile) if (writeVTKFile)
{ {
mkDir(mesh.time().path()/"VTK"/currentSet.name()); fileName outputName
fileName vtkName
( (
"VTK"/currentSet.name()/currentSet.name() mesh.time().path()/"VTK"/currentSet.name()
+ "_" / currentSet.name() + "_"
+ name(mesh.time().timeIndex()) + Foam::name(mesh.time().timeIndex())
); );
mkDir(outputName.path());
Info<< " Writing " << currentSet.name() Info<< " and to vtk file "
<< " (size " << outputName.relative(mesh.time().path())
<< returnReduce(currentSet.size(), sumOp<label>()) << nl << nl;
<< ") to "
<< currentSet.instance()/currentSet.local()
/currentSet.name()
<< " and to vtk file " << vtkName << endl << endl;
writeVTK(mesh, currentSet, vtkName); writeVTK(mesh, currentSet, outputName);
} }
else else
{ {
Info<< " Writing " << currentSet.name() Info<< nl << nl;
<< " (size "
<< returnReduce(currentSet.size(), sumOp<label>())
<< ") to "
<< currentSet.instance()/currentSet.local()
/currentSet.name() << endl << endl;
} }
if (writeCurrentTime) if (writeCurrentTime)

View File

@ -168,8 +168,7 @@ Note
#include "foamVtkPatchWriter.H" #include "foamVtkPatchWriter.H"
#include "foamVtkSurfaceMeshWriter.H" #include "foamVtkSurfaceMeshWriter.H"
#include "foamVtkLagrangianWriter.H" #include "foamVtkLagrangianWriter.H"
#include "foamVtkWriteFaceSet.H" #include "foamVtkWriteTopoSet.H"
#include "foamVtkWritePointSet.H"
#include "foamVtkWriteSurfFields.H" #include "foamVtkWriteSurfFields.H"
#include "memInfo.H" #include "memInfo.H"
@ -629,21 +628,25 @@ int main(int argc, char *argv[])
vtuMeshCells.clear(); vtuMeshCells.clear();
} }
// Attempt topoSets first
bool shortCircuit = false;
// If faceSet: write faceSet only (as polydata) // If faceSet: write faceSet only (as polydata)
if (faceSetName.size()) if (faceSetName.size())
{ {
// Load the faceSet // Load
faceSet set(mesh, faceSetName); faceSet set(mesh, faceSetName);
// Filename as if patch with same name. // Filename as if patch with same name.
mkDir(fvPath/set.name()); const fileName outputName
fileName outputName
( (
fvPath/set.name()/set.name() fvPath/set.name()
+ "_" / set.name() + "_" + timeDesc
+ timeDesc
); );
mkDir(outputName.path());
Info<< " faceSet : " Info<< " faceSet : "
<< outputName.relative(runTime.path()) << nl; << outputName.relative(runTime.path()) << nl;
@ -651,27 +654,29 @@ int main(int argc, char *argv[])
( (
meshProxy.mesh(), meshProxy.mesh(),
set, set,
fmtType,
outputName, outputName,
fmtType false // In parallel (later)
); );
continue;
shortCircuit = true;
} }
// If pointSet: write pointSet only (as polydata) // If pointSet: write pointSet only (as polydata)
if (pointSetName.size()) if (pointSetName.size())
{ {
// Load the pointSet // Load
pointSet set(mesh, pointSetName); pointSet set(mesh, pointSetName);
// Filename as if patch with same name. // Filename as if patch with same name.
mkDir(fvPath/set.name()); const fileName outputName
fileName outputName
( (
fvPath/set.name()/set.name() fvPath/set.name()
+ "_" / set.name() + "_" + timeDesc
+ timeDesc
); );
mkDir(outputName.path());
Info<< " pointSet : " Info<< " pointSet : "
<< outputName.relative(runTime.path()) << nl; << outputName.relative(runTime.path()) << nl;
@ -679,9 +684,16 @@ int main(int argc, char *argv[])
( (
meshProxy.mesh(), meshProxy.mesh(),
set, set,
fmtType,
outputName, outputName,
fmtType false // In parallel (later)
); );
shortCircuit = true;
}
if (shortCircuit)
{
continue; continue;
} }

View File

@ -297,6 +297,8 @@ meshStructure/meshStructure.C
meshStructure/topoDistanceData.C meshStructure/topoDistanceData.C
meshStructure/pointTopoDistanceData.C meshStructure/pointTopoDistanceData.C
output/foamVtkIndPatchWriter.C
output/foamVtkWriteTopoSet.C
output/foamVtkWriteFaceSet.C output/foamVtkWriteFaceSet.C
output/foamVtkWritePointSet.C output/foamVtkWritePointSet.C
output/foamVtkWriteCellSetFaces.C output/foamVtkWriteCellSetFaces.C

View File

@ -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);
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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();
}
}
// ************************************************************************* //

View File

@ -2,8 +2,8 @@
========= | ========= |
\\ / 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 OpenFOAM Foundation \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -23,36 +23,34 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "foamVtkWriteCellSetFaces.H" #include "foamVtkWriteTopoSet.H"
#include "foamVtkOutputOptions.H" #include "foamVtkIndPatchWriter.H"
#include "OFstream.H" #include "polyMesh.H"
#include "primitiveMesh.H"
#include "cellSet.H" #include "cellSet.H"
#include "uindirectPrimitivePatch.H" #include "globalIndex.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
void Foam::vtk::writeCellSetFaces bool Foam::vtk::writeCellSetFaces
( (
const primitiveMesh& mesh, const polyMesh& mesh,
const cellSet& set, const cellSet& set,
const fileName& baseName, const vtk::outputOptions opts,
const vtk::outputOptions outOpts const fileName& file,
bool parallel
) )
{ {
outputOptions opts(outOpts); typedef IndirectList<face> FaceListType;
opts.legacy(true); // Legacy only, no xml, no append
const bool legacy_(opts.legacy()); const globalIndex cellIdOffset(mesh.nCells());
std::ofstream os(baseName + (legacy_ ? ".vtk" : ".vtp")); indirectPrimitivePatch pp
(
FaceListType(mesh.faces(), labelList()),
mesh.points()
);
FaceListType& faces = pp;
autoPtr<vtk::formatter> format = opts.newFormatter(os);
if (legacy_)
{
legacy::fileHeader(format(), set.name(), vtk::fileTag::POLY_DATA);
}
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -87,57 +85,48 @@ void Foam::vtk::writeCellSetFaces
} }
} }
const labelList faceLabels(cellFaces.sortedToc()); // Use these faces
labelList faceValues(cellFaces.size()); 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 const label off = cellIdOffset.localStart();
(
UIndirectList<face>(mesh.faces(), faceLabels), forAll(faceValues, facei)
mesh.points() {
); faceValues[facei] = cellFaces[faceIds[facei]] + off;
}
}
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Write points and faces as polygons indirectPatchWriter writer(pp, opts);
legacy::beginPoints(os, pp.nPoints());
vtk::writeList(format(), pp.localPoints()); writer.open(file, parallel);
format().flush();
// connectivity count without additional storage (done internally) writer.beginFile(set.name());
uint64_t nConnectivity = 0; writer.writeGeometry();
forAll(pp, facei)
//-------------------------------------------------------------------------
// CellData - cellID only
{ {
nConnectivity += pp[facei].size(); writer.beginCellData(1);
writer.write("faceID", faceValues);
// End CellData/PointData is implicit
} }
legacy::beginPolys(os, pp.size(), nConnectivity); writer.close();
return true;
// 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();
// Write data - faceId/cellId
legacy::beginCellData(format(), pp.size(), 1);
os << "cellID 1 " << pp.size() << " int" << nl;
vtk::writeList(format(), faceValues);
format().flush();
} }

View File

@ -2,8 +2,8 @@
========= | ========= |
\\ / 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 OpenFOAM Foundation \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -23,85 +23,62 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "foamVtkWriteFaceSet.H" #include "foamVtkWriteTopoSet.H"
#include "foamVtkOutputOptions.H" #include "foamVtkIndPatchWriter.H"
#include "OFstream.H" #include "polyMesh.H"
#include "primitiveMesh.H"
#include "faceSet.H" #include "faceSet.H"
#include "uindirectPrimitivePatch.H" #include "globalIndex.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
void Foam::vtk::writeFaceSet bool Foam::vtk::writeFaceSet
( (
const primitiveMesh& mesh, const polyMesh& mesh,
const faceSet& set, const faceSet& set,
const fileName& baseName, const vtk::outputOptions opts,
const vtk::outputOptions outOpts const fileName& file,
bool parallel
) )
{ {
outputOptions opts(outOpts); typedef IndirectList<face> FaceListType;
opts.legacy(true); // Legacy only, no xml, no append
const bool legacy_(opts.legacy()); const globalIndex faceIdOffset(mesh.nFaces());
std::ofstream os(baseName + (legacy_ ? ".vtk" : ".vtp")); indirectPrimitivePatch pp
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
( (
UIndirectList<face>(mesh.faces(), faceLabels), FaceListType(mesh.faces(), labelList()),
mesh.points() mesh.points()
); );
FaceListType& faces = pp;
// Use the faces from faceSet
faces.resetAddressing(set.sortedToc());
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Write points and faces as polygons indirectPatchWriter writer(pp, opts);
legacy::beginPoints(os, pp.nPoints());
vtk::writeList(format(), pp.localPoints()); writer.open(file, parallel);
format().flush();
// connectivity count without additional storage (done internally) writer.beginFile(set.name());
uint64_t nConnectivity = 0; writer.writeGeometry();
forAll(pp, facei)
// CellData - faceID only
{ {
nConnectivity += pp[facei].size(); writer.beginCellData(1);
labelField faceValues(faces.addressing());
faceValues += faceIdOffset.localStart();
writer.write("faceID", faceValues);
// End CellData/PointData is implicit
} }
legacy::beginPolys(os, pp.size(), nConnectivity);
writer.close();
// legacy: size + connectivity together return true;
// [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();
// Write data - faceId/cellId
legacy::beginCellData(format(), pp.size(), 1);
os << "faceID 1 " << pp.size() << " int" << nl;
vtk::writeList(format(), faceLabels);
format().flush();
} }

View File

@ -2,8 +2,8 @@
========= | ========= |
\\ / 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 OpenFOAM Foundation \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -23,53 +23,209 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "foamVtkWritePointSet.H" #include <fstream>
#include "foamVtkOutputOptions.H" #include "foamVtkWriteTopoSet.H"
#include "OFstream.H" #include "polyMesh.H"
#include "primitiveMesh.H"
#include "pointSet.H" #include "pointSet.H"
#include "globalIndex.H"
#include "OSspecific.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
void Foam::vtk::writePointSet bool Foam::vtk::writePointSet
( (
const primitiveMesh& mesh, const polyMesh& mesh,
const pointSet& set, const pointSet& set,
const fileName& baseName, const vtk::outputOptions opts,
const vtk::outputOptions outOpts const fileName& file,
bool parallel
) )
{ {
outputOptions opts(outOpts); vtk::outputOptions opts_(opts);
opts.legacy(true); // Legacy only, no xml, no append 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)
{ {
legacy::fileHeader(format(), set.name(), vtk::fileTag::POLY_DATA); 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 labelList pointLabels(set.sortedToc()); const globalIndex pointIdOffset(mesh.nPoints());
// Write points labelField pointLabels(set.sortedToc());
legacy::beginPoints(os, pointLabels.size());
vtk::writeList(format(), mesh.points(), pointLabels); label numberOfPoints = pointLabels.size();
format().flush();
// Write data - pointID if (parallel)
legacy::beginPointData(format(), pointLabels.size(), 1); {
reduce(numberOfPoints, sumOp<label>());
}
os << "pointID 1 " << pointLabels.size() << " int" << nl; if (format)
{
const auto& title = set.name();
vtk::writeList(format(), pointLabels); if (legacy)
format().flush(); {
// 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);
}
}
//-------------------------------------------------------------------------
// pointLabels are the addressing for an indirect list
if (parallel)
{
vtk::writeListParallel(format(), mesh.points(), pointLabels);
}
else
{
vtk::writeList(format(), mesh.points(), pointLabels);
}
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();
}
}
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);
}
}
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;
} }

View File

@ -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
// ************************************************************************* //

View File

@ -2,8 +2,8 @@
========= | ========= |
\\ / 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 OpenFOAM Foundation \\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -21,53 +21,65 @@ License
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. 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 #include "foamVtkWriteTopoSet.H"
#define foamVtkWriteFaceSet_H #include "polyMesh.H"
#include "topoSet.H"
#include "foamVtkOutputOptions.H" #include "faceSet.H"
#include "cellSet.H"
#include "pointSet.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam bool Foam::vtk::writeTopoSet
{
// 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
( (
const primitiveMesh& mesh, const polyMesh& mesh,
const faceSet& set, const topoSet& set,
const fileName& baseName, const vtk::outputOptions opts,
const vtk::outputOptions outOpts 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;
} // End namespace vtk return false;
} // End namespace Foam }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* // // ************************************************************************* //

View File

@ -2,7 +2,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) 2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -25,20 +25,21 @@ InNamespace
Foam::vtk Foam::vtk
Description Description
Write faces of cellSet to vtk polydata file. Write topoSet in VTK format
The data are the original cell ids
SourceFiles SourceFiles
foamVtkWriteTopoSet.C
foamVtkWriteCellSetFaces.C foamVtkWriteCellSetFaces.C
foamVtkWriteFaceSet.C
foamVtkWritePointSet.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef foamVtkWriteCellSetFaces_H #ifndef foamVtkWriteCellSetFaces_H
#define foamVtkWriteCellSetFaces_H #define foamVtkWriteCellSetFaces_H
#include "primitiveMesh.H" #include "fileName.H"
#include "uindirectPrimitivePatch.H" #include "UPstream.H"
#include "foamVtkOutputOptions.H" #include "foamVtkOutputOptions.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -47,27 +48,74 @@ namespace Foam
{ {
// Forward declarations // Forward declarations
class primitiveMesh; class polyMesh;
class topoSet;
class faceSet;
class cellSet; class cellSet;
class fileName; class pointSet;
namespace vtk 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. //- Write perimeter faces of cellset to vtk polydata file.
// The data are the original cell ids // 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 cellSet& set,
const fileName& baseName, const vtk::outputOptions opts,
const vtk::outputOptions outOpts 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 vtk
} // End namespace Foam } // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif #endif