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

@ -28,7 +28,7 @@ Group
grpPostProcessingUtilities
Description
Legacy VTK file format writer.
VTK file format writer.
- Handles volFields, pointFields, surfaceScalarField, surfaceVectorField
fields.
@ -46,6 +46,9 @@ Usage
- \par -ascii
Write VTK data in ASCII format instead of binary.
- \par -xml
Write VTK data in XML format instead of legacy format
- \par -mesh \<name\>
Use a different mesh name (instead of -region)
@ -243,6 +246,11 @@ foamVtkOutput::outputOptions getOutputOptions(const argList& args)
{
foamVtkOutput::outputOptions opts;
if (args.optionFound("xml"))
{
opts.ascii(args.optionFound("ascii"));
}
else
{
opts.legacy(true);
@ -335,6 +343,11 @@ int main(int argc, char *argv[])
"write in ASCII format instead of binary"
);
argList::addBoolOption
(
"xml",
"write VTK xml instead of legacy format"
);
argList::addBoolOption
(
"poly",
"write polyhedral cells without tet/pyramid decomposition"
@ -902,6 +915,8 @@ int main(int argc, char *argv[])
writer.endPointData();
}
writer.writeFooter();
}
//---------------------------------------------------------------------
@ -1041,6 +1056,8 @@ int main(int argc, char *argv[])
writer.endPointData();
}
writer.writeFooter();
}
else
{
@ -1118,6 +1135,8 @@ int main(int argc, char *argv[])
writer.endPointData();
}
}
writer.writeFooter();
}
}
@ -1190,6 +1209,8 @@ int main(int argc, char *argv[])
writer.write(sVectorFld);
writer.endCellData();
writer.writeFooter();
}
}
@ -1288,6 +1309,8 @@ int main(int argc, char *argv[])
writer.writeIOField<tensor>(tensorNames);
writer.endParcelData();
writer.writeFooter();
}
else
{
@ -1304,6 +1327,8 @@ int main(int argc, char *argv[])
writer.beginParcelData(0);
writer.endParcelData();
writer.writeFooter();
}
}

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,6 +27,134 @@ License
#include "Cloud.H"
#include "passiveParticle.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::foamVtkOutput::lagrangianWriter::beginPiece()
{
if (!legacy_)
{
if (useVerts_)
{
format()
.openTag(vtkFileTag::PIECE)
( "NumberOfPoints", nParcels_ )
( "NumberOfVerts", nParcels_ )
.closeTag();
}
else
{
format()
.openTag(vtkFileTag::PIECE)
( "NumberOfPoints", nParcels_ )
.closeTag();
}
}
}
void Foam::foamVtkOutput::lagrangianWriter::writePoints()
{
Cloud<passiveParticle> parcels(mesh_, cloudName_, false);
nParcels_ = parcels.size();
const uint64_t payLoad = (nParcels_ * 3 * sizeof(float));
if (legacy_)
{
legacy::beginPoints(os_, nParcels_);
}
else
{
beginPiece(); // Tricky - hide in here
format().tag(vtkFileTag::POINTS)
.openDataArray<float,3>(vtkFileTag::POINTS)
.closeTag();
}
format().writeSize(payLoad);
forAllConstIters(parcels, iter)
{
const point& pt = iter().position();
foamVtkOutput::write(format(), pt);
}
format().flush();
if (!legacy_)
{
format()
.endDataArray()
.endTag(vtkFileTag::POINTS);
}
}
void Foam::foamVtkOutput::lagrangianWriter::writeVertsLegacy()
{
os_ << "VERTICES " << nParcels_ << ' ' << 2*nParcels_ << nl;
// legacy has cells + connectivity together
// count the number of vertices referenced
for (label i=0; i < nParcels_; ++i)
{
format().write(1); // Number of vertices for this cell (==1)
format().write(i);
}
format().flush();
}
void Foam::foamVtkOutput::lagrangianWriter::writeVerts()
{
format().tag(vtkFileTag::VERTS);
// Same payload throughout
const uint64_t payLoad = (nParcels_ * sizeof(label));
//
// 'connectivity'
// = linear mapping onto points
//
{
format().openDataArray<label>("connectivity")
.closeTag();
format().writeSize(payLoad);
for (label i=0; i < nParcels_; ++i)
{
format().write(i);
}
format().flush();
format().endDataArray();
}
//
// 'offsets' (connectivity offsets)
// = linear mapping onto points (with 1 offset)
//
{
format().openDataArray<label>("offsets")
.closeTag();
format().writeSize(payLoad);
for (label i=0; i < nParcels_; ++i)
{
format().write(i+1);
}
format().flush();
format().endDataArray();
}
format().endTag(vtkFileTag::VERTS);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::foamVtkOutput::lagrangianWriter::lagrangianWriter
@ -39,43 +167,54 @@ Foam::foamVtkOutput::lagrangianWriter::lagrangianWriter
)
:
mesh_(mesh),
legacy_(outOpts.legacy()),
useVerts_(false),
format_(),
cloudName_(cloudName),
os_(),
nParcels_(0)
{
outputOptions opts(outOpts);
opts.legacy(true); // Legacy only, no append
os_.open((baseName + (opts.legacy() ? ".vtk" : ".vtp")).c_str());
opts.append(false); // No append supported
os_.open((baseName + (legacy_ ? ".vtk" : ".vtp")).c_str());
format_ = opts.newFormatter(os_);
if (opts.legacy())
{
foamVtkOutput::legacy::fileHeader(format(), mesh_.time().caseName())
<< "DATASET POLYDATA" << nl;
}
const auto& title = mesh_.time().caseName();
if (dummyCloud)
if (legacy_)
{
os_ << "POINTS " << nParcels_ << " float" << nl;
legacy::fileHeader(format(), title, vtkFileTag::POLY_DATA);
if (dummyCloud)
{
legacy::beginPoints(os_, nParcels_);
}
else
{
writePoints();
if (useVerts_) writeVertsLegacy();
}
}
else
{
Cloud<passiveParticle> parcels(mesh, cloudName_, false);
// XML (inline)
nParcels_ = parcels.size();
format()
.xmlHeader()
.xmlComment(title)
.beginVTKFile(vtkFileTag::POLY_DATA, "0.1");
os_ << "POINTS " << nParcels_ << " float" << nl;
forAllConstIters(parcels, iter)
if (dummyCloud)
{
const point& pt = iter().position();
foamVtkOutput::write(format(), pt);
beginPiece();
}
else
{
writePoints();
if (useVerts_) writeVerts();
}
format().flush();
}
}
@ -88,17 +227,53 @@ Foam::foamVtkOutput::lagrangianWriter::~lagrangianWriter()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::foamVtkOutput::lagrangianWriter::beginParcelData
(
const label nFields
)
void Foam::foamVtkOutput::lagrangianWriter::beginParcelData(label nFields)
{
foamVtkOutput::legacy::pointDataHeader(os_, nParcels_, nFields);
const vtkFileTag dataType =
(
useVerts_
? vtkFileTag::CELL_DATA
: vtkFileTag::POINT_DATA
);
if (legacy_)
{
legacy::dataHeader(os_, dataType, nParcels_, nFields);
}
else
{
format().tag(dataType);
}
}
void Foam::foamVtkOutput::lagrangianWriter::endParcelData()
{}
{
const vtkFileTag dataType =
(
useVerts_
? vtkFileTag::CELL_DATA
: vtkFileTag::POINT_DATA
);
if (!legacy_)
{
format().endTag(dataType);
}
}
void Foam::foamVtkOutput::lagrangianWriter::writeFooter()
{
if (!legacy_)
{
// slight cheat. </Piece> too
format().endTag(vtkFileTag::PIECE);
format().endTag(vtkFileTag::POLY_DATA)
.endVTKFile();
}
}
// ************************************************************************* //

View File

@ -52,20 +52,51 @@ namespace foamVtkOutput
{
/*---------------------------------------------------------------------------*\
Class lagrangianWriter Declaration
Class lagrangianWriter Declaration
\*---------------------------------------------------------------------------*/
class lagrangianWriter
{
const fvMesh& mesh_;
// Private Member Data
autoPtr<foamVtkOutput::formatter> format_;
//- Reference to the OpenFOAM mesh (or subset)
const fvMesh& mesh_;
const word cloudName_;
//- Commonly used query
const bool legacy_;
std::ofstream os_;
//- Write lagrangian as cell data (verts) or point data?
const bool useVerts_;
label nParcels_;
autoPtr<foamVtkOutput::formatter> format_;
const word cloudName_;
std::ofstream os_;
label nParcels_;
// Private Member Functions
//- Begin piece
void beginPiece();
//- Write positions
void writePoints();
//- Write vertex (cells)
void writeVertsLegacy();
//- Write vertex (cells)
void writeVerts();
//- Disallow default bitwise copy construct
lagrangianWriter(const lagrangianWriter&) = delete;
//- Disallow default bitwise assignment
void operator=(const lagrangianWriter&) = delete;
public:
@ -104,13 +135,15 @@ public:
return nParcels_;
}
void beginParcelData(const label nFields);
void beginParcelData(label nFields);
void endParcelData();
//- Write file footer
void writeFooter();
//- Write IOField
template<class Type>
void writeIOField(const wordList&);
void writeIOField(const wordList& objectNames);
};

View File

@ -31,33 +31,78 @@ License
template<class Type>
void Foam::foamVtkOutput::lagrangianWriter::writeIOField
(
const wordList& objects
const wordList& objectNames
)
{
forAll(objects, i)
{
const word& object = objects[i];
const int nCmpt(pTraits<Type>::nComponents);
const bool useIntField =
std::is_integral<typename pTraits<Type>::cmptType>();
for (const word& fldName : objectNames)
{
IOobject header
(
object,
fldName,
mesh_.time().timeName(),
cloud::prefix/cloudName_,
mesh_,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
false // no register
);
IOField<Type> fld(header);
// Legacy
os()<< object << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< fld.size() << " float" << nl;
if (useIntField)
{
const uint64_t payLoad(fld.size() * nCmpt * sizeof(label));
if (legacy_)
{
legacy::intField(os(), fldName, nCmpt, fld.size());
}
else
{
format().openDataArray<label, nCmpt>(fldName)
.closeTag();
}
format().writeSize(payLoad);
// Ensure consistent output width
for (const Type& val : fld)
{
for (int cmpt=0; cmpt < nCmpt; ++cmpt)
{
format().write(label(component(val, cmpt)));
}
}
}
else
{
const uint64_t payLoad(fld.size() * nCmpt * sizeof(float));
if (legacy_)
{
legacy::floatField(os(), fldName, nCmpt, fld.size());
}
else
{
format().openDataArray<float, nCmpt>(fldName)
.closeTag();
}
format().writeSize(payLoad);
foamVtkOutput::writeList(format(), fld);
}
foamVtkOutput::writeList(format(), fld);
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
}

View File

@ -1,5 +1,6 @@
EXE_INC = \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude

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

View File

@ -65,7 +65,7 @@ Foam::foamVtkOutput::formatter::xmlHeader()
Foam::foamVtkOutput::formatter&
Foam::foamVtkOutput::formatter::comment(const std::string& text)
Foam::foamVtkOutput::formatter::xmlComment(const std::string& comment)
{
if (inTag_)
{
@ -75,7 +75,7 @@ Foam::foamVtkOutput::formatter::comment(const std::string& text)
}
indent();
os_ << "<!-- " << text << " -->" << nl;
os_ << "<!-- " << comment << " -->" << nl;
return *this;
}

View File

@ -152,7 +152,7 @@ public:
//- Write XML comment (at the current indentation level)
// \return formatter for chaining
formatter& comment(const std::string& text);
formatter& xmlComment(const std::string& comment);
//- Open XML tag

View File

@ -36,15 +36,11 @@ License
// * * * * * * * * * * * * * * * Static Data * * * * * * * * * * * * * * * * //
const Foam::Enum<Foam::foamVtkOutput::legacy::textElemType>
Foam::foamVtkOutput::legacy::textNames
const Foam::Enum<Foam::vtkFileTag>
Foam::foamVtkOutput::legacy::contentNames
{
{ textElemType::POINTS, "POINTS" },
{ textElemType::CELLS, "CELLS" },
{ textElemType::POLYS, "POLYGONS" },
{ textElemType::VERTS, "VERTICES" },
{ textElemType::POLY_DATA, "POLYDATA" },
{ textElemType::UNSTRUCTURED_GRID, "UNSTRUCTURED_GRID" },
{ vtkFileTag::POLY_DATA, "POLYDATA" },
{ vtkFileTag::UNSTRUCTURED_GRID, "UNSTRUCTURED_GRID" },
};
@ -128,66 +124,23 @@ Foam::label Foam::foamVtkOutput::writeVtmFile
}
std::ostream& Foam::foamVtkOutput::legacy::fileHeader
(
std::ostream& os,
const std::string& title,
const bool binary
)
{
os << "# vtk DataFile Version 2.0" << nl
<< title << nl
<< (binary ? "BINARY" : "ASCII") << nl;
return os;
}
std::ostream& Foam::foamVtkOutput::legacy::fileHeader
(
foamVtkOutput::formatter& fmt,
const std::string& title
const std::string& title,
const std::string& contentType
)
{
return fileHeader(fmt.os(), title, isType<legacyRawFormatter>(fmt));
}
std::ostream& os = fmt.os();
std::ostream& Foam::foamVtkOutput::legacy::dataHeader
(
std::ostream& os,
const vtkFileTag& dataTypeTag,
const label nEntries,
const label nFields
)
{
os << dataTypeNames[dataTypeTag] << ' ' << nEntries << nl
<< "FIELD attributes " << nFields << nl;
fileHeader(os, title, isType<legacyRawFormatter>(fmt));
if (!contentType.empty())
{
os << "DATASET " << contentType.c_str() << nl;
}
return os;
}
std::ostream& Foam::foamVtkOutput::legacy::cellDataHeader
(
std::ostream& os,
const label nEntries,
const label nFields
)
{
return dataHeader(os, vtkFileTag::CELL_DATA, nEntries, nFields);
}
std::ostream& Foam::foamVtkOutput::legacy::pointDataHeader
(
std::ostream& os,
const label nEntries,
const label nFields
)
{
return dataHeader(os, vtkFileTag::POINT_DATA, nEntries, nFields);
}
// ************************************************************************* //

View File

@ -32,7 +32,7 @@ Namespace
Foam::foamVtkOutput::legacy
Description
Namespace for legacy VTK output functions.
Namespace for legacy VTK output constants and functions.
SourceFiles
foamVtkOutput.C
@ -65,6 +65,9 @@ namespace foamVtkOutput
typedef formatter::headerType headerType;
// Constants
// General Functions
//- Return a default asciiFormatter
@ -101,6 +104,15 @@ namespace foamVtkOutput
const UList<Type>& lst
);
//- Write a list of values.
// The output does not include the payload size.
template<class Type, unsigned Size>
void writeList
(
foamVtkOutput::formatter& fmt,
const FixedList<Type, Size>& lst
);
//- Write a list of values via indirect addressing.
// The output does not include the payload size.
@ -120,49 +132,68 @@ namespace foamVtkOutput
//- Some minimal additional support for writing legacy files
namespace legacy
{
//- Some standard text elements for legacy vtk files
enum class textElemType
{
POINTS, //!< "POINTS"
CELLS, //!< "CELLS"
POLYS, //!< "POLYGONS"
VERTS, //!< "VERTICES"
POLY_DATA, //!< "POLYDATA"
UNSTRUCTURED_GRID, //!< "UNSTRUCTURED_GRID"
};
//- Strings corresponding to the elements
extern const Foam::Enum<textElemType> textNames;
// Constants
//- Strings corresponding to the elements
extern const Foam::Enum<vtkFileTag> dataTypeNames;
//- Strings corresponding to the (POLYDATA, UNSTRUCTURED_GRID) elements
extern const Foam::Enum<vtkFileTag> contentNames;
//- Strings corresponding to the (CELL_DATA, POINT_DATA) elements
extern const Foam::Enum<vtkFileTag> dataTypeNames;
// Functions
//- Emit header for legacy file.
// Writes "ASCII" or "BINARY" depending on specified type.
std::ostream& fileHeader
inline std::ostream& fileHeader
(
std::ostream& os,
const std::string& title,
const bool binary = false
const bool binary
);
//- Emit header for legacy file.
// Writes "ASCII" or "BINARY" depending on the formatter type.
//- Emit header for legacy file, with "ASCII" or "BINARY" depending on
// the formatter type.
// Includes "DATASET" with the specified dataset type.
inline void fileHeader
(
foamVtkOutput::formatter& fmt,
const std::string& title,
const vtkFileTag& contentTypeTag
);
//- Emit header for legacy file, with "ASCII" or "BINARY" depending on
// the formatter type.
// If the contentType is non-empty, it is used for "DATASET" line.
std::ostream& fileHeader
(
foamVtkOutput::formatter& fmt,
const std::string& title
const std::string& title,
const std::string& contentType
);
//- Emit header for legacy CELL_DATA or POINT_DATA, corresponding to the
// enumeration textElemType::CELLS or textElemType::POINTS, respectively.
//- Emit header for POINTS (with trailing newline).
inline void beginPoints(std::ostream& os, const label nPoints);
//- Emit header for POLYGONS (with trailing newline).
// The nConnectivity is the sum of all connectivity points used,
// but \b without additional space for the size prefixes.
// The additional prefix sizes are added internally.
inline void beginPolys
(
std::ostream& os,
const label nPolys,
const label nConnectivity
);
//- Use the enumerations vtkFileTag::CELL_DATA, vtkFileTag::POINT_DATA,
// to emit a legacy CELL_DATA, POINT_DATA element.
// The nEntries corresponds similarly to the number of cells or points,
// respectively.
std::ostream& dataHeader
inline void dataHeader
(
std::ostream& os,
const vtkFileTag& dataTypeTag,
@ -170,62 +201,36 @@ namespace legacy
const label nFields
);
//- Emit header for legacy CELL_DATA.
// The nEntries should normally correspond to the number of cells.
std::ostream& cellDataHeader
//- Start output of float field with the specified name.
inline void floatField
(
std::ostream& os,
const label nEntries,
const label nFields
const word& name,
const label nCmpt,
const label nEntries
);
//- Emit header for legacy POINT_DATA
// The nEntries should normally correspond to the number of points.
std::ostream& pointDataHeader
//- Start output of int field with the specified name.
inline void intField
(
std::ostream& os,
const label nEntries,
const label nFields
const word& name,
const label nCmpt,
const label nEntries
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Template specialization for label
template<>
inline void write<label>(foamVtkOutput::formatter& fmt, const label& val)
{
fmt.write(val);
}
//- Template specialization for float
template<>
inline void write<float>(foamVtkOutput::formatter& fmt, const float& val)
{
fmt.write(val);
}
//- Template specialization for double
template<>
inline void write<double>(foamVtkOutput::formatter& fmt, const double& val)
{
fmt.write(val);
}
} // End namespace foamVtkOutput
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "foamVtkOutputI.H"
#ifdef NoRepository
#include "foamVtkOutputTemplates.C"
#endif

View File

@ -0,0 +1,146 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * Specializations * * * * * * * * * * * * * * * //
namespace Foam
{
namespace foamVtkOutput
{
//- Template specialization for label
template<>
inline void write<label>(foamVtkOutput::formatter& fmt, const label& val)
{
fmt.write(val);
}
//- Template specialization for float
template<>
inline void write<float>(foamVtkOutput::formatter& fmt, const float& val)
{
fmt.write(val);
}
//- Template specialization for double
template<>
inline void write<double>(foamVtkOutput::formatter& fmt, const double& val)
{
fmt.write(val);
}
} // End namespace foamVtkOutput
} // End namespace Foam
// * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * //
inline std::ostream& Foam::foamVtkOutput::legacy::fileHeader
(
std::ostream& os,
const std::string& title,
const bool binary
)
{
os << "# vtk DataFile Version 2.0" << nl
<< title << nl
<< (binary ? "BINARY" : "ASCII") << nl;
return os;
}
inline void Foam::foamVtkOutput::legacy::fileHeader
(
foamVtkOutput::formatter& fmt,
const std::string& title,
const vtkFileTag& contentTypeTag
)
{
fileHeader(fmt, title, contentNames[contentTypeTag]);
}
inline void Foam::foamVtkOutput::legacy::beginPoints
(
std::ostream& os,
const label nPoints
)
{
os << "POINTS " << nPoints << " float" << nl;
}
inline void Foam::foamVtkOutput::legacy::beginPolys
(
std::ostream& os,
const label nPolys,
const label nConnectivity
)
{
os << "POLYGONS " << nPolys << ' ' << (nPolys + nConnectivity) << nl;
}
inline void Foam::foamVtkOutput::legacy::dataHeader
(
std::ostream& os,
const vtkFileTag& dataTypeTag,
const label nEntries,
const label nFields
)
{
os << dataTypeNames[dataTypeTag] << ' ' << nEntries << nl
<< "FIELD attributes " << nFields << nl;
}
inline void Foam::foamVtkOutput::legacy::floatField
(
std::ostream& os,
const word& fieldName,
const label nCmpt,
const label nEntries
)
{
os << fieldName << ' ' << nCmpt << ' ' << nEntries << " float" << nl;
}
inline void Foam::foamVtkOutput::legacy::intField
(
std::ostream& os,
const word& fieldName,
const label nCmpt,
const label nEntries
)
{
os << fieldName << ' ' << nCmpt << ' ' << nEntries << " int" << nl;
}
// ************************************************************************* //

View File

@ -53,6 +53,20 @@ void Foam::foamVtkOutput::writeList
}
template<class Type, unsigned Size>
void Foam::foamVtkOutput::writeList
(
foamVtkOutput::formatter& fmt,
const FixedList<Type, Size>& lst
)
{
for (unsigned i=0; i<Size; ++i)
{
write(fmt, lst[i]);
}
}
template<class Type>
void Foam::foamVtkOutput::writeList
(

View File

@ -43,14 +43,15 @@ void Foam::foamVtkOutput::writeCellSetFaces
outputOptions opts(outOpts);
opts.legacy(true); // Legacy only, no append
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())
if (legacy_)
{
foamVtkOutput::legacy::fileHeader(format(), set.name())
<< "DATASET POLYDATA" << nl;
legacy::fileHeader(format(), set.name(), vtkFileTag::POLY_DATA);
}
//-------------------------------------------------------------------------
@ -106,30 +107,35 @@ void Foam::foamVtkOutput::writeCellSetFaces
//-------------------------------------------------------------------------
// Write points and faces as polygons
os << "POINTS " << pp.nPoints() << " float" << nl;
legacy::beginPoints(os, pp.nPoints());
foamVtkOutput::writeList(format(), pp.localPoints());
format().flush();
label count = pp.size();
// connectivity count without additional storage (done internally)
uint64_t nConnectivity = 0;
forAll(pp, facei)
{
count += pp.localFaces()[facei].size();
nConnectivity += pp[facei].size();
}
os << "POLYGONS " << pp.size() << ' ' << count << nl;
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());
format().write(f.size()); // The size prefix
foamVtkOutput::writeList(format(), f);
}
format().flush();
// Write data - faceId/cellId
foamVtkOutput::legacy::cellDataHeader(os, pp.size(), 1);
legacy::dataHeader(os, vtkFileTag::CELL_DATA, pp.size(), 1);
os << "cellID 1 " << pp.size() << " int" << nl;

View File

@ -43,14 +43,15 @@ void Foam::foamVtkOutput::writeFaceSet
outputOptions opts(outOpts);
opts.legacy(true); // Legacy only, no append
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())
if (legacy_)
{
foamVtkOutput::legacy::fileHeader(format(), set.name())
<< "DATASET POLYDATA" << nl;
legacy::fileHeader(format(), set.name(), vtkFileTag::POLY_DATA);
}
//-------------------------------------------------------------------------
@ -67,28 +68,36 @@ void Foam::foamVtkOutput::writeFaceSet
//-------------------------------------------------------------------------
// Write points and faces as polygons
os << "POINTS " << pp.nPoints() << " float" << nl;
legacy::beginPoints(os, pp.nPoints());
foamVtkOutput::writeList(format(), pp.localPoints());
format().flush();
label count = pp.size();
// connectivity count without additional storage (done internally)
uint64_t nConnectivity = 0;
forAll(pp, facei)
{
count += pp.localFaces()[facei].size();
nConnectivity += pp[facei].size();
}
os << "POLYGONS " << pp.size() << ' ' << count << nl;
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());
format().write(f.size()); // The size prefix
foamVtkOutput::writeList(format(), f);
}
format().flush();
// Write data - faceId/cellId
legacy::dataHeader(os, vtkFileTag::CELL_DATA, pp.size(), 1);
os << "faceID 1 " << pp.size() << " int" << nl;
foamVtkOutput::writeList(format(), faceLabels);

View File

@ -42,14 +42,15 @@ void Foam::foamVtkOutput::writePointSet
outputOptions opts(outOpts);
opts.legacy(true); // Legacy only, no append
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())
if (legacy_)
{
foamVtkOutput::legacy::fileHeader(format(), set.name())
<< "DATASET POLYDATA" << nl;
legacy::fileHeader(format(), set.name(), vtkFileTag::POLY_DATA);
}
//-------------------------------------------------------------------------
@ -57,14 +58,13 @@ void Foam::foamVtkOutput::writePointSet
const labelList pointLabels(set.sortedToc());
// Write points
os << "POINTS " << pointLabels.size() << " float" << nl;
legacy::beginPoints(os, pointLabels.size());
foamVtkOutput::writeList(format(), mesh.points(), pointLabels);
format().flush();
// Write data - pointID
foamVtkOutput::legacy::pointDataHeader(os, pointLabels.size(), 1);
legacy::dataHeader(os, vtkFileTag::POINT_DATA, pointLabels.size(), 1);
os << "pointID 1 " << pointLabels.size() << " int" << nl;