mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
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:
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user