ENH: add VTP, VTU output for most vtk writers (insitu only)

- with the xml append format it is possible to write raw binary
  (instead of base64), but the writer becomes more complicated.
  Either needs two passes to create, or need to allocate a block
  of space for the header information (like VTK itself does) and
  write later.

    * internalWriter
    * patchWriter
    * surfaceMeshWriter
    * lagrangianWriter

 Also these special purpose ones:
    * foamVtkWriteSurfFields
This commit is contained in:
Mark Olesen
2017-06-01 18:28:40 +02:00
parent c4f1349496
commit a2e978d43e
25 changed files with 1762 additions and 435 deletions

View File

@ -25,51 +25,62 @@ License
#include "foamVtkInternalWriter.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::foamVtkOutput::internalWriter::internalWriter
(
const fvMesh& mesh,
const foamVtkCells& cells,
const fileName& baseName,
const foamVtkOutput::outputOptions outOpts
)
:
mesh_(mesh),
format_(),
vtkCells_(cells),
os_()
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::foamVtkOutput::internalWriter::beginPiece()
{
outputOptions opts(outOpts);
opts.legacy(true); // Legacy only, no append
os_.open((baseName + (opts.legacy() ? ".vtk" : ".vtu")).c_str());
format_ = opts.newFormatter(os_);
if (opts.legacy())
if (!legacy_)
{
foamVtkOutput::legacy::fileHeader(format(), mesh.time().caseName())
<< "DATASET UNSTRUCTURED_GRID" << nl;
format()
.openTag(vtkFileTag::PIECE)
( "NumberOfPoints", vtkCells_.nFieldPoints() )
( "NumberOfCells", vtkCells_.nFieldCells() )
.closeTag();
}
}
void Foam::foamVtkOutput::internalWriter::writePoints()
{
// payload size
const uint64_t payLoad = (vtkCells_.nFieldPoints() * 3 * sizeof(float));
if (legacy_)
{
legacy::beginPoints(os_, vtkCells_.nFieldPoints());
}
else
{
format()
.tag(vtkFileTag::POINTS)
.openDataArray<float,3>(vtkFileTag::POINTS)
.closeTag();
}
//------------------------------------------------------------------
//
// Write topology
//
//------------------------------------------------------------------
format().writeSize(payLoad);
os_ << "POINTS " << vtkCells_.nFieldPoints() << " float" << nl;
foamVtkOutput::writeList(format(), mesh.points());
const pointField& ctrs = mesh.cellCentres();
foamVtkOutput::writeList(format(), ctrs, vtkCells_.addPointCellLabels());
foamVtkOutput::writeList(format(), mesh_.points());
foamVtkOutput::writeList
(
format(),
mesh_.cellCentres(),
vtkCells_.addPointCellLabels()
);
format().flush();
//
// Write cells
//
if (!legacy_)
{
format()
.endDataArray()
.endTag(vtkFileTag::POINTS);
}
}
void Foam::foamVtkOutput::internalWriter::writeCellsLegacy()
{
const List<uint8_t>& cellTypes = vtkCells_.cellTypes();
const labelList& vertLabels = vtkCells_.vertLabels();
@ -90,6 +101,177 @@ Foam::foamVtkOutput::internalWriter::internalWriter
}
void Foam::foamVtkOutput::internalWriter::writeCells()
{
format().tag(vtkFileTag::CELLS);
//
// 'connectivity'
//
{
const labelList& vertLabels = vtkCells_.vertLabels();
const uint64_t payLoad = vertLabels.size() * sizeof(label);
format().openDataArray<label>("connectivity")
.closeTag();
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), vertLabels);
format().flush();
format().endDataArray();
}
//
// 'offsets' (connectivity offsets)
//
{
const labelList& vertOffsets = vtkCells_.vertOffsets();
const uint64_t payLoad = vertOffsets.size() * sizeof(label);
format().openDataArray<label>("offsets")
.closeTag();
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), vertOffsets);
format().flush();
format().endDataArray();
}
//
// 'types' (cell types)
//
{
const List<uint8_t>& cellTypes = vtkCells_.cellTypes();
const uint64_t payLoad = cellTypes.size() * sizeof(uint8_t);
format().openDataArray<uint8_t>("types")
.closeTag();
format().writeSize(payLoad);
forAll(cellTypes, i)
{
// No nComponents for char, cannot use foamVtkOutput::writeList here
format().write(cellTypes[i]);
}
format().flush();
format().endDataArray();
}
//
// can quit here if there are NO face streams
//
if (vtkCells_.faceLabels().empty())
{
format().endTag(vtkFileTag::CELLS);
return;
}
// --------------------------------------------------
//
// 'faces' (face streams)
//
{
const labelList& faceLabels = vtkCells_.faceLabels();
const uint64_t payLoad = faceLabels.size() * sizeof(label);
format().openDataArray<label>("faces")
.closeTag();
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), faceLabels);
format().flush();
format().endDataArray();
}
// 'faceoffsets' (face stream offsets)
// -1 to indicate that the cell is a primitive type that does not
// have a face stream
{
const labelList& faceOffsets = vtkCells_.faceOffsets();
const uint64_t payLoad = faceOffsets.size() * sizeof(label);
format().openDataArray<label>("faceoffsets")
.closeTag();
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), faceOffsets);
format().flush();
format().endDataArray();
}
format().endTag(vtkFileTag::CELLS);
}
void Foam::foamVtkOutput::internalWriter::writeMesh()
{
writePoints();
if (legacy_)
{
writeCellsLegacy();
}
else
{
writeCells();
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::foamVtkOutput::internalWriter::internalWriter
(
const fvMesh& mesh,
const foamVtkCells& cells,
const fileName& baseName,
const foamVtkOutput::outputOptions outOpts
)
:
mesh_(mesh),
legacy_(outOpts.legacy()),
format_(),
vtkCells_(cells),
os_()
{
outputOptions opts(outOpts);
opts.append(false); // No append supported
os_.open((baseName + (legacy_ ? ".vtk" : ".vtu")).c_str());
format_ = opts.newFormatter(os_);
const auto& title = mesh_.time().caseName();
if (legacy_)
{
legacy::fileHeader(format(), title, vtkFileTag::UNSTRUCTURED_GRID);
}
else
{
// XML (inline)
format()
.xmlHeader()
.xmlComment(title)
.beginVTKFile(vtkFileTag::UNSTRUCTURED_GRID, "0.1");
}
beginPiece();
writeMesh();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::foamVtkOutput::internalWriter::~internalWriter()
@ -101,43 +283,98 @@ Foam::foamVtkOutput::internalWriter::~internalWriter()
void Foam::foamVtkOutput::internalWriter::beginCellData(label nFields)
{
foamVtkOutput::legacy::cellDataHeader
(
os(),
vtkCells_.nFieldCells(),
nFields
);
if (legacy_)
{
legacy::dataHeader
(
os(),
vtkFileTag::CELL_DATA,
vtkCells_.nFieldCells(),
nFields
);
}
else
{
format().tag(vtkFileTag::CELL_DATA);
}
}
void Foam::foamVtkOutput::internalWriter::endCellData()
{}
{
if (!legacy_)
{
format().endTag(vtkFileTag::CELL_DATA);
}
}
void Foam::foamVtkOutput::internalWriter::beginPointData(label nFields)
{
foamVtkOutput::legacy::pointDataHeader
(
os(),
vtkCells_.nFieldPoints(),
nFields
);
if (legacy_)
{
legacy::dataHeader
(
os(),
vtkFileTag::POINT_DATA,
vtkCells_.nFieldPoints(),
nFields
);
}
else
{
format().tag(vtkFileTag::POINT_DATA);
}
}
void Foam::foamVtkOutput::internalWriter::endPointData()
{}
{
if (!legacy_)
{
format().endTag(vtkFileTag::POINT_DATA);
}
}
void Foam::foamVtkOutput::internalWriter::writeFooter()
{
if (!legacy_)
{
// slight cheat. </Piece> too
format().endTag(vtkFileTag::PIECE);
format().endTag(vtkFileTag::UNSTRUCTURED_GRID)
.endVTKFile();
}
}
void Foam::foamVtkOutput::internalWriter::writeCellIDs()
{
const labelList& cellMap = vtkCells_.cellMap();
// Cell ids first
os_ << "cellID 1 " << vtkCells_.nFieldCells() << " int" << nl;
const labelList& cellMap = vtkCells_.cellMap();
const uint64_t payLoad = vtkCells_.nFieldCells() * sizeof(label);
if (legacy_)
{
os_ << "cellID 1 " << vtkCells_.nFieldCells() << " int" << nl;
}
else
{
format().openDataArray<label>("cellID")
.closeTag();
}
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), cellMap);
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}

View File

@ -64,6 +64,9 @@ class internalWriter
//- Reference to the OpenFOAM mesh (or subset)
const fvMesh& mesh_;
//- Commonly used query
const bool legacy_;
autoPtr<foamVtkOutput::formatter> format_;
//- The volume cells (internalMesh)
@ -71,6 +74,32 @@ class internalWriter
std::ofstream os_;
// Private Member Functions
//- Begin piece
void beginPiece();
//- Write mesh points
void writePoints();
//- Write mesh cells
void writeCellsLegacy();
//- Write mesh cells
void writeCells();
//- Write mesh topology
void writeMesh();
//- Disallow default bitwise copy construct
internalWriter(const internalWriter&) = delete;
//- Disallow default bitwise assignment
void operator=(const internalWriter&) = delete;
public:
// Constructors
@ -120,6 +149,10 @@ public:
//- Write cellIDs
void writeCellIDs();
//- Write file footer
void writeFooter();
//- Write internal fields
template<class Type>
void write

View File

@ -36,21 +36,32 @@ void Foam::foamVtkOutput::internalWriter::write
const UPtrList<const DimensionedField<Type, volMesh>>& flds
)
{
const int nCmpt(pTraits<Type>::nComponents);
const labelList& cellMap = vtkCells_.cellMap();
const int nCmpt(pTraits<Type>::nComponents);
// const uint64_t payLoad(cellMap.size() * nCmpt * sizeof(float));
forAll(flds, i)
{
const auto& fld = flds[i];
// Legacy
os()<< fld.name() << ' '
<< nCmpt << ' '
<< cellMap.size() << " float"
<< nl;
if (legacy_)
{
legacy::floatField(os(), fld.name(), nCmpt, cellMap.size());
}
else
{
format().openDataArray<float, nCmpt>(fld.name())
.closeTag();
}
// writeField includes payload size
foamVtkOutput::writeField(format(), fld, cellMap);
if (!legacy_)
{
format().endDataArray();
}
}
}
@ -61,21 +72,32 @@ void Foam::foamVtkOutput::internalWriter::write
const UPtrList<const GeometricField<Type, PatchField, volMesh>>& flds
)
{
const int nCmpt(pTraits<Type>::nComponents);
const labelList& cellMap = vtkCells_.cellMap();
const int nCmpt(pTraits<Type>::nComponents);
// const uint64_t payLoad(cellMap.size() * nCmpt * sizeof(float));
forAll(flds, i)
{
const auto& fld = flds[i];
// Legacy
os()<< fld.name() << ' '
<< nCmpt << ' '
<< cellMap.size() << " float"
<< nl;
if (legacy_)
{
legacy::floatField(os(), fld.name(), nCmpt, cellMap.size());
}
else
{
format().openDataArray<float, nCmpt>(fld.name())
.closeTag();
}
// writeField includes payload size
foamVtkOutput::writeField(format(), fld, cellMap);
if (!legacy_)
{
format().endDataArray();
}
}
}
@ -86,25 +108,27 @@ void Foam::foamVtkOutput::internalWriter::write
const UPtrList<const GeometricField<Type, PatchField, pointMesh>>& flds
)
{
const int nCmpt(pTraits<Type>::nComponents);
const int nVals(vtkCells_.nFieldPoints());
const labelList& addPointCellLabels = vtkCells_.addPointCellLabels();
const int nCmpt(pTraits<Type>::nComponents);
const int nVals(vtkCells_.nFieldPoints());
// Only needed for non-legacy
const uint64_t payLoad
(
nVals * nCmpt * sizeof(float)
);
const uint64_t payLoad(nVals * nCmpt * sizeof(float));
forAll(flds, i)
{
const auto& fld = flds[i];
// Legacy
os()<< fld.name() << ' '
<< nCmpt << ' '
<< nVals << " float"
<< nl;
if (legacy_)
{
legacy::floatField(os(), fld.name(), nCmpt, nVals);
}
else
{
format().openDataArray<float, nCmpt>(fld.name())
.closeTag();
}
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), fld);
@ -116,6 +140,11 @@ void Foam::foamVtkOutput::internalWriter::write
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
}
@ -127,31 +156,38 @@ void Foam::foamVtkOutput::internalWriter::write
const UPtrList<const DimensionedField<Type, volMesh>>& flds
)
{
const int nCmpt(pTraits<Type>::nComponents);
const int nVals(vtkCells_.nFieldPoints());
const labelList& addPointCellLabels = vtkCells_.addPointCellLabels();
const int nCmpt(pTraits<Type>::nComponents);
const int nVals(vtkCells_.nFieldPoints());
// Only needed for non-legacy
const uint64_t payLoad
(
nVals * nCmpt * sizeof(float)
);
const uint64_t payLoad(nVals * nCmpt * sizeof(float));
forAll(flds, i)
{
const auto& vfield = flds[i];
const auto& pfield = pInterp.interpolate(vfield)();
// Legacy
os()<< vfield.name() << ' '
<< nCmpt << ' '
<< nVals << " float"
<< nl;
if (legacy_)
{
legacy::floatField(os(), vfield.name(), nCmpt, nVals);
}
else
{
format().openDataArray<float, nCmpt>(vfield.name())
.closeTag();
}
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), pfield);
foamVtkOutput::writeList(format(), vfield, addPointCellLabels);
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
}
@ -163,31 +199,38 @@ void Foam::foamVtkOutput::internalWriter::write
const UPtrList<const GeometricField<Type, PatchField, volMesh>>& flds
)
{
const int nCmpt(pTraits<Type>::nComponents);
const int nVals(vtkCells_.nFieldPoints());
const labelList& addPointCellLabels = vtkCells_.addPointCellLabels();
const int nCmpt(pTraits<Type>::nComponents);
const int nVals(vtkCells_.nFieldPoints());
// Only needed for non-legacy
const uint64_t payLoad
(
nVals * nCmpt * sizeof(float)
);
const uint64_t payLoad(nVals * nCmpt * sizeof(float));
forAll(flds, i)
{
const auto& vfield = flds[i];
const auto& pfield = pInterp.interpolate(vfield)();
// Legacy
os()<< vfield.name() << ' '
<< nCmpt << ' '
<< nVals << " float"
<< nl;
if (legacy_)
{
legacy::floatField(os(), vfield.name(), nCmpt, nVals);
}
else
{
format().openDataArray<float, nCmpt>(vfield.name())
.closeTag();
}
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), pfield);
foamVtkOutput::writeList(format(), vfield, addPointCellLabels);
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
}

View File

@ -26,6 +26,206 @@ License
#include "foamVtkPatchWriter.H"
#include "foamVtkOutput.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::foamVtkOutput::patchWriter::beginPiece()
{
if (!legacy_)
{
format()
.openTag(vtkFileTag::PIECE)
( "NumberOfPoints", nPoints_ )
( "NumberOfPolys", nFaces_ )
.closeTag();
}
}
void Foam::foamVtkOutput::patchWriter::writePoints()
{
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
// payload count
const uint64_t payLoad = (nPoints_*3* sizeof(float));
if (legacy_)
{
legacy::beginPoints(os_, nPoints_);
}
else
{
format().tag(vtkFileTag::POINTS)
.openDataArray<float, 3>(vtkFileTag::POINTS)
.closeTag();
}
format().writeSize(payLoad);
forAll(patchIDs_, i)
{
const polyPatch& pp = patches[patchIDs_[i]];
foamVtkOutput::writeList(format(), pp.localPoints());
}
format().flush();
if (!legacy_)
{
format()
.endDataArray()
.endTag(vtkFileTag::POINTS);
}
}
void Foam::foamVtkOutput::patchWriter::writePolysLegacy()
{
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
// connectivity count without additional storage (done internally)
uint64_t nConnectivity = 0;
forAll(patchIDs_, i)
{
const polyPatch& pp = patches[patchIDs_[i]];
forAll(pp, facei)
{
nConnectivity += pp[facei].size();
}
}
legacy::beginPolys(os_, nFaces_, nConnectivity);
// legacy: size + connectivity together
// [nPts, id1, id2, ..., nPts, id1, id2, ...]
label off = 0;
forAll(patchIDs_, i)
{
const polyPatch& pp = patches[patchIDs_[i]];
forAll(pp, facei)
{
const face& f = pp.localFaces()[facei];
format().write(f.size()); // The size prefix
forAll(f, fi)
{
format().write(off + f[fi]);
}
}
off += pp.nPoints();
}
format().flush();
}
void Foam::foamVtkOutput::patchWriter::writePolys()
{
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
//
// 'connectivity'
//
format().tag(vtkFileTag::POLYS);
//
// 'connectivity'
//
{
// payload count
uint64_t payLoad = 0;
forAll(patchIDs_, i)
{
const polyPatch& pp = patches[patchIDs_[i]];
forAll(pp, facei)
{
const face& f = pp.localFaces()[facei];
payLoad += f.size();
}
}
format().openDataArray<label>("connectivity")
.closeTag();
// payload size
format().writeSize(payLoad * sizeof(label));
label off = 0;
forAll(patchIDs_, i)
{
const polyPatch& pp = patches[patchIDs_[i]];
forAll(pp, facei)
{
const face& f = pp.localFaces()[facei];
forAll(f, fi)
{
format().write(off + f[fi]);
}
}
off += pp.nPoints();
}
format().flush();
format()
.endDataArray();
}
//
// 'offsets' (connectivity offsets)
//
{
format()
.openDataArray<label>("offsets")
.closeTag();
// payload size
format().writeSize(nFaces_ * sizeof(label));
label off = 0;
forAll(patchIDs_, i)
{
const polyPatch& pp = patches[patchIDs_[i]];
forAll(pp, facei)
{
off += pp[facei].size();
format().write(off);
}
}
format().flush();
format().endDataArray();
}
format().endTag(vtkFileTag::POLYS);
}
void Foam::foamVtkOutput::patchWriter::writeMesh()
{
writePoints();
if (legacy_)
{
writePolysLegacy();
}
else
{
writePolys();
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::foamVtkOutput::patchWriter::patchWriter
@ -38,84 +238,56 @@ Foam::foamVtkOutput::patchWriter::patchWriter
)
:
mesh_(mesh),
legacy_(outOpts.legacy()),
format_(),
nearCellValue_(nearCellValue),
patchIDs_(patchIDs),
os_()
os_(),
nPoints_(0),
nFaces_(0)
{
outputOptions opts(outOpts);
opts.legacy(true); // Legacy only, no append
opts.append(false); // No append
os_.open((baseName + (opts.legacy() ? ".vtk" : ".vtp")).c_str());
os_.open((baseName + (legacy_ ? ".vtk" : ".vtp")).c_str());
format_ = opts.newFormatter(os_);
const polyBoundaryMesh& patches = mesh.boundaryMesh();
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
if (opts.legacy())
{
foamVtkOutput::legacy::fileHeader
(
format(),
(
patchIDs_.size() == 1
? patches[patchIDs_.first()].name()
: "patches"
)
) << "DATASET POLYDATA" << nl;
}
//------------------------------------------------------------------
// Write topology
nPoints_ = 0;
nFaces_ = 0;
label nFaceVerts = 0;
const word& title =
(
patchIDs_.size() == 1
? patches[patchIDs_.first()].name()
: "patches"
);
// Basic sizes
nPoints_ = nFaces_ = 0;
forAll(patchIDs_, i)
{
const polyPatch& pp = patches[patchIDs_[i]];
nPoints_ += pp.nPoints();
nFaces_ += pp.size();
nFaceVerts += pp.size();
forAll(pp, facei)
{
nFaceVerts += pp[facei].size();
}
nFaces_ += pp.size();
}
os_ << "POINTS " << nPoints_ << " float" << nl;
forAll(patchIDs_, i)
if (legacy_)
{
const polyPatch& pp = patches[patchIDs_[i]];
foamVtkOutput::writeList(format(), pp.localPoints());
legacy::fileHeader(format(), title, vtkFileTag::POLY_DATA);
}
format().flush();
os_ << "POLYGONS " << nFaces_ << ' ' << nFaceVerts << nl;
label off = 0;
forAll(patchIDs_, i)
else
{
const polyPatch& pp = patches[patchIDs_[i]];
// XML (inline)
forAll(pp, facei)
{
const face& f = pp.localFaces()[facei];
format().write(f.size());
forAll(f, fi)
{
format().write(off + f[fi]);
}
}
off += pp.nPoints();
format()
.xmlHeader()
.xmlComment(title)
.beginVTKFile(vtkFileTag::POLY_DATA, "0.1");
}
format().flush();
beginPiece();
writeMesh();
}
@ -129,40 +301,107 @@ Foam::foamVtkOutput::patchWriter::~patchWriter()
void Foam::foamVtkOutput::patchWriter::beginCellData(label nFields)
{
foamVtkOutput::legacy::cellDataHeader(os(), nFaces_, nFields);
if (legacy_)
{
legacy::dataHeader
(
os(),
vtkFileTag::CELL_DATA,
nFaces_,
nFields
);
}
else
{
format().tag(vtkFileTag::CELL_DATA);
}
}
void Foam::foamVtkOutput::patchWriter::endCellData()
{}
{
if (!legacy_)
{
format().endTag(vtkFileTag::CELL_DATA);
}
}
void Foam::foamVtkOutput::patchWriter::beginPointData(label nFields)
{
foamVtkOutput::legacy::pointDataHeader(os(), nPoints_, nFields);
if (legacy_)
{
legacy::dataHeader
(
os(),
vtkFileTag::POINT_DATA,
nPoints_,
nFields
);
}
else
{
format().tag(vtkFileTag::POINT_DATA);
}
}
void Foam::foamVtkOutput::patchWriter::endPointData()
{}
{
if (!legacy_)
{
format().endTag(vtkFileTag::POINT_DATA);
}
}
void Foam::foamVtkOutput::patchWriter::writeFooter()
{
if (!legacy_)
{
// slight cheat. </Piece> too
format().endTag(vtkFileTag::PIECE);
format().endTag(vtkFileTag::POLY_DATA)
.endVTKFile();
}
}
void Foam::foamVtkOutput::patchWriter::writePatchIDs()
{
os_ << "patchID 1 " << nFaces_ << " float" << nl;
// Patch ids first
const uint64_t payLoad = nFaces_ * sizeof(label);
if (legacy_)
{
legacy::intField(os_, "patchID", 1, nFaces_);
}
else
{
format().openDataArray<label>("patchID")
.closeTag();
}
format().writeSize(payLoad);
forAll(patchIDs_, i)
{
const label patchId = patchIDs_[i];
const polyPatch& pp = mesh_.boundaryMesh()[patchId];
const label sz = mesh_.boundaryMesh()[patchId].size();
forAll(pp, facei)
for (label facei = 0; facei < sz; ++facei)
{
format().write(patchId);
}
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}

View File

@ -59,20 +59,51 @@ namespace foamVtkOutput
class patchWriter
{
//- Reference to the OpenFOAM mesh (or subset)
const fvMesh& mesh_;
// Private Member Data
autoPtr<foamVtkOutput::formatter> format_;
//- Reference to the OpenFOAM mesh (or subset)
const fvMesh& mesh_;
const bool nearCellValue_;
//- Commonly used query
const bool legacy_;
const labelList patchIDs_;
autoPtr<foamVtkOutput::formatter> format_;
std::ofstream os_;
const bool nearCellValue_;
label nPoints_;
const labelList patchIDs_;
std::ofstream os_;
label nPoints_;
label nFaces_;
// 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();
//- Disallow default bitwise copy construct
patchWriter(const patchWriter&) = delete;
//- Disallow default bitwise assignment
void operator=(const patchWriter&) = delete;
label nFaces_;
public:
@ -132,6 +163,10 @@ public:
//- Write cellIDs
void writePatchIDs();
//- Write file footer
void writeFooter();
//- Write volFields
template<class Type, template<class> class PatchField>
void write

View File

@ -34,13 +34,24 @@ void Foam::foamVtkOutput::patchWriter::write
const UPtrList<const GeometricField<Type, PatchField, volMesh>>& flds
)
{
const int nCmpt(pTraits<Type>::nComponents);
const uint64_t payLoad(nFaces_ * nCmpt * sizeof(float));
forAll(flds, fieldi)
{
const auto& fld = flds[fieldi];
os_ << fld.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< nFaces_ << " float" << nl;
if (legacy_)
{
legacy::floatField(os_, fld.name(), nCmpt, nFaces_);
}
else
{
format().openDataArray<float, nCmpt>(fld.name())
.closeTag();
}
format().writeSize(payLoad);
forAll(patchIDs_, i)
{
@ -57,6 +68,11 @@ void Foam::foamVtkOutput::patchWriter::write
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
}
@ -67,13 +83,24 @@ void Foam::foamVtkOutput::patchWriter::write
const UPtrList<const GeometricField<Type, PatchField, pointMesh>>& flds
)
{
const int nCmpt(pTraits<Type>::nComponents);
const uint64_t payLoad(nPoints_ * nCmpt * sizeof(float));
forAll(flds, fieldi)
{
const auto& fld = flds[fieldi];
os_ << fld.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< nPoints_ << " float" << nl;
if (legacy_)
{
legacy::floatField(os_, fld.name(), nCmpt, nPoints_);
}
else
{
format().openDataArray<float, nCmpt>(fld.name())
.closeTag();
}
format().writeSize(payLoad);
forAll(patchIDs_, i)
{
@ -81,7 +108,13 @@ void Foam::foamVtkOutput::patchWriter::write
foamVtkOutput::writeList(format(), pfld.patchInternalField()());
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
}
@ -93,15 +126,24 @@ void Foam::foamVtkOutput::patchWriter::write
const UPtrList<const GeometricField<Type, fvPatchField, volMesh>>& flds
)
{
const int nCmpt(pTraits<Type>::nComponents);
const uint64_t payLoad(nPoints_ * nCmpt * sizeof(float));
forAll(flds, fieldi)
{
const auto& fld = flds[fieldi];
os_ << fld.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< nPoints_ << " float" << nl;
if (legacy_)
{
legacy::floatField(os_, fld.name(), nCmpt, nPoints_);
}
else
{
format().openDataArray<float, nCmpt>(fld.name())
.closeTag();
}
DynamicList<floatScalar> fField(pTraits<Type>::nComponents*nPoints_);
format().writeSize(payLoad);
forAll(patchIDs_, i)
{
@ -121,7 +163,13 @@ void Foam::foamVtkOutput::patchWriter::write
foamVtkOutput::writeList(format(), tfield());
}
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
}

View File

@ -26,6 +26,158 @@ License
#include "foamVtkSurfaceMeshWriter.H"
#include "foamVtkOutput.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::foamVtkOutput::surfaceMeshWriter::beginPiece()
{
if (!legacy_)
{
format()
.openTag(vtkFileTag::PIECE)
( "NumberOfPoints", pp_.nPoints() )
( "NumberOfPolys", pp_.size() )
.closeTag();
}
}
void Foam::foamVtkOutput::surfaceMeshWriter::writePoints()
{
// payload count
const uint64_t payLoad = (pp_.nPoints()*3*sizeof(float));
if (legacy_)
{
legacy::beginPoints(os_, pp_.nPoints());
}
else
{
format().tag(vtkFileTag::POINTS)
.openDataArray<float, 3>(vtkFileTag::POINTS)
.closeTag();
}
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), pp_.localPoints());
format().flush();
if (!legacy_)
{
format()
.endDataArray()
.endTag(vtkFileTag::POINTS);
}
}
void Foam::foamVtkOutput::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
foamVtkOutput::writeList(format(), f);
}
format().flush();
}
void Foam::foamVtkOutput::surfaceMeshWriter::writePolys()
{
//
// 'connectivity'
//
format().tag(vtkFileTag::POLYS);
//
// 'connectivity'
//
{
// payload count
uint64_t payLoad = 0;
forAll(pp_, facei)
{
payLoad += pp_[facei].size();
}
format().openDataArray<label>("connectivity")
.closeTag();
// payload size
format().writeSize(payLoad * sizeof(label));
forAll(pp_, facei)
{
const face& f = pp_.localFaces()[facei];
foamVtkOutput::writeList(format(), f);
}
format().flush();
format()
.endDataArray();
}
//
// 'offsets' (connectivity offsets)
//
{
format()
.openDataArray<label>("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(vtkFileTag::POLYS);
}
void Foam::foamVtkOutput::surfaceMeshWriter::writeMesh()
{
writePoints();
if (legacy_)
{
writePolysLegacy();
}
else
{
writePolys();
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::foamVtkOutput::surfaceMeshWriter::surfaceMeshWriter
@ -37,46 +189,33 @@ Foam::foamVtkOutput::surfaceMeshWriter::surfaceMeshWriter
)
:
pp_(pp),
legacy_(outOpts.legacy()),
format_(),
os_()
{
outputOptions opts(outOpts);
opts.legacy(true); // Legacy only, no append
opts.legacy(true); // No append supported
os_.open((baseName + (opts.legacy() ? ".vtk" : ".vtp")).c_str());
os_.open((baseName + (legacy_ ? ".vtk" : ".vtp")).c_str());
format_ = opts.newFormatter(os_);
if (opts.legacy())
if (legacy_)
{
foamVtkOutput::legacy::fileHeader(format(), name)
<< "DATASET POLYDATA" << nl;
legacy::fileHeader(format(), name, vtkFileTag::POLY_DATA);
}
else
{
// XML (inline)
format()
.xmlHeader()
.xmlComment(name)
.beginVTKFile(vtkFileTag::POLY_DATA, "0.1");
}
//------------------------------------------------------------------
// Write topology
label nFaceVerts = pp.size();
forAll(pp, facei)
{
nFaceVerts += pp[facei].size();
}
os_ << "POINTS " << pp.nPoints() << " float" << nl;
foamVtkOutput::writeList(format(), pp.localPoints());
format().flush();
os_ << "POLYGONS " << pp.size() << ' ' << nFaceVerts << nl;
forAll(pp, facei)
{
const face& f = pp.localFaces()[facei];
format().write(f.size());
foamVtkOutput::writeList(format(), f);
}
format().flush();
beginPiece();
writeMesh();
}
@ -90,12 +229,37 @@ Foam::foamVtkOutput::surfaceMeshWriter::~surfaceMeshWriter()
void Foam::foamVtkOutput::surfaceMeshWriter::beginCellData(label nFields)
{
foamVtkOutput::legacy::cellDataHeader(os(), pp_.size(), nFields);
if (legacy_)
{
legacy::dataHeader(os(), vtkFileTag::CELL_DATA, pp_.size(), nFields);
}
else
{
format().tag(vtkFileTag::CELL_DATA);
}
}
void Foam::foamVtkOutput::surfaceMeshWriter::endCellData()
{}
{
if (!legacy_)
{
format().endTag(vtkFileTag::CELL_DATA);
}
}
void Foam::foamVtkOutput::surfaceMeshWriter::writeFooter()
{
if (!legacy_)
{
// slight cheat. </Piece> too
format().endTag(vtkFileTag::PIECE);
format().endTag(vtkFileTag::POLY_DATA)
.endVTKFile();
}
}
// ************************************************************************* //

View File

@ -58,12 +58,41 @@ namespace foamVtkOutput
class surfaceMeshWriter
{
const indirectPrimitivePatch& pp_;
// Private Member Data
autoPtr<foamVtkOutput::formatter> format_;
const indirectPrimitivePatch& pp_;
std::ofstream os_;
//- Commonly used query
const bool legacy_;
autoPtr<foamVtkOutput::formatter> format_;
std::ofstream os_;
// 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();
//- Disallow default bitwise copy construct
surfaceMeshWriter(const surfaceMeshWriter&) = delete;
//- Disallow default bitwise assignment
void operator=(const surfaceMeshWriter&) = delete;
public:
@ -95,19 +124,25 @@ public:
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();
//- Extract face data
//- Get face field
template<class Type>
tmp<Field<Type>> getFaceField
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& sfld
) const;
//- Write surfaceFields
//- Write surface fields
template<class Type>
void write
(

View File

@ -50,7 +50,7 @@ Foam::foamVtkOutput::surfaceMeshWriter::getFaceField
}
else
{
label localFacei = facei - patches[patchi].start();
const label localFacei = facei - patches[patchi].start();
fld[i] = sfld.boundaryField()[patchi][localFacei];
}
}
@ -68,18 +68,32 @@ void Foam::foamVtkOutput::surfaceMeshWriter::write
>& sflds
)
{
const int nCmpt(pTraits<Type>::nComponents);
const uint64_t payLoad(pp_.size() * nCmpt * sizeof(float));
forAll(sflds, fieldi)
{
const GeometricField<Type, fvsPatchField, surfaceMesh>& fld =
sflds[fieldi];
const auto& fld = sflds[fieldi];
os_ << fld.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< pp_.size() << " float" << std::endl;
if (legacy_)
{
legacy::floatField(os(), fld.name(), nCmpt, pp_.size());
}
else
{
format().openDataArray<float, nCmpt>(fld.name())
.closeTag();
}
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), getFaceField(fld)());
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
}

View File

@ -41,47 +41,98 @@ void Foam::foamVtkOutput::writeSurfFields
)
{
outputOptions opts(outOpts);
opts.legacy(true); // Legacy only, no append
opts.append(false); // No append supported
std::ofstream os((baseName + (opts.legacy() ? ".vtk" : ".vtp")).c_str());
const bool legacy_(opts.legacy());
std::ofstream os((baseName + (legacy_ ? ".vtk" : ".vtp")).c_str());
autoPtr<foamVtkOutput::formatter> format = opts.newFormatter(os);
if (opts.legacy())
// Same payload size for points and vector fields!
const int nCmpt(3); // vector
const uint64_t payLoad(mesh.nFaces() * 3 * sizeof(float));
if (legacy_)
{
foamVtkOutput::legacy::fileHeader(format(), "surfaceFields")
<< "DATASET POLYDATA" << nl;
legacy::fileHeader(format(), "surfaceFields", vtkFileTag::POLY_DATA);
legacy::beginPoints(os, mesh.nFaces());
}
else
{
// XML (inline)
format()
.xmlHeader()
.xmlComment("surfaceFields")
.beginVTKFile(vtkFileTag::POLY_DATA, "0.1");
// Tricky - hide in beginPiece()
format()
.openTag(vtkFileTag::PIECE)
( "NumberOfPoints", mesh.nFaces() )
.closeTag();
format().tag(vtkFileTag::POINTS)
.openDataArray<float,3>(vtkFileTag::POINTS)
.closeTag();
}
const pointField& fc = mesh.faceCentres();
os << "POINTS " << mesh.nFaces() << " float" << nl;
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), fc);
format().flush();
foamVtkOutput::legacy::pointDataHeader
(
os,
mesh.nFaces(),
surfVectorFields.size()
);
if (!legacy_)
{
format()
.endDataArray()
.endTag(vtkFileTag::POINTS);
}
// Fields
if (legacy_)
{
legacy::dataHeader
(
os,
vtkFileTag::POINT_DATA,
mesh.nFaces(),
surfVectorFields.size()
);
}
else
{
format().tag(vtkFileTag::POINT_DATA);
}
// surfVectorFields
forAll(surfVectorFields, fieldi)
{
const surfaceVectorField& svf = surfVectorFields[fieldi];
const auto& fld = surfVectorFields[fieldi];
os << svf.name() << " 3 " << mesh.nFaces() << " float" << nl;
for (label facei=0; facei < mesh.nInternalFaces(); ++facei)
if (legacy_)
{
foamVtkOutput::write(format(), svf[facei]);
legacy::floatField(os, fld.name(), nCmpt, mesh.nFaces());
}
else
{
format().openDataArray<float, nCmpt>(fld.name())
.closeTag();
}
forAll(svf.boundaryField(), patchi)
format().writeSize(payLoad);
for (label facei=0; facei < mesh.nInternalFaces(); ++facei)
{
foamVtkOutput::write(format(), fld[facei]);
}
forAll(fld.boundaryField(), patchi)
{
const fvPatch& pp = mesh.boundary()[patchi];
const fvsPatchVectorField& pf = svf.boundaryField()[patchi];
const auto& pf = fld.boundaryField()[patchi];
if (isA<emptyFvsPatchVectorField>(pf))
{
@ -98,6 +149,22 @@ void Foam::foamVtkOutput::writeSurfFields
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
if (!legacy_)
{
format().endTag(vtkFileTag::POINT_DATA);
// slight cheat. </Piece> too
format().endTag(vtkFileTag::PIECE);
format().endTag(vtkFileTag::POLY_DATA)
.endVTKFile();
}
}

View File

@ -25,7 +25,7 @@ InNamespace
Foam::foamVtkOutput
Description
Write a patch with its data.
Write surface fields as vectors
SourceFiles
foamVtkWriteSurfFields.C