Merge branch 'feature-paraview-vtk' into 'develop'

Feature paraview vtk

See merge request !116
This commit is contained in:
Andrew Heather
2017-06-14 14:16:18 +01:00
163 changed files with 12446 additions and 9478 deletions

View File

@ -1,7 +1,3 @@
writePointSet.C
writeFuns.C
writePatch.C
setSet.C
EXE = $(FOAM_APPBIN)/setSet

View File

@ -1,4 +1,5 @@
EXE_INC = \
-I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
$(COMP_FLAGS)

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 |
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -44,8 +44,9 @@ Description
#include "OFstream.H"
#include "IFstream.H"
#include "demandDrivenData.H"
#include "writePatch.H"
#include "writePointSet.H"
#include "foamVtkWriteCellSetFaces.H"
#include "foamVtkWriteFaceSet.H"
#include "foamVtkWritePointSet.H"
#include "IOobjectList.H"
#include "cellZoneSet.H"
#include "faceZoneSet.H"
@ -75,104 +76,39 @@ void writeVTK
(
const polyMesh& mesh,
const topoSet& currentSet,
const fileName& vtkName
const fileName& vtkBaseName
)
{
if (isA<faceSet>(currentSet))
{
// Faces of set with OpenFOAM faceID as value
faceList setFaces(currentSet.size());
labelList faceValues(currentSet.size());
label setFacei = 0;
forAllConstIter(topoSet, currentSet, iter)
{
setFaces[setFacei] = mesh.faces()[iter.key()];
faceValues[setFacei] = iter.key();
setFacei++;
}
primitiveFacePatch fp(setFaces, mesh.points());
writePatch
vtk::writeFaceSet
(
true,
currentSet.name(),
fp,
"faceID",
faceValues,
mesh.time().path()/vtkName
mesh,
currentSet,
mesh.time().path()/vtkBaseName,
vtk::formatType::LEGACY_BINARY
);
}
else if (isA<cellSet>(currentSet))
{
// External faces of cellset with OpenFOAM cellID as value
Map<label> cellFaces(currentSet.size());
forAllConstIter(cellSet, currentSet, iter)
{
label celli = iter.key();
const cell& cFaces = mesh.cells()[celli];
forAll(cFaces, i)
{
label facei = cFaces[i];
if (mesh.isInternalFace(facei))
{
label otherCelli = mesh.faceOwner()[facei];
if (otherCelli == celli)
{
otherCelli = mesh.faceNeighbour()[facei];
}
if (!currentSet.found(otherCelli))
{
cellFaces.insert(facei, celli);
}
}
else
{
cellFaces.insert(facei, celli);
}
}
}
faceList setFaces(cellFaces.size());
labelList faceValues(cellFaces.size());
label setFacei = 0;
forAllConstIter(Map<label>, cellFaces, iter)
{
setFaces[setFacei] = mesh.faces()[iter.key()];
faceValues[setFacei] = iter(); // Cell ID
setFacei++;
}
primitiveFacePatch fp(setFaces, mesh.points());
writePatch
vtk::writeCellSetFaces
(
true,
currentSet.name(),
fp,
"cellID",
faceValues,
mesh.time().path()/vtkName
mesh,
currentSet,
mesh.time().path()/vtkBaseName,
vtk::formatType::LEGACY_BINARY
);
}
else if (isA<pointSet>(currentSet))
{
writePointSet
vtk::writePointSet
(
true,
mesh,
currentSet,
mesh.time().path()/vtkName
mesh.time().path()/vtkBaseName,
vtk::formatType::LEGACY_BINARY
);
}
else
@ -187,58 +123,58 @@ void writeVTK
void printHelp(Ostream& os)
{
os << "Please type 'help', 'list', 'quit', 'time ddd'"
<< " or a set command after prompt." << endl
<< "'list' will show all current cell/face/point sets." << endl
<< "'time ddd' will change the current time." << endl
<< endl
<< "A set command should be of the following form" << endl
<< endl
<< " or a set command after prompt." << nl
<< "'list' will show all current cell/face/point sets." << nl
<< "'time ddd' will change the current time." << nl
<< nl
<< "A set command should be of the following form" << nl
<< nl
<< " cellSet|faceSet|pointSet <setName> <action> <source>"
<< endl
<< endl
<< "The <action> is one of" << endl
<< " list - prints the contents of the set" << endl
<< " clear - clears the set" << endl
<< " invert - inverts the set" << endl
<< " remove - remove the set" << endl
<< " new <source> - sets to set to the source set" << endl
<< " add <source> - adds all elements from the source set" << endl
<< " delete <source> - deletes ,," << endl
<< nl
<< nl
<< "The <action> is one of" << nl
<< " list - prints the contents of the set" << nl
<< " clear - clears the set" << nl
<< " invert - inverts the set" << nl
<< " remove - remove the set" << nl
<< " new <source> - sets to set to the source set" << nl
<< " add <source> - adds all elements from the source set" << nl
<< " delete <source> - deletes ,," << nl
<< " subset <source> - combines current set with the source set"
<< endl
<< endl
<< nl
<< nl
<< "The sources come in various forms. Type a wrong source"
<< " to see all the types available." << endl
<< endl
<< " to see all the types available." << nl
<< nl
<< "Example: pick up all cells connected by point or face to patch"
<< " movingWall" << endl
<< endl
<< "Pick up all faces of patch:" << endl
<< " faceSet f0 new patchToFace movingWall" << endl
<< "Add faces 0,1,2:" << endl
<< " faceSet f0 add labelToFace (0 1 2)" << endl
<< "Pick up all points used by faces in faceSet f0:" << endl
<< " pointSet p0 new faceToPoint f0 all" << endl
<< "Pick up cell which has any face in f0:" << endl
<< " cellSet c0 new faceToCell f0 any" << endl
<< "Add cells which have any point in p0:" << endl
<< " cellSet c0 add pointToCell p0 any" << endl
<< "List set:" << endl
<< " cellSet c0 list" << endl
<< endl
<< "Zones can be set using zoneSets from corresponding sets:" << endl
<< " cellZoneSet c0Zone new setToCellZone c0" << endl
<< " faceZoneSet f0Zone new setToFaceZone f0" << endl
<< endl
<< "or if orientation is important:" << endl
<< " faceZoneSet f0Zone new setsToFaceZone f0 c0" << endl
<< endl
<< "ZoneSets can be manipulated using the general actions:" << endl
<< " list - prints the contents of the set" << endl
<< " clear - clears the set" << endl
<< " movingWall" << nl
<< nl
<< "Pick up all faces of patch:" << nl
<< " faceSet f0 new patchToFace movingWall" << nl
<< "Add faces 0,1,2:" << nl
<< " faceSet f0 add labelToFace (0 1 2)" << nl
<< "Pick up all points used by faces in faceSet f0:" << nl
<< " pointSet p0 new faceToPoint f0 all" << nl
<< "Pick up cell which has any face in f0:" << nl
<< " cellSet c0 new faceToCell f0 any" << nl
<< "Add cells which have any point in p0:" << nl
<< " cellSet c0 add pointToCell p0 any" << nl
<< "List set:" << nl
<< " cellSet c0 list" << nl
<< nl
<< "Zones can be set using zoneSets from corresponding sets:" << nl
<< " cellZoneSet c0Zone new setToCellZone c0" << nl
<< " faceZoneSet f0Zone new setToFaceZone f0" << nl
<< nl
<< "or if orientation is important:" << nl
<< " faceZoneSet f0Zone new setsToFaceZone f0 c0" << nl
<< nl
<< "ZoneSets can be manipulated using the general actions:" << nl
<< " list - prints the contents of the set" << nl
<< " clear - clears the set" << nl
<< " invert - inverts the set (undefined orientation)"
<< endl
<< " remove - remove the set" << endl
<< nl
<< " remove - remove the set" << nl
<< endl;
}
@ -577,7 +513,6 @@ bool doCommand
"VTK"/currentSet.name()/currentSet.name()
+ "_"
+ name(mesh.time().timeIndex())
+ ".vtk"
);
Info<< " Writing " << currentSet.name()

View File

@ -1,225 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "writeFuns.H"
#include "endian.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
void Foam::writeFuns::swapWord(int32_t& word32)
{
char* mem = reinterpret_cast<char*>(&word32);
char a = mem[0];
mem[0] = mem[3];
mem[3] = a;
a = mem[1];
mem[1] = mem[2];
mem[2] = a;
}
void Foam::writeFuns::swapWords(const label nWords, int32_t* words32)
{
for (label i=0; i<nWords; i++)
{
swapWord(words32[i]);
}
}
void Foam::writeFuns::write
(
std::ostream& os,
const bool binary,
List<floatScalar>& fField
)
{
if (binary)
{
#ifdef WM_LITTLE_ENDIAN
swapWords(fField.size(), reinterpret_cast<int32_t*>(fField.begin()));
#endif
os.write
(
reinterpret_cast<char*>(fField.begin()),
fField.size()*sizeof(float)
);
os << std::endl;
}
else
{
forAll(fField, i)
{
os << fField[i] << ' ';
if (i > 0 && (i % 10) == 0)
{
os << std::endl;
}
}
os << std::endl;
}
}
void Foam::writeFuns::write
(
std::ostream& os,
const bool binary,
DynamicList<floatScalar>& fField
)
{
List<floatScalar>& fld = fField.shrink();
write(os, binary, fld);
}
void Foam::writeFuns::write
(
std::ostream& os,
const bool binary,
labelList& elems
)
{
if (binary)
{
#ifdef WM_LITTLE_ENDIAN
swapWords
(
(sizeof(label)/4)*elems.size(),
reinterpret_cast<int32_t*>(elems.begin())
);
#endif
os.write
(
reinterpret_cast<char*>(elems.begin()),
elems.size()*sizeof(label)
);
os << std::endl;
}
else
{
forAll(elems, i)
{
os << elems[i] << ' ';
if (i > 0 && (i % 10) == 0)
{
os << std::endl;
}
}
os << std::endl;
}
}
void Foam::writeFuns::write
(
std::ostream& os,
const bool binary,
DynamicList<label>& elems
)
{
labelList& fld = elems.shrink();
write(os, binary, fld);
}
void Foam::writeFuns::insert(const point& pt, DynamicList<floatScalar>& dest)
{
dest.append(float(pt.x()));
dest.append(float(pt.y()));
dest.append(float(pt.z()));
}
void Foam::writeFuns::insert(const labelList& source, DynamicList<label>& dest)
{
forAll(source, i)
{
dest.append(source[i]);
}
}
void Foam::writeFuns::insert
(
const List<scalar>& source,
DynamicList<floatScalar>& dest
)
{
forAll(source, i)
{
dest.append(float(source[i]));
}
}
void Foam::writeFuns::insert
(
const labelList& map,
const List<scalar>& source,
DynamicList<floatScalar>& dest
)
{
forAll(map, i)
{
dest.append(float(source[map[i]]));
}
}
void Foam::writeFuns::insert
(
const List<point>& source,
DynamicList<floatScalar>& dest
)
{
forAll(source, i)
{
insert(source[i], dest);
}
}
void Foam::writeFuns::insert
(
const labelList& map,
const List<point>& source,
DynamicList<floatScalar>& dest
)
{
forAll(map, i)
{
insert(source[map[i]], dest);
}
}
// ************************************************************************* //

View File

@ -1,127 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::writeFuns
Description
Various functions for collecting and writing binary data.
The LITTLE_ENDIAN is based on 32bit words.
It is not clear how 64bit labels should be handled, currently they are
split into two 32bit words and swapWord applied to these two.
writeFuns should be a namespace rather than a class.
SourceFiles
writeFuns.C
\*---------------------------------------------------------------------------*/
#ifndef writeFuns_H
#define writeFuns_H
#include "labelList.H"
#include "floatScalar.H"
#include "OFstream.H"
#include "DynamicList.H"
#include "point.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class writeFuns Declaration
\*---------------------------------------------------------------------------*/
class writeFuns
{
// Private member functions
//- Swap halves of word
static void swapWord(int32_t& word32);
//- Swap halves of word
static void swapWords(const label nWords, int32_t* words32);
public:
//- Write floats ascii or binary.
// If binary optionally in-place swaps argument
static void write(std::ostream&, const bool, DynamicList<floatScalar>&);
//- Write labels ascii or binary.
// If binary optionally in-place swaps argument
static void write(std::ostream&, const bool, DynamicList<label>&);
//- Write floats ascii or binary.
// If binary optionally in-place swaps argument
static void write(std::ostream&, const bool, List<floatScalar>&);
//- Write labels ascii or binary.
// If binary optionally in-place swaps argument
static void write(std::ostream&, const bool, labelList&);
//- Append point to given DynamicList
static void insert(const point&, DynamicList<floatScalar>& dest);
//- Append elements of labelList to given DynamicList
static void insert(const labelList&, DynamicList<label>&);
//- Append elements of scalarList to given DynamicList
static void insert(const List<scalar>&, DynamicList<floatScalar>&);
//- Append elements of scalarList to given DynamicList using map
static void insert
(
const labelList& map,
const List<scalar>& source,
DynamicList<floatScalar>&
);
//- Append points to given DynamicList of floats
static void insert(const List<point>& source, DynamicList<floatScalar>&);
//- Append points to given DynamicList of floats using map
static void insert
(
const labelList& map,
const List<point>& source,
DynamicList<floatScalar>&
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,127 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "writePatch.H"
#include "OFstream.H"
#include "writeFuns.H"
#include "primitiveFacePatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
void writePatch
(
const bool binary,
const word& setName,
const primitiveFacePatch& fp,
const word& fieldName,
labelList& fieldValues,
const fileName& fileName
)
{
std::ofstream pStream(fileName.c_str());
pStream
<< "# vtk DataFile Version 2.0" << std::endl
<< setName << std::endl;
if (binary)
{
pStream << "BINARY" << std::endl;
}
else
{
pStream << "ASCII" << std::endl;
}
pStream << "DATASET POLYDATA" << std::endl;
//------------------------------------------------------------------
//
// Write topology
//
//------------------------------------------------------------------
// Write points and faces as polygons
pStream << "POINTS " << fp.nPoints() << " float" << std::endl;
DynamicList<floatScalar> ptField(3*fp.nPoints());
writeFuns::insert(fp.localPoints(), ptField);
writeFuns::write(pStream, binary, ptField);
label nFaceVerts = 0;
forAll(fp.localFaces(), facei)
{
nFaceVerts += fp.localFaces()[facei].size() + 1;
}
pStream << "POLYGONS " << fp.size() << ' ' << nFaceVerts
<< std::endl;
DynamicList<label> vertLabels(nFaceVerts);
forAll(fp.localFaces(), facei)
{
const face& f = fp.localFaces()[facei];
vertLabels.append(f.size());
writeFuns::insert(f, vertLabels);
}
writeFuns::write(pStream, binary, vertLabels);
//-----------------------------------------------------------------
//
// Write data
//
//-----------------------------------------------------------------
// Write faceID
pStream
<< "CELL_DATA " << fp.size() << std::endl
<< "FIELD attributes 1" << std::endl;
// Cell ids first
pStream << fieldName << " 1 " << fp.size() << " int" << std::endl;
writeFuns::write(pStream, binary, fieldValues);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -1,105 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "writePointSet.H"
#include "OFstream.H"
#include "writeFuns.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
void writePointSet
(
const bool binary,
const primitiveMesh& mesh,
const topoSet& set,
const fileName& fileName
)
{
std::ofstream pStream(fileName.c_str());
pStream
<< "# vtk DataFile Version 2.0" << std::endl
<< set.name() << std::endl;
if (binary)
{
pStream << "BINARY" << std::endl;
}
else
{
pStream << "ASCII" << std::endl;
}
pStream << "DATASET POLYDATA" << std::endl;
//------------------------------------------------------------------
//
// Write topology
//
//------------------------------------------------------------------
labelList pointLabels(set.toc());
pointField setPoints(mesh.points(), pointLabels);
// Write points
pStream << "POINTS " << pointLabels.size() << " float" << std::endl;
DynamicList<floatScalar> ptField(3*pointLabels.size());
writeFuns::insert(setPoints, ptField);
writeFuns::write(pStream, binary, ptField);
//-----------------------------------------------------------------
//
// Write data
//
//-----------------------------------------------------------------
// Write pointID
pStream
<< "POINT_DATA " << pointLabels.size() << std::endl
<< "FIELD attributes 1" << std::endl;
// Cell ids first
pStream << "pointID 1 " << pointLabels.size() << " int" << std::endl;
writeFuns::write(pStream, binary, pointLabels);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -173,8 +173,7 @@ int main(int argc, char *argv[])
(
"name",
"subdir",
"define sub-directory name to use for ensight data "
"(default: 'EnSight')"
"sub-directory name for ensight output (default: 'EnSight')"
);
argList::addOption
(

View File

@ -128,8 +128,7 @@ int main(int argc, char *argv[])
(
"name",
"subdir",
"define sub-directory name to use for Ensight data "
"(default: \"Ensight\")"
"sub-directory name for ensight output (default: 'Ensight')"
);
argList::addOption
(

View File

@ -1,10 +0,0 @@
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
# Parse arguments for library compilation
. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments
wmake $targetType foamToVTK
wmake $targetType
#------------------------------------------------------------------------------

View File

@ -1,3 +1,4 @@
foamVtkLagrangianWriter.C
foamToVTK.C
EXE = $(FOAM_APPBIN)/foamToVTK

View File

@ -1,12 +1,13 @@
EXE_INC = \
-IfoamToVTK/lnInclude \
-I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/conversion/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lfoamToVTK \
-lconversion \
-ldynamicMesh \
-llagrangian \
-lgenericPatchFields

View File

@ -1,13 +0,0 @@
surfaceMeshWriter.C
internalWriter.C
lagrangianWriter.C
patchWriter.C
writeFuns.C
writeFaceSet.C
writePointSet.C
writeSurfFields.C
vtkTopo.C
writeVTK/writeVTK.C
LIB = $(FOAM_LIBBIN)/libfoamToVTK

View File

@ -1,10 +0,0 @@
EXE_INC = \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
LIB_LIBS = \
-ldynamicMesh \
-llagrangian \
-lgenericPatchFields

View File

@ -1,165 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "internalWriter.H"
#include "writeFuns.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::internalWriter::internalWriter
(
const vtkMesh& vMesh,
const bool binary,
const fileName& fName
)
:
vMesh_(vMesh),
binary_(binary),
fName_(fName),
os_(fName.c_str())
{
const fvMesh& mesh = vMesh_.mesh();
const vtkTopo& topo = vMesh_.topo();
// Write header
writeFuns::writeHeader(os_, binary_, mesh.time().caseName());
os_ << "DATASET UNSTRUCTURED_GRID" << std::endl;
//------------------------------------------------------------------
//
// Write topology
//
//------------------------------------------------------------------
const labelList& addPointCellLabels = topo.addPointCellLabels();
const label nTotPoints = mesh.nPoints() + addPointCellLabels.size();
os_ << "POINTS " << nTotPoints << " float" << std::endl;
DynamicList<floatScalar> ptField(3*nTotPoints);
writeFuns::insert(mesh.points(), ptField);
const pointField& ctrs = mesh.cellCentres();
forAll(addPointCellLabels, api)
{
writeFuns::insert(ctrs[addPointCellLabels[api]], ptField);
}
writeFuns::write(os_, binary_, ptField);
//
// Write cells
//
const labelListList& vtkVertLabels = topo.vertLabels();
// Count total number of vertices referenced.
label nFaceVerts = 0;
forAll(vtkVertLabels, celli)
{
nFaceVerts += vtkVertLabels[celli].size() + 1;
}
os_ << "CELLS " << vtkVertLabels.size() << ' ' << nFaceVerts << std::endl;
DynamicList<label> vertLabels(nFaceVerts);
forAll(vtkVertLabels, celli)
{
const labelList& vtkVerts = vtkVertLabels[celli];
vertLabels.append(vtkVerts.size());
writeFuns::insert(vtkVerts, vertLabels);
}
writeFuns::write(os_, binary_, vertLabels);
const labelList& vtkCellTypes = topo.cellTypes();
os_ << "CELL_TYPES " << vtkCellTypes.size() << std::endl;
// Make copy since writing might swap stuff.
DynamicList<label> cellTypes(vtkCellTypes.size());
writeFuns::insert(vtkCellTypes, cellTypes);
writeFuns::write(os_, binary_, cellTypes);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::internalWriter::writeCellIDs()
{
const fvMesh& mesh = vMesh_.mesh();
const vtkTopo& topo = vMesh_.topo();
const labelList& vtkCellTypes = topo.cellTypes();
const labelList& superCells = topo.superCells();
// Cell ids first
os_ << "cellID 1 " << vtkCellTypes.size() << " int" << std::endl;
labelList cellId(vtkCellTypes.size());
label labelI = 0;
if (vMesh_.useSubMesh())
{
const labelList& cMap = vMesh_.subsetter().cellMap();
forAll(mesh.cells(), celli)
{
cellId[labelI++] = cMap[celli];
}
forAll(superCells, superCelli)
{
label origCelli = cMap[superCells[superCelli]];
cellId[labelI++] = origCelli;
}
}
else
{
forAll(mesh.cells(), celli)
{
cellId[labelI++] = celli;
}
forAll(superCells, superCelli)
{
label origCelli = superCells[superCelli];
cellId[labelI++] = origCelli;
}
}
writeFuns::write(os_, binary_, cellId);
}
// ************************************************************************* //

View File

@ -1,99 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "internalWriter.H"
#include "writeFuns.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type, template<class> class PatchField, class GeoMesh>
void Foam::internalWriter::write
(
const UPtrList<const GeometricField<Type, PatchField, GeoMesh>>& flds
)
{
forAll(flds, i)
{
writeFuns::write(os_, binary_, flds[i], vMesh_);
}
}
template<class Type, class GeoMesh>
void Foam::internalWriter::write
(
const PtrList<const DimensionedField<Type, volMesh>>& flds
)
{
forAll(flds, i)
{
writeFuns::write(os_, binary_, flds[i], vMesh_);
}
}
template<class Type>
void Foam::internalWriter::write
(
const volPointInterpolation& pInterp,
const UPtrList<const GeometricField<Type, fvPatchField, volMesh>>& flds
)
{
forAll(flds, i)
{
writeFuns::write
(
os_,
binary_,
flds[i],
pInterp.interpolate(flds[i])(),
vMesh_
);
}
}
template<class Type, class GeoMesh>
void Foam::internalWriter::write
(
const volPointInterpolation& pInterp,
const PtrList<const DimensionedField<Type, volMesh>>& flds
)
{
forAll(flds, i)
{
writeFuns::write
(
os_,
binary_,
flds[i],
pInterp.interpolate(flds[i])(),
vMesh_
);
}
}
// ************************************************************************* //

View File

@ -1,87 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "lagrangianWriter.H"
#include "writeFuns.H"
#include "Cloud.H"
#include "passiveParticle.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::lagrangianWriter::lagrangianWriter
(
const fvMesh& mesh,
const bool binary,
const fileName& fName,
const word& cloudName,
const bool dummyCloud
)
:
mesh_(mesh),
binary_(binary),
fName_(fName),
cloudName_(cloudName),
os_(fName.c_str())
{
// Write header
writeFuns::writeHeader(os_, binary_, mesh_.time().caseName());
os_ << "DATASET POLYDATA" << std::endl;
if (dummyCloud)
{
nParcels_ = 0;
os_ << "POINTS " << nParcels_ << " float" << std::endl;
}
else
{
Cloud<passiveParticle> parcels(mesh, cloudName_, false);
nParcels_ = parcels.size();
os_ << "POINTS " << nParcels_ << " float" << std::endl;
DynamicList<floatScalar> partField(3*parcels.size());
forAllConstIter(Cloud<passiveParticle>, parcels, elmnt)
{
writeFuns::insert(elmnt().position(), partField);
}
writeFuns::write(os_, binary_, partField);
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::lagrangianWriter::writeParcelHeader(const label nFields)
{
os_ << "POINT_DATA " << nParcels_ << std::endl
<< "FIELD attributes " << nFields
<< std::endl;
}
// ************************************************************************* //

View File

@ -1,65 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "lagrangianWriter.H"
#include "writeFuns.H"
#include "IOField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
void Foam::lagrangianWriter::writeIOField(const wordList& objects)
{
forAll(objects, i)
{
const word& object = objects[i];
IOobject header
(
object,
mesh_.time().timeName(),
cloud::prefix/cloudName_,
mesh_,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
);
IOField<Type> fld(header);
os_ << object << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< fld.size() << " float" << std::endl;
DynamicList<floatScalar> fField(pTraits<Type>::nComponents*fld.size());
writeFuns::insert(fld, fField);
writeFuns::write(os_, binary_, fField);
}
}
// ************************************************************************* //

View File

@ -1,136 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "patchWriter.H"
#include "writeFuns.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::patchWriter::patchWriter
(
const fvMesh& mesh,
const bool binary,
const bool nearCellValue,
const fileName& fName,
const labelList& patchIDs
)
:
mesh_(mesh),
binary_(binary),
nearCellValue_(nearCellValue),
fName_(fName),
patchIDs_(patchIDs),
os_(fName.c_str())
{
const polyBoundaryMesh& patches = mesh.boundaryMesh();
// Write header
if (patchIDs_.size() == 1)
{
writeFuns::writeHeader(os_, binary_, patches[patchIDs_[0]].name());
}
else
{
writeFuns::writeHeader(os_, binary_, "patches");
}
os_ << "DATASET POLYDATA" << std::endl;
// Write topology
nPoints_ = 0;
nFaces_ = 0;
label nFaceVerts = 0;
forAll(patchIDs_, i)
{
const polyPatch& pp = patches[patchIDs_[i]];
nPoints_ += pp.nPoints();
nFaces_ += pp.size();
forAll(pp, facei)
{
nFaceVerts += pp[facei].size() + 1;
}
}
os_ << "POINTS " << nPoints_ << " float" << std::endl;
DynamicList<floatScalar> ptField(3*nPoints_);
forAll(patchIDs_, i)
{
const polyPatch& pp = patches[patchIDs_[i]];
writeFuns::insert(pp.localPoints(), ptField);
}
writeFuns::write(os_, binary_, ptField);
os_ << "POLYGONS " << nFaces_ << ' ' << nFaceVerts << std::endl;
DynamicList<label> vertLabels(nFaceVerts);
label offset = 0;
forAll(patchIDs_, i)
{
const polyPatch& pp = patches[patchIDs_[i]];
forAll(pp, facei)
{
const face& f = pp.localFaces()[facei];
vertLabels.append(f.size());
writeFuns::insert(f + offset, vertLabels);
}
offset += pp.nPoints();
}
writeFuns::write(os_, binary_, vertLabels);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::patchWriter::writePatchIDs()
{
DynamicList<floatScalar> fField(nFaces_);
os_ << "patchID 1 " << nFaces_ << " float" << std::endl;
forAll(patchIDs_, i)
{
label patchi = patchIDs_[i];
const polyPatch& pp = mesh_.boundaryMesh()[patchi];
if (!isA<emptyPolyPatch>(pp))
{
writeFuns::insert(scalarField(pp.size(), patchi), fField);
}
}
writeFuns::write(os_, binary_, fField);
}
// ************************************************************************* //

View File

@ -1,153 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::patchWriter
Description
Write patch fields
SourceFiles
patchWriter.C
patchWriterTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef patchWriter_H
#define patchWriter_H
#include "pointMesh.H"
#include "OFstream.H"
#include "volFields.H"
#include "pointFields.H"
#include "indirectPrimitivePatch.H"
#include "PrimitivePatchInterpolation.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class volPointInterpolation;
/*---------------------------------------------------------------------------*\
Class patchWriter Declaration
\*---------------------------------------------------------------------------*/
class patchWriter
{
//- Reference to the OpenFOAM mesh (or subset)
const fvMesh& mesh_;
const bool binary_;
const bool nearCellValue_;
const fileName fName_;
const labelList patchIDs_;
std::ofstream os_;
label nPoints_;
label nFaces_;
public:
// Constructors
//- Construct from components
patchWriter
(
const fvMesh&,
const bool binary,
const bool nearCellValue,
const fileName&,
const labelList& patchIDs
);
// Member Functions
std::ofstream& os()
{
return os_;
}
label nPoints() const
{
return nPoints_;
}
label nFaces() const
{
return nFaces_;
}
//- Write cellIDs
void writePatchIDs();
//- Write volFields
template<class Type>
void write
(
const UPtrList<const GeometricField<Type, fvPatchField, volMesh>>&
);
//- Write pointFields
template<class Type>
void write
(
const UPtrList
<
const GeometricField<Type, pointPatchField, pointMesh>
>&
);
//- Interpolate and write volFields
template<class Type>
void write
(
const PrimitivePatchInterpolation<primitivePatch>&,
const UPtrList<const GeometricField<Type, fvPatchField, volMesh>>&
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "patchWriterTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,145 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "patchWriter.H"
#include "writeFuns.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
void Foam::patchWriter::write
(
const UPtrList<const GeometricField<Type, fvPatchField, volMesh>>& flds
)
{
forAll(flds, fieldi)
{
const GeometricField<Type, fvPatchField, volMesh>& fld = flds[fieldi];
os_ << fld.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< nFaces_ << " float" << std::endl;
DynamicList<floatScalar> fField(pTraits<Type>::nComponents*nFaces_);
forAll(patchIDs_, j)
{
label patchi = patchIDs_[j];
const fvPatchField<Type>& pfld = fld.boundaryField()[patchi];
if (nearCellValue_)
{
writeFuns::insert(pfld.patchInternalField()(), fField);
}
else
{
writeFuns::insert(pfld, fField);
}
}
writeFuns::write(os_, binary_, fField);
}
}
template<class Type>
void Foam::patchWriter::write
(
const UPtrList<const GeometricField<Type, pointPatchField, pointMesh>>& flds
)
{
forAll(flds, fieldi)
{
const GeometricField<Type, pointPatchField, pointMesh>& fld =
flds[fieldi];
os_ << fld.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< nPoints_ << " float" << std::endl;
DynamicList<floatScalar> fField(pTraits<Type>::nComponents*nPoints_);
forAll(patchIDs_, j)
{
label patchi = patchIDs_[j];
const pointPatchField<Type>& pfld = fld.boundaryField()[patchi];
writeFuns::insert(pfld.patchInternalField()(), fField);
}
writeFuns::write(os_, binary_, fField);
}
}
template<class Type>
void Foam::patchWriter::write
(
const PrimitivePatchInterpolation<primitivePatch>& pInter,
const UPtrList<const GeometricField<Type, fvPatchField, volMesh>>& flds
)
{
forAll(flds, fieldi)
{
const GeometricField<Type, fvPatchField, volMesh>& fld = flds[fieldi];
os_ << fld.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< nPoints_ << " float" << std::endl;
DynamicList<floatScalar> fField(pTraits<Type>::nComponents*nPoints_);
forAll(patchIDs_, j)
{
label patchi = patchIDs_[j];
const fvPatchField<Type>& pfld = fld.boundaryField()[patchi];
if (nearCellValue_)
{
writeFuns::insert
(
pInter.faceToPointInterpolate
(
pfld.patchInternalField()()
)(),
fField
);
}
else
{
writeFuns::insert
(
pInter.faceToPointInterpolate(pfld)(),
fField
);
}
}
writeFuns::write(os_, binary_, fField);
}
}
// ************************************************************************* //

View File

@ -1,137 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::vtkMesh
Description
Encapsulation of VTK mesh data. Holds mesh or meshsubset and
polyhedral-cell decomposition on it.
SourceFiles
vtkMesh.C
\*---------------------------------------------------------------------------*/
#ifndef vtkMesh_H
#define vtkMesh_H
#include "meshSubsetHelper.H"
#include "vtkTopo.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class vtkMesh Declaration
\*---------------------------------------------------------------------------*/
class vtkMesh
:
public meshSubsetHelper
{
// Private data
//- Current decomposition of topology
mutable autoPtr<vtkTopo> topoPtr_;
// Private Member Functions
//- Disallow default bitwise copy construct
vtkMesh(const vtkMesh&) = delete;
//- Disallow default bitwise assignment
void operator=(const vtkMesh&) = delete;
public:
// Constructors
//- Construct from components
vtkMesh(fvMesh& baseMesh, const word& setName = word::null)
:
meshSubsetHelper(baseMesh, meshSubsetHelper::SET, setName)
{}
// Member Functions
// Access
//- Topology
const vtkTopo& topo() const
{
if (topoPtr_.empty())
{
topoPtr_.reset(new vtkTopo(mesh()));
}
return topoPtr_();
}
//- Number of field cells
label nFieldCells() const
{
return topo().cellTypes().size();
}
//- Number of field points
label nFieldPoints() const
{
return mesh().nPoints() + topo().addPointCellLabels().size();
}
// Edit
//- Read mesh, forcing topo update if necessary
polyMesh::readUpdateState readUpdate()
{
polyMesh::readUpdateState meshState
= meshSubsetHelper::readUpdate();
if (meshState != polyMesh::UNCHANGED)
{
topoPtr_.clear();
}
return meshState;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,373 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ 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/>.
Description
Note: bug in vtk displaying wedges? Seems to display ok if we decompose
them. Should be thoroughly tested!
(they appear rarely in polyhedral meshes, do appear in some cut meshes)
\*---------------------------------------------------------------------------*/
#include "vtkTopo.H"
#include "polyMesh.H"
#include "cellShape.H"
#include "cellModeller.H"
#include "Swap.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
bool Foam::vtkTopo::decomposePoly = true;
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::vtkTopo::vtkTopo(const polyMesh& mesh)
:
mesh_(mesh),
vertLabels_(),
cellTypes_(),
addPointCellLabels_(),
superCells_()
{
const cellModel& tet = *(cellModeller::lookup("tet"));
const cellModel& pyr = *(cellModeller::lookup("pyr"));
const cellModel& prism = *(cellModeller::lookup("prism"));
const cellModel& wedge = *(cellModeller::lookup("wedge"));
const cellModel& tetWedge = *(cellModeller::lookup("tetWedge"));
const cellModel& hex = *(cellModeller::lookup("hex"));
const cellShapeList& cellShapes = mesh_.cellShapes();
// Number of additional points needed by the decomposition of polyhedra
label nAddPoints = 0;
// Number of additional cells generated by the decomposition of polyhedra
label nAddCells = 0;
// face owner is needed to determine the face orientation
const labelList& owner = mesh.faceOwner();
// Scan for cells which need to be decomposed and count additional points
// and cells
if (decomposePoly)
{
forAll(cellShapes, celli)
{
const cellModel& model = cellShapes[celli].model();
if
(
model != hex
&& model != wedge // See above.
&& model != prism
&& model != pyr
&& model != tet
&& model != tetWedge
)
{
const cell& cFaces = mesh_.cells()[celli];
forAll(cFaces, cFacei)
{
const face& f = mesh_.faces()[cFaces[cFacei]];
label nQuads = 0;
label nTris = 0;
f.nTrianglesQuads(mesh_.points(), nTris, nQuads);
nAddCells += nQuads + nTris;
}
nAddCells--;
nAddPoints++;
}
}
}
// Set size of additional point addressing array
// (from added point to original cell)
addPointCellLabels_.setSize(nAddPoints);
// Set size of additional cells mapping array
// (from added cell to original cell)
superCells_.setSize(nAddCells);
// List of vertex labels in VTK ordering
vertLabels_.setSize(cellShapes.size() + nAddCells);
// Label of vtk type
cellTypes_.setSize(cellShapes.size() + nAddCells);
// Set counters for additional points and additional cells
label addPointi = 0, addCelli = 0;
forAll(cellShapes, celli)
{
const cellShape& cellShape = cellShapes[celli];
const cellModel& cellModel = cellShape.model();
labelList& vtkVerts = vertLabels_[celli];
if (cellModel == tet)
{
vtkVerts = cellShape;
cellTypes_[celli] = VTK_TETRA;
}
else if (cellModel == pyr)
{
vtkVerts = cellShape;
cellTypes_[celli] = VTK_PYRAMID;
}
else if (cellModel == prism)
{
// VTK has a different node order for VTK_WEDGE
// their triangles point outwards!
vtkVerts = cellShape;
Foam::Swap(vtkVerts[1], vtkVerts[2]);
Foam::Swap(vtkVerts[4], vtkVerts[5]);
cellTypes_[celli] = VTK_WEDGE;
}
else if (cellModel == tetWedge && decomposePoly)
{
// Treat as squeezed prism (VTK_WEDGE)
vtkVerts.setSize(6);
vtkVerts[0] = cellShape[0];
vtkVerts[1] = cellShape[2];
vtkVerts[2] = cellShape[1];
vtkVerts[3] = cellShape[3];
vtkVerts[4] = cellShape[4];
vtkVerts[5] = cellShape[3];
cellTypes_[celli] = VTK_WEDGE;
}
else if (cellModel == wedge)
{
// Treat as squeezed hex
vtkVerts.setSize(8);
vtkVerts[0] = cellShape[0];
vtkVerts[1] = cellShape[1];
vtkVerts[2] = cellShape[2];
vtkVerts[3] = cellShape[2];
vtkVerts[4] = cellShape[3];
vtkVerts[5] = cellShape[4];
vtkVerts[6] = cellShape[5];
vtkVerts[7] = cellShape[6];
cellTypes_[celli] = VTK_HEXAHEDRON;
}
else if (cellModel == hex)
{
vtkVerts = cellShape;
cellTypes_[celli] = VTK_HEXAHEDRON;
}
else if (decomposePoly)
{
// Polyhedral cell. Decompose into tets + pyramids.
// Mapping from additional point to cell
addPointCellLabels_[addPointi] = celli;
// The new vertex from the cell-centre
const label newVertexLabel = mesh_.nPoints() + addPointi;
// Whether to insert cell in place of original or not.
bool substituteCell = true;
const labelList& cFaces = mesh_.cells()[celli];
forAll(cFaces, cFacei)
{
const face& f = mesh_.faces()[cFaces[cFacei]];
const bool isOwner = (owner[cFaces[cFacei]] == celli);
// Number of triangles and quads in decomposition
label nTris = 0;
label nQuads = 0;
f.nTrianglesQuads(mesh_.points(), nTris, nQuads);
// Do actual decomposition into triFcs and quadFcs.
faceList triFcs(nTris);
faceList quadFcs(nQuads);
label trii = 0;
label quadi = 0;
f.trianglesQuads(mesh_.points(), trii, quadi, triFcs, quadFcs);
forAll(quadFcs, quadI)
{
label thisCelli;
if (substituteCell)
{
thisCelli = celli;
substituteCell = false;
}
else
{
thisCelli = mesh_.nCells() + addCelli;
superCells_[addCelli++] = celli;
}
labelList& addVtkVerts = vertLabels_[thisCelli];
addVtkVerts.setSize(5);
const face& quad = quadFcs[quadI];
// Ensure we have the correct orientation for the
// base of the primitive cell shape.
// If the cell is face owner, the orientation needs to be
// flipped.
// At the moment, VTK doesn't actually seem to care if
// negative cells are defined, but we'll do it anyhow
// (for safety).
if (isOwner)
{
addVtkVerts[0] = quad[3];
addVtkVerts[1] = quad[2];
addVtkVerts[2] = quad[1];
addVtkVerts[3] = quad[0];
}
else
{
addVtkVerts[0] = quad[0];
addVtkVerts[1] = quad[1];
addVtkVerts[2] = quad[2];
addVtkVerts[3] = quad[3];
}
addVtkVerts[4] = newVertexLabel;
cellTypes_[thisCelli] = VTK_PYRAMID;
}
forAll(triFcs, triI)
{
label thisCelli;
if (substituteCell)
{
thisCelli = celli;
substituteCell = false;
}
else
{
thisCelli = mesh_.nCells() + addCelli;
superCells_[addCelli++] = celli;
}
labelList& addVtkVerts = vertLabels_[thisCelli];
const face& tri = triFcs[triI];
addVtkVerts.setSize(4);
// See note above about the orientation.
if (isOwner)
{
addVtkVerts[0] = tri[2];
addVtkVerts[1] = tri[1];
addVtkVerts[2] = tri[0];
}
else
{
addVtkVerts[0] = tri[0];
addVtkVerts[1] = tri[1];
addVtkVerts[2] = tri[2];
}
addVtkVerts[3] = newVertexLabel;
cellTypes_[thisCelli] = VTK_TETRA;
}
}
addPointi++;
}
else
{
// Polyhedral cell - not decomposed
cellTypes_[celli] = VTK_POLYHEDRON;
const labelList& cFaces = mesh_.cells()[celli];
// space for the number of faces and size of each face
label nData = 1 + cFaces.size();
// count total number of face points
forAll(cFaces, cFacei)
{
const face& f = mesh.faces()[cFaces[cFacei]];
nData += f.size(); // space for the face labels
}
vtkVerts.setSize(nData);
nData = 0;
vtkVerts[nData++] = cFaces.size();
// build face stream
forAll(cFaces, cFacei)
{
const face& f = mesh.faces()[cFaces[cFacei]];
const bool isOwner = (owner[cFaces[cFacei]] == celli);
// number of labels for this face
vtkVerts[nData++] = f.size();
if (isOwner)
{
forAll(f, fp)
{
vtkVerts[nData++] = f[fp];
}
}
else
{
// fairly immaterial if we reverse the list
// or use face::reverseFace()
forAllReverse(f, fp)
{
vtkVerts[nData++] = f[fp];
}
}
}
}
}
if (decomposePoly)
{
Pout<< " Original cells:" << mesh_.nCells()
<< " points:" << mesh_.nPoints()
<< " Additional cells:" << superCells_.size()
<< " additional points:" << addPointCellLabels_.size()
<< nl << endl;
}
}
// ************************************************************************* //

View File

@ -1,139 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::vtkTopo
Description
Polyhedral cell decomposition for VTK.
SourceFiles
vtkTopo.C
\*---------------------------------------------------------------------------*/
#ifndef vtkTopo_H
#define vtkTopo_H
#include "labelList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class polyMesh;
/*---------------------------------------------------------------------------*\
Class vtkTopo Declaration
\*---------------------------------------------------------------------------*/
class vtkTopo
{
// Private data
const polyMesh& mesh_;
//- Vertices per cell (including added cells) in vtk ordering
labelListList vertLabels_;
//- Cell types (including added cells) in vtk numbering
labelList cellTypes_;
labelList addPointCellLabels_;
labelList superCells_;
// Private Member Functions
//- Disallow default bitwise copy construct
vtkTopo(const vtkTopo&);
//- Disallow default bitwise assignment
void operator=(const vtkTopo&);
public:
// Public static data
//- Equivalent to enumeration in "vtkCellType.h"
enum vtkTypes
{
VTK_TRIANGLE = 5,
VTK_POLYGON = 7,
VTK_QUAD = 9,
VTK_TETRA = 10,
VTK_HEXAHEDRON = 12,
VTK_WEDGE = 13,
VTK_PYRAMID = 14,
VTK_POLYHEDRON = 42
};
//- Enable/disable polyhedron decomposition. Default = true
static bool decomposePoly;
// Constructors
//- Construct from components
vtkTopo(const polyMesh&);
// Member Functions
// Access
const labelListList& vertLabels() const
{
return vertLabels_;
}
const labelList& cellTypes() const
{
return cellTypes_;
}
const labelList& addPointCellLabels() const
{
return addPointCellLabels_;
}
const labelList& superCells() const
{
return superCells_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,127 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "writeFaceSet.H"
#include "OFstream.H"
#include "writeFuns.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
void Foam::writeFaceSet
(
const bool binary,
const fvMesh& mesh,
const faceSet& set,
const fileName& fileName
)
{
const faceList& faces = mesh.faces();
std::ofstream ostr(fileName.c_str());
writeFuns::writeHeader
(
ostr,
binary,
set.name()
);
ostr<< "DATASET POLYDATA" << std::endl;
//------------------------------------------------------------------
//
// Write topology
//
//------------------------------------------------------------------
// Construct primitivePatch of faces in faceSet.
faceList setFaces(set.size());
labelList setFaceLabels(set.size());
label setFacei = 0;
forAllConstIter(faceSet, set, iter)
{
setFaceLabels[setFacei] = iter.key();
setFaces[setFacei] = faces[iter.key()];
setFacei++;
}
primitiveFacePatch fp(setFaces, mesh.points());
// Write points and faces as polygons
ostr<< "POINTS " << fp.nPoints() << " float" << std::endl;
DynamicList<floatScalar> ptField(3*fp.nPoints());
writeFuns::insert(fp.localPoints(), ptField);
writeFuns::write(ostr, binary, ptField);
label nFaceVerts = 0;
forAll(fp.localFaces(), facei)
{
nFaceVerts += fp.localFaces()[facei].size() + 1;
}
ostr<< "POLYGONS " << fp.size() << ' ' << nFaceVerts << std::endl;
DynamicList<label> vertLabels(nFaceVerts);
forAll(fp.localFaces(), facei)
{
const face& f = fp.localFaces()[facei];
vertLabels.append(f.size());
writeFuns::insert(f, vertLabels);
}
writeFuns::write(ostr, binary, vertLabels);
//-----------------------------------------------------------------
//
// Write data
//
//-----------------------------------------------------------------
// Write faceID
ostr
<< "CELL_DATA " << fp.size() << std::endl
<< "FIELD attributes 1" << std::endl;
// Cell ids first
ostr<< "faceID 1 " << fp.size() << " int" << std::endl;
writeFuns::write(ostr, binary, setFaceLabels);
}
// ************************************************************************* //

View File

@ -1,264 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "writeFuns.H"
#include "vtkTopo.H"
#include "endian.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
void Foam::writeFuns::swapWord(label& word32)
{
char* mem = reinterpret_cast<char*>(&word32);
char a = mem[0];
mem[0] = mem[3];
mem[3] = a;
a = mem[1];
mem[1] = mem[2];
mem[2] = a;
}
void Foam::writeFuns::swapWords(const label nWords, label* words32)
{
for (label i = 0; i < nWords; i++)
{
swapWord(words32[i]);
}
}
void Foam::writeFuns::write
(
std::ostream& os,
const bool binary,
List<floatScalar>& fField
)
{
if (binary)
{
#ifdef WM_LITTLE_ENDIAN
swapWords(fField.size(), reinterpret_cast<label*>(fField.begin()));
#endif
os.write
(
reinterpret_cast<char*>(fField.begin()),
fField.size()*sizeof(float)
);
os << std::endl;
}
else
{
forAll(fField, i)
{
os << fField[i];
if (i > 0 && (i % 10) == 0)
{
os << std::endl;
}
else
{
os << ' ';
}
}
os << std::endl;
}
}
void Foam::writeFuns::write
(
std::ostream& os,
const bool binary,
DynamicList<floatScalar>& fField
)
{
List<floatScalar>& fld = fField.shrink();
write(os, binary, fld);
}
void Foam::writeFuns::write
(
std::ostream& os,
const bool binary,
labelList& elems
)
{
if (binary)
{
#ifdef WM_LITTLE_ENDIAN
swapWords(elems.size(), reinterpret_cast<label*>(elems.begin()));
#endif
os.write
(
reinterpret_cast<char*>(elems.begin()),
elems.size()*sizeof(label)
);
os << std::endl;
}
else
{
forAll(elems, i)
{
os << elems[i];
if (i > 0 && (i % 10) == 0)
{
os << std::endl;
}
else
{
os << ' ';
}
}
os << std::endl;
}
}
void Foam::writeFuns::write
(
std::ostream& os,
const bool binary,
DynamicList<label>& elems
)
{
labelList& fld = elems.shrink();
write(os, binary, fld);
}
void Foam::writeFuns::writeHeader
(
std::ostream& os,
const bool binary,
const std::string& title
)
{
os << "# vtk DataFile Version 2.0" << std::endl
<< title << std::endl;
if (binary)
{
os << "BINARY" << std::endl;
}
else
{
os << "ASCII" << std::endl;
}
}
void Foam::writeFuns::writeCellDataHeader
(
std::ostream& os,
const label nCells,
const label nFields
)
{
os << "CELL_DATA " << nCells << std::endl
<< "FIELD attributes " << nFields << std::endl;
}
void Foam::writeFuns::writePointDataHeader
(
std::ostream& os,
const label nPoints,
const label nFields
)
{
os << "POINT_DATA " << nPoints << std::endl
<< "FIELD attributes " << nFields << std::endl;
}
void Foam::writeFuns::insert(const scalar src, DynamicList<floatScalar>& dest)
{
dest.append(float(src));
}
void Foam::writeFuns::insert(const vector& src, DynamicList<floatScalar>& dest)
{
for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
{
dest.append(float(src[cmpt]));
}
}
void Foam::writeFuns::insert
(
const sphericalTensor& src,
DynamicList<floatScalar>& dest
)
{
for (direction cmpt = 0; cmpt < sphericalTensor::nComponents; ++cmpt)
{
dest.append(float(src[cmpt]));
}
}
void Foam::writeFuns::insert
(
const symmTensor& src,
DynamicList<floatScalar>& dest
)
{
dest.append(float(src.xx()));
dest.append(float(src.yy()));
dest.append(float(src.zz()));
dest.append(float(src.xy()));
dest.append(float(src.yz()));
dest.append(float(src.xz()));
}
void Foam::writeFuns::insert(const tensor& src, DynamicList<floatScalar>& dest)
{
for (direction cmpt = 0; cmpt < tensor::nComponents; ++cmpt)
{
dest.append(float(src[cmpt]));
}
}
void Foam::writeFuns::insert(const labelList& src, DynamicList<label>& dest)
{
dest.append(src);
}
// ************************************************************************* //

View File

@ -1,161 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::writeFuns
Description
Various functions for collecting and writing binary data.
SourceFiles
writeFuns.C
\*---------------------------------------------------------------------------*/
#ifndef writeFuns_H
#define writeFuns_H
#include "floatScalar.H"
#include "DynamicList.H"
#include "volFieldsFwd.H"
#include "pointFieldsFwd.H"
#include "vtkMesh.H"
#include "volPointInterpolation.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class writeFuns Declaration
\*---------------------------------------------------------------------------*/
class writeFuns
{
// Private Member Functions
// Swap halves of word.
static void swapWord(label& word32);
static void swapWords(const label nWords, label* words32);
public:
// Write ascii or binary. If binary optionally in-place swaps argument
static void write(std::ostream&, const bool, List<floatScalar>&);
static void write(std::ostream&, const bool, DynamicList<floatScalar>&);
static void write(std::ostream&, const bool, labelList&);
static void write(std::ostream&, const bool, DynamicList<label>&);
// Write header
static void writeHeader
(
std::ostream&,
const bool isBinary,
const std::string& title
);
static void writeCellDataHeader
(
std::ostream&,
const label nCells,
const label nFields
);
static void writePointDataHeader
(
std::ostream&,
const label nPoints,
const label nFields
);
// Convert to VTK and store
static void insert(const scalar, DynamicList<floatScalar>&);
static void insert(const point&, DynamicList<floatScalar>&);
static void insert(const sphericalTensor&, DynamicList<floatScalar>&);
static void insert(const symmTensor&, DynamicList<floatScalar>&);
static void insert(const tensor&, DynamicList<floatScalar>&);
//- Append elements to DynamicList
static void insert(const labelList&, DynamicList<label>&);
template<class Type>
static void insert(const List<Type>&, DynamicList<floatScalar>&);
//- Write volField with cell values (including decomposed cells)
template<class Type>
static void write
(
std::ostream&,
const bool binary,
const DimensionedField<Type, volMesh>&,
const vtkMesh&
);
//- Write pointField on all mesh points. Interpolate to cell centre
// for decomposed cell centres.
template<class Type>
static void write
(
std::ostream&,
const bool binary,
const GeometricField<Type, pointPatchField, pointMesh>&,
const vtkMesh&
);
//- Write interpolated field on points and original cell values on
// decomposed cell centres.
template<class Type>
static void write
(
std::ostream&,
const bool binary,
const DimensionedField<Type, volMesh>&,
const DimensionedField<Type, pointMesh>&,
const vtkMesh&
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "writeFunsTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,146 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "writeFuns.H"
#include "interpolatePointToCell.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Store List in dest
template<class Type>
void Foam::writeFuns::insert
(
const List<Type>& source,
DynamicList<floatScalar>& dest
)
{
forAll(source, i)
{
insert(source[i], dest);
}
}
template<class Type>
void Foam::writeFuns::write
(
std::ostream& os,
const bool binary,
const DimensionedField<Type, volMesh>& df,
const vtkMesh& vMesh
)
{
const fvMesh& mesh = vMesh.mesh();
const labelList& superCells = vMesh.topo().superCells();
label nValues = mesh.nCells() + superCells.size();
os << df.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< nValues << " float" << std::endl;
DynamicList<floatScalar> fField(pTraits<Type>::nComponents*nValues);
insert(df.field(), fField);
forAll(superCells, superCelli)
{
label origCelli = superCells[superCelli];
insert(df[origCelli], fField);
}
write(os, binary, fField);
}
template<class Type>
void Foam::writeFuns::write
(
std::ostream& os,
const bool binary,
const GeometricField<Type, pointPatchField, pointMesh>& pvf,
const vtkMesh& vMesh
)
{
const fvMesh& mesh = vMesh.mesh();
const vtkTopo& topo = vMesh.topo();
const labelList& addPointCellLabels = topo.addPointCellLabels();
const label nTotPoints = mesh.nPoints() + addPointCellLabels.size();
os << pvf.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< nTotPoints << " float" << std::endl;
DynamicList<floatScalar> fField(pTraits<Type>::nComponents*nTotPoints);
insert(pvf, fField);
forAll(addPointCellLabels, api)
{
label origCelli = addPointCellLabels[api];
insert(interpolatePointToCell(pvf, origCelli), fField);
}
write(os, binary, fField);
}
template<class Type>
void Foam::writeFuns::write
(
std::ostream& os,
const bool binary,
const DimensionedField<Type, volMesh>& vvf,
const DimensionedField<Type, pointMesh>& pvf,
const vtkMesh& vMesh
)
{
const fvMesh& mesh = vMesh.mesh();
const vtkTopo& topo = vMesh.topo();
const labelList& addPointCellLabels = topo.addPointCellLabels();
const label nTotPoints = mesh.nPoints() + addPointCellLabels.size();
os << vvf.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< nTotPoints << " float" << std::endl;
DynamicList<floatScalar> fField(pTraits<Type>::nComponents*nTotPoints);
insert(pvf, fField);
forAll(addPointCellLabels, api)
{
label origCelli = addPointCellLabels[api];
insert(vvf[origCelli], fField);
}
write(os, binary, fField);
}
// ************************************************************************* //

View File

@ -1,103 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "writePointSet.H"
#include "OFstream.H"
#include "writeFuns.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
void writePointSet
(
const bool binary,
const fvMesh& mesh,
const pointSet& set,
const fileName& fileName
)
{
std::ofstream ostr(fileName.c_str());
writeFuns::writeHeader
(
ostr,
binary,
set.name()
);
ostr<< "DATASET POLYDATA" << std::endl;
//------------------------------------------------------------------
//
// Write topology
//
//------------------------------------------------------------------
// Write points
ostr<< "POINTS " << set.size() << " float" << std::endl;
DynamicList<floatScalar> ptField(3*set.size());
writeFuns::insert
(
UIndirectList<point>(mesh.points(), set.toc())(),
ptField
);
writeFuns::write(ostr, binary, ptField);
//-----------------------------------------------------------------
//
// Write data
//
//-----------------------------------------------------------------
// Write faceID
ostr
<< "POINT_DATA " << set.size() << std::endl
<< "FIELD attributes 1" << std::endl;
// Cell ids first
ostr<< "pointID 1 " << set.size() << " int" << std::endl;
labelList pointIDs(set.toc());
writeFuns::write(ostr, binary, pointIDs);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -1,63 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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.
-------------------------------------------------------------------------------
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/>.
InClass
Foam::writePointSet
Description
Write pointSet to vtk polydata file. Only one data which is original
pointID.
SourceFiles
writePointSet.C
\*---------------------------------------------------------------------------*/
#ifndef writePointSet_H
#define writePointSet_H
#include "fvMesh.H"
#include "pointSet.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Write lagrangian fields.
void writePointSet
(
const bool binary,
const fvMesh& mesh,
const pointSet& set,
const fileName& fileName
);
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,113 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "writeSurfFields.H"
#include "OFstream.H"
#include "floatScalar.H"
#include "writeFuns.H"
#include "emptyFvsPatchFields.H"
#include "fvsPatchFields.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
void Foam::writeSurfFields
(
const bool binary,
const fvMesh& mesh,
const fileName& fileName,
const UPtrList<const surfaceVectorField>& surfVectorFields
)
{
std::ofstream str(fileName.c_str());
writeFuns::writeHeader
(
str,
binary,
"surfaceFields"
);
str << "DATASET POLYDATA" << std::endl;
const pointField& fc = mesh.faceCentres();
str << "POINTS " << mesh.nFaces() << " float" << std::endl;
DynamicList<floatScalar> pField(3*mesh.nFaces());
for (label facei = 0; facei < mesh.nFaces(); facei++)
{
writeFuns::insert(fc[facei], pField);
}
writeFuns::write(str, binary, pField);
str << "POINT_DATA " << mesh.nFaces() << std::endl
<< "FIELD attributes " << surfVectorFields.size() << std::endl;
// surfVectorFields
forAll(surfVectorFields, fieldi)
{
const surfaceVectorField& svf = surfVectorFields[fieldi];
str << svf.name() << " 3 "
<< mesh.nFaces() << " float" << std::endl;
DynamicList<floatScalar> fField(3*mesh.nFaces());
for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
{
writeFuns::insert(svf[facei], fField);
}
forAll(svf.boundaryField(), patchi)
{
const fvsPatchVectorField& pf = svf.boundaryField()[patchi];
const fvPatch& pp = mesh.boundary()[patchi];
if (isA<emptyFvsPatchVectorField>(pf))
{
// Note: loop over polypatch size, not fvpatch size.
forAll(pp.patch(), i)
{
writeFuns::insert(vector::zero, fField);
}
}
else
{
forAll(pf, i)
{
writeFuns::insert(pf[i], fField);
}
}
}
writeFuns::write(str, binary, fField);
}
}
// ************************************************************************* //

View File

@ -1,81 +0,0 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// So we get a decent warning if we have multiple functionObject entries
// with the same name.
#inputMode error;
application icoFoam;
startFrom startTime;
startTime 0;
stopAt endTime;
endTime 0.5;
deltaT 0.005;
writeControl timeStep;
writeInterval 20;
purgeWrite 0;
writeFormat ascii;
writePrecision 6;
writeCompression off;
timeFormat general;
timePrecision 6;
runTimeModifiable yes;
functions
{
writeVTK
{
type writeVTK;
// Where to load it from
libs ("libfoamToVTK.so");
// When to write:
// timeStep (with optional writeInterval)
// writeTime (with optional writeInterval)
// adjustableTime
// runTime
// clockTime
// cpuTime
writeControl writeTime;
// Write every writeInterval (only valid for timeStemp, writeTime)
writeInterval 1;
// Interval of time (valid for adjustableTime, runTime, clockTime,
// cpuTime)
writeInterval 1;
// Objects to write
objectNames ();
}
}
// ************************************************************************* //

View File

@ -1,156 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "writeVTK.H"
#include "dictionary.H"
#include "Time.H"
#include "vtkMesh.H"
#include "internalWriter.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
defineTypeNameAndDebug(writeVTK, 0);
addToRunTimeSelectionTable(functionObject, writeVTK, dictionary);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::writeVTK::writeVTK
(
const word& name,
const Time& runTime,
const dictionary& dict
)
:
fvMeshFunctionObject(name, runTime, dict),
objectNames_()
{
read(dict);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::functionObjects::writeVTK::~writeVTK()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::writeVTK::read(const dictionary& dict)
{
dict.lookup("objects") >> objectNames_;
return true;
}
bool Foam::functionObjects::writeVTK::execute()
{
return true;
}
bool Foam::functionObjects::writeVTK::write()
{
Info<< type() << " " << name() << " output:" << nl;
Info<< "Time: " << time_.timeName() << endl;
word timeDesc = time_.timeName();
// VTK/ directory in the case
fileName fvPath(time_.path()/"VTK");
mkDir(fvPath);
string vtkName = time_.caseName();
if (Pstream::parRun())
{
// Strip off leading casename, leaving just processor_DDD ending.
string::size_type i = vtkName.rfind("processor");
if (i != string::npos)
{
vtkName = vtkName.substr(i);
}
}
// Create file and write header
fileName vtkFileName
(
fvPath/vtkName
+ "_"
+ timeDesc
+ ".vtk"
);
Info<< " Internal : " << vtkFileName << endl;
vtkMesh vMesh(const_cast<fvMesh&>(mesh_));
// Write mesh
internalWriter writer(vMesh, false, vtkFileName);
UPtrList<const volScalarField> vsf(lookupFields<volScalarField>());
UPtrList<const volVectorField> vvf(lookupFields<volVectorField>());
UPtrList<const volSphericalTensorField> vsptf
(
lookupFields<volSphericalTensorField>()
);
UPtrList<const volSymmTensorField> vstf(lookupFields<volSymmTensorField>());
UPtrList<const volTensorField> vtf(lookupFields<volTensorField>());
// Write header for cellID and volFields
writeFuns::writeCellDataHeader
(
writer.os(),
vMesh.nFieldCells(),
1 + vsf.size() + vvf.size() + vsptf.size() + vstf.size() + vtf.size()
);
// Write cellID field
writer.writeCellIDs();
// Write volFields
writer.write(vsf);
writer.write(vvf);
writer.write(vsptf);
writer.write(vstf);
writer.write(vtf);
return true;
}
// ************************************************************************* //

View File

@ -0,0 +1,279 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkLagrangianWriter.H"
#include "Cloud.H"
#include "passiveParticle.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::vtk::lagrangianWriter::beginPiece()
{
if (!legacy_)
{
if (useVerts_)
{
format()
.openTag(vtk::fileTag::PIECE)
.xmlAttr(fileAttr::NUMBER_OF_POINTS, nParcels_)
.xmlAttr(fileAttr::NUMBER_OF_VERTS, nParcels_)
.closeTag();
}
else
{
format()
.openTag(vtk::fileTag::PIECE)
.xmlAttr(fileAttr::NUMBER_OF_POINTS, nParcels_)
.closeTag();
}
}
}
void Foam::vtk::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(vtk::fileTag::POINTS)
.openDataArray<float,3>(vtk::dataArrayAttr::POINTS)
.closeTag();
}
format().writeSize(payLoad);
forAllConstIters(parcels, iter)
{
const point& pt = iter().position();
vtk::write(format(), pt);
}
format().flush();
if (!legacy_)
{
format()
.endDataArray()
.endTag(vtk::fileTag::POINTS);
}
}
void Foam::vtk::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::vtk::lagrangianWriter::writeVerts()
{
format().tag(vtk::fileTag::VERTS);
// Same payload throughout
const uint64_t payLoad = (nParcels_ * sizeof(label));
//
// 'connectivity'
// = linear mapping onto points
//
{
format().openDataArray<label>(vtk::dataArrayAttr::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>(vtk::dataArrayAttr::OFFSETS)
.closeTag();
format().writeSize(payLoad);
for (label i=0; i < nParcels_; ++i)
{
format().write(i+1);
}
format().flush();
format().endDataArray();
}
format().endTag(vtk::fileTag::VERTS);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::vtk::lagrangianWriter::lagrangianWriter
(
const fvMesh& mesh,
const word& cloudName,
const fileName& baseName,
const vtk::outputOptions outOpts,
const bool dummyCloud
)
:
mesh_(mesh),
legacy_(outOpts.legacy()),
useVerts_(false),
format_(),
cloudName_(cloudName),
os_(),
nParcels_(0)
{
outputOptions opts(outOpts);
opts.append(false); // No append supported
os_.open((baseName + (legacy_ ? ".vtk" : ".vtp")).c_str());
format_ = opts.newFormatter(os_);
const auto& title = mesh_.time().caseName();
if (legacy_)
{
legacy::fileHeader(format(), title, vtk::fileTag::POLY_DATA);
if (dummyCloud)
{
legacy::beginPoints(os_, nParcels_);
}
else
{
writePoints();
if (useVerts_) writeVertsLegacy();
}
}
else
{
// XML (inline)
format()
.xmlHeader()
.xmlComment(title)
.beginVTKFile(vtk::fileTag::POLY_DATA, "0.1");
if (dummyCloud)
{
beginPiece();
}
else
{
writePoints();
if (useVerts_) writeVerts();
}
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::vtk::lagrangianWriter::~lagrangianWriter()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtk::lagrangianWriter::beginParcelData(label nFields)
{
const vtk::fileTag dataType =
(
useVerts_
? vtk::fileTag::CELL_DATA
: vtk::fileTag::POINT_DATA
);
if (legacy_)
{
legacy::dataHeader(os_, dataType, nParcels_, nFields);
}
else
{
format().tag(dataType);
}
}
void Foam::vtk::lagrangianWriter::endParcelData()
{
const vtk::fileTag dataType =
(
useVerts_
? vtk::fileTag::CELL_DATA
: vtk::fileTag::POINT_DATA
);
if (!legacy_)
{
format().endTag(dataType);
}
}
void Foam::vtk::lagrangianWriter::writeFooter()
{
if (!legacy_)
{
// slight cheat. </Piece> too
format().endTag(vtk::fileTag::PIECE);
format().endTag(vtk::fileTag::POLY_DATA)
.endVTKFile();
}
}
// ************************************************************************* //

View File

@ -22,7 +22,7 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::lagrangianWriter
Foam::vtk::lagrangianWriter
Description
Write fields (internal).
@ -33,32 +33,42 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef lagrangianWriter_H
#define lagrangianWriter_H
#ifndef foamVtkLagrangianWriter_H
#define foamVtkLagrangianWriter_H
#include "OFstream.H"
#include "Cloud.H"
#include "volFields.H"
#include "pointFields.H"
#include "foamVtkOutputOptions.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class volPointInterpolation;
namespace vtk
{
/*---------------------------------------------------------------------------*\
Class lagrangianWriter Declaration
\*---------------------------------------------------------------------------*/
class lagrangianWriter
{
// Private Member Data
//- Reference to the OpenFOAM mesh (or subset)
const fvMesh& mesh_;
const bool binary_;
//- Commonly used query
const bool legacy_;
const fileName fName_;
//- Write lagrangian as cell data (verts) or point data?
const bool useVerts_;
autoPtr<vtk::formatter> format_;
const word cloudName_;
@ -67,6 +77,28 @@ class lagrangianWriter
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:
// Constructors
@ -74,37 +106,56 @@ public:
//- Construct from components
lagrangianWriter
(
const fvMesh&,
const bool binary,
const fileName&,
const word&,
const bool dummyCloud
const fvMesh& mesh,
const word& cloudName,
const fileName& baseName,
const vtk::outputOptions outOpts,
const bool dummyCloud = false
);
//- Destructor
~lagrangianWriter();
// Member Functions
std::ofstream& os()
inline std::ofstream& os()
{
return os_;
}
void writeParcelHeader(const label nFields);
inline vtk::formatter& format()
{
return format_();
}
inline label nParcels() const
{
return nParcels_;
}
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);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace vtk
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "lagrangianWriterTemplates.C"
#include "foamVtkLagrangianWriterTemplates.C"
#endif

View File

@ -0,0 +1,110 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkLagrangianWriter.H"
#include "IOField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
void Foam::vtk::lagrangianWriter::writeIOField
(
const wordList& objectNames
)
{
const int nCmpt(pTraits<Type>::nComponents);
const bool useIntField =
std::is_integral<typename pTraits<Type>::cmptType>();
for (const word& fldName : objectNames)
{
IOobject header
(
fldName,
mesh_.time().timeName(),
cloud::prefix/cloudName_,
mesh_,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false // no register
);
IOField<Type> fld(header);
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);
vtk::writeList(format(), fld);
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
}
// ************************************************************************* //

View File

@ -48,7 +48,7 @@ namespace Foam
template<class GeoField>
void readFields
(
const meshSubsetHelper&,
const meshSubsetHelper& helper,
const typename GeoField::Mesh& mesh,
const IOobjectList& objects,
const HashSet<word>& selectedFields,

View File

@ -12,6 +12,7 @@ link_directories(
include_directories(
$ENV{WM_PROJECT_DIR}/src/OpenFOAM/lnInclude
$ENV{WM_PROJECT_DIR}/src/OSspecific/$ENV{WM_OSTYPE}/lnInclude
$ENV{WM_PROJECT_DIR}/src/conversion/lnInclude
$ENV{WM_PROJECT_DIR}/src/finiteVolume/lnInclude
${PROJECT_SOURCE_DIR}/../vtkPVFoam
${PROJECT_SOURCE_DIR}/../../foamPv/lnInclude
@ -64,6 +65,7 @@ target_link_libraries(
LINK_PUBLIC
vtkPVFoam-pv${PARAVIEW_VERSION_MAJOR}.${PARAVIEW_VERSION_MINOR}
foamPv-pv${PARAVIEW_VERSION_MAJOR}.${PARAVIEW_VERSION_MINOR}
conversion
finiteVolume
OpenFOAM
)

View File

@ -27,6 +27,8 @@
</Documentation>
</DoubleVectorProperty>
<!-- General Controls -->
<!-- Refresh (push button) -->
<Property
name="Refresh"
@ -35,12 +37,10 @@
<Documentation>Rescan for updated times/fields.</Documentation>
</Property>
<!-- General Controls -->
<!-- Skip Zero Time (check-box) -->
<IntVectorProperty animateable="0"
name="ZeroTime"
label="Skip Zero Time"
label="Skip 0/ time"
command="SetSkipZeroTime"
default_values="1"
number_of_elements="1"
@ -54,26 +54,28 @@
<!-- Include Sets (check-box) -->
<IntVectorProperty animateable="0"
name="IncludeSets"
label="With Sets"
command="SetIncludeSets"
default_values="0"
number_of_elements="1"
panel_visibility="default">
<BooleanDomain name="bool"/>
<Documentation>
Search the polyMesh/sets/ directory
Search the polyMesh/sets/ directory for {cell,face,point} sets
</Documentation>
</IntVectorProperty>
<!-- Include Zones (check-box) -->
<IntVectorProperty animateable="0"
name="IncludeZones"
label="With Zones"
command="SetIncludeZones"
default_values="0"
number_of_elements="1"
panel_visibility="default">
<BooleanDomain name="bool"/>
<Documentation>
ZoneMesh information is used to find {cell,face,point}Zones.
ZoneMesh information is used to find {cell,face,point} zones.
The polyMesh/ directory is only checked on startup.
</Documentation>
</IntVectorProperty>
@ -88,7 +90,7 @@
panel_visibility="default">
<BooleanDomain name="bool"/>
<Documentation>
Show patchGroups only.
Display patchGroups only instead of individual patches.
</Documentation>
</IntVectorProperty>
@ -109,6 +111,7 @@
<!-- Interpolate Fields (check-box) -->
<IntVectorProperty animateable="0"
name="InterpolateFields"
label="cell-to-point"
command="SetInterpolateVolFields"
default_values="1"
number_of_elements="1"
@ -122,6 +125,7 @@
<!-- Extrapolate Patches (check-box) -->
<IntVectorProperty animateable="0"
name="ExtrapolatePatches"
label="field-to-patch"
command="SetExtrapolatePatches"
default_values="0"
number_of_elements="1"
@ -132,7 +136,7 @@
</Documentation>
</IntVectorProperty>
<!-- Force GUI update (check-box) -->
<!-- Force GUI update (push button) -->
<IntVectorProperty animateable="0"
name="UpdateGUI"
command="SetUpdateGUI"
@ -148,7 +152,7 @@
<!-- Use VTK Polyhedron (check-box) -->
<IntVectorProperty animateable="0"
name="UseVTKPolyhedron"
label="Use VTK Polyhedron"
label="VTK Polyhedra"
command="SetUseVTKPolyhedron"
default_values="0"
number_of_elements="1"
@ -159,16 +163,22 @@
</Documentation>
</IntVectorProperty>
<!-- Cache Mesh (check-box) -->
<!-- Mesh Caching (combo-box) -->
<IntVectorProperty animateable="0"
name="CacheMesh"
command="SetCacheMesh"
default_values="1"
name="MeshCaching"
command="SetMeshCaching"
default_values="3"
number_of_elements="1"
panel_visibility="default">
<BooleanDomain name="bool"/>
<EnumerationDomain name="enum">
<Entry text="No caching" value="0" />
<Entry text="Cache fvMesh" value="1" />
<Entry text="Cache vtk,fvMesh" value="3" />
</EnumerationDomain>
<Documentation>
Cache the fvMesh in memory.
Mesh caching styles.
Caching the OpenFOAM fvMesh reduces disk access.
Caching the VTK mesh reduces transcription overhead.
</Documentation>
</IntVectorProperty>
@ -185,7 +195,7 @@
<Property name="ShowPatchNames"/>
<Property name="UpdateGUI"/>
<Property name="UseVTKPolyhedron"/>
<Property name="CacheMesh"/>
<Property name="MeshCaching"/>
</PropertyGroup>
<!-- Parts Selections -->

View File

@ -26,6 +26,7 @@ License
#include "pqFoamReaderControls.h"
#include <QCheckBox>
#include <QComboBox>
#include <QFrame>
#include <QGridLayout>
#include <QPushButton>
@ -37,18 +38,31 @@ License
#include "vtkSMIntVectorProperty.h"
#include "vtkSMPropertyGroup.h"
#include "vtkSMSourceProxy.h"
#include "vtkSMEnumerationDomain.h"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// file-scope
static QAbstractButton* setButtonProperties
// Add horizontal divider to layout
static void addHline(QGridLayout* layout, int row, int nCols)
{
QFrame* hline = new QFrame(layout->parentWidget());
hline->setFrameStyle(QFrame::HLine | QFrame::Sunken);
layout->addWidget(hline, row, 0, 1, nCols);
}
// file-scope
// Widget properties
static QWidget* setWidgetProperties
(
QAbstractButton* b,
QWidget* widget,
vtkSMProperty* prop
)
{
QString tip;
widget->setFocusPolicy(Qt::NoFocus); // avoid dotted border
vtkSMDocumentation* doc = prop->GetDocumentation();
if (doc)
@ -56,21 +70,33 @@ static QAbstractButton* setButtonProperties
const char* txt = doc->GetDescription();
if (txt)
{
tip = QString(txt).simplified();
QString tip = QString(txt).simplified();
if (tip.size())
{
widget->setToolTip(tip);
}
}
}
return widget;
}
// file-scope
// Button properties
static QAbstractButton* setButtonProperties
(
QAbstractButton* b,
vtkSMProperty* prop
)
{
setWidgetProperties(b, prop);
b->setText(prop->GetXMLLabel());
if (tip.size())
{
b->setToolTip(tip);
}
b->setFocusPolicy(Qt::NoFocus); // avoid dotted border
vtkSMIntVectorProperty* intProp =
vtkSMIntVectorProperty::SafeDownCast(prop);
// initial checked state for integer (bool) properties
// Initial checked state for integer (bool) properties
if (intProp)
{
b->setChecked(intProp->GetElement(0));
@ -80,6 +106,66 @@ static QAbstractButton* setButtonProperties
}
// file-scope
// Fill combo-box from XML enumeration
static QComboBox* setComboBoxContent
(
QComboBox* b,
vtkSMIntVectorProperty* prop
)
{
vtkSMEnumerationDomain* propEnum =
vtkSMEnumerationDomain::SafeDownCast
(
prop->FindDomain("vtkSMEnumerationDomain")
);
if (propEnum)
{
unsigned int n = propEnum->GetNumberOfEntries();
for (unsigned int idx=0; idx < n; ++idx)
{
const int val = propEnum->GetEntryValue(idx);
const char* txt = propEnum->GetEntryText(idx);
b->insertItem(val, txt);
}
// Set default
const int val = prop->GetElement(0);
unsigned int idx = 0;
if (!propEnum->IsInDomain(val, idx))
{
idx = 0;
}
b->setCurrentIndex(idx);
}
return b;
}
// file-scope
// Translate a combo-box index to a lookup value
static int comboBoxValue(vtkSMIntVectorProperty* prop, int idx)
{
vtkSMEnumerationDomain* propEnum =
vtkSMEnumerationDomain::SafeDownCast
(
prop->FindDomain("vtkSMEnumerationDomain")
);
if (propEnum)
{
return propEnum->GetEntryValue(idx);
}
else
{
return idx;
}
}
static vtkSMIntVectorProperty* lookupIntProp
(
vtkSMPropertyGroup* group,
@ -102,12 +188,12 @@ static vtkSMIntVectorProperty* lookupIntProp
void pqFoamReaderControls::fireCommand
(
vtkSMIntVectorProperty* prop,
bool checked
int val
)
{
vtkSMProxy* pxy = this->proxy();
prop->SetElement(0, checked); // Toogle bool
prop->SetElement(0, val); // Set int value, toogle bool, etc
// Fire off command
prop->Modified();
@ -140,9 +226,9 @@ void pqFoamReaderControls::refreshPressed()
}
void pqFoamReaderControls::cacheMesh(bool checked)
void pqFoamReaderControls::cacheMesh(int idx)
{
fireCommand(cacheMesh_, checked);
fireCommand(meshCaching_, comboBoxValue(meshCaching_, idx));
}
@ -196,12 +282,14 @@ pqFoamReaderControls::pqFoamReaderControls
showGroupsOnly_(lookupIntProp(group, "ShowGroupsOnly")),
includeSets_(lookupIntProp(group, "IncludeSets")),
includeZones_(lookupIntProp(group, "IncludeZones")),
cacheMesh_(lookupIntProp(group, "CacheMesh"))
meshCaching_(lookupIntProp(group, "MeshCaching"))
{
typedef vtkSMIntVectorProperty intProp;
QGridLayout* form = new QGridLayout(this);
const int nCols = 3;
// ROW
// ~~~
int row = 0;
@ -222,17 +310,14 @@ pqFoamReaderControls::pqFoamReaderControls
setButtonProperties(b, zeroTime);
form->addWidget(b, row, 1, Qt::AlignLeft);
addPropertyLink(b, "checked", SIGNAL(toggled(bool)), zeroTime);
addPropertyLink
(
b, "checked", SIGNAL(toggled(bool)), zeroTime
);
}
// LINE
// ~~~~
++row;
{
QFrame* hline = new QFrame(this);
hline->setFrameStyle(QFrame::HLine | QFrame::Sunken);
form->addWidget(hline, row, 0, 1, 4);
}
addHline(form, ++row, nCols);
// ROW
// ~~~
@ -244,8 +329,14 @@ pqFoamReaderControls::pqFoamReaderControls
setButtonProperties(b, includeSets_);
form->addWidget(b, row, 0, Qt::AlignLeft);
addPropertyLink(b, "checked", SIGNAL(toggled(bool)), includeSets_);
connect(b, SIGNAL(toggled(bool)), this, SLOT(includeSets(bool)));
addPropertyLink
(
b, "checked", SIGNAL(toggled(bool)), includeSets_
);
connect
(
b, SIGNAL(toggled(bool)), this, SLOT(includeSets(bool))
);
}
if (showGroupsOnly_)
@ -254,8 +345,14 @@ pqFoamReaderControls::pqFoamReaderControls
setButtonProperties(b, showGroupsOnly_);
form->addWidget(b, row, 1, Qt::AlignLeft);
addPropertyLink(b, "checked", SIGNAL(toggled(bool)), showGroupsOnly_);
connect(b, SIGNAL(toggled(bool)), this, SLOT(showGroupsOnly(bool)));
addPropertyLink
(
b, "checked", SIGNAL(toggled(bool)), showGroupsOnly_
);
connect
(
b, SIGNAL(toggled(bool)), this, SLOT(showGroupsOnly(bool))
);
}
@ -269,8 +366,14 @@ pqFoamReaderControls::pqFoamReaderControls
setButtonProperties(b, includeZones_);
form->addWidget(b, row, 0, Qt::AlignLeft);
addPropertyLink(b, "checked", SIGNAL(toggled(bool)), includeZones_);
connect(b, SIGNAL(toggled(bool)), this, SLOT(includeZones(bool)));
addPropertyLink
(
b, "checked", SIGNAL(toggled(bool)), includeZones_
);
connect
(
b, SIGNAL(toggled(bool)), this, SLOT(includeZones(bool))
);
}
if (showPatchNames_)
@ -279,17 +382,14 @@ pqFoamReaderControls::pqFoamReaderControls
setButtonProperties(b, showPatchNames_);
form->addWidget(b, row, 1, Qt::AlignLeft);
connect(b, SIGNAL(toggled(bool)), this, SLOT(showPatchNames(bool)));
connect
(
b, SIGNAL(toggled(bool)), this, SLOT(showPatchNames(bool))
);
}
// LINE
// ~~~~
++row;
{
QFrame* hline = new QFrame(this);
hline->setFrameStyle(QFrame::HLine | QFrame::Sunken);
form->addWidget(hline, row, 0, 1, 4);
}
addHline(form, ++row, nCols);
// ROW
// ~~~
@ -302,7 +402,10 @@ pqFoamReaderControls::pqFoamReaderControls
setButtonProperties(b, interpolate);
form->addWidget(b, row, 0, Qt::AlignLeft);
addPropertyLink(b, "checked", SIGNAL(toggled(bool)), interpolate);
addPropertyLink
(
b, "checked", SIGNAL(toggled(bool)), interpolate
);
}
intProp* extrapolate = lookupIntProp(group, "ExtrapolatePatches");
@ -312,17 +415,14 @@ pqFoamReaderControls::pqFoamReaderControls
setButtonProperties(b, extrapolate);
form->addWidget(b, row, 1, Qt::AlignLeft);
addPropertyLink(b, "checked", SIGNAL(toggled(bool)), extrapolate);
addPropertyLink
(
b, "checked", SIGNAL(toggled(bool)), extrapolate
);
}
// LINE
// ~~~~
++row;
{
QFrame* hline = new QFrame(this);
hline->setFrameStyle(QFrame::HLine | QFrame::Sunken);
form->addWidget(hline, row, 0, 1, 4);
}
addHline(form, ++row, nCols);
// ROW
// ~~~
@ -335,7 +435,10 @@ pqFoamReaderControls::pqFoamReaderControls
setButtonProperties(b, updateGui);
form->addWidget(b, row, 0, Qt::AlignLeft);
addPropertyLink(b, "checked", SIGNAL(clicked()), updateGui);
addPropertyLink
(
b, "checked", SIGNAL(clicked()), updateGui
);
}
intProp* usePolyhedron = lookupIntProp(group, "UseVTKPolyhedron");
@ -345,16 +448,29 @@ pqFoamReaderControls::pqFoamReaderControls
setButtonProperties(b, usePolyhedron);
form->addWidget(b, row, 1, Qt::AlignLeft);
addPropertyLink(b, "checked", SIGNAL(toggled(bool)), usePolyhedron);
addPropertyLink
(
b, "checked", SIGNAL(toggled(bool)), usePolyhedron
);
}
if (cacheMesh_)
if (meshCaching_)
{
QCheckBox* b = new QCheckBox(this);
setButtonProperties(b, cacheMesh_);
QComboBox* b = new QComboBox(this);
form->addWidget(b, row, 2, Qt::AlignLeft);
connect(b, SIGNAL(toggled(bool)), this, SLOT(cacheMesh(bool)));
setWidgetProperties(b, meshCaching_);
setComboBoxContent(b, meshCaching_);
addPropertyLink
(
b, "indexChanged", SIGNAL(currentIndexChanged(int)), meshCaching_
);
connect
(
b, SIGNAL(currentIndexChanged(int)), this, SLOT(cacheMesh(int))
);
}
}

View File

@ -69,8 +69,8 @@ class pqFoamReaderControls
//- IncludeZones (bool property)
vtkSMIntVectorProperty* includeZones_;
//- CacheMesh (bool property)
vtkSMIntVectorProperty* cacheMesh_;
//- MeshCaching (enum property)
vtkSMIntVectorProperty* meshCaching_;
// Private Member Functions
@ -78,8 +78,8 @@ class pqFoamReaderControls
//- Update property
void fireCommand(vtkSMProperty* prop);
//- Toggle and update bool property
void fireCommand(vtkSMIntVectorProperty* prop, bool checked);
//- Update int property or toggle bool property
void fireCommand(vtkSMIntVectorProperty* prop, int val);
//- Disallow default bitwise copy construct
@ -102,7 +102,7 @@ protected slots:
// Protected Member Functions
void refreshPressed();
void cacheMesh(bool checked);
void cacheMesh(int idx);
void showPatchNames(bool checked);
void showGroupsOnly(bool checked);
void includeSets(bool checked);

View File

@ -39,6 +39,7 @@ License
#include "vtkSMRenderViewProxy.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkStringArray.h"
#include "vtkSmartPointer.h"
// OpenFOAM includes
#include "vtkPVFoam.H"
@ -46,7 +47,7 @@ License
// STL includes
#include <vector>
#undef EXPERIMENTAL_TIME_CACHING
#undef VTKPVFOAM_DUALPORT
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -61,27 +62,26 @@ vtkPVFoamReader::vtkPVFoamReader()
vtkDebugMacro(<<"Constructor");
SetNumberOfInputPorts(0);
FileName = nullptr;
backend_ = nullptr;
output0_ = nullptr;
#ifdef VTKPVFOAM_DUALPORT
// Add second output for the Lagrangian
this->SetNumberOfOutputPorts(2);
vtkMultiBlockDataSet *lagrangian = vtkMultiBlockDataSet::New();
auto lagrangian = vtkSmartPointer<vtkMultiBlockDataSet>::New();
lagrangian->ReleaseData();
this->GetExecutive()->SetOutputData(1, lagrangian);
lagrangian->Delete();
#endif
TimeStepRange[0] = 0;
TimeStepRange[1] = 0;
CacheMesh = true;
MeshCaching = 3; // fvMesh+vtk
SkipZeroTime = false;
SkipZeroTime = true;
ExtrapolatePatches = false;
UseVTKPolyhedron = false;
IncludeSets = false;
@ -146,15 +146,9 @@ vtkPVFoamReader::~vtkPVFoamReader()
if (FileName)
{
delete [] FileName;
delete[] FileName;
}
if (output0_)
{
output0_->Delete();
}
PartSelection->RemoveAllObservers();
VolFieldSelection->RemoveAllObservers();
PointFieldSelection->RemoveAllObservers();
@ -218,7 +212,7 @@ int vtkPVFoamReader::RequestInformation
{
vtkErrorMacro("could not find valid OpenFOAM mesh");
// delete foamData and flag it as fatal error
// delete backend handler and flag it as fatal error
delete backend_;
backend_ = nullptr;
return 0;
@ -255,7 +249,7 @@ int vtkPVFoamReader::RequestInformation
<<"time-range " << times.front() << ':' << times.back() << "\n"
<<"times " << times.size() << "(";
for (const double& val : times)
for (auto val : times)
{
cout<< ' ' << val;
}
@ -291,12 +285,12 @@ int vtkPVFoamReader::RequestData
if (!FileName)
{
vtkErrorMacro("FileName has to be specified!");
vtkErrorMacro("FileName must be specified!");
return 0;
}
if (!backend_)
{
// catch some previous error
// Catch some previous error
vtkErrorMacro("Reader failed - perhaps no mesh?");
return 0;
}
@ -326,7 +320,8 @@ int vtkPVFoamReader::RequestData
{
vtkInformation *outInfo = outputVector->GetInformationObject(infoI);
int nsteps = outInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
const int nsteps =
outInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
if
(
@ -361,76 +356,23 @@ int vtkPVFoamReader::RequestData
)
);
if (Foam::vtkPVFoam::debug)
{
cout<< "update output with "
<< output->GetNumberOfBlocks() << " blocks\n";
}
#ifdef EXPERIMENTAL_TIME_CACHING
bool needsUpdate = false;
if (!output0_)
{
output0_ = vtkMultiBlockDataSet::New();
needsUpdate = true;
}
// This experimental bit of code seems to work for the geometry,
// but trashes the fields and still triggers the GeometryFilter
if (needsUpdate)
{
backend_->Update(output);
output0_->ShallowCopy(output);
}
else
{
output->ShallowCopy(output0_);
}
if (Foam::vtkPVFoam::debug)
{
if (needsUpdate)
{
cout<< "full UPDATE ---------\n";
}
else
{
cout<< "cached UPDATE ---------\n";
}
cout<< "UPDATED output: ";
output->Print(cout);
cout<< "UPDATED output0_: ";
output0_->Print(cout);
}
#else
#ifdef VTKPVFOAM_DUALPORT
backend_->Update
(
output,
vtkMultiBlockDataSet::SafeDownCast
vtkMultiBlockDataSet* output1 = vtkMultiBlockDataSet::SafeDownCast
(
outputVector->GetInformationObject(1)->Get
(
vtkMultiBlockDataSet::DATA_OBJECT()
)
);
);
backend_->Update(output, output1);
#else
backend_->Update(output, output);
backend_->Update(output, nullptr);
#endif
updatePatchNamesView(ShowPatchNames);
#endif
// Do any cleanup on the OpenFOAM side
backend_->CleanUp();
backend_->UpdateFinalize();
return 1;
}
@ -525,13 +467,11 @@ void vtkPVFoamReader::updatePatchNamesView(const bool show)
}
// Get all the pqRenderView instances
QList<pqRenderView*> renderViews = smModel->findItems<pqRenderView*>();
for (int viewI=0; viewI < renderViews.size(); ++viewI)
for (auto view : smModel->findItems<pqRenderView*>())
{
backend_->renderPatchNames
(
renderViews[viewI]->getRenderViewProxy()->GetRenderer(),
view->getRenderViewProxy()->GetRenderer(),
show
);
}

View File

@ -46,6 +46,7 @@ SourceFiles
// VTK forward declarations
class vtkDataArraySelection;
class vtkCallbackCommand;
template<class T> class vtkSmartPointer;
// OpenFOAM forward declarations
namespace Foam
@ -82,9 +83,9 @@ public:
virtual void PrintInfo();
// Description:
// OpenFOAM mesh caching control
vtkSetMacro(CacheMesh, bool);
vtkGetMacro(CacheMesh, bool);
// Mesh caching control (0:none,1:fvMesh,3:fvMesh+vtk)
vtkSetMacro(MeshCaching, int);
vtkGetMacro(MeshCaching, int);
// Description:
// OpenFOAM refresh times/fields
@ -231,7 +232,7 @@ private:
void updatePatchNamesView(const bool show);
int TimeStepRange[2];
bool CacheMesh;
int MeshCaching;
bool SkipZeroTime;
bool ExtrapolatePatches;
@ -250,9 +251,6 @@ private:
vtkDataArraySelection* PointFieldSelection;
vtkDataArraySelection* LagrangianFieldSelection;
//- Cached data for output port0 (experimental!)
vtkMultiBlockDataSet* output0_;
//- Backend portion of the reader
Foam::vtkPVFoam* backend_;
};

View File

@ -37,24 +37,50 @@ License
#include "vtkRenderer.h"
#include "vtkTextActor.h"
#include "vtkTextProperty.h"
#include "vtkSmartPointer.h"
#include "vtkInformation.h"
// Templates (only needed here)
#include "vtkPVFoamUpdateTemplates.C"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(vtkPVFoam, 0);
// file-scope
static word updateStateName(polyMesh::readUpdateState state)
{
switch (state)
{
case polyMesh::UNCHANGED: return "UNCHANGED";
case polyMesh::POINTS_MOVED: return "POINTS_MOVED";
case polyMesh::TOPO_CHANGE: return "TOPO_CHANGE";
case polyMesh::TOPO_PATCH_CHANGE: return "TOPO_PATCH_CHANGE";
};
return "UNKNOWN";
}
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
vtkTextActor* Foam::vtkPVFoam::createTextActor
(
const string& s,
const point& pt
)
namespace Foam
{
vtkTextActor* txt = vtkTextActor::New();
// file-scope
//- Create a text actor
vtkSmartPointer<vtkTextActor> createTextActor
(
const std::string& s,
const Foam::point& pt
)
{
vtkSmartPointer<vtkTextActor> txt =
vtkSmartPointer<vtkTextActor>::New();
txt->SetInput(s.c_str());
// Set text properties
@ -71,6 +97,7 @@ vtkTextActor* Foam::vtkPVFoam::createTextActor
txt->GetPositionCoordinate()->SetValue(pt.x(), pt.y(), pt.z());
return txt;
}
}
@ -79,40 +106,79 @@ vtkTextActor* Foam::vtkPVFoam::createTextActor
void Foam::vtkPVFoam::resetCounters()
{
// Reset array range information (ids and sizes)
arrayRangeVolume_.reset();
arrayRangePatches_.reset();
arrayRangeLagrangian_.reset();
arrayRangeCellZones_.reset();
arrayRangeFaceZones_.reset();
arrayRangePointZones_.reset();
arrayRangeCellSets_.reset();
arrayRangeFaceSets_.reset();
arrayRangePointSets_.reset();
rangeVolume_.reset();
rangePatches_.reset();
rangeLagrangian_.reset();
rangeCellZones_.reset();
rangeFaceZones_.reset();
rangePointZones_.reset();
rangeCellSets_.reset();
rangeFaceSets_.reset();
rangePointSets_.reset();
}
void Foam::vtkPVFoam::reduceMemory()
template<class Container>
bool Foam::vtkPVFoam::addOutputBlock
(
vtkMultiBlockDataSet* output,
const HashTable<Container, string>& cache,
const arrayRange& selector,
const bool singleDataset
) const
{
forAll(regionPolyDecomp_, i)
const auto blockNo = output->GetNumberOfBlocks();
vtkSmartPointer<vtkMultiBlockDataSet> block;
int datasetNo = 0;
for (auto partId : selector)
{
regionPolyDecomp_[i].clear();
if (selectedPartIds_.found(partId))
{
const auto& longName = selectedPartIds_[partId];
const word shortName = getFoamName(longName);
auto iter = cache.find(longName);
if (iter.found() && iter.object().dataset)
{
auto dataset = iter.object().dataset;
if (singleDataset)
{
output->SetBlock(blockNo, dataset);
output->GetMetaData(blockNo)->Set
(
vtkCompositeDataSet::NAME(),
shortName.c_str()
);
++datasetNo;
break;
}
else if (datasetNo == 0)
{
block = vtkSmartPointer<vtkMultiBlockDataSet>::New();
output->SetBlock(blockNo, block);
output->GetMetaData(blockNo)->Set
(
vtkCompositeDataSet::NAME(),
selector.name()
);
}
forAll(zonePolyDecomp_, i)
{
zonePolyDecomp_[i].clear();
block->SetBlock(datasetNo, dataset);
block->GetMetaData(datasetNo)->Set
(
vtkCompositeDataSet::NAME(),
shortName.c_str()
);
++datasetNo;
}
}
}
forAll(csetPolyDecomp_, i)
{
csetPolyDecomp_[i].clear();
}
if (!reader_->GetCacheMesh())
{
delete meshPtr_;
meshPtr_ = nullptr;
}
return datasetNo;
}
@ -151,27 +217,14 @@ int Foam::vtkPVFoam::setTime(int nRequest, const double requestTimes[])
<< ", nearestIndex = " << nearestIndex << endl;
}
// see what has changed
// See what has changed
if (timeIndex_ != nearestIndex)
{
timeIndex_ = nearestIndex;
runTime.setTime(Times[nearestIndex], nearestIndex);
// the fields change each time
fieldsChanged_ = true;
if (meshPtr_)
{
if (meshPtr_->readUpdate() != polyMesh::UNCHANGED)
{
meshChanged_ = true;
}
}
else
{
meshChanged_ = true;
}
// When the changes, so do the fields
meshState_ = meshPtr_ ? meshPtr_->readUpdate() : polyMesh::TOPO_CHANGE;
reader_->UpdateProgress(0.05);
@ -184,63 +237,16 @@ int Foam::vtkPVFoam::setTime(int nRequest, const double requestTimes[])
Info<< "<end> setTime() - selectedTime="
<< Times[nearestIndex].name() << " index=" << timeIndex_
<< "/" << Times.size()
<< " meshChanged=" << Switch(meshChanged_)
<< " fieldsChanged=" << Switch(fieldsChanged_) << endl;
<< " meshUpdateState=" << updateStateName(meshState_) << endl;
}
return nearestIndex;
}
void Foam::vtkPVFoam::updateMeshPartsStatus()
Foam::word Foam::vtkPVFoam::getReaderPartName(const int partId) const
{
if (debug)
{
Info<< "<beg> updateMeshPartsStatus" << endl;
}
vtkDataArraySelection* selection = reader_->GetPartSelection();
label nElem = selection->GetNumberOfArrays();
if (partStatus_.size() != nElem)
{
partStatus_.setSize(nElem);
partStatus_ = false;
meshChanged_ = true;
}
// this needs fixing if we wish to re-use the datasets
partDataset_.setSize(nElem);
partDataset_ = -1;
// Read the selected mesh parts (zones, patches ...) and add to list
forAll(partStatus_, partId)
{
const int setting = selection->GetArraySetting(partId);
if (partStatus_[partId] != setting)
{
partStatus_[partId] = setting;
meshChanged_ = true;
}
if (debug > 1)
{
Info<< " part[" << partId << "] = "
<< partStatus_[partId]
<< " : " << selection->GetArrayName(partId) << endl;
}
}
if (debug)
{
Info<< "<end> updateMeshPartsStatus" << endl;
}
}
Foam::word Foam::vtkPVFoam::getPartName(const int partId)
{
return getFirstWord(reader_->GetPartArrayName(partId));
return getFoamName(reader_->GetPartArrayName(partId));
}
@ -258,17 +264,17 @@ Foam::vtkPVFoam::vtkPVFoam
meshRegion_(polyMesh::defaultRegion),
meshDir_(polyMesh::meshSubDir),
timeIndex_(-1),
meshChanged_(true),
fieldsChanged_(true),
arrayRangeVolume_("unzoned"),
arrayRangePatches_("patches"),
arrayRangeLagrangian_("lagrangian"),
arrayRangeCellZones_("cellZone"),
arrayRangeFaceZones_("faceZone"),
arrayRangePointZones_("pointZone"),
arrayRangeCellSets_("cellSet"),
arrayRangeFaceSets_("faceSet"),
arrayRangePointSets_("pointSet")
decomposePoly_(false),
meshState_(polyMesh::TOPO_CHANGE),
rangeVolume_("unzoned"),
rangePatches_("patch"),
rangeLagrangian_("lagrangian"),
rangeCellZones_("cellZone"),
rangeFaceZones_("faceZone"),
rangePointZones_("pointZone"),
rangeCellSets_("cellSet"),
rangeFaceSets_("faceSet"),
rangePointSets_("pointSet")
{
if (debug)
{
@ -393,16 +399,16 @@ void Foam::vtkPVFoam::updateInfo()
// time of the vtkDataArraySelection, but the qt/paraview proxy
// layer doesn't care about that anyhow.
stringList enabledEntries;
HashSet<string> enabled;
if (!partSelection->GetNumberOfArrays() && !meshPtr_)
{
// enable 'internalMesh' on the first call
enabledEntries = { "internalMesh" };
// Fake enable 'internalMesh' on the first call
enabled = { "internalMesh" };
}
else
{
// preserve the enabled selections
enabledEntries = getSelectedArrayEntries(partSelection);
enabled = getSelectedArraySet(partSelection);
}
// Clear current mesh parts list
@ -410,21 +416,27 @@ void Foam::vtkPVFoam::updateInfo()
// Update mesh parts list - add Lagrangian at the bottom
updateInfoInternalMesh(partSelection);
updateInfoPatches(partSelection, enabledEntries);
updateInfoPatches(partSelection, enabled);
updateInfoSets(partSelection);
updateInfoZones(partSelection);
updateInfoLagrangian(partSelection);
// restore the enabled selections
setSelectedArrayEntries(partSelection, enabledEntries);
if (meshChanged_)
{
fieldsChanged_ = true;
}
// Adjust/restore the enabled selections
setSelectedArrayEntries(partSelection, enabled);
// Update volume, point and lagrangian fields
updateInfoFields();
updateInfoFields<fvPatchField, volMesh>
(
reader_->GetVolFieldSelection()
);
updateInfoFields<pointPatchField, pointMesh>
(
reader_->GetPointFieldSelection()
);
updateInfoLagrangianFields
(
reader_->GetLagrangianFieldSelection()
);
if (debug)
{
@ -433,15 +445,97 @@ void Foam::vtkPVFoam::updateInfo()
}
void Foam::vtkPVFoam::updateFoamMesh()
void Foam::vtkPVFoam::Update
(
vtkMultiBlockDataSet* output,
vtkMultiBlockDataSet* outputLagrangian
)
{
if (debug)
{
cout<< "<beg> Foam::vtkPVFoam::Update\n";
output->Print(cout);
if (outputLagrangian) outputLagrangian->Print(cout);
printMemory();
}
reader_->UpdateProgress(0.1);
const int caching = reader_->GetMeshCaching();
const bool oldDecomp = decomposePoly_;
decomposePoly_ = !reader_->GetUseVTKPolyhedron();
// Set up mesh parts selection(s)
// Update cached, saved, unneed values.
{
vtkDataArraySelection* selection = reader_->GetPartSelection();
const int n = selection->GetNumberOfArrays();
selectedPartIds_.clear();
HashSet<string> nowActive;
for (int id=0; id < n; ++id)
{
const string str(selection->GetArrayName(id));
const bool status = selection->GetArraySetting(id);
if (status)
{
selectedPartIds_.set(id, str); // id -> name
nowActive.set(str);
}
if (debug > 1)
{
Info<< " part[" << id << "] = " << status
<< " : " << str << nl;
}
}
// Dispose of unneeded components
cachedVtp_.retain(nowActive);
cachedVtu_.retain(nowActive);
if
(
!caching
|| meshState_ == polyMesh::TOPO_CHANGE
|| meshState_ == polyMesh::TOPO_PATCH_CHANGE
)
{
// Eliminate cached values that would be unreliable
forAllIters(cachedVtp_, iter)
{
iter.object().clearGeom();
iter.object().clear();
}
forAllIters(cachedVtu_, iter)
{
iter.object().clearGeom();
iter.object().clear();
}
}
else if (oldDecomp != decomposePoly_)
{
// poly-decompose changed - dispose of cached values
forAllIters(cachedVtu_, iter)
{
iter.object().clearGeom();
iter.object().clear();
}
}
}
reader_->UpdateProgress(0.15);
// Update the OpenFOAM mesh
{
if (debug)
{
Info<< "<beg> updateFoamMesh" << endl;
printMemory();
}
if (!reader_->GetCacheMesh())
if (!caching)
{
delete meshPtr_;
meshPtr_ = nullptr;
@ -453,9 +547,7 @@ void Foam::vtkPVFoam::updateFoamMesh()
if (debug)
{
Info<< "Creating OpenFOAM mesh for region " << meshRegion_
<< " at time=" << dbPtr_().timeName()
<< endl;
<< " at time=" << dbPtr_().timeName() << endl;
}
meshPtr_ = new fvMesh
@ -469,7 +561,7 @@ void Foam::vtkPVFoam::updateFoamMesh()
)
);
meshChanged_ = true;
meshState_ = polyMesh::TOPO_CHANGE; // New mesh
}
else
{
@ -484,84 +576,89 @@ void Foam::vtkPVFoam::updateFoamMesh()
Info<< "<end> updateFoamMesh" << endl;
printMemory();
}
}
void Foam::vtkPVFoam::Update
(
vtkMultiBlockDataSet* output,
vtkMultiBlockDataSet* lagrangianOutput
)
{
if (debug)
{
cout<< "<beg> Foam::vtkPVFoam::Update - output with "
<< output->GetNumberOfBlocks() << " and "
<< lagrangianOutput->GetNumberOfBlocks() << " blocks\n";
output->Print(cout);
lagrangianOutput->Print(cout);
printMemory();
}
reader_->UpdateProgress(0.1);
// Set up mesh parts selection(s)
updateMeshPartsStatus();
reader_->UpdateProgress(0.15);
// Update the OpenFOAM mesh
updateFoamMesh();
reader_->UpdateProgress(0.4);
// Convert meshes - start port0 at block=0
int blockNo = 0;
convertMeshVolume(output, blockNo);
convertMeshPatches(output, blockNo);
convertMeshVolume();
convertMeshPatches();
reader_->UpdateProgress(0.6);
if (reader_->GetIncludeZones())
{
convertMeshCellZones(output, blockNo);
convertMeshFaceZones(output, blockNo);
convertMeshPointZones(output, blockNo);
convertMeshCellZones();
convertMeshFaceZones();
convertMeshPointZones();
reader_->UpdateProgress(0.65);
}
if (reader_->GetIncludeSets())
{
convertMeshCellSets(output, blockNo);
convertMeshFaceSets(output, blockNo);
convertMeshPointSets(output, blockNo);
convertMeshCellSets();
convertMeshFaceSets();
convertMeshPointSets();
reader_->UpdateProgress(0.7);
}
#ifdef VTKPVFOAM_DUALPORT
// restart port1 at block=0
blockNo = 0;
#endif
convertMeshLagrangian(lagrangianOutput, blockNo);
convertMeshLagrangian();
reader_->UpdateProgress(0.8);
// Update fields
convertVolFields(output);
convertPointFields(output);
convertLagrangianFields(lagrangianOutput);
convertVolFields();
convertPointFields();
convertLagrangianFields();
// Assemble multiblock output
addOutputBlock(output, cachedVtu_, rangeVolume_, true); // One dataset
addOutputBlock(output, cachedVtp_, rangePatches_);
addOutputBlock(output, cachedVtu_, rangeCellZones_);
addOutputBlock(output, cachedVtp_, rangeFaceZones_);
addOutputBlock(output, cachedVtp_, rangePointZones_);
addOutputBlock(output, cachedVtu_, rangeCellSets_);
addOutputBlock(output, cachedVtp_, rangeFaceSets_);
addOutputBlock(output, cachedVtp_, rangePointSets_);
addOutputBlock
(
(outputLagrangian ? outputLagrangian : output),
cachedVtp_,
rangeLagrangian_
);
if (debug)
{
Info<< "done reader part" << nl << endl;
}
reader_->UpdateProgress(0.95);
meshChanged_ = fieldsChanged_ = false;
meshState_ = polyMesh::UNCHANGED;
if (caching & 2)
{
// Suppress caching of Lagrangian since it normally always changes.
cachedVtp_.filterKeys
(
[](const word& k){ return k.startsWith("lagrangian/"); },
true // prune
);
}
else
{
cachedVtp_.clear();
cachedVtu_.clear();
}
}
void Foam::vtkPVFoam::CleanUp()
void Foam::vtkPVFoam::UpdateFinalize()
{
// reclaim some memory
reduceMemory();
if (!reader_->GetMeshCaching())
{
delete meshPtr_;
meshPtr_ = nullptr;
}
reader_->UpdateProgress(1.0);
}
@ -640,20 +737,19 @@ void Foam::vtkPVFoam::renderPatchNames
{
// always remove old actors first
forAll(patchTextActorsPtrs_, patchi)
forAll(patchTextActors_, patchi)
{
renderer->RemoveViewProp(patchTextActorsPtrs_[patchi]);
patchTextActorsPtrs_[patchi]->Delete();
renderer->RemoveViewProp(patchTextActors_[patchi]);
}
patchTextActorsPtrs_.clear();
patchTextActors_.clear();
if (show && meshPtr_)
{
// get the display patches, strip off any suffix
// get the display patches, strip off any prefix/suffix
hashedWordList selectedPatches = getSelected
(
reader_->GetPartSelection(),
arrayRangePatches_
rangePatches_
);
if (selectedPatches.empty())
@ -750,7 +846,7 @@ void Foam::vtkPVFoam::renderPatchNames
}
// Set the size of the patch labels to max number of zones
patchTextActorsPtrs_.setSize(displayZoneI);
patchTextActors_.setSize(displayZoneI);
if (debug)
{
@ -783,7 +879,7 @@ void Foam::vtkPVFoam::renderPatchNames
}
// Into a list for later removal
patchTextActorsPtrs_[displayZoneI++] = createTextActor
patchTextActors_[displayZoneI++] = createTextActor
(
pp.name(),
zoneCentre[patchi][globalZoneI]
@ -792,13 +888,13 @@ void Foam::vtkPVFoam::renderPatchNames
}
// Resize the patch names list to the actual number of patch names added
patchTextActorsPtrs_.setSize(displayZoneI);
patchTextActors_.setSize(displayZoneI);
}
// Add text to each renderer
forAll(patchTextActorsPtrs_, actori)
forAll(patchTextActors_, actori)
{
renderer->AddViewProp(patchTextActorsPtrs_[actori]);
renderer->AddViewProp(patchTextActors_[actori]);
}
}

View File

@ -25,7 +25,25 @@ Class
Foam::vtkPVFoam
Description
Provides a reader interface for OpenFOAM to VTK interaction.
The backend for the vtkPVFoamReader reader module -
providing a paraview reader interface for OpenFOAM meshes and fields.
Similar, and sometimes better, functionality may be provided by the
native VTK OpenFOAM reader. OpenCFD has recently (2017) been working
on improving the native VTK OpenFOAM reader for the benefit of everyone.
In some areas the reader module lacks compared to the native reader
(notably the ability to work on decomosed datasets), but provides
additional handling of sets,zones,groups. Some features have also since
been adapted to the native reader. Additionally, the reader module
provides a useful platform for testing new ideas.
Note
The reader module allows two levels of caching. The OpenFOAM fvMesh
can be cached in memory, for faster loading of fields. Additionally,
the translated VTK geometries are held in a local cache. The cached
VTK geometries should incur no additional overhead since they use
the VTK reference counting for their storage management.
SourceFiles
vtkPVFoam.C
@ -35,7 +53,6 @@ SourceFiles
vtkPVFoamMeshVolume.C
vtkPVFoamTemplates.C
vtkPVFoamUpdateInfo.C
vtkPVFoamUtils.C
vtkPVFoamFieldTemplates.C
vtkPVFoamUpdateTemplates.C
@ -55,22 +72,24 @@ SourceFiles
#include "PrimitivePatchInterpolation.H"
#include "volPointInterpolation.H"
#include "foamPvCore.H"
#include "foamVtkMeshMaps.H"
#undef VTKPVFOAM_DUALPORT
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"
#include "vtkUnstructuredGrid.h"
// * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * //
class vtkCellArray;
class vtkDataArraySelection;
class vtkDataSet;
class vtkFloatArray;
class vtkPoints;
class vtkIndent;
class vtkMultiBlockDataSet;
class vtkPVFoamReader;
class vtkRenderer;
class vtkTextActor;
class vtkMultiBlockDataSet;
class vtkPolyData;
class vtkUnstructuredGrid;
class vtkIndent;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -83,6 +102,7 @@ class Time;
class fvMesh;
class IOobjectList;
class polyPatch;
class fvMeshSubset;
template<class Type> class IOField;
template<class Type> class Field;
@ -102,66 +122,101 @@ class vtkPVFoam
// Private classes
//- Bookkeeping for polyhedral cell decomposition
// hide in extra pointMap (cellSet/cellZone) for now
class polyDecomp
//- Bookkeeping for internal caching.
// Retain an original copy of the geometry as well as a shallow copy
// with the output fields.
// The original copy is reused for different timestep
template<class DataType>
class foamVtkCaching
{
labelList superCells_;
labelList addPointCellLabels_;
labelList pointMap_;
public:
typedef DataType dataType;
polyDecomp()
{}
//- The geometry, without any cell/point data
vtkSmartPointer<dataType> vtkgeom;
//- Label of original cell for decomposed cells
labelList& superCells()
//- The shallow-copy of geometry, plus additional data
vtkSmartPointer<dataType> dataset;
//- Number of points associated with geometry
inline uint64_t nPoints() const
{
return superCells_;
return vtkgeom ? vtkgeom->GetNumberOfPoints() : 0;
}
//- Label of original cell for decomposed cells
const labelList& superCells() const
//- Clear geometry and dataset
void clearGeom()
{
return superCells_;
vtkgeom = nullptr;
dataset = nullptr;
}
//- Cell-centre labels for additional points of decomposed cells
labelList& addPointCellLabels()
//- Return a shallow copy of vtkgeom for manipulation
vtkSmartPointer<dataType> getCopy() const
{
return addPointCellLabels_;
auto copy = vtkSmartPointer<dataType>::New();
copy->ShallowCopy(vtkgeom);
return copy;
}
//- Cell-centre labels for additional points of decomposed cells
const labelList& addPointCellLabels() const
//- Make a shallow copy of vtkgeom into dataset
void reuse()
{
return addPointCellLabels_;
dataset = vtkSmartPointer<dataType>::New();
dataset->ShallowCopy(vtkgeom);
}
//- Point labels for subsetted meshes
labelList& pointMap()
//- Set the geometry and make a shallow copy to dataset
void set(vtkSmartPointer<dataType> geom)
{
return pointMap_;
vtkgeom = geom;
reuse();
}
//- Point labels for subsetted meshes
const labelList& pointMap() const
//- Report basic information to output
void PrintSelf(std::ostream& os) const
{
return pointMap_;
os << "geom" << nl;
if (vtkgeom)
{
vtkgeom->PrintSelf(std::cout, vtkIndent(2));
}
//- Clear
void clear()
else
{
superCells_.clear();
addPointCellLabels_.clear();
pointMap_.clear();
os << "nullptr";
}
os << nl;
os << "copy" << nl;
if (dataset)
{
dataset->PrintSelf(std::cout, vtkIndent(2));
}
else
{
os << "nullptr";
}
os << nl;
}
};
//- Bookkeeping for vtkPolyData
class foamVtpData
:
public foamVtkCaching<vtkPolyData>,
public foamVtkMeshMaps
{};
//- Bookkeeping for vtkUnstructuredGrid
class foamVtuData
:
public foamVtkCaching<vtkUnstructuredGrid>,
public foamVtkMeshMaps
{};
// Private Data
//- Access to the controlling vtkPVFoamReader
@ -182,72 +237,74 @@ class vtkPVFoam
//- The time index
int timeIndex_;
//- Previous/current decomposition request
bool decomposePoly_;
//- Track changes in mesh geometry
bool meshChanged_;
enum polyMesh::readUpdateState meshState_;
//- Track changes in fields
bool fieldsChanged_;
//- The index of selected parts mapped to their names
Map<string> selectedPartIds_;
//- Selected geometrical parts (internalMesh, patches, ...)
boolList partStatus_;
//- Any information for 2D (VTP) geometries
HashTable<foamVtpData, string> cachedVtp_;
//- Datasets corresponding to selected geometrical pieces
// a negative number indicates that no vtkmesh exists for this piece
labelList partDataset_;
//- Cell maps and other information for 3D (VTU) geometries
HashTable<foamVtuData, string> cachedVtu_;
//- First instance and size of various mesh parts
// used to index into partStatus_ and partDataset_
arrayRange arrayRangeVolume_;
arrayRange arrayRangePatches_;
arrayRange arrayRangeLagrangian_;
arrayRange arrayRangeCellZones_;
arrayRange arrayRangeFaceZones_;
arrayRange arrayRangePointZones_;
arrayRange arrayRangeCellSets_;
arrayRange arrayRangeFaceSets_;
arrayRange arrayRangePointSets_;
//- Decomposed cells information (mesh regions)
// TODO: regions
List<polyDecomp> regionPolyDecomp_;
//- Decomposed cells information (cellZone meshes)
List<polyDecomp> zonePolyDecomp_;
//- Decomposed cells information (cellSet meshes)
List<polyDecomp> csetPolyDecomp_;
// used to index into selectedPartIds and thus indirectly into
// cachedVtp, cachedVtu
arrayRange rangeVolume_;
arrayRange rangePatches_;
arrayRange rangeLagrangian_;
arrayRange rangeCellZones_;
arrayRange rangeFaceZones_;
arrayRange rangePointZones_;
arrayRange rangeCellSets_;
arrayRange rangeFaceSets_;
arrayRange rangePointSets_;
//- List of patch names for rendering to window
List<vtkTextActor*> patchTextActorsPtrs_;
List<vtkSmartPointer<vtkTextActor>> patchTextActors_;
// Private Member Functions
//- Create a text actor
static vtkTextActor* createTextActor(const string& s, const point& pt);
template<class Container>
bool addOutputBlock
(
vtkMultiBlockDataSet* output,
const HashTable<Container, string>& cache,
const arrayRange& selector,
const bool singleDataset = false
) const;
//- Reset data counters
void resetCounters();
// Update information helper functions
//- Update the mesh parts selected in the GUI
void updateMeshPartsStatus();
//- Internal mesh info
void updateInfoInternalMesh(vtkDataArraySelection*);
void updateInfoInternalMesh(vtkDataArraySelection* select);
//- Lagrangian info
void updateInfoLagrangian(vtkDataArraySelection*);
void updateInfoLagrangian(vtkDataArraySelection* select);
//- Patch info
void updateInfoPatches(vtkDataArraySelection*, stringList&);
//- Patch info, modifies enabledEntries
void updateInfoPatches
(
vtkDataArraySelection* select,
HashSet<string>& enabledEntries
);
//- Set info
void updateInfoSets(vtkDataArraySelection*);
void updateInfoSets(vtkDataArraySelection* select);
//- Zone info
void updateInfoZones(vtkDataArraySelection*);
void updateInfoZones(vtkDataArraySelection* select);
//- Get non-empty zone names for zoneType from file
wordList getZoneNames(const word& zoneType) const;
@ -259,9 +316,6 @@ class vtkPVFoam
const ZoneMesh<ZoneType, polyMesh>& zmesh
);
//- Field (volume, point, lagrangian) info
void updateInfoFields();
//- Field info
template<template<class> class patchType, class meshType>
void updateInfoFields
@ -273,105 +327,171 @@ class vtkPVFoam
void updateInfoLagrangianFields(vtkDataArraySelection* select);
// Update helper functions
//- OpenFOAM mesh
void updateFoamMesh();
//- Reduce memory footprint after conversion
void reduceMemory();
// Mesh conversion functions
//- Convert volume mesh
void convertMeshVolume(vtkMultiBlockDataSet* output, int& blockNo);
//- Convert InternalMesh
void convertMeshVolume();
//- Convert Lagrangian points
void convertMeshLagrangian(vtkMultiBlockDataSet* output, int& blockNo);
void convertMeshLagrangian();
//- Convert mesh patches
void convertMeshPatches(vtkMultiBlockDataSet* output, int& blockNo);
//- Convert mesh patches.
// The additionalIds (cached data) contain the patch Ids.
// There will be several for groups, but only one for regular patches.
void convertMeshPatches();
//- Convert cell zones
void convertMeshCellZones(vtkMultiBlockDataSet* output, int& blockNo);
//- Convert face zones
void convertMeshFaceZones(vtkMultiBlockDataSet* output, int& blockNo);
//- Convert point zones
void convertMeshPointZones(vtkMultiBlockDataSet* output, int& blockNo);
void convertMeshCellZones();
//- Convert cell sets
void convertMeshCellSets(vtkMultiBlockDataSet* output, int& blockNo);
void convertMeshCellSets();
//- Convert face zones
void convertMeshFaceZones();
//- Convert face sets
void convertMeshFaceSets(vtkMultiBlockDataSet* output, int& blockNo);
// The cellMap (cached data) contains the face-labels.
void convertMeshFaceSets();
//- Convert point zones
// The pointMap (cached data) contains the point-labels.
void convertMeshPointZones();
//- Convert point sets
void convertMeshPointSets(vtkMultiBlockDataSet* output, int& blockNo);
// The pointMap (cached data) contains the point-labels.
void convertMeshPointSets();
// Add mesh functions
//- Volume meshes as vtkUnstructuredGrid
vtkUnstructuredGrid* volumeVTKMesh
//- Generate vtk points for the current mesh points/decomposition
static vtkSmartPointer<vtkPoints> movePoints
(
const fvMesh& mesh,
polyDecomp& decompInfo
const foamVtuData& vtuData
);
//- Generate vtk points for the current mesh points/decomposition,
// using the provided pointMap
static vtkSmartPointer<vtkPoints> movePoints
(
const fvMesh& mesh,
const foamVtuData& vtuData,
const labelUList& pointMap
);
//- Volume mesh as vtkUnstructuredGrid
static vtkSmartPointer<vtkUnstructuredGrid> volumeVTKMesh
(
const fvMesh& mesh,
foamVtuData& vtuData,
const bool decompPoly
);
//- Subsetted mesh as vtkUnstructuredGrid
static vtkSmartPointer<vtkUnstructuredGrid> volumeVTKSubsetMesh
(
const fvMeshSubset& subsetter,
foamVtuData& vtuData,
const bool decompPoly
);
//- Volume mesh as vtkUnstructuredGrid
vtkSmartPointer<vtkUnstructuredGrid> volumeVTKMesh
(
const fvMesh& mesh,
foamVtuData& vtuData
) const;
//- Subsetted mesh as vtkUnstructuredGrid
vtkSmartPointer<vtkUnstructuredGrid> volumeVTKSubsetMesh
(
const fvMeshSubset& subsetter,
foamVtuData& vtuData
) const;
//- Lagrangian positions as vtkPolyData
vtkPolyData* lagrangianVTKMesh
vtkSmartPointer<vtkPolyData> lagrangianVTKMesh
(
const polyMesh& mesh,
const word& cloudName
) const;
//- Patch points
template<class PatchType>
static vtkSmartPointer<vtkPoints> movePatchPoints
(
const PatchType& p
);
//- Patch faces as vtk-cells
template<class PatchType>
static vtkSmartPointer<vtkCellArray> patchFacesVTKCells
(
const PatchType& p
);
//- Patches (mesh or primitive) as vtkPolyData
template<class PatchType>
vtkPolyData* patchVTKMesh
static vtkSmartPointer<vtkPolyData> patchVTKMesh
(
const word& name,
const PatchType& p
);
// Field conversion functions
//- Convert Field to VTK field
//- Copy list to pre-allocated vtk array.
// \return number of input items copied
template<class Type>
vtkFloatArray* convertFieldToVTK
static label transcribeFloatData
(
vtkFloatArray* array,
const UList<Type>& input,
const label start = 0
);
//- Create named field initialized to zero
template<class Type>
static vtkSmartPointer<vtkFloatArray> zeroVTKField
(
const word& name,
const Field<Type>& fld
const label size
);
//- Convert float data to VTK field
template<class Type>
vtkSmartPointer<vtkFloatArray> convertFieldToVTK
(
const word& name,
const UList<Type>& fld
) const;
//- Face set/zone field
template<class Type>
vtkFloatArray* convertFaceFieldToVTK
vtkSmartPointer<vtkFloatArray> convertFaceFieldToVTK
(
const GeometricField<Type, fvPatchField, volMesh>& fld,
const labelUList& faceLabels
);
) const;
//- Volume field
template<class Type>
vtkFloatArray* convertVolFieldToVTK
vtkSmartPointer<vtkFloatArray> convertVolFieldToVTK
(
const GeometricField<Type, fvPatchField, volMesh>& fld,
const polyDecomp& decompInfo
);
const foamVtuData& vtuData
) const;
//- Convert volume fields
void convertVolFields(vtkMultiBlockDataSet* output);
void convertVolFields();
//- Convert point fields
void convertPointFields(vtkMultiBlockDataSet* output);
void convertPointFields();
//- Convert Lagrangian fields
void convertLagrangianFields(vtkMultiBlockDataSet* output);
void convertLagrangianFields();
// Convert OpenFOAM fields
@ -381,8 +501,7 @@ class vtkPVFoam
void convertVolField
(
const PtrList<patchInterpolator>& patchInterpList,
const GeometricField<Type, fvPatchField, volMesh>& fld,
vtkMultiBlockDataSet* output
const GeometricField<Type, fvPatchField, volMesh>& fld
);
//- Volume fields - all types
@ -391,8 +510,7 @@ class vtkPVFoam
(
const fvMesh& mesh,
const PtrList<patchInterpolator>& patchInterpList,
const IOobjectList& objects,
vtkMultiBlockDataSet* output
const IOobjectList& objects
);
//- Volume internal fields (DimensionedField)- all types
@ -401,8 +519,7 @@ class vtkPVFoam
(
const fvMesh& mesh,
const PtrList<patchInterpolator>& patchInterpList,
const IOobjectList& objects,
vtkMultiBlockDataSet* output
const IOobjectList& objects
);
//- Volume field - all selected parts
@ -411,9 +528,7 @@ class vtkPVFoam
(
const GeometricField<Type, fvPatchField, volMesh>& fld,
autoPtr<GeometricField<Type, pointPatchField, pointMesh>>& ptfPtr,
vtkMultiBlockDataSet* output,
const arrayRange& range,
const List<polyDecomp>& decompLst
const arrayRange& range
);
//- Lagrangian fields - all types
@ -421,8 +536,7 @@ class vtkPVFoam
void convertLagrangianFields
(
const IOobjectList& objects,
vtkMultiBlockDataSet* output,
const label datasetNo
vtkPolyData* vtkmesh
);
//- Point fields - all types
@ -430,8 +544,7 @@ class vtkPVFoam
void convertPointFields
(
const pointMesh& pMesh,
const IOobjectList& objects,
vtkMultiBlockDataSet* output
const IOobjectList& objectst
);
//- Point field - all selected parts
@ -439,33 +552,23 @@ class vtkPVFoam
void convertPointFieldBlock
(
const GeometricField<Type, pointPatchField, pointMesh>& pfld,
vtkMultiBlockDataSet* output,
const arrayRange& range,
const List<polyDecomp>& decompLst
const arrayRange& range
);
//- Point field
template<class Type>
void convertPointField
vtkSmartPointer<vtkFloatArray> convertPointField
(
vtkUnstructuredGrid* vtkmesh,
const GeometricField<Type, pointPatchField, pointMesh>& pfld,
const GeometricField<Type, fvPatchField, volMesh>& vfld,
const polyDecomp& decomp
const foamVtuData& vtuData
);
// GUI selection helper functions
//- Only retain specified fields
static void pruneObjectList
(
IOobjectList& objects,
const hashedWordList& retain
);
//- Get the first word from the reader 'parts' selection
word getPartName(const int partId);
word getReaderPartName(const int partId) const;
// Constructors
@ -506,19 +609,19 @@ public:
void Update
(
vtkMultiBlockDataSet* output,
vtkMultiBlockDataSet* lagrangianOutput
vtkMultiBlockDataSet* outputLagrangian
);
//- Clean any storage
void CleanUp();
//- Final part of Update(), after any last minute rendering.
void UpdateFinalize();
//- Add/remove patch names to/from the view
void renderPatchNames(vtkRenderer* renderer, const bool show);
//- Return a list of selected times.
// Use STL container since these values are used by the plugin
std::vector<double> findTimes(const bool skipZero = false) const;
//- Add/remove patch names to/from the view
void renderPatchNames(vtkRenderer*, const bool show);
//- Set the runTime to the first plausible request time,
// returns the timeIndex
// sets to "constant" on error

View File

@ -40,32 +40,7 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtkPVFoam::pruneObjectList
(
IOobjectList& objects,
const hashedWordList& retain
)
{
if (retain.empty())
{
objects.clear();
}
// only retain specified fields
forAllIter(IOobjectList, objects, iter)
{
if (!retain.found(iter()->name()))
{
objects.erase(iter);
}
}
}
void Foam::vtkPVFoam::convertVolFields
(
vtkMultiBlockDataSet* output
)
void Foam::vtkPVFoam::convertVolFields()
{
const fvMesh& mesh = *meshPtr_;
@ -83,7 +58,7 @@ void Foam::vtkPVFoam::convertVolFields
// Get objects (fields) for this time - only keep selected fields
// the region name is already in the mesh db
IOobjectList objects(mesh, dbPtr_().timeName());
pruneObjectList(objects, selectedFields);
objects.filterKeys(selectedFields);
if (objects.empty())
{
@ -92,8 +67,8 @@ void Foam::vtkPVFoam::convertVolFields
if (debug)
{
Info<< "<beg> convert volume fields" << endl;
forAllConstIter(IOobjectList, objects, iter)
Info<< "<beg> " << FUNCTION_NAME << endl;
forAllConstIters(objects, iter)
{
Info<< " " << iter()->name()
<< " == " << iter()->objectPath() << endl;
@ -121,30 +96,27 @@ void Foam::vtkPVFoam::convertVolFields
}
}
convertVolFields<scalar>(mesh, interpLst, objects, output);
convertVolFields<vector>(mesh, interpLst, objects, output);
convertVolFields<sphericalTensor>(mesh, interpLst, objects, output);
convertVolFields<symmTensor>(mesh, interpLst, objects, output);
convertVolFields<tensor>(mesh, interpLst, objects, output);
convertVolFields<scalar>(mesh, interpLst, objects);
convertVolFields<vector>(mesh, interpLst, objects);
convertVolFields<sphericalTensor>(mesh, interpLst, objects);
convertVolFields<symmTensor>(mesh, interpLst, objects);
convertVolFields<tensor>(mesh, interpLst, objects);
convertDimFields<scalar>(mesh, interpLst, objects, output);
convertDimFields<vector>(mesh, interpLst, objects, output);
convertDimFields<sphericalTensor>(mesh, interpLst, objects, output);
convertDimFields<symmTensor>(mesh, interpLst, objects, output);
convertDimFields<tensor>(mesh, interpLst, objects, output);
convertDimFields<scalar>(mesh, interpLst, objects);
convertDimFields<vector>(mesh, interpLst, objects);
convertDimFields<sphericalTensor>(mesh, interpLst, objects);
convertDimFields<symmTensor>(mesh, interpLst, objects);
convertDimFields<tensor>(mesh, interpLst, objects);
if (debug)
{
Info<< "<end> convert volume fields" << endl;
Info<< "<end> " << FUNCTION_NAME << endl;
printMemory();
}
}
void Foam::vtkPVFoam::convertPointFields
(
vtkMultiBlockDataSet* output
)
void Foam::vtkPVFoam::convertPointFields()
{
const fvMesh& mesh = *meshPtr_;
@ -165,7 +137,7 @@ void Foam::vtkPVFoam::convertPointFields
// Get objects (fields) for this time - only keep selected fields
// the region name is already in the mesh db
IOobjectList objects(mesh, dbPtr_().timeName());
pruneObjectList(objects, selectedFields);
objects.filterKeys(selectedFields);
if (objects.empty())
{
@ -175,7 +147,7 @@ void Foam::vtkPVFoam::convertPointFields
if (debug)
{
Info<< "<beg> convert volume -> point fields" << endl;
forAllConstIter(IOobjectList, objects, iter)
forAllConstIters(objects, iter)
{
Info<< " " << iter()->name()
<< " == " << iter()->objectPath() << endl;
@ -186,11 +158,11 @@ void Foam::vtkPVFoam::convertPointFields
// Construct interpolation on the raw mesh
const pointMesh& pMesh = pointMesh::New(mesh);
convertPointFields<scalar>(pMesh, objects, output);
convertPointFields<vector>(pMesh, objects, output);
convertPointFields<sphericalTensor>(pMesh, objects, output);
convertPointFields<symmTensor>(pMesh, objects, output);
convertPointFields<tensor>(pMesh, objects, output);
convertPointFields<scalar>(pMesh, objects);
convertPointFields<vector>(pMesh, objects);
convertPointFields<sphericalTensor>(pMesh, objects);
convertPointFields<symmTensor>(pMesh, objects);
convertPointFields<tensor>(pMesh, objects);
if (debug)
{
@ -200,12 +172,9 @@ void Foam::vtkPVFoam::convertPointFields
}
void Foam::vtkPVFoam::convertLagrangianFields
(
vtkMultiBlockDataSet* output
)
void Foam::vtkPVFoam::convertLagrangianFields()
{
arrayRange& range = arrayRangeLagrangian_;
const arrayRange& range = rangeLagrangian_;
const fvMesh& mesh = *meshPtr_;
hashedWordList selectedFields = getSelected
@ -220,20 +189,28 @@ void Foam::vtkPVFoam::convertLagrangianFields
if (debug)
{
Info<< "<beg> convert Lagrangian fields" << endl;
Info<< "<beg> " << FUNCTION_NAME << endl;
printMemory();
}
for (int partId = range.start(); partId < range.end(); ++partId)
for (auto partId : range)
{
const word cloudName = getPartName(partId);
const label datasetNo = partDataset_[partId];
if (!partStatus_[partId] || datasetNo < 0)
if (!selectedPartIds_.found(partId))
{
continue;
}
const auto& longName = selectedPartIds_[partId];
const word cloudName = getFoamName(longName);
auto iter = cachedVtp_.find(longName);
if (!iter.found() || !iter.object().dataset)
{
// Should not happen, but for safety require a vtk geometry
continue;
}
auto dataset = iter.object().dataset;
// Get the Lagrangian fields for this time and this cloud
// but only keep selected fields
// the region name is already in the mesh db
@ -243,7 +220,7 @@ void Foam::vtkPVFoam::convertLagrangianFields
dbPtr_().timeName(),
cloud::prefix/cloudName
);
pruneObjectList(objects, selectedFields);
objects.filterKeys(selectedFields);
if (objects.empty())
{
@ -253,24 +230,24 @@ void Foam::vtkPVFoam::convertLagrangianFields
if (debug)
{
Info<< "converting OpenFOAM lagrangian fields" << endl;
forAllConstIter(IOobjectList, objects, iter)
forAllConstIters(objects, iter)
{
Info<< " " << iter()->name()
<< " == " << iter()->objectPath() << endl;
}
}
convertLagrangianFields<label>(objects, output, datasetNo);
convertLagrangianFields<scalar>(objects, output, datasetNo);
convertLagrangianFields<vector>(objects, output, datasetNo);
convertLagrangianFields<sphericalTensor>(objects, output, datasetNo);
convertLagrangianFields<symmTensor>(objects, output, datasetNo);
convertLagrangianFields<tensor>(objects, output, datasetNo);
convertLagrangianFields<label>(objects, dataset);
convertLagrangianFields<scalar>(objects, dataset);
convertLagrangianFields<vector>(objects, dataset);
convertLagrangianFields<sphericalTensor>(objects, dataset);
convertLagrangianFields<symmTensor>(objects, dataset);
convertLagrangianFields<tensor>(objects, dataset);
}
if (debug)
{
Info<< "<end> convert Lagrangian fields" << endl;
Info<< "<end> " << FUNCTION_NAME << endl;
printMemory();
}
}

View File

@ -35,16 +35,17 @@ License
#include "vtkCellArray.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
vtkPolyData* Foam::vtkPVFoam::lagrangianVTKMesh
vtkSmartPointer<vtkPolyData> Foam::vtkPVFoam::lagrangianVTKMesh
(
const polyMesh& mesh,
const word& cloudName
)
) const
{
vtkPolyData* vtkmesh = nullptr;
vtkSmartPointer<vtkPolyData> vtkmesh;
if (debug)
{
@ -72,27 +73,19 @@ vtkPolyData* Foam::vtkPVFoam::lagrangianVTKMesh
Info<< "cloud with " << parcels.size() << " parcels" << endl;
}
vtkmesh = vtkPolyData::New();
vtkPoints* vtkpoints = vtkPoints::New();
vtkCellArray* vtkcells = vtkCellArray::New();
vtkpoints->Allocate(parcels.size());
vtkcells->Allocate(parcels.size());
auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(parcels.size());
vtkIdType particleId = 0;
forAllConstIter(Cloud<passiveParticle>, parcels, iter)
forAllConstIters(parcels, iter)
{
vtkpoints->InsertNextPoint(iter().position().v_);
vtkcells->InsertNextCell(1, &particleId);
particleId++;
vtkpoints->SetPoint(particleId, iter().position().v_);
++particleId;
}
vtkmesh = vtkSmartPointer<vtkPolyData>::New();
vtkmesh->SetPoints(vtkpoints);
vtkpoints->Delete();
vtkmesh->SetVerts(vtkcells);
vtkcells->Delete();
vtkmesh->SetVerts(foamPvCore::identityVertices(parcels.size()));
}
if (debug)

View File

@ -28,397 +28,188 @@ License
// OpenFOAM includes
#include "fvMesh.H"
#include "cellModeller.H"
#include "fvMeshSubset.H"
#include "foamVtkAdaptors.H"
#include "foamVtuSizing.H"
// VTK includes
#include "vtkCellArray.h"
#include "vtkIdTypeArray.h"
#include "vtkUnstructuredGrid.h"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
vtkUnstructuredGrid* Foam::vtkPVFoam::volumeVTKMesh
vtkSmartPointer<vtkPoints> Foam::vtkPVFoam::movePoints
(
const fvMesh& mesh,
polyDecomp& decompInfo
const foamVtuData& vtuData
)
{
const cellModel& tet = *(cellModeller::lookup("tet"));
const cellModel& pyr = *(cellModeller::lookup("pyr"));
const cellModel& prism = *(cellModeller::lookup("prism"));
const cellModel& wedge = *(cellModeller::lookup("wedge"));
const cellModel& tetWedge = *(cellModeller::lookup("tetWedge"));
const cellModel& hex = *(cellModeller::lookup("hex"));
// Convert OpenFOAM mesh vertices to VTK
auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkUnstructuredGrid* vtkmesh = vtkUnstructuredGrid::New();
// Normal points
const pointField& points = mesh.points();
// Additional cell centres
const labelList& addPoints = vtuData.additionalIds();
vtkpoints->SetNumberOfPoints(points.size() + addPoints.size());
// Normal points
label pointi = 0;
forAll(points, i)
{
vtkpoints->SetPoint(pointi++, points[i].v_);
}
// Cell centres
forAll(addPoints, i)
{
vtkpoints->SetPoint(pointi++, mesh.C()[addPoints[i]].v_);
}
return vtkpoints;
}
vtkSmartPointer<vtkPoints> Foam::vtkPVFoam::movePoints
(
const fvMesh& mesh,
const foamVtuData& vtuData,
const labelUList& pointMap
)
{
// Convert OpenFOAM mesh vertices to VTK
auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
// Normal points
const pointField& points = mesh.points();
// Additional cell centres
const labelList& addPoints = vtuData.additionalIds();
vtkpoints->SetNumberOfPoints(pointMap.size() + addPoints.size());
// Normal points
label pointi = 0;
forAll(pointMap, i)
{
vtkpoints->SetPoint(pointi++, points[pointMap[i]].v_);
}
// Cell centres
forAll(addPoints, i)
{
vtkpoints->SetPoint(pointi++, mesh.C()[addPoints[i]].v_);
}
return vtkpoints;
}
vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKMesh
(
const fvMesh& mesh,
foamVtuData& vtuData,
const bool decompPoly
)
{
if (debug)
{
Info<< "<beg> volumeVTKMesh" << endl;
Info<< "<beg> " << FUNCTION_NAME << endl;
printMemory();
}
const cellShapeList& cellShapes = mesh.cellShapes();
vtk::vtuSizing sizing(mesh, decompPoly);
// Number of additional points needed by the decomposition of polyhedra
label nAddPoints = 0;
auto cellTypes = vtkSmartPointer<vtkUnsignedCharArray>::New();
// Number of additional cells generated by the decomposition of polyhedra
label nAddCells = 0;
auto cells = vtkSmartPointer<vtkCellArray>::New();
auto faces = vtkSmartPointer<vtkIdTypeArray>::New();
// face owner is needed to determine the face orientation
const labelList& owner = mesh.faceOwner();
auto cellLocations = vtkSmartPointer<vtkIdTypeArray>::New();
auto faceLocations = vtkSmartPointer<vtkIdTypeArray>::New();
labelList& superCells = decompInfo.superCells();
labelList& addPointCellLabels = decompInfo.addPointCellLabels();
// Scan for cells which need to be decomposed and count additional points
// and cells
if (!reader_->GetUseVTKPolyhedron())
{
forAll(cellShapes, celli)
{
const cellModel& model = cellShapes[celli].model();
if
UList<uint8_t> cellTypesUL =
vtkUList
(
model != hex
&& model != wedge
&& model != prism
&& model != pyr
&& model != tet
&& model != tetWedge
)
{
const cell& cFaces = mesh.cells()[celli];
cellTypes,
sizing.nFieldCells()
);
forAll(cFaces, cFacei)
{
const face& f = mesh.faces()[cFaces[cFacei]];
UList<vtkIdType> cellsUL =
vtkUList
(
cells,
sizing.nFieldCells(),
sizing.sizeInternal(vtk::vtuSizing::slotType::CELLS)
);
label nQuads = 0;
label nTris = 0;
f.nTrianglesQuads(mesh.points(), nTris, nQuads);
UList<vtkIdType> cellLocationsUL =
vtkUList
(
cellLocations,
sizing.sizeInternal(vtk::vtuSizing::slotType::CELLS_OFFSETS)
);
nAddCells += nQuads + nTris;
}
UList<vtkIdType> facesUL =
vtkUList
(
faces,
sizing.sizeInternal(vtk::vtuSizing::slotType::FACES)
);
nAddCells--;
nAddPoints++;
}
}
}
UList<vtkIdType> faceLocationsUL =
vtkUList
(
faceLocations,
sizing.sizeInternal(vtk::vtuSizing::slotType::FACES_OFFSETS)
);
// Set size of additional point addressing array
// (from added point to original cell)
addPointCellLabels.setSize(nAddPoints);
// Set size of additional cells mapping array
// (from added cell to original cell)
sizing.populateInternal
(
mesh,
cellTypesUL,
cellsUL,
cellLocationsUL,
facesUL,
faceLocationsUL,
static_cast<foamVtkMeshMaps&>(vtuData)
);
superCells.setSize(mesh.nCells() + nAddCells);
auto vtkmesh = vtkSmartPointer<vtkUnstructuredGrid>::New();
// Convert OpenFOAM mesh vertices to VTK
vtkPoints* vtkpoints = vtkPoints::New();
vtkpoints->Allocate(mesh.nPoints() + nAddPoints);
// - can only do this *after* populating the decompInfo with cell-ids
// for any additional points (ie, mesh cell-centres)
vtkmesh->SetPoints(movePoints(mesh, vtuData));
const Foam::pointField& points = mesh.points();
forAll(points, i)
if (facesUL.size())
{
vtkpoints->InsertNextPoint(points[i].v_);
}
vtkmesh->Allocate(mesh.nCells() + nAddCells);
// Set counters for additional points and additional cells
label addPointi = 0, addCelli = 0;
// Create storage for points - needed for mapping from OpenFOAM to VTK
// data types - max 'order' = hex = 8 points
vtkIdType nodeIds[8];
// face-stream for a polyhedral cell
// [numFace0Pts, id1, id2, id3, numFace1Pts, id1, id2, id3, ...]
DynamicList<vtkIdType> faceStream(256);
forAll(cellShapes, celli)
{
const cellShape& cellShape = cellShapes[celli];
const cellModel& cellModel = cellShape.model();
superCells[addCelli++] = celli;
if (cellModel == tet)
{
for (int j = 0; j < 4; j++)
{
nodeIds[j] = cellShape[j];
}
vtkmesh->InsertNextCell
vtkmesh->SetCells
(
VTK_TETRA,
4,
nodeIds
cellTypes,
cellLocations,
cells,
faceLocations,
faces
);
}
else if (cellModel == pyr)
{
for (int j = 0; j < 5; j++)
{
nodeIds[j] = cellShape[j];
}
vtkmesh->InsertNextCell
(
VTK_PYRAMID,
5,
nodeIds
);
}
else if (cellModel == prism)
{
// VTK has a different node order for VTK_WEDGE
// their triangles point outwards!
nodeIds[0] = cellShape[0];
nodeIds[1] = cellShape[2];
nodeIds[2] = cellShape[1];
nodeIds[3] = cellShape[3];
nodeIds[4] = cellShape[5];
nodeIds[5] = cellShape[4];
vtkmesh->InsertNextCell
(
VTK_WEDGE,
6,
nodeIds
);
}
else if (cellModel == tetWedge && !reader_->GetUseVTKPolyhedron())
{
// Treat as squeezed prism (VTK_WEDGE)
nodeIds[0] = cellShape[0];
nodeIds[1] = cellShape[2];
nodeIds[2] = cellShape[1];
nodeIds[3] = cellShape[3];
nodeIds[4] = cellShape[4];
nodeIds[5] = cellShape[3];
vtkmesh->InsertNextCell
(
VTK_WEDGE,
6,
nodeIds
);
}
else if (cellModel == wedge)
{
// Treat as squeezed hex
nodeIds[0] = cellShape[0];
nodeIds[1] = cellShape[1];
nodeIds[2] = cellShape[2];
nodeIds[3] = cellShape[2];
nodeIds[4] = cellShape[3];
nodeIds[5] = cellShape[4];
nodeIds[6] = cellShape[5];
nodeIds[7] = cellShape[6];
vtkmesh->InsertNextCell
(
VTK_HEXAHEDRON,
8,
nodeIds
);
}
else if (cellModel == hex)
{
for (int j = 0; j < 8; j++)
{
nodeIds[j] = cellShape[j];
}
vtkmesh->InsertNextCell
(
VTK_HEXAHEDRON,
8,
nodeIds
);
}
else if (reader_->GetUseVTKPolyhedron())
{
// Polyhedral cell - use VTK_POLYHEDRON
const labelList& cFaces = mesh.cells()[celli];
vtkIdType nFaces = cFaces.size();
vtkIdType nLabels = nFaces;
// count size for face stream
forAll(cFaces, cFacei)
{
const face& f = mesh.faces()[cFaces[cFacei]];
nLabels += f.size();
}
// build face-stream
// [numFace0Pts, id1, id2, id3, numFace1Pts, id1, id2, id3, ...]
// point Ids are global
faceStream.clear();
faceStream.reserve(nLabels + nFaces);
forAll(cFaces, cFacei)
{
const face& f = mesh.faces()[cFaces[cFacei]];
const bool isOwner = (owner[cFaces[cFacei]] == celli);
const label nFacePoints = f.size();
// number of labels for this face
faceStream.append(nFacePoints);
if (isOwner)
{
forAll(f, fp)
{
faceStream.append(f[fp]);
}
}
else
{
// fairly immaterial if we reverse the list
// or use face::reverseFace()
forAllReverse(f, fp)
{
faceStream.append(f[fp]);
}
}
}
vtkmesh->InsertNextCell(VTK_POLYHEDRON, nFaces, faceStream.data());
}
else
{
// Polyhedral cell. Decompose into tets + prisms.
// Mapping from additional point to cell
addPointCellLabels[addPointi] = celli;
// The new vertex from the cell-centre
const label newVertexLabel = mesh.nPoints() + addPointi;
vtkpoints->InsertNextPoint(mesh.C()[celli].v_);
// Whether to insert cell in place of original or not.
bool substituteCell = true;
const labelList& cFaces = mesh.cells()[celli];
forAll(cFaces, cFacei)
{
const face& f = mesh.faces()[cFaces[cFacei]];
const bool isOwner = (owner[cFaces[cFacei]] == celli);
// Number of triangles and quads in decomposition
label nTris = 0;
label nQuads = 0;
f.nTrianglesQuads(mesh.points(), nTris, nQuads);
// Do actual decomposition into triFcs and quadFcs.
faceList triFcs(nTris);
faceList quadFcs(nQuads);
label trii = 0;
label quadi = 0;
f.trianglesQuads(mesh.points(), trii, quadi, triFcs, quadFcs);
forAll(quadFcs, quadI)
{
if (substituteCell)
{
substituteCell = false;
}
else
{
superCells[addCelli++] = celli;
}
const face& quad = quadFcs[quadI];
// Ensure we have the correct orientation for the
// base of the primitive cell shape.
// If the cell is face owner, the orientation needs to be
// flipped.
// At the moment, VTK doesn't actually seem to care if
// negative cells are defined, but we'll do it anyhow
// (for safety).
if (isOwner)
{
nodeIds[0] = quad[3];
nodeIds[1] = quad[2];
nodeIds[2] = quad[1];
nodeIds[3] = quad[0];
}
else
{
nodeIds[0] = quad[0];
nodeIds[1] = quad[1];
nodeIds[2] = quad[2];
nodeIds[3] = quad[3];
}
nodeIds[4] = newVertexLabel;
vtkmesh->InsertNextCell
vtkmesh->SetCells
(
VTK_PYRAMID,
5,
nodeIds
cellTypes,
cellLocations,
cells,
nullptr,
nullptr
);
}
forAll(triFcs, triI)
{
if (substituteCell)
{
substituteCell = false;
}
else
{
superCells[addCelli++] = celli;
}
const face& tri = triFcs[triI];
// See note above about the orientation.
if (isOwner)
{
nodeIds[0] = tri[2];
nodeIds[1] = tri[1];
nodeIds[2] = tri[0];
}
else
{
nodeIds[0] = tri[0];
nodeIds[1] = tri[1];
nodeIds[2] = tri[2];
}
nodeIds[3] = newVertexLabel;
vtkmesh->InsertNextCell
(
VTK_TETRA,
4,
nodeIds
);
}
}
addPointi++;
}
}
vtkmesh->SetPoints(vtkpoints);
vtkpoints->Delete();
if (debug)
{
Info<<"nCells=" << mesh.nCells() <<" nPoints=" << mesh.nPoints()
<<" nAddCells=" << nAddCells <<" nAddPoints=" << nAddPoints
<< nl
<< "<end> volumeVTKMesh" << endl;
Info<< "<end> " << FUNCTION_NAME << endl;
printMemory();
}
@ -426,4 +217,48 @@ vtkUnstructuredGrid* Foam::vtkPVFoam::volumeVTKMesh
}
vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKSubsetMesh
(
const fvMeshSubset& subsetter,
foamVtuData& vtuData,
const bool decompPoly
)
{
vtkSmartPointer<vtkUnstructuredGrid> vtkmesh = volumeVTKMesh
(
subsetter.subMesh(),
vtuData,
decompPoly
);
// Convert cellMap, addPointCellLabels to global cell ids
vtuData.renumberCells(subsetter.cellMap());
// Copy pointMap as well, otherwise pointFields fail
vtuData.pointMap() = subsetter.pointMap();
return vtkmesh;
}
vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKMesh
(
const fvMesh& mesh,
foamVtuData& vtuData
) const
{
return volumeVTKMesh(mesh, vtuData, this->decomposePoly_);
}
vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKSubsetMesh
(
const fvMeshSubset& subsetter,
foamVtuData& vtuData
) const
{
return volumeVTKSubsetMesh(subsetter, vtuData, this->decomposePoly_);
}
// ************************************************************************* //

View File

@ -28,67 +28,91 @@ License
// OpenFOAM includes
#include "polyPatch.H"
#include "primitivePatch.H"
#include "foamVtkAdaptors.H"
// VTK includes
#include "vtkCellArray.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class PatchType>
vtkPolyData* Foam::vtkPVFoam::patchVTKMesh
vtkSmartPointer<vtkPoints> Foam::vtkPVFoam::movePatchPoints
(
const word& name,
const PatchType& p
)
{
vtkPolyData* vtkmesh = vtkPolyData::New();
if (debug)
{
Info<< "<beg> patchVTKMesh - " << name << endl;
printMemory();
}
// Convert OpenFOAM mesh vertices to VTK
const Foam::pointField& points = p.localPoints();
const pointField& points = p.localPoints();
vtkPoints* vtkpoints = vtkPoints::New();
vtkpoints->Allocate(points.size());
auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(points.size());
forAll(points, i)
{
vtkpoints->InsertNextPoint(points[i].v_);
vtkpoints->SetPoint(i, points[i].v_);
}
vtkmesh->SetPoints(vtkpoints);
vtkpoints->Delete();
return vtkpoints;
}
// Add faces as polygons
template<class PatchType>
vtkSmartPointer<vtkCellArray> Foam::vtkPVFoam::patchFacesVTKCells
(
const PatchType& p
)
{
// Faces as polygons
const faceList& faces = p.localFaces();
vtkCellArray* vtkcells = vtkCellArray::New();
vtkcells->Allocate(faces.size());
label nAlloc = faces.size();
forAll(faces, facei)
{
nAlloc += faces[facei].size();
}
auto cells = vtkSmartPointer<vtkCellArray>::New();
UList<vtkIdType> cellsUL =
vtkUList
(
cells,
faces.size(),
nAlloc
);
// Cell connectivity for polygons
// [size, verts..., size, verts... ]
label idx = 0;
forAll(faces, facei)
{
const face& f = faces[facei];
vtkIdType nodeIds[f.size()];
cellsUL[idx++] = f.size();
forAll(f, fp)
{
nodeIds[fp] = f[fp];
cellsUL[idx++] = f[fp];
}
vtkcells->InsertNextCell(f.size(), nodeIds);
}
vtkmesh->SetPolys(vtkcells);
vtkcells->Delete();
return cells;
}
if (debug)
{
Info<< "<end> patchVTKMesh - " << name << endl;
printMemory();
}
template<class PatchType>
vtkSmartPointer<vtkPolyData> Foam::vtkPVFoam::patchVTKMesh
(
const PatchType& p
)
{
auto vtkmesh = vtkSmartPointer<vtkPolyData>::New();
vtkmesh->SetPoints(movePatchPoints(p));
vtkmesh->SetPolys(patchFacesVTKCells(p));
return vtkmesh;
}

View File

@ -39,10 +39,6 @@ License
// VTK includes
#include "vtkDataArraySelection.h"
// Templates (only needed here)
#include "vtkPVFoamUpdateTemplates.C"
// * * * * * * * * * * * * * * * Private Classes * * * * * * * * * * * * * * //
namespace Foam
@ -89,11 +85,11 @@ Foam::wordList Foam::vtkPVFoam::getZoneNames
wordList names(zmesh.size());
label nZone = 0;
forAll(zmesh, zoneI)
forAll(zmesh, zonei)
{
if (!zmesh[zoneI].empty())
if (!zmesh[zonei].empty())
{
names[nZone++] = zmesh[zoneI].name();
names[nZone++] = zmesh[zonei].name();
}
}
names.setSize(nZone);
@ -128,9 +124,9 @@ Foam::wordList Foam::vtkPVFoam::getZoneNames(const word& zoneType) const
zonesEntries zones(ioObj);
names.setSize(zones.size());
forAll(zones, zoneI)
forAll(zones, zonei)
{
names[zoneI] = zones[zoneI].keyword();
names[zonei] = zones[zonei].keyword();
}
}
@ -140,7 +136,7 @@ Foam::wordList Foam::vtkPVFoam::getZoneNames(const word& zoneType) const
void Foam::vtkPVFoam::updateInfoInternalMesh
(
vtkDataArraySelection* arraySelection
vtkDataArraySelection* select
)
{
if (debug)
@ -150,12 +146,8 @@ void Foam::vtkPVFoam::updateInfoInternalMesh
// Determine mesh parts (internalMesh, patches...)
//- Add internal mesh as first entry
arrayRangeVolume_.reset(arraySelection->GetNumberOfArrays());
arraySelection->AddArray
(
"internalMesh"
);
arrayRangeVolume_ += 1;
rangeVolume_.reset(select->GetNumberOfArrays(), 1);
select->AddArray("internalMesh");
if (debug)
{
@ -166,16 +158,15 @@ void Foam::vtkPVFoam::updateInfoInternalMesh
void Foam::vtkPVFoam::updateInfoLagrangian
(
vtkDataArraySelection* arraySelection
vtkDataArraySelection* select
)
{
if (debug)
{
Info<< "<beg> updateInfoLagrangian" << nl
Info<< "<beg> " << FUNCTION_NAME << nl
<< " " << dbPtr_->timePath()/cloud::prefix << endl;
}
// use the db directly since this might be called without a mesh,
// but the region must get added back in
fileName lagrangianPrefix(cloud::prefix);
@ -190,96 +181,101 @@ void Foam::vtkPVFoam::updateInfoLagrangian
readDir(dbPtr_->timePath()/lagrangianPrefix, fileName::DIRECTORY)
);
arrayRangeLagrangian_.reset(arraySelection->GetNumberOfArrays());
int nClouds = 0;
forAll(cloudDirs, cloudI)
rangeLagrangian_.reset(select->GetNumberOfArrays());
forAll(cloudDirs, cloudi)
{
// Add cloud to GUI list
arraySelection->AddArray
select->AddArray
(
(cloudDirs[cloudI] + " - lagrangian").c_str()
("lagrangian/" + cloudDirs[cloudi]).c_str()
);
++nClouds;
++rangeLagrangian_;
}
arrayRangeLagrangian_ += nClouds;
if (debug)
{
Info<< "<end> updateInfoLagrangian" << endl;
Info<< "<end> " << FUNCTION_NAME << endl;
}
}
void Foam::vtkPVFoam::updateInfoPatches
(
vtkDataArraySelection* arraySelection,
stringList& enabledEntries
vtkDataArraySelection* select,
HashSet<string>& enabledEntries
)
{
if (debug)
{
Info<< "<beg> updateInfoPatches"
Info<< "<beg> " << FUNCTION_NAME
<< " [meshPtr=" << (meshPtr_ ? "set" : "null") << "]" << endl;
}
rangePatches_.reset(select->GetNumberOfArrays());
HashSet<string> enabledEntriesSet(enabledEntries);
arrayRangePatches_.reset(arraySelection->GetNumberOfArrays());
int nPatches = 0;
if (meshPtr_)
{
const polyBoundaryMesh& patches = meshPtr_->boundaryMesh();
const HashTable<labelList>& groups = patches.groupPatchIDs();
const wordList allPatchNames = patches.names();
DynamicList<string> displayNames(groups.size());
// Add patch groups
// ~~~~~~~~~~~~~~~~
// Add (non-zero) patch groups to the list of mesh parts
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
forAllConstIters(groups, iter)
{
const word& groupName = iter.key();
const labelList& patchIDs = iter.object();
const auto& groupName = iter.key();
const auto& patchIDs = iter.object();
label nFaces = 0;
forAll(patchIDs, i)
for (auto patchId : patchIDs)
{
nFaces += patches[patchIDs[i]].size();
nFaces += patches[patchId].size();
}
if (!nFaces)
{
// Skip if group has no faces
continue;
}
// Valid patch if nFace > 0 - add patch to GUI list
if (nFaces)
{
string vtkGrpName = groupName + " - group";
arraySelection->AddArray(vtkGrpName.c_str());
const string dpyName = "group/" + groupName;
displayNames.append(dpyName);
++nPatches;
if (enabledEntriesSet.found(vtkGrpName))
// Optionally replace group with patch name selections
// - must remove the group from the select itself, otherwise
// it can toggle on, but not toggle off very well
if
(
!reader_->GetShowGroupsOnly()
&& enabledEntries.erase(dpyName)
)
{
if (!reader_->GetShowGroupsOnly())
for (auto patchId : patchIDs)
{
enabledEntriesSet.erase(vtkGrpName);
forAll(patchIDs, i)
{
const polyPatch& pp = patches[patchIDs[i]];
const polyPatch& pp = patches[patchId];
if (pp.size())
{
string vtkPatchName = pp.name() + " - patch";
enabledEntriesSet.insert(vtkPatchName);
}
}
enabledEntries.insert
(
"patch/" + pp.name()
);
}
}
}
}
// Sort group names
Foam::sort(displayNames);
for (const auto& name : displayNames)
{
select->AddArray(name.c_str());
++rangePatches_;
}
// Add patches
// ~~~~~~~~~~~
// Add (non-zero) patches to the list of mesh parts
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (!reader_->GetShowGroupsOnly())
{
@ -290,12 +286,11 @@ void Foam::vtkPVFoam::updateInfoPatches
if (pp.size())
{
// Add patch to GUI list
arraySelection->AddArray
select->AddArray
(
(pp.name() + " - patch").c_str()
("patch/" + pp.name()).c_str()
);
++nPatches;
++rangePatches_;
}
}
}
@ -320,94 +315,76 @@ void Foam::vtkPVFoam::updateInfoPatches
false
);
// this should only ever fail if the mesh region doesn't exist
// This should only ever fail if the mesh region doesn't exist
if (ioObj.typeHeaderOk<polyBoundaryMesh>(true, false))
{
polyBoundaryMeshEntries patchEntries(ioObj);
// Read patches and determine sizes
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Read patches, determine sizes and patch groups
wordList names(patchEntries.size());
labelList sizes(patchEntries.size());
HashTable<labelHashSet> groups(2*patchEntries.size());
forAll(patchEntries, patchi)
{
const dictionary& patchDict = patchEntries[patchi].dict();
wordList groupNames;
sizes[patchi] = readLabel(patchDict.lookup("nFaces"));
names[patchi] = patchEntries[patchi].keyword();
if
(
sizes[patchi] // Valid patch if nFace > 0
&& patchDict.readIfPresent("inGroups", groupNames)
)
{
forAll(groupNames, groupI)
{
groups(groupNames[groupI]).insert(patchi);
}
}
}
// Add (non-zero) patch groups to the list of mesh parts
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HashTable<labelList> groups(patchEntries.size());
forAll(patchEntries, patchi)
{
const dictionary& patchDict = patchEntries[patchi].dict();
wordList groupNames;
patchDict.readIfPresent("inGroups", groupNames);
forAll(groupNames, groupI)
{
HashTable<labelList>::iterator iter = groups.find
(
groupNames[groupI]
);
if (iter != groups.end())
{
iter().append(patchi);
}
else
{
groups.insert(groupNames[groupI], labelList{patchi});
}
}
}
DynamicList<string> displayNames(groups.size());
forAllConstIters(groups, iter)
{
const word& groupName = iter.key();
const labelList& patchIDs = iter.object();
const auto& groupName = iter.key();
const auto& patchIDs = iter.object();
label nFaces = 0;
forAll(patchIDs, i)
{
nFaces += sizes[patchIDs[i]];
}
const string dpyName = "group/" + groupName;
displayNames.append(dpyName);
// Valid patch if nFace > 0 - add patch to GUI list
if (nFaces)
// Optionally replace group with patch name selections
// - must remove the group from the select itself, otherwise
// it can toggle on, but not toggle off very well
if
(
!reader_->GetShowGroupsOnly()
&& enabledEntries.erase(dpyName)
)
{
string vtkGrpName = groupName + " - group";
arraySelection->AddArray(vtkGrpName.c_str());
++nPatches;
if (enabledEntriesSet.found(vtkGrpName))
for (auto patchId : patchIDs)
{
if (!reader_->GetShowGroupsOnly())
{
enabledEntriesSet.erase(vtkGrpName);
forAll(patchIDs, i)
{
if (sizes[patchIDs[i]])
{
string vtkPatchName =
names[patchIDs[i]] + " - patch";
enabledEntriesSet.insert(vtkPatchName);
}
}
}
enabledEntries.insert
(
"patch/" + names[patchId]
);
}
}
}
// Sort group names
Foam::sort(displayNames);
for (const auto& name : displayNames)
{
select->AddArray(name.c_str());
++rangePatches_;
}
// Add (non-zero) patches to the list of mesh parts
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -419,32 +396,27 @@ void Foam::vtkPVFoam::updateInfoPatches
// Valid patch if nFace > 0 - add patch to GUI list
if (sizes[patchi])
{
arraySelection->AddArray
select->AddArray
(
(names[patchi] + " - patch").c_str()
("patch/" + names[patchi]).c_str()
);
++nPatches;
++rangePatches_;
}
}
}
}
}
arrayRangePatches_ += nPatches;
// Update enabled entries in case of group selection
enabledEntries = enabledEntriesSet.toc();
if (debug)
{
Info<< "<end> updateInfoPatches" << endl;
Info<< "<end> " << FUNCTION_NAME << endl;
}
}
void Foam::vtkPVFoam::updateInfoZones
(
vtkDataArraySelection* arraySelection
vtkDataArraySelection* select
)
{
if (!reader_->GetIncludeZones())
@ -472,15 +444,15 @@ void Foam::vtkPVFoam::updateInfoZones
namesLst = getZoneNames("cellZones");
}
arrayRangeCellZones_.reset(arraySelection->GetNumberOfArrays());
rangeCellZones_.reset(select->GetNumberOfArrays());
forAll(namesLst, elemI)
{
arraySelection->AddArray
select->AddArray
(
(namesLst[elemI] + " - cellZone").c_str()
("cellZone/" + namesLst[elemI]).c_str()
);
++rangeCellZones_;
}
arrayRangeCellZones_ += namesLst.size();
//
@ -495,15 +467,15 @@ void Foam::vtkPVFoam::updateInfoZones
namesLst = getZoneNames("faceZones");
}
arrayRangeFaceZones_.reset(arraySelection->GetNumberOfArrays());
rangeFaceZones_.reset(select->GetNumberOfArrays());
forAll(namesLst, elemI)
{
arraySelection->AddArray
select->AddArray
(
(namesLst[elemI] + " - faceZone").c_str()
("faceZone/" + namesLst[elemI]).c_str()
);
++rangeFaceZones_;
}
arrayRangeFaceZones_ += namesLst.size();
//
@ -518,15 +490,15 @@ void Foam::vtkPVFoam::updateInfoZones
namesLst = getZoneNames("pointZones");
}
arrayRangePointZones_.reset(arraySelection->GetNumberOfArrays());
rangePointZones_.reset(select->GetNumberOfArrays());
forAll(namesLst, elemI)
{
arraySelection->AddArray
select->AddArray
(
(namesLst[elemI] + " - pointZone").c_str()
("pointZone/" + namesLst[elemI]).c_str()
);
++rangePointZones_;
}
arrayRangePointZones_ += namesLst.size();
if (debug)
{
@ -537,7 +509,7 @@ void Foam::vtkPVFoam::updateInfoZones
void Foam::vtkPVFoam::updateInfoSets
(
vtkDataArraySelection* arraySelection
vtkDataArraySelection* select
)
{
if (!reader_->GetIncludeSets())
@ -577,28 +549,28 @@ void Foam::vtkPVFoam::updateInfoSets
}
arrayRangeCellSets_.reset(arraySelection->GetNumberOfArrays());
arrayRangeCellSets_ += addToSelection<cellSet>
rangeCellSets_.reset(select->GetNumberOfArrays());
rangeCellSets_ += addToSelection<cellSet>
(
arraySelection,
select,
objects,
" - cellSet"
"cellSet/"
);
arrayRangeFaceSets_.reset(arraySelection->GetNumberOfArrays());
arrayRangeFaceSets_ += addToSelection<faceSet>
rangeFaceSets_.reset(select->GetNumberOfArrays());
rangeFaceSets_ += addToSelection<faceSet>
(
arraySelection,
select,
objects,
" - faceSet"
"faceSet/"
);
arrayRangePointSets_.reset(arraySelection->GetNumberOfArrays());
arrayRangePointSets_ += addToSelection<pointSet>
rangePointSets_.reset(select->GetNumberOfArrays());
rangePointSets_ += addToSelection<pointSet>
(
arraySelection,
select,
objects,
" - pointSet"
"pointSet/"
);
if (debug)
@ -608,23 +580,6 @@ void Foam::vtkPVFoam::updateInfoSets
}
void Foam::vtkPVFoam::updateInfoFields()
{
updateInfoFields<fvPatchField, volMesh>
(
reader_->GetVolFieldSelection()
);
updateInfoFields<pointPatchField, pointMesh>
(
reader_->GetPointFieldSelection()
);
updateInfoLagrangianFields
(
reader_->GetLagrangianFieldSelection()
);
}
void Foam::vtkPVFoam::updateInfoLagrangianFields
(
vtkDataArraySelection* select
@ -635,22 +590,23 @@ void Foam::vtkPVFoam::updateInfoLagrangianFields
Info<< "<beg> updateInfoLagrangianFields" << endl;
}
// preserve the enabled selections
stringList enabledEntries = getSelectedArrayEntries(select);
// Preserve the enabled selections
HashSet<string> enabled = getSelectedArraySet(select);
select->RemoveAllArrays();
// TODO - currently only get fields from ONE cloud
// have to decide if the second set of fields get mixed in
// or dealt with separately
const arrayRange& range = arrayRangeLagrangian_;
const arrayRange& range = rangeLagrangian_;
if (range.empty())
{
return;
}
int partId = range.start();
word cloudName = getPartName(partId);
// Add Lagrangian fields even if particles are not enabled?
const int partId = range.start();
const word cloudName = getReaderPartName(partId);
// use the db directly since this might be called without a mesh,
// but the region must get added back in
@ -674,26 +630,8 @@ void Foam::vtkPVFoam::updateInfoLagrangianFields
addToSelection<IOField<symmTensor>>(select, objects);
addToSelection<IOField<tensor>>(select, objects);
// restore the enabled selections
setSelectedArrayEntries(select, enabledEntries);
if (debug > 1)
{
boolList status;
const label nElem = getSelected(status, select);
forAll(status, i)
{
Info<< " lagrangian[" << i << "] = "
<< status[i]
<< " : " << select->GetArrayName(i) << nl;
}
if (!nElem)
{
Info<< " lagrangian[none]" << nl;
}
}
// Restore the enabled selections
setSelectedArrayEntries(select, enabled);
if (debug)
{

View File

@ -45,16 +45,16 @@ void Foam::vtkPVFoam::updateInfoFields
<< endl;
}
stringList enabledEntries;
HashSet<string> enabled;
if (!select->GetNumberOfArrays() && !meshPtr_)
{
// enable 'p' and 'U' only on the first call
enabledEntries = { "p", "U" };
// Enable 'p' and 'U' only on the first call
enabled = { "p", "U" };
}
else
{
// preserve the enabled selections
enabledEntries = getSelectedArrayEntries(select);
// Preserve the enabled selections
enabled = getSelectedArraySet(select);
}
select->RemoveAllArrays();
@ -126,8 +126,8 @@ void Foam::vtkPVFoam::updateInfoFields
);
// restore the enabled selections
setSelectedArrayEntries(select, enabledEntries);
// Restore the enabled selections
setSelectedArrayEntries(select, enabled);
if (debug)
{

View File

@ -40,13 +40,14 @@ License
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// file-scope
static QAbstractButton* setButtonProperties
// Widget properties
static QWidget* setWidgetProperties
(
QAbstractButton* b,
QWidget* widget,
vtkSMProperty* prop
)
{
QString tip;
widget->setFocusPolicy(Qt::NoFocus); // avoid dotted border
vtkSMDocumentation* doc = prop->GetDocumentation();
if (doc)
@ -54,22 +55,33 @@ static QAbstractButton* setButtonProperties
const char* txt = doc->GetDescription();
if (txt)
{
tip = QString(txt).simplified();
}
}
b->setText(prop->GetXMLLabel());
QString tip = QString(txt).simplified();
if (tip.size())
{
b->setToolTip(tip);
widget->setToolTip(tip);
}
}
}
b->setFocusPolicy(Qt::NoFocus); // avoid dotted border
return widget;
}
// file-scope
// Button properties
static QAbstractButton* setButtonProperties
(
QAbstractButton* b,
vtkSMProperty* prop
)
{
setWidgetProperties(b, prop);
b->setText(prop->GetXMLLabel());
vtkSMIntVectorProperty* intProp =
vtkSMIntVectorProperty::SafeDownCast(prop);
// initial checked state for integer (bool) properties
// Initial checked state for integer (bool) properties
if (intProp)
{
b->setChecked(intProp->GetElement(0));
@ -111,12 +123,12 @@ void pqFoamBlockMeshControls::fireCommand(vtkSMProperty* prop)
void pqFoamBlockMeshControls::fireCommand
(
vtkSMIntVectorProperty* prop,
bool checked
int val
)
{
vtkSMProxy* pxy = this->proxy();
prop->SetElement(0, checked); // Toogle bool
prop->SetElement(0, val); // Set int value, toogle bool, etc
// Fire off command
prop->Modified();
@ -200,7 +212,10 @@ pqFoamBlockMeshControls::pqFoamBlockMeshControls
setButtonProperties(b, refresh_);
form->addWidget(b, 0, 0, Qt::AlignLeft);
connect(b, SIGNAL(clicked()), this, SLOT(refreshPressed()));
connect
(
b, SIGNAL(clicked()), this, SLOT(refreshPressed())
);
}
if (showPatchNames_)
@ -209,7 +224,10 @@ pqFoamBlockMeshControls::pqFoamBlockMeshControls
setButtonProperties(b, showPatchNames_);
form->addWidget(b, 0, 1, Qt::AlignLeft);
connect(b, SIGNAL(toggled(bool)), this, SLOT(showPatchNames(bool)));
connect
(
b, SIGNAL(toggled(bool)), this, SLOT(showPatchNames(bool))
);
}
if (showPointNumbers_)
@ -218,7 +236,10 @@ pqFoamBlockMeshControls::pqFoamBlockMeshControls
setButtonProperties(b, showPointNumbers_);
form->addWidget(b, 0, 2, Qt::AlignLeft);
connect(b, SIGNAL(toggled(bool)), this, SLOT(showPointNumbers(bool)));
connect
(
b, SIGNAL(toggled(bool)), this, SLOT(showPointNumbers(bool))
);
}
}

View File

@ -71,8 +71,8 @@ class pqFoamBlockMeshControls
//- Update property
void fireCommand(vtkSMProperty* prop);
//- Toggle and update bool property
void fireCommand(vtkSMIntVectorProperty* prop, bool checked);
//- Update int property or toggle bool property
void fireCommand(vtkSMIntVectorProperty* prop, int val);
//- Update "BlockArrayStatus", "CurvedEdgesArrayStatus" information
void updateParts();

View File

@ -106,7 +106,7 @@ vtkPVblockMeshReader::~vtkPVblockMeshReader()
if (FileName)
{
delete [] FileName;
delete[] FileName;
}
BlockSelection->RemoveAllObservers();
@ -165,20 +165,19 @@ int vtkPVblockMeshReader::RequestData
if (!FileName)
{
vtkErrorMacro("FileName has to be specified!");
vtkErrorMacro("FileName must be specified!");
return 0;
}
// Catch previous error
if (!backend_)
{
vtkErrorMacro("Reader failed - perhaps no mesh?");
// Catch some previous error
vtkErrorMacro("Reader failed - perhaps no blockMesh?");
return 0;
}
if (Foam::vtkPVblockMesh::debug)
{
cout<<"REQUEST_DATA:\n";
cout<<"RequestData:\n";
outputVector->GetInformationObject(0)->Print(cout);
}
@ -190,19 +189,12 @@ int vtkPVblockMeshReader::RequestData
)
);
if (Foam::vtkPVblockMesh::debug)
{
cout<< "update output with "
<< output->GetNumberOfBlocks() << " blocks\n";
}
backend_->Update(output);
updatePatchNamesView(ShowPatchNames);
updatePointNumbersView(ShowPointNumbers);
// Do any cleanup on the OpenFOAM side
backend_->CleanUp();
backend_->UpdateFinalize();
return 1;
}
@ -263,12 +255,11 @@ void vtkPVblockMeshReader::updatePatchNamesView(const bool show)
}
// Get all the pqRenderView instances
QList<pqRenderView*> renderViews = smModel->findItems<pqRenderView*>();
for (int viewI=0; viewI<renderViews.size(); ++viewI)
for (auto view : smModel->findItems<pqRenderView*>())
{
backend_->renderPatchNames
(
renderViews[viewI]->getRenderViewProxy()->GetRenderer(),
view->getRenderViewProxy()->GetRenderer(),
show
);
}
@ -295,12 +286,11 @@ void vtkPVblockMeshReader::updatePointNumbersView(const bool show)
}
// Get all the pqRenderView instances
QList<pqRenderView*> renderViews = smModel->findItems<pqRenderView*>();
for (int viewI=0; viewI<renderViews.size(); ++viewI)
for (auto view : smModel->findItems<pqRenderView*>())
{
backend_->renderPointNumbers
(
renderViews[viewI]->getRenderViewProxy()->GetRenderer(),
view->getRenderViewProxy()->GetRenderer(),
show
);
}

View File

@ -39,6 +39,7 @@ License
#include "vtkRenderer.h"
#include "vtkTextActor.h"
#include "vtkTextProperty.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -47,16 +48,20 @@ namespace Foam
defineTypeNameAndDebug(vtkPVblockMesh, 0);
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
vtkTextActor* Foam::vtkPVblockMesh::createTextActor
(
const string& s,
const point& pt
)
namespace Foam
{
vtkTextActor* txt = vtkTextActor::New();
// file-scope
//- Create a text actor
static vtkSmartPointer<vtkTextActor> createTextActor
(
const std::string& s,
const Foam::point& pt
)
{
auto txt = vtkSmartPointer<vtkTextActor>::New();
txt->SetInput(s.c_str());
// Set text properties
@ -73,6 +78,7 @@ vtkTextActor* Foam::vtkPVblockMesh::createTextActor
txt->GetPositionCoordinate()->SetValue(pt.x(), pt.y(), pt.z());
return txt;
}
}
@ -81,9 +87,9 @@ vtkTextActor* Foam::vtkPVblockMesh::createTextActor
void Foam::vtkPVblockMesh::resetCounters()
{
// Reset mesh part ids and sizes
arrayRangeBlocks_.reset();
arrayRangeEdges_.reset();
arrayRangeCorners_.reset();
rangeBlocks_.reset();
rangeEdges_.reset();
rangeCorners_.reset();
}
@ -92,15 +98,13 @@ void Foam::vtkPVblockMesh::updateInfoBlocks
vtkDataArraySelection* select
)
{
arrayRange& range = arrayRangeBlocks_;
if (debug)
{
Info<< "<beg> updateInfoBlocks"
<< " [meshPtr=" << (meshPtr_ ? "set" : "null") << "]" << endl;
}
range.reset(select->GetNumberOfArrays());
rangeBlocks_.reset(select->GetNumberOfArrays());
const blockMesh& blkMesh = *meshPtr_;
@ -122,10 +126,9 @@ void Foam::vtkPVblockMesh::updateInfoBlocks
// Add "blockId" or "blockId - zoneName" to GUI list
select->AddArray(ostr.str().c_str());
++rangeBlocks_;
}
range += nBlocks;
if (debug)
{
Info<< "<end> updateInfoBlocks" << endl;
@ -138,15 +141,13 @@ void Foam::vtkPVblockMesh::updateInfoEdges
vtkDataArraySelection* select
)
{
arrayRange& range = arrayRangeEdges_;
if (debug)
{
Info<< "<beg> updateInfoEdges"
<< " [meshPtr=" << (meshPtr_ ? "set" : "null") << "]" << endl;
}
range.reset(select->GetNumberOfArrays());
rangeEdges_.reset(select->GetNumberOfArrays());
const blockMesh& blkMesh = *meshPtr_;
const blockEdgeList& edges = blkMesh.edges();
@ -161,10 +162,9 @@ void Foam::vtkPVblockMesh::updateInfoEdges
// Add "beg:end - type" to GUI list
select->AddArray(ostr.str().c_str());
++rangeEdges_;
}
range += edges.size();
if (debug)
{
Info<< "<end> updateInfoEdges" << endl;
@ -185,9 +185,9 @@ Foam::vtkPVblockMesh::vtkPVblockMesh
meshPtr_(nullptr),
meshRegion_(polyMesh::defaultRegion),
meshDir_(polyMesh::meshSubDir),
arrayRangeBlocks_("block"),
arrayRangeEdges_("edges"),
arrayRangeCorners_("corners")
rangeBlocks_("block"),
rangeEdges_("edges"),
rangeCorners_("corners")
{
if (debug)
{
@ -302,14 +302,15 @@ void Foam::vtkPVblockMesh::updateInfo()
vtkDataArraySelection* blockSelection = reader_->GetBlockSelection();
vtkDataArraySelection* edgeSelection = reader_->GetCurvedEdgesSelection();
// preserve the enabled selections if possible
stringList enabledParts;
stringList enabledEdges;
const bool firstTime = (!blockSelection->GetNumberOfArrays() && !meshPtr_);
// Preserve the enabled selections if possible
HashSet<string> enabledParts;
HashSet<string> enabledEdges;
if (!firstTime)
{
enabledParts = getSelectedArrayEntries(blockSelection);
enabledEdges = getSelectedArrayEntries(edgeSelection);
enabledParts = getSelectedArraySet(blockSelection);
enabledEdges = getSelectedArraySet(edgeSelection);
}
// Clear current mesh parts list
@ -325,7 +326,7 @@ void Foam::vtkPVblockMesh::updateInfo()
// Update curved edges list
updateInfoEdges(edgeSelection);
// restore the enabled selections
// Restore the enabled selections
if (!firstTime)
{
setSelectedArrayEntries(blockSelection, enabledParts);
@ -405,14 +406,6 @@ void Foam::vtkPVblockMesh::Update
{
reader_->UpdateProgress(0.1);
// Set up mesh parts selection(s)
getSelected(blockStatus_, reader_->GetBlockSelection());
// Set up curved edges selection(s)
getSelected(edgeStatus_, reader_->GetCurvedEdgesSelection());
reader_->UpdateProgress(0.2);
// Update the OpenFOAM mesh
updateFoamMesh();
reader_->UpdateProgress(0.5);
@ -425,11 +418,10 @@ void Foam::vtkPVblockMesh::Update
convertMeshEdges(output, blockNo);
reader_->UpdateProgress(0.8);
}
void Foam::vtkPVblockMesh::CleanUp()
void Foam::vtkPVblockMesh::UpdateFinalize()
{
reader_->UpdateProgress(1.0);
}
@ -442,12 +434,11 @@ void Foam::vtkPVblockMesh::renderPatchNames
)
{
// always remove old actors first
forAll(patchTextActorsPtrs_, actori)
forAll(patchTextActors_, actori)
{
renderer->RemoveViewProp(patchTextActorsPtrs_[actori]);
patchTextActorsPtrs_[actori]->Delete();
renderer->RemoveViewProp(patchTextActors_[actori]);
}
patchTextActorsPtrs_.clear();
patchTextActors_.clear();
// the number of text actors
label nActors = 0;
@ -465,7 +456,7 @@ void Foam::vtkPVblockMesh::renderPatchNames
}
// 8 sides per block is plenty
patchTextActorsPtrs_.setSize(8*blkMesh.size());
patchTextActors_.setSize(8*blkMesh.size());
// Collect all variables
dictionary varDict(meshDescription.subOrEmptyDict("namedVertices"));
@ -501,33 +492,33 @@ void Foam::vtkPVblockMesh::renderPatchNames
const face& f = patchFaces[facei];
// Into a list for later removal
patchTextActorsPtrs_[nActors++] = createTextActor
patchTextActors_[nActors++] = createTextActor
(
patchName,
f.centre(cornerPts) * scaleFactor
);
if (nActors == patchTextActorsPtrs_.size())
if (nActors == patchTextActors_.size())
{
// hit max allocated space - bail out
break;
}
}
if (nActors == patchTextActorsPtrs_.size())
if (nActors == patchTextActors_.size())
{
// hit max allocated space - bail out
break;
}
}
patchTextActorsPtrs_.setSize(nActors);
patchTextActors_.setSize(nActors);
}
// Add text to each renderer
forAll(patchTextActorsPtrs_, actori)
forAll(patchTextActors_, actori)
{
renderer->AddViewProp(patchTextActorsPtrs_[actori]);
renderer->AddViewProp(patchTextActors_[actori]);
}
}
@ -540,12 +531,11 @@ void Foam::vtkPVblockMesh::renderPointNumbers
{
// always remove old actors first
forAll(pointTextActorsPtrs_, actori)
forAll(pointTextActors_, actori)
{
renderer->RemoveViewProp(pointTextActorsPtrs_[actori]);
pointTextActorsPtrs_[actori]->Delete();
renderer->RemoveViewProp(pointTextActors_[actori]);
}
pointTextActorsPtrs_.clear();
pointTextActors_.clear();
if (show && meshPtr_)
{
@ -553,7 +543,7 @@ void Foam::vtkPVblockMesh::renderPointNumbers
const pointField& cornerPts = blkMesh.vertices();
const scalar scaleFactor = blkMesh.scaleFactor();
pointTextActorsPtrs_.setSize(cornerPts.size());
pointTextActors_.setSize(cornerPts.size());
forAll(cornerPts, pointi)
{
// Display either pointi as a number or with its name
@ -562,7 +552,7 @@ void Foam::vtkPVblockMesh::renderPointNumbers
blockVertex::write(os, pointi, blkMesh.meshDict());
// Into a list for later removal
pointTextActorsPtrs_[pointi] = createTextActor
pointTextActors_[pointi] = createTextActor
(
os.str(),
cornerPts[pointi]*scaleFactor
@ -571,9 +561,9 @@ void Foam::vtkPVblockMesh::renderPointNumbers
}
// Add text to each renderer
forAll(pointTextActorsPtrs_, actori)
forAll(pointTextActors_, actori)
{
renderer->AddViewProp(pointTextActorsPtrs_[actori]);
renderer->AddViewProp(pointTextActors_[actori]);
}
}

View File

@ -25,13 +25,18 @@ Class
Foam::vtkPVblockMesh
Description
Provides a reader interface for OpenFOAM blockMesh to VTK interaction
The backend for the vtkPVblockMeshReader reader module -
providing a paraview reader interface for OpenFOAM blockMesh.
The block reader module can assist when creating a blockMeshDict
for use with the blockMesh utility. As well as blocks, it can be
used to visualize edges,corners and patch names.
There is no native VTK equivalent for this functionality.
SourceFiles
vtkPVblockMesh.C
vtkPVblockMeshConvert.C
vtkPVblockMeshUpdate.C
vtkPVblockMeshUtils.C
// Needed by VTK:
vtkDataArrayTemplateImplicit.txx
@ -56,6 +61,8 @@ class vtkPolyData;
class vtkUnstructuredGrid;
class vtkIndent;
template<class T> class vtkSmartPointer;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
@ -93,34 +100,25 @@ class vtkPVblockMesh
//- The mesh directory for the region
fileName meshDir_;
//- Selected geometrical parts
boolList blockStatus_;
//- Selected curved edges
boolList edgeStatus_;
//- First instance and size of bleckMesh blocks
// used to index into blockStatus_
arrayRange arrayRangeBlocks_;
arrayRange rangeBlocks_;
//- First instance and size of CurvedEdges (only partially used)
arrayRange arrayRangeEdges_;
arrayRange rangeEdges_;
//- First instance and size of block corners (only partially used)
arrayRange arrayRangeCorners_;
arrayRange rangeCorners_;
//- List of patch names for rendering to window
List<vtkTextActor*> patchTextActorsPtrs_;
List<vtkSmartPointer<vtkTextActor>> patchTextActors_;
//- List of point numbers for rendering to window
List<vtkTextActor*> pointTextActorsPtrs_;
List<vtkSmartPointer<vtkTextActor>> pointTextActors_;
// Private Member Functions
//- Create a text actor
static vtkTextActor* createTextActor(const string& s, const point& pt);
//- Reset data counters
void resetCounters();
@ -178,14 +176,15 @@ public:
void Update(vtkMultiBlockDataSet* output);
//- Clean any storage
void CleanUp();
//- Final part of Update(), after any last minute rendering.
void UpdateFinalize();
//- Add/remove patch names to/from the view
void renderPatchNames(vtkRenderer*, const bool show);
void renderPatchNames(vtkRenderer* renderer, const bool show);
//- Add/remove point numbers to/from the view
void renderPointNumbers(vtkRenderer*, const bool show);
void renderPointNumbers(vtkRenderer* renderer, const bool show);
// Access

View File

@ -37,28 +37,9 @@ License
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkUnstructuredGrid.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
//! \cond fileScope
inline static void insertNextPoint
(
vtkPoints *points,
const Foam::point& p,
const Foam::scalar scaleFactor
)
{
points->InsertNextPoint
(
p.x()*scaleFactor,
p.y()*scaleFactor,
p.z()*scaleFactor
);
}
//! \endcond
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtkPVblockMesh::convertMeshBlocks
@ -67,56 +48,52 @@ void Foam::vtkPVblockMesh::convertMeshBlocks
int& blockNo
)
{
vtkDataArraySelection* selection = reader_->GetBlockSelection();
arrayRange& range = arrayRangeBlocks_;
range.block(blockNo); // set output block
label datasetNo = 0; // restart at dataset 0
const blockMesh& blkMesh = *meshPtr_;
const Foam::pointField& blockPoints = blkMesh.vertices();
if (debug)
{
Info<< "<beg> convertMeshBlocks" << endl;
}
int blockI = 0;
const scalar scaleFactor = blkMesh.scaleFactor();
for
const Map<string> blockStatus = getSelectedArrayMap
(
int partId = range.start();
partId < range.end();
++partId, ++blockI
)
reader_->GetBlockSelection()
);
arrayRange& range = rangeBlocks_;
range.block(blockNo); // set output block
label datasetNo = 0; // restart at dataset 0
const blockMesh& blkMesh = *meshPtr_;
const pointField blkPoints(blkMesh.vertices() * blkMesh.scaleFactor());
vtkIdType nodeIds[8]; // Space for VTK_HEXAHEDRON vertices
int blockId = -1;
for (auto partId : range)
{
if (!blockStatus_[partId])
++blockId; // Increment first
if (!blockStatus.found(partId))
{
continue;
}
const auto& longName = blockStatus[partId];
const blockDescriptor& blockDef = blkMesh[blockI];
// Convert OpenFOAM mesh vertices to VTK
vtkPoints *vtkpoints = vtkPoints::New();
vtkpoints->Allocate(blockDef.nPoints());
const blockDescriptor& blockDef = blkMesh[blockId];
const labelList& blockLabels = blockDef.blockShape();
vtkIdType nodeIds[8];
auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(blockLabels.size());
forAll(blockLabels, ptI)
forAll(blockLabels, pointi)
{
insertNextPoint
vtkpoints->SetPoint
(
vtkpoints,
blockPoints[blockLabels[ptI]],
scaleFactor
pointi,
blkPoints[blockLabels[pointi]].v_
);
nodeIds[ptI] = ptI;
nodeIds[pointi] = pointi;
}
vtkUnstructuredGrid* vtkmesh = vtkUnstructuredGrid::New();
auto vtkmesh = vtkSmartPointer<vtkUnstructuredGrid>::New();
vtkmesh->Allocate(1);
vtkmesh->InsertNextCell
(
@ -126,16 +103,9 @@ void Foam::vtkPVblockMesh::convertMeshBlocks
);
vtkmesh->SetPoints(vtkpoints);
vtkpoints->Delete();
addToBlock
(
output, vtkmesh, range, datasetNo,
selection->GetArrayName(partId)
);
vtkmesh->Delete();
datasetNo++;
addToBlock(output, vtkmesh, range, datasetNo, longName);
++datasetNo;
}
@ -158,34 +128,34 @@ void Foam::vtkPVblockMesh::convertMeshEdges
int& blockNo
)
{
vtkDataArraySelection* selection = reader_->GetCurvedEdgesSelection();
arrayRange& range = arrayRangeEdges_;
const Map<string> edgeStatus = getSelectedArrayMap
(
reader_->GetCurvedEdgesSelection()
);
arrayRange& range = rangeEdges_;
range.block(blockNo); // set output block
label datasetNo = 0; // restart at dataset 0
const blockMesh& blkMesh = *meshPtr_;
const blockEdgeList& edges = blkMesh.edges();
int edgeI = 0;
const scalar scaleFactor = blkMesh.scaleFactor();
for
(
int partId = range.start();
partId < range.end();
++partId, ++edgeI
)
int edgeId = -1;
for (auto partId : range)
{
if (!edgeStatus_[partId])
++edgeId; // Increment first
if (!edgeStatus.found(partId))
{
continue;
}
const auto& longName = edgeStatus[partId];
// search each block
forAll(blkMesh, blockI)
// Search each block
forAll(blkMesh, blockId)
{
const blockDescriptor& blockDef = blkMesh[blockI];
const blockDescriptor& blockDef = blkMesh[blockId];
edgeList blkEdges = blockDef.blockShape().edges();
@ -198,7 +168,7 @@ void Foam::vtkPVblockMesh::convertMeshEdges
label foundEdgeI = -1;
forAll(blkEdges, blkEdgeI)
{
if (edges[edgeI].compare(blkEdges[blkEdgeI]))
if (edges[edgeId].compare(blkEdges[blkEdgeI]))
{
foundEdgeI = blkEdgeI;
break;
@ -209,24 +179,21 @@ void Foam::vtkPVblockMesh::convertMeshEdges
{
const List<point>& edgePoints = edgesPoints[foundEdgeI];
vtkPolyData* vtkmesh = vtkPolyData::New();
vtkPoints* vtkpoints = vtkPoints::New();
vtkpoints->Allocate( edgePoints.size() );
vtkmesh->Allocate(1);
auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(edgePoints.size());
vtkIdType pointIds[edgePoints.size()];
forAll(edgePoints, ptI)
forAll(edgePoints, pointi)
{
insertNextPoint
(
vtkpoints,
edgePoints[ptI],
scaleFactor
);
pointIds[ptI] = ptI;
const point p = edgePoints[pointi] * scaleFactor;
vtkpoints->SetPoint(pointi, p.v_);
pointIds[pointi] = pointi;
}
auto vtkmesh = vtkSmartPointer<vtkPolyData>::New();
vtkmesh->Allocate(1);
vtkmesh->InsertNextCell
(
VTK_POLY_LINE,
@ -235,16 +202,9 @@ void Foam::vtkPVblockMesh::convertMeshEdges
);
vtkmesh->SetPoints(vtkpoints);
vtkpoints->Delete();
addToBlock
(
output, vtkmesh, range, datasetNo,
selection->GetArrayName(partId)
);
vtkmesh->Delete();
datasetNo++;
addToBlock(output, vtkmesh, range, datasetNo, longName);
++datasetNo;
break;
}
@ -271,51 +231,34 @@ void Foam::vtkPVblockMesh::convertMeshCorners
int& blockNo
)
{
arrayRange& range = arrayRangeCorners_;
arrayRange& range = rangeCorners_;
range.block(blockNo); // set output block
label datasetNo = 0; // restart at dataset 0
const pointField& blockPoints = meshPtr_->vertices();
const scalar& scaleFactor = meshPtr_->scaleFactor();
const pointField blkPoints(meshPtr_->vertices() * meshPtr_->scaleFactor());
if (debug)
{
Info<< "<beg> convertMeshCorners" << endl;
Info<< "<beg> " << FUNCTION_NAME << endl;
}
if (true) // or some flag or other condition
if (true) // Or some flag or other condition
{
vtkPolyData* vtkmesh = vtkPolyData::New();
vtkPoints* vtkpoints = vtkPoints::New();
vtkCellArray* vtkcells = vtkCellArray::New();
auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(blkPoints.size());
vtkpoints->Allocate( blockPoints.size() );
vtkcells->Allocate( blockPoints.size() );
vtkIdType pointId = 0;
forAll(blockPoints, ptI)
forAll(blkPoints, pointi)
{
insertNextPoint
(
vtkpoints,
blockPoints[ptI],
scaleFactor
);
vtkcells->InsertNextCell(1, &pointId); // VTK_VERTEX
pointId++;
vtkpoints->SetPoint(pointi, blkPoints[pointi].v_);
}
auto vtkmesh = vtkSmartPointer<vtkPolyData>::New();
vtkmesh->SetPoints(vtkpoints);
vtkpoints->Delete();
vtkmesh->SetVerts(vtkcells);
vtkcells->Delete();
vtkmesh->SetVerts(foamPvCore::identityVertices(blkPoints.size()));
addToBlock(output, vtkmesh, range, datasetNo, range.name());
vtkmesh->Delete();
datasetNo++;
++datasetNo;
}
// anything added?
@ -326,7 +269,7 @@ void Foam::vtkPVblockMesh::convertMeshCorners
if (debug)
{
Info<< "<end> convertMeshCorners" << endl;
Info<< "<end> " << FUNCTION_NAME << endl;
}
}

View File

@ -32,6 +32,9 @@ License
#include "vtkDataSet.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkInformation.h"
#include "vtkSmartPointer.h"
#include "foamVtkAdaptors.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -54,7 +57,8 @@ void Foam::foamPvCore::addToBlock
const int blockNo = selector.block();
vtkDataObject* dataObj = output->GetBlock(blockNo);
vtkMultiBlockDataSet* block = vtkMultiBlockDataSet::SafeDownCast(dataObj);
vtkSmartPointer<vtkMultiBlockDataSet> block =
vtkMultiBlockDataSet::SafeDownCast(dataObj);
if (!block)
{
@ -66,9 +70,8 @@ void Foam::foamPvCore::addToBlock
return;
}
block = vtkMultiBlockDataSet::New();
block = vtkSmartPointer<vtkMultiBlockDataSet>::New();
output->SetBlock(blockNo, block);
block->Delete();
}
if (debug)
@ -81,7 +84,7 @@ void Foam::foamPvCore::addToBlock
block->SetBlock(datasetNo, dataset);
// name the output block when assigning dataset 0
// Name the output block when assigning dataset 0
if (datasetNo == 0)
{
output->GetMetaData(blockNo)->Set
@ -102,56 +105,6 @@ void Foam::foamPvCore::addToBlock
}
int Foam::foamPvCore::getNumberOfDataSets
(
vtkMultiBlockDataSet* output,
const arrayRange& selector
)
{
const int blockNo = selector.block();
vtkMultiBlockDataSet* block = vtkMultiBlockDataSet::SafeDownCast
(
output->GetBlock(blockNo)
);
if (block)
{
return block->GetNumberOfBlocks();
}
return 0;
}
int Foam::foamPvCore::getSelected
(
boolList& status,
vtkDataArraySelection* selection
)
{
const int n = selection->GetNumberOfArrays();
if (status.size() != n)
{
status.setSize(n);
status = false;
}
int count = 0;
forAll(status, i)
{
const bool setting = selection->GetArraySetting(i);
if (setting)
{
++count;
}
status[i] = setting;
}
return count;
}
Foam::hashedWordList Foam::foamPvCore::getSelected
(
vtkDataArraySelection* select
@ -164,7 +117,7 @@ Foam::hashedWordList Foam::foamPvCore::getSelected
{
if (select->GetArraySetting(i))
{
selected.append(getFirstWord(select->GetArrayName(i)));
selected.append(getFoamName(select->GetArrayName(i)));
}
}
@ -181,11 +134,11 @@ Foam::hashedWordList Foam::foamPvCore::getSelected
const int n = select->GetNumberOfArrays();
DynamicList<word> selected(n);
for (int i = selector.start(); i < selector.end(); ++i)
for (auto i : selector)
{
if (select->GetArraySetting(i))
{
selected.append(getFirstWord(select->GetArrayName(i)));
selected.append(getFoamName(select->GetArrayName(i)));
}
}
@ -193,119 +146,88 @@ Foam::hashedWordList Foam::foamPvCore::getSelected
}
Foam::stringList Foam::foamPvCore::getSelectedArrayEntries
Foam::HashSet<Foam::string>
Foam::foamPvCore::getSelectedArraySet
(
vtkDataArraySelection* select
)
{
stringList selections(select->GetNumberOfArrays());
label nElem = 0;
forAll(selections, elemI)
{
if (select->GetArraySetting(elemI))
{
selections[nElem++] = select->GetArrayName(elemI);
}
}
selections.setSize(nElem);
if (debug > 1)
{
const int n = select->GetNumberOfArrays();
Info<< "available(";
HashSet<string> enabled(2*n);
for (int i=0; i < n; ++i)
{
Info<< " \"" << select->GetArrayName(i) << "\"";
}
Info<< " )\nselected(";
forAll(selections, elemI)
{
Info<< " " << selections[elemI];
}
Info<< " )\n";
}
return selections;
}
Foam::stringList Foam::foamPvCore::getSelectedArrayEntries
(
vtkDataArraySelection* select,
const arrayRange& selector
)
{
stringList selections(selector.size());
label nElem = 0;
for (int i = selector.start(); i < selector.end(); ++i)
{
if (select->GetArraySetting(i))
{
selections[nElem++] = select->GetArrayName(i);
enabled.insert(select->GetArrayName(i));
}
}
selections.setSize(nElem);
if (debug > 1)
{
const int n = select->GetNumberOfArrays();
Info<< "available(";
for (int i = selector.start(); i < selector.end(); ++i)
for (int i=0; i < n; ++i)
{
Info<< " \"" << select->GetArrayName(i) << "\"";
}
Info<< " )\nselected(";
forAll(selections, elemI)
for (auto k : enabled)
{
Info<< " " << selections[elemI];
Info<< " " << k;
}
Info<< " )\n";
}
return selections;
return enabled;
}
void Foam::foamPvCore::setSelectedArrayEntries
Foam::Map<Foam::string>
Foam::foamPvCore::getSelectedArrayMap
(
vtkDataArraySelection* select,
const stringList& selections
vtkDataArraySelection* select
)
{
const int n = select->GetNumberOfArrays();
select->DisableAllArrays();
Map<string> enabled(2*n);
// Loop through entries, setting values from selectedEntries
for (int i=0; i < n; ++i)
{
const string arrayName(select->GetArrayName(i));
if (select->GetArraySetting(i))
{
enabled.insert(i, select->GetArrayName(i));
}
}
forAll(selections, elemI)
{
if (selections[elemI] == arrayName)
{
select->EnableArray(arrayName.c_str());
break;
}
}
}
return enabled;
}
Foam::word Foam::foamPvCore::getFirstWord(const char* str)
Foam::word Foam::foamPvCore::getFoamName(const std::string& str)
{
if (str)
if (str.size())
{
label n = 0;
while (str[n] && word::valid(str[n]))
std::string::size_type beg = str.rfind('/');
if (beg == std::string::npos)
{
++n;
beg = 0;
}
// don't need to re-check for invalid chars
return word(str, n, false);
else
{
++beg;
}
std::string::size_type end = beg;
while (str[end] && word::valid(str[end]))
{
++end;
}
// Already checked for valid/invalid chars
return word(str.substr(beg, beg+end), false);
}
else
{
@ -324,4 +246,30 @@ void Foam::foamPvCore::printMemory()
}
}
vtkSmartPointer<vtkCellArray> Foam::foamPvCore::identityVertices
(
const label size
)
{
// VTK_VERTEX
auto cells = vtkSmartPointer<vtkCellArray>::New();
UList<vtkIdType> cellsUL = vtkUList(cells, size, 2*size);
// Cell connectivity for vertex
// [size, ids.., size, ids...]
// which means
// [1, id, 1, id, ...]
label idx = 0;
for (label id=0; id < size; ++id)
{
cellsUL[idx++] = 1;
cellsUL[idx++] = id;
}
return cells;
}
// ************************************************************************* //

View File

@ -39,16 +39,20 @@ SourceFiles
#include "pointList.H"
#include "wordList.H"
#include "Hash.H"
#include "HashSet.H"
#include "Map.H"
#include "hashedWordList.H"
#include "vtkPoints.h"
#include "labelRange.H"
// * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * //
class vtkCellArray;
class vtkDataArraySelection;
class vtkDataSet;
class vtkMultiBlockDataSet;
class vtkIndent;
class vtkMultiBlockDataSet;
class vtkPoints;
template<class T> class vtkSmartPointer;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -69,21 +73,20 @@ public:
//- Bookkeeping for GUI checklists and multi-block organization
// Works like a SubList selection.
class arrayRange
:
public labelRange
{
const char *name_;
int block_;
int start_;
int size_;
public:
//- Construct with given name for the specified block
arrayRange(const char *name, const int blockNo=0)
arrayRange(const char *name, int blockNo=0)
:
labelRange(),
name_(name),
block_(blockNo),
start_(0),
size_(0)
block_(blockNo)
{}
//- Return the block holding these datasets
@ -106,47 +109,21 @@ public:
return name_;
}
//- The array start index
int start() const
{
return start_;
}
//- The array end index
int end() const
{
return start_ + size_;
}
//- The sub-list size
int size() const
{
return size_;
}
//- True if the sub-list is empty
bool empty() const
{
return !size_;
}
//- Reset the start/size directly
using labelRange::reset;
//- Reset the size to zero and optionally assign a new start
void reset(const int startAt = 0)
void reset(label startAt = 0)
{
start_ = startAt;
size_ = 0;
clear();
setStart(startAt);
}
//- Assign new start and reset the size
void operator=(const int i)
{
reset(i);
}
//- Increment the size
void operator+=(const int n)
void operator+=(label n)
{
size_ += n;
setSize(size() + n);
}
}; // End class arrayRange
@ -183,48 +160,26 @@ public:
const std::string& datasetName
);
//- Convenience method for the VTK multiblock API
// Always returns a nullptr if datasetNo is negative
template<class Type=vtkDataSet>
static Type* getDataFromBlock
(
vtkMultiBlockDataSet* output,
const arrayRange& selector,
const label datasetNo
);
//- Convenience method for the VTK multiblock API
static int getNumberOfDataSets
(
vtkMultiBlockDataSet* output,
const arrayRange& selector
);
//- Add objects of Type to array selection
template<class Type>
static label addToSelection
(
vtkDataArraySelection* select,
const IOobjectList& objects,
const string& suffix = string::null
const std::string& prefix = string::null
);
//- Retrieve the current selections into a boolList
static int getSelected
(
boolList& lst,
vtkDataArraySelection* select
);
//- Retrieve the current selections as a wordHashSet
//- Retrieve the current selections as a hashedWordList,
// while stripping off any prefix or suffix
static hashedWordList getSelected
(
vtkDataArraySelection* select
);
//- Retrieve a sub-list of the current selections
//- Retrieve a sub-list of the current selections as a hashedWordList,
// while stripping off any prefix or suffix
static hashedWordList getSelected
(
vtkDataArraySelection* select,
@ -232,35 +187,42 @@ public:
);
//- Retrieve the current selections
static stringList getSelectedArrayEntries
//- Retrieve the currently enabled selections as hashset
static HashSet<string> getSelectedArraySet
(
vtkDataArraySelection* select
);
//- Retrieve a sub-list of the current selections
static stringList getSelectedArrayEntries
//- Retrieve the currently enabled selections as id/name map
static Map<string> getSelectedArrayMap
(
vtkDataArraySelection* select,
const arrayRange& selector
vtkDataArraySelection* select
);
//- Set selection(s)
//- Enable the selection(s)
template<class AnyValue, class AnyHasher>
static void setSelectedArrayEntries
(
vtkDataArraySelection* select,
const stringList& selections
const HashTable<AnyValue, string, AnyHasher>& enabled
);
//- Extract up to the first non-word characters
static word getFirstWord(const char* str);
//- Extract the first word characters after a slash
static word getFoamName(const std::string& str);
//- Simple memory used debugging information
static void printMemory();
//- Return an identity list of VTK_VERTEX
static vtkSmartPointer<vtkCellArray> identityVertices
(
const label size
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
}; // End class foamPvCore

View File

@ -25,55 +25,28 @@ License
#include "IOobjectList.H"
#include "vtkDataArraySelection.h"
#include "vtkMultiBlockDataSet.h"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
Type* Foam::foamPvCore::getDataFromBlock
(
vtkMultiBlockDataSet* output,
const arrayRange& selector,
const label datasetNo
)
{
const int blockNo = selector.block();
vtkMultiBlockDataSet* block =
(
datasetNo < 0
? nullptr
: vtkMultiBlockDataSet::SafeDownCast(output->GetBlock(blockNo))
);
if (block)
{
return Type::SafeDownCast(block->GetBlock(datasetNo));
}
return nullptr;
}
template<class Type>
Foam::label Foam::foamPvCore::addToSelection
(
vtkDataArraySelection *select,
const IOobjectList& objects,
const string& suffix
const std::string& prefix
)
{
const wordList names = objects.sortedNames(Type::typeName);
forAll(names, i)
{
if (suffix.empty())
if (prefix.empty())
{
select->AddArray(names[i].c_str());
}
else
{
select->AddArray((names[i] + suffix).c_str());
select->AddArray((prefix + names[i]).c_str());
}
}
@ -81,4 +54,27 @@ Foam::label Foam::foamPvCore::addToSelection
}
template<class AnyValue, class AnyHasher>
void Foam::foamPvCore::setSelectedArrayEntries
(
vtkDataArraySelection* select,
const HashTable<AnyValue, string, AnyHasher>& enabled
)
{
const int n = select->GetNumberOfArrays();
// disable everything not explicitly enabled
select->DisableAllArrays();
// Loop through entries, enabling as required
for (int i=0; i < n; ++i)
{
const char* arrayName = select->GetArrayName(i);
if (enabled.found(arrayName))
{
select->EnableArray(arrayName);
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
\*---------------------------------------------------------------------------*/
#ifndef foamVtkAdaptors_H
#define foamVtkAdaptors_H
// OpenFOAM includes
#include "labelList.H"
// VTK includes
#include "vtkCellArray.h"
#include "vtkIdTypeArray.h"
#include "vtkSmartPointer.h"
#include "vtkUnsignedCharArray.h"
#include "vtkAOSDataArrayTemplate.h"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
//- Attach a smart pointer, or generate a non-null one.
template<class T>
inline vtkSmartPointer<T> nonNullSmartPointer(T* ptr)
{
return vtkSmartPointer<T>(ptr ? ptr : T::New());
}
//- Helper to wrap vtkUnsignedCharArray as a UList
inline UList<uint8_t> vtkUList
(
vtkUnsignedCharArray* array,
const label size
)
{
array->SetNumberOfComponents(1);
array->SetNumberOfTuples(size);
UList<uint8_t> list
(
array->WritePointer(0, size),
size
);
return list;
}
//- Helper to wrap vtkIdTypeArray as a UList
inline UList<vtkIdType> vtkUList
(
vtkIdTypeArray* array,
const label size
)
{
array->SetNumberOfComponents(1);
array->SetNumberOfTuples(size);
UList<vtkIdType> list
(
array->WritePointer(0, size),
size
);
return list;
}
//- Special helper to wrap vtkCellArray as a UList
inline UList<vtkIdType> vtkUList
(
vtkCellArray* cells,
const label nCells,
const label size
)
{
cells->GetData()->SetNumberOfTuples(size);
UList<vtkIdType> list
(
cells->WritePointer(nCells, size),
size
);
return list;
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

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

@ -158,6 +158,9 @@ int main(int argc, char *argv[])
}
if
(
!args.optionFound("triSurface")
&&
(
!MeshedSurface<face>::canRead(importName, true)
||
@ -166,6 +169,7 @@ int main(int argc, char *argv[])
&& !MeshedSurface<face>::canWriteType(exportName.ext(), true)
)
)
)
{
return 1;
}

View File

@ -26,10 +26,10 @@
# paraFoam
#
# Description
# start paraview with the OpenFOAM libraries
# Start paraview with the OpenFOAM libraries and reader modules.
#
# Note
# combining -block or -builtin options with the -region option yields
# Combining -block or -builtin options with -region option yields
# undefined behaviour
#------------------------------------------------------------------------------
usage() {
@ -37,7 +37,7 @@ usage() {
while [ "$#" -ge 1 ]; do echo "$1"; shift; done
cat<<USAGE
Usage: ${0##*/} [OPTION] [PARAVIEW_OPTION]
Usage: ${0##*/} [OPTION] [--] [PARAVIEW_OPTION]
options:
-block use blockMesh reader (uses .blockMesh extension)
-case <dir> specify alternative case directory, default is the cwd
@ -46,10 +46,10 @@ options:
-touchAll create .blockMesh, .OpenFOAM files (and for all regions)
-vtk | -builtin use VTK builtin OpenFOAM reader (uses .foam extension)
-help print the usage
--help paraview help
Paraview options start with a double dashes.
* start paraview with the OpenFOAM libraries
Start paraview with the OpenFOAM libraries and reader modules.
Note that paraview options begin with double dashes.
paraview=$(command -v paraview)
@ -57,12 +57,9 @@ USAGE
exit 1
}
# We want to do nice exit when running paraview to give paraview opportunity
# to clean up
# Do a nice exit to give paraview an opportunity to clean up
unset FOAM_ABORT
unset regionName optTouch
# Hack: change all locale to 'C' i.e. using '.' for decimal point. This is
# only needed temporarily until paraview is locale aware. (git version is
# already 2010-07)
@ -73,18 +70,19 @@ extension=OpenFOAM
plugin=PVFoamReader
# Parse options
unset regionName optTouch
while [ "$#" -gt 0 ]
do
case "$1" in
-h | -help)
usage
;;
-block | -blockMesh)
-block*)
extension=blockMesh
plugin=PVblockMeshReader
shift
;;
-builtin | -vtk)
-vtk | -built*)
extension=foam
unset plugin
shift
@ -113,6 +111,11 @@ do
shift
break # Stop here, treat balance as paraview options
;;
--help) # Emit paraview help directly
exec paraview "$@"
echo "Error: could not exec paraview" 1>&2
exit 1 # This should not have happened
;;
--*)
break # Stop here, treat this and balance as paraview options
;;
@ -253,6 +256,8 @@ then
# Has --data=.., send directly to paraview
exec paraview "$@"
echo "Error: could not exec paraview" 1>&2
exit 1 # This should not have happened
else

View File

@ -52,7 +52,7 @@
#------------------------------------------------------------------------------
# USER EDITABLE PART: Changes made here may be lost with the next upgrade
setenv ParaView_VERSION 5.3.0
setenv ParaView_VERSION 5.4.0
setenv ParaView_MAJOR detect # Automatically determine major version
set cmake_version=cmake-system

View File

@ -2563,8 +2563,8 @@ _of_foamToVTK()
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local opts="-allPatches -ascii -constant -latestTime -nearCellValue -newTimes -noFaceZones -noFunctionObjects -noInternal -noLagrangian -noLinks -noPointValues -noZero -parallel -poly -surfaceFields -useTimeName -srcDoc -doc -help "
local optsWithArgs="-case -cellSet -decomposeParDict -excludePatches -faceSet -fields -pointSet -region -roots -time "
local opts="-allPatches -ascii -constant -latestTime -nearCellValue -newTimes -noFaceZones -noFunctionObjects -noInternal -noLagrangian -noLinks -noPointValues -noZero -parallel -poly -surfaceFields -useTimeName -xml -srcDoc -doc -help "
local optsWithArgs="-case -cellSet -decomposeParDict -excludePatches -faceSet -fields -name -pointSet -region -roots -time "
case ${prev} in
-case)

View File

@ -55,7 +55,7 @@
#------------------------------------------------------------------------------
# USER EDITABLE PART: Changes made here may be lost with the next upgrade
ParaView_VERSION=5.3.0
ParaView_VERSION=5.4.0
ParaView_MAJOR=detect # Automatically determine major version
cmake_version=cmake-system

View File

@ -24,7 +24,13 @@ starcd/STARCDMeshWriter.C
polyDualMesh/polyDualMesh.C
vtk/part/foamVtkCells.C
vtk/output/foamVtkOutput.C
vtk/output/foamVtkInternalWriter.H
vtk/output/foamVtkPatchWriter.H
vtk/output/foamVtkSurfaceMeshWriter.C
vtk/output/foamVtkWriteSurfFields.C
vtk/part/foamVtkMeshMaps.C
vtk/part/foamVtuCells.C
vtk/part/foamVtuSizing.C
LIB = $(FOAM_LIBBIN)/libconversion

View File

@ -0,0 +1,380 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkInternalWriter.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::vtk::internalWriter::beginPiece()
{
if (!legacy_)
{
format()
.openTag(vtk::fileTag::PIECE)
.xmlAttr(vtk::fileAttr::NUMBER_OF_POINTS, vtuCells_.nFieldPoints())
.xmlAttr(vtk::fileAttr::NUMBER_OF_CELLS, vtuCells_.nFieldCells())
.closeTag();
}
}
void Foam::vtk::internalWriter::writePoints()
{
// payload size
const uint64_t payLoad = (vtuCells_.nFieldPoints() * 3 * sizeof(float));
if (legacy_)
{
legacy::beginPoints(os_, vtuCells_.nFieldPoints());
}
else
{
format()
.tag(vtk::fileTag::POINTS)
.openDataArray<float,3>(vtk::dataArrayAttr::POINTS)
.closeTag();
}
format().writeSize(payLoad);
vtk::writeList(format(), mesh_.points());
vtk::writeList
(
format(),
mesh_.cellCentres(),
vtuCells_.addPointCellLabels()
);
format().flush();
if (!legacy_)
{
format()
.endDataArray()
.endTag(vtk::fileTag::POINTS);
}
}
void Foam::vtk::internalWriter::writeCellsLegacy()
{
const List<uint8_t>& cellTypes = vtuCells_.cellTypes();
const labelList& vertLabels = vtuCells_.vertLabels();
os_ << "CELLS " << vtuCells_.nFieldCells() << ' '
<< vertLabels.size() << nl;
vtk::writeList(format(), vertLabels);
format().flush();
os_ << "CELL_TYPES " << cellTypes.size() << nl;
// No nComponents for char, so cannot use vtk::writeList
forAll(cellTypes, i)
{
format().write(cellTypes[i]);
}
format().flush();
}
void Foam::vtk::internalWriter::writeCells()
{
format().tag(vtk::fileTag::CELLS);
//
// 'connectivity'
//
{
const labelList& vertLabels = vtuCells_.vertLabels();
const uint64_t payLoad = vertLabels.size() * sizeof(label);
format().openDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY)
.closeTag();
format().writeSize(payLoad);
vtk::writeList(format(), vertLabels);
format().flush();
format().endDataArray();
}
//
// 'offsets' (connectivity offsets)
//
{
const labelList& vertOffsets = vtuCells_.vertOffsets();
const uint64_t payLoad = vertOffsets.size() * sizeof(label);
format().openDataArray<label>(vtk::dataArrayAttr::OFFSETS)
.closeTag();
format().writeSize(payLoad);
vtk::writeList(format(), vertOffsets);
format().flush();
format().endDataArray();
}
//
// 'types' (cell types)
//
{
const List<uint8_t>& cellTypes = vtuCells_.cellTypes();
const uint64_t payLoad = cellTypes.size() * sizeof(uint8_t);
format().openDataArray<uint8_t>(vtk::dataArrayAttr::TYPES)
.closeTag();
format().writeSize(payLoad);
forAll(cellTypes, i)
{
// No nComponents for char, cannot use vtk::writeList here
format().write(cellTypes[i]);
}
format().flush();
format().endDataArray();
}
//
// can quit here if there are NO face streams
//
if (vtuCells_.faceLabels().empty())
{
format().endTag(vtk::fileTag::CELLS);
return;
}
// --------------------------------------------------
//
// 'faces' (face streams)
//
{
const labelList& faceLabels = vtuCells_.faceLabels();
const uint64_t payLoad = faceLabels.size() * sizeof(label);
format().openDataArray<label>(vtk::dataArrayAttr::FACES)
.closeTag();
format().writeSize(payLoad);
vtk::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 = vtuCells_.faceOffsets();
const uint64_t payLoad = faceOffsets.size() * sizeof(label);
format().openDataArray<label>(vtk::dataArrayAttr::FACEOFFSETS)
.closeTag();
format().writeSize(payLoad);
vtk::writeList(format(), faceOffsets);
format().flush();
format().endDataArray();
}
format().endTag(vtk::fileTag::CELLS);
}
void Foam::vtk::internalWriter::writeMesh()
{
writePoints();
if (legacy_)
{
writeCellsLegacy();
}
else
{
writeCells();
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::vtk::internalWriter::internalWriter
(
const fvMesh& mesh,
const vtk::vtuCells& cells,
const fileName& baseName,
const vtk::outputOptions outOpts
)
:
mesh_(mesh),
legacy_(outOpts.legacy()),
format_(),
vtuCells_(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, vtk::fileTag::UNSTRUCTURED_GRID);
}
else
{
// XML (inline)
format()
.xmlHeader()
.xmlComment(title)
.beginVTKFile(vtk::fileTag::UNSTRUCTURED_GRID, "0.1");
}
beginPiece();
writeMesh();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::vtk::internalWriter::~internalWriter()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtk::internalWriter::beginCellData(label nFields)
{
if (legacy_)
{
legacy::dataHeader
(
os(),
vtk::fileTag::CELL_DATA,
vtuCells_.nFieldCells(),
nFields
);
}
else
{
format().tag(vtk::fileTag::CELL_DATA);
}
}
void Foam::vtk::internalWriter::endCellData()
{
if (!legacy_)
{
format().endTag(vtk::fileTag::CELL_DATA);
}
}
void Foam::vtk::internalWriter::beginPointData(label nFields)
{
if (legacy_)
{
legacy::dataHeader
(
os(),
vtk::fileTag::POINT_DATA,
vtuCells_.nFieldPoints(),
nFields
);
}
else
{
format().tag(vtk::fileTag::POINT_DATA);
}
}
void Foam::vtk::internalWriter::endPointData()
{
if (!legacy_)
{
format().endTag(vtk::fileTag::POINT_DATA);
}
}
void Foam::vtk::internalWriter::writeFooter()
{
if (!legacy_)
{
// slight cheat. </Piece> too
format().endTag(vtk::fileTag::PIECE);
format().endTag(vtk::fileTag::UNSTRUCTURED_GRID)
.endVTKFile();
}
}
void Foam::vtk::internalWriter::writeCellIDs()
{
// Cell ids first
const labelList& cellMap = vtuCells_.cellMap();
const uint64_t payLoad = vtuCells_.nFieldCells() * sizeof(label);
if (legacy_)
{
os_ << "cellID 1 " << vtuCells_.nFieldCells() << " int" << nl;
}
else
{
format().openDataArray<label>("cellID")
.closeTag();
}
format().writeSize(payLoad);
vtk::writeList(format(), cellMap);
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
// ************************************************************************* //

View File

@ -0,0 +1,255 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::vtk::internalWriter
Description
Write fields (internal).
SourceFiles
foamVtkInternalWriter.C
foamVtkInternalWriterTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef foamVtkInternalWriter_H
#define foamVtkInternalWriter_H
#include "OFstream.H"
#include "volFields.H"
#include "pointFields.H"
#include "foamVtkOutputFields.H"
#include "foamVtkOutputOptions.H"
#include "foamVtuCells.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class volPointInterpolation;
namespace vtk
{
/*---------------------------------------------------------------------------*\
Class internalWriter Declaration
\*---------------------------------------------------------------------------*/
class internalWriter
{
// Private Member Data
//- Reference to the OpenFOAM mesh (or subset)
const fvMesh& mesh_;
//- Commonly used query
const bool legacy_;
autoPtr<vtk::formatter> format_;
//- The volume cells (internalMesh)
const vtuCells& vtuCells_;
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
//- Construct from components
internalWriter
(
const fvMesh& mesh,
const vtk::vtuCells& cells,
const fileName& baseName,
const vtk::outputOptions outOpts
);
//- Destructor
~internalWriter();
// Member Functions
inline std::ofstream& os()
{
return os_;
}
inline vtk::formatter& format()
{
return format_();
}
//- Open write for CellData of count fields.
// The parameters are only used for the legacy format.
void beginCellData(label nFields);
//- Close write for CellData
void endCellData();
//- Open write for PointData of count fields
// The parameters are only used for the legacy format.
void beginPointData(label nFields);
//- Close write for PointData
void endPointData();
//- Write cellIDs
void writeCellIDs();
//- Write file footer
void writeFooter();
// Write fields (individually)
//- Write the internal field
template<class Type>
void write(const DimensionedField<Type, volMesh>& field);
//- Write the volume field (internal part)
template<class Type, template<class> class PatchField>
void write(const GeometricField<Type, PatchField, volMesh>& field);
//- Write the point field
// Interpolate to originating cell centre for decomposed cells.
template<class Type, template<class> class PatchField>
void write
(
const GeometricField<Type, PatchField, pointMesh>& field
);
//- Write point-interpolated internal field
template<class Type>
void write
(
const volPointInterpolation& pInterp,
const DimensionedField<Type, volMesh>& vfield
);
//- Write point-interpolated volume field
template<class Type>
void write
(
const volPointInterpolation& pInterp,
const GeometricField<Type, fvPatchField, volMesh>& vfield
);
// Write fields (collectively)
//- Write multiple internal fields
template<class Type>
void write
(
const UPtrList
<
const DimensionedField<Type, volMesh>
>& flds
);
//- Write multiple volume/point fields
template<class Type, template<class> class PatchField, class GeoMesh>
void write
(
const UPtrList
<
const GeometricField<Type, PatchField, GeoMesh>
>& flds
);
//- Write multiple point-interpolated internal fields
template<class Type>
void write
(
const volPointInterpolation& pInterp,
const UPtrList
<
const DimensionedField<Type, volMesh>
>& flds
);
//- Write multiple point-interpolated volume fields
template<class Type>
void write
(
const volPointInterpolation& pInterp,
const UPtrList
<
const GeometricField<Type, fvPatchField, volMesh>
>& flds
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace vtk
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "foamVtkInternalWriterTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,256 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkInternalWriter.H"
#include "foamVtkOutput.H"
#include "volPointInterpolation.H"
#include "interpolatePointToCell.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
void Foam::vtk::internalWriter::write
(
const DimensionedField<Type, volMesh>& field
)
{
const labelList& cellMap = vtuCells_.cellMap();
const int nCmpt(pTraits<Type>::nComponents);
// const uint64_t payLoad(cellMap.size() * nCmpt * sizeof(float));
if (legacy_)
{
legacy::floatField(os(), field.name(), nCmpt, cellMap.size());
}
else
{
format().openDataArray<float, nCmpt>(field.name())
.closeTag();
}
// writeField includes payload size, and flush
vtk::writeField(format(), field, cellMap);
if (!legacy_)
{
format().endDataArray();
}
}
template<class Type, template<class> class PatchField>
void Foam::vtk::internalWriter::write
(
const GeometricField<Type, PatchField, volMesh>& field
)
{
write(field.internalField());
}
template<class Type, template<class> class PatchField>
void Foam::vtk::internalWriter::write
(
const GeometricField<Type, PatchField, pointMesh>& field
)
{
const labelList& addPointCellLabels = vtuCells_.addPointCellLabels();
const int nCmpt(pTraits<Type>::nComponents);
const label nVals(vtuCells_.nFieldPoints());
// Only needed for non-legacy
const uint64_t payLoad(nVals * nCmpt * sizeof(float));
if (legacy_)
{
legacy::floatField(os(), field.name(), nCmpt, nVals);
}
else
{
format().openDataArray<float, nCmpt>(field.name())
.closeTag();
}
format().writeSize(payLoad);
vtk::writeList(format(), field);
for (const label cellId : addPointCellLabels)
{
const Type val = interpolatePointToCell(field, cellId);
vtk::write(format(), val);
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
template<class Type>
void Foam::vtk::internalWriter::write
(
const volPointInterpolation& pInterp,
const DimensionedField<Type, volMesh>& vfield
)
{
typedef DimensionedField<Type, pointMesh> PointFieldType;
// Use tmp intermediate. Compiler sometimes weird otherwise.
tmp<PointFieldType> tfield = pInterp.interpolate(vfield);
const PointFieldType& pfield = tfield();
const labelList& addPointCellLabels = vtuCells_.addPointCellLabels();
const int nCmpt(pTraits<Type>::nComponents);
const label nVals(vtuCells_.nFieldPoints());
// Only needed for non-legacy
const uint64_t payLoad(nVals * nCmpt * sizeof(float));
if (legacy_)
{
legacy::floatField(os(), vfield.name(), nCmpt, nVals);
}
else
{
format().openDataArray<float, nCmpt>(vfield.name())
.closeTag();
}
format().writeSize(payLoad);
vtk::writeList(format(), pfield);
vtk::writeList(format(), vfield, addPointCellLabels);
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
template<class Type>
void Foam::vtk::internalWriter::write
(
const volPointInterpolation& pInterp,
const GeometricField<Type, fvPatchField, volMesh>& vfield
)
{
typedef GeometricField<Type, pointPatchField, pointMesh> PointFieldType;
// Use tmp intermediate. Compiler sometimes weird otherwise.
tmp<PointFieldType> tfield = pInterp.interpolate(vfield);
const PointFieldType& pfield = tfield();
const labelList& addPointCellLabels = vtuCells_.addPointCellLabels();
const int nCmpt(pTraits<Type>::nComponents);
const label nVals(vtuCells_.nFieldPoints());
// Only needed for non-legacy
const uint64_t payLoad(nVals * nCmpt * sizeof(float));
if (legacy_)
{
legacy::floatField(os(), vfield.name(), nCmpt, nVals);
}
else
{
format().openDataArray<float, nCmpt>(vfield.name())
.closeTag();
}
format().writeSize(payLoad);
vtk::writeList(format(), pfield);
vtk::writeList(format(), vfield, addPointCellLabels);
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
template<class Type>
void Foam::vtk::internalWriter::write
(
const UPtrList<const DimensionedField<Type, volMesh>>& flds
)
{
for (const auto& field : flds)
{
write(field);
}
}
template<class Type, template<class> class PatchField, class GeoMesh>
void Foam::vtk::internalWriter::write
(
const UPtrList<const GeometricField<Type, PatchField, GeoMesh>>& flds
)
{
for (const auto& field : flds)
{
write(field);
}
}
template<class Type>
void Foam::vtk::internalWriter::write
(
const volPointInterpolation& pInterp,
const UPtrList<const DimensionedField<Type, volMesh>>& flds
)
{
for (const auto& field : flds)
{
write(pInterp, field);
}
}
template<class Type>
void Foam::vtk::internalWriter::write
(
const volPointInterpolation& pInterp,
const UPtrList<const GeometricField<Type, fvPatchField, volMesh>>& flds
)
{
for (const auto& field : flds)
{
write(pInterp, field);
}
}
// ************************************************************************* //

View File

@ -1,119 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-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/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkOutput.H"
#include "foamVtkAsciiFormatter.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::word Foam::foamVtkOutput::legacy::EXT = "vtk";
//! \cond fileScope
static inline std::ostream& legacyDataHeader
(
std::ostream& os,
const char* tag,
const Foam::label nItems,
const Foam::label nFields
)
{
os << tag << ' ' << nItems << '\n'
<< "FIELD attributes " << nFields << '\n';
return os;
}
//! \endcond
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::label Foam::foamVtkOutput::writeVtmFile
(
std::ostream& os,
const UList<fileName>& files
)
{
const word& content = "vtkMultiBlockDataSet";
foamVtkAsciiFormatter vtmFile(os);
vtmFile
.xmlHeader()
.beginVTKFile(content, "1.0");
forAll(files, i)
{
vtmFile
.openTag("DataSet")
( "index", i )
( "file", files[i] )
.closeTag(true);
}
vtmFile.endTag(content).endVTKFile();
return files.size();
}
std::ostream& Foam::foamVtkOutput::legacy::writeHeader
(
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::writeCellDataHeader
(
std::ostream& os,
const label nCells,
const label nFields
)
{
return legacyDataHeader(os, "CELL_DATA", nCells, nFields);
}
std::ostream& Foam::foamVtkOutput::legacy::writePointDataHeader
(
std::ostream& os,
const label nPoints,
const label nFields
)
{
return legacyDataHeader(os, "POINT_DATA", nPoints, nFields);
}
// ************************************************************************* //

View File

@ -1,222 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
foamVtkOutput
Description
A collection of functions for writing vtk file content.
SourceFiles
foamVtkOutput.C
foamVtkOutputTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef foamVtkOutput_H
#define foamVtkOutput_H
#include "floatScalar.H"
#include "volFields.H"
#include "foamVtkFormatter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class foamVtkOutput Declaration
\*---------------------------------------------------------------------------*/
class foamVtkOutput
{
// Private Member Functions
//- Disallow construction
foamVtkOutput() = delete;
public:
// Public typedefs
//- Use UInt64 for header data
typedef foamVtkFormatter::headerType headerType;
// Forward declarations
class legacy;
// Static Members
//- Write vtm datasets for specified files
static Foam::label writeVtmFile
(
std::ostream& os,
const UList<fileName>& files
);
//- Write a value component-wise.
template<class Type>
inline static void write(foamVtkFormatter&, const Type&);
//- Write a list of values.
// The output does not include the payload size.
template<class Type>
static void writeList
(
foamVtkFormatter&,
const UList<Type>&
);
//- Write a list of values via indirect addressing.
// The output does not include the payload size.
template<class Type>
static void writeList
(
foamVtkFormatter&,
const UList<Type>&,
const UList<label>& addressing
);
//- Write volField with cell values (including decomposed cells).
// The output includes the payload size and flush.
template<class Type>
static void writeField
(
foamVtkFormatter&,
const GeometricField<Type, fvPatchField, volMesh>&,
const UList<label>& superCells
);
};
/*---------------------------------------------------------------------------*\
Class foamVtkOutput::legacy Declaration
\*---------------------------------------------------------------------------*/
//- Basic support for legacy files
class foamVtkOutput::legacy
{
// Private Member Functions
//- Disallow construction
legacy() = delete;
public:
// Static data members
//- file extension for legacy files (vtk)
static const Foam::word EXT;
// Static Members
//- Emit header for legacy file
static std::ostream& writeHeader
(
std::ostream&,
const std::string& title,
const bool binary = false
);
//- Emit header for legacy CELL_DATA
static std::ostream& writeCellDataHeader
(
std::ostream& os,
const label nCells,
const label nFields
);
//- Emit header for legacy POINT_DATA
static std::ostream& writePointDataHeader
(
std::ostream& os,
const label nPoints,
const label nFields
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Template specialization for label
template<>
inline void Foam::foamVtkOutput::write<label>
(
foamVtkFormatter& fmt,
const label& val
)
{
fmt.write(val);
}
//- Template specialization for float
template<>
inline void Foam::foamVtkOutput::write<float>
(
foamVtkFormatter& fmt,
const float& val
)
{
fmt.write(val);
}
//- Template specialization for double
template<>
inline void Foam::foamVtkOutput::write<double>
(
foamVtkFormatter& fmt,
const double& val
)
{
fmt.write(val);
}
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "foamVtkOutputTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,105 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2107 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/>.
InNamespace
Foam::vtk
Description
Additional functions for writing fields in VTK format.
SourceFiles
foamVtkOutputFieldsTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef foamVtkOutputFields_H
#define foamVtkOutputFields_H
#include "foamVtkOutput.H"
#include "volFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace vtk
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Write DimensionedField for mesh
// The output includes the payload size and flush.
template<class Type>
void writeField
(
vtk::formatter& fmt,
const DimensionedField<Type, volMesh>& fld
);
//- Write DimensionedField based on the cellMap
// The output includes the payload size and flush.
template<class Type>
void writeField
(
vtk::formatter& fmt,
const DimensionedField<Type, volMesh>& fld,
const UList<label>& cellMap
);
//- Write internalField for mesh
// The output includes the payload size and flush.
template<class Type>
void writeField
(
vtk::formatter& fmt,
const GeometricField<Type, fvPatchField, volMesh>& fld
);
//- Write internalField based on the cellMap
// The output includes the payload size and flush.
template<class Type>
void writeField
(
vtk::formatter& fmt,
const GeometricField<Type, fvPatchField, volMesh>& fld,
const UList<label>& cellMap
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace vtk
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "foamVtkOutputFieldsTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,107 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2107 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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
void Foam::vtk::writeField
(
vtk::formatter& fmt,
const DimensionedField<Type, volMesh>& fld
)
{
const uint64_t payLoad =
(
fld.size() * pTraits<Type>::nComponents * sizeof(float)
);
fmt.writeSize(payLoad);
writeList(fmt, fld);
fmt.flush();
}
template<class Type>
void Foam::vtk::writeField
(
vtk::formatter& fmt,
const DimensionedField<Type, volMesh>& fld,
const UList<label>& cellMap
)
{
const uint64_t payLoad =
(
cellMap.size() * pTraits<Type>::nComponents * sizeof(float)
);
fmt.writeSize(payLoad);
writeList(fmt, fld, cellMap);
fmt.flush();
}
template<class Type>
void Foam::vtk::writeField
(
vtk::formatter& fmt,
const GeometricField<Type, fvPatchField, volMesh>& fld
)
{
const uint64_t payLoad =
(
fld.size() * pTraits<Type>::nComponents * sizeof(float)
);
fmt.writeSize(payLoad);
writeList(fmt, fld.internalField());
fmt.flush();
}
template<class Type>
void Foam::vtk::writeField
(
vtk::formatter& fmt,
const GeometricField<Type, fvPatchField, volMesh>& fld,
const UList<label>& cellMap
)
{
const uint64_t payLoad =
(
cellMap.size() * pTraits<Type>::nComponents * sizeof(float)
);
fmt.writeSize(payLoad);
writeList(fmt, fld.internalField(), cellMap);
fmt.flush();
}
// ************************************************************************* //

View File

@ -0,0 +1,404 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkPatchWriter.H"
#include "foamVtkOutput.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::vtk::patchWriter::beginPiece()
{
if (!legacy_)
{
format()
.openTag(vtk::fileTag::PIECE)
.xmlAttr(vtk::fileAttr::NUMBER_OF_POINTS, nPoints_)
.xmlAttr(vtk::fileAttr::NUMBER_OF_POLYS, nFaces_)
.closeTag();
}
}
void Foam::vtk::patchWriter::writePoints()
{
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
const uint64_t payLoad = (nPoints_*3*sizeof(float));
if (legacy_)
{
legacy::beginPoints(os_, nPoints_);
}
else
{
format().tag(vtk::fileTag::POINTS)
.openDataArray<float, 3>(vtk::dataArrayAttr::POINTS)
.closeTag();
}
format().writeSize(payLoad);
for (const label patchId : patchIDs_)
{
const polyPatch& pp = patches[patchId];
vtk::writeList(format(), pp.localPoints());
}
format().flush();
if (!legacy_)
{
format()
.endDataArray()
.endTag(vtk::fileTag::POINTS);
}
}
void Foam::vtk::patchWriter::writePolysLegacy()
{
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
// connectivity count without additional storage (done internally)
uint64_t nConnectivity = 0;
for (const label patchId : patchIDs_)
{
const polyPatch& pp = patches[patchId];
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;
for (const label patchId : patchIDs_)
{
const polyPatch& pp = patches[patchId];
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::vtk::patchWriter::writePolys()
{
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
//
// 'connectivity'
//
format().tag(vtk::fileTag::POLYS);
//
// 'connectivity'
//
{
// payload count
uint64_t payLoad = 0;
for (const label patchId : patchIDs_)
{
const polyPatch& pp = patches[patchId];
forAll(pp, facei)
{
payLoad += pp[facei].size();
}
}
format().openDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY)
.closeTag();
// payload size
format().writeSize(payLoad * sizeof(label));
label off = 0;
for (const label patchId : patchIDs_)
{
const polyPatch& pp = patches[patchId];
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>(vtk::dataArrayAttr::OFFSETS)
.closeTag();
// payload size
format().writeSize(nFaces_ * sizeof(label));
label off = 0;
for (const label patchId : patchIDs_)
{
const polyPatch& pp = patches[patchId];
forAll(pp, facei)
{
off += pp[facei].size();
format().write(off);
}
}
format().flush();
format().endDataArray();
}
format().endTag(vtk::fileTag::POLYS);
}
void Foam::vtk::patchWriter::writeMesh()
{
writePoints();
if (legacy_)
{
writePolysLegacy();
}
else
{
writePolys();
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::vtk::patchWriter::patchWriter
(
const fvMesh& mesh,
const fileName& baseName,
const vtk::outputOptions outOpts,
const bool nearCellValue,
const labelList& patchIDs
)
:
mesh_(mesh),
legacy_(outOpts.legacy()),
format_(),
nearCellValue_(nearCellValue),
patchIDs_(patchIDs),
os_(),
nPoints_(0),
nFaces_(0)
{
outputOptions opts(outOpts);
opts.append(false); // No append
os_.open((baseName + (legacy_ ? ".vtk" : ".vtp")).c_str());
format_ = opts.newFormatter(os_);
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
const word& title =
(
patchIDs_.size() == 1
? patches[patchIDs_.first()].name()
: "patches"
);
// Basic sizes
nPoints_ = nFaces_ = 0;
for (const label patchId : patchIDs_)
{
const polyPatch& pp = patches[patchId];
nPoints_ += pp.nPoints();
nFaces_ += pp.size();
}
if (legacy_)
{
legacy::fileHeader(format(), title, vtk::fileTag::POLY_DATA);
}
else
{
// XML (inline)
format()
.xmlHeader()
.xmlComment(title)
.beginVTKFile(vtk::fileTag::POLY_DATA, "0.1");
}
beginPiece();
writeMesh();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::vtk::patchWriter::~patchWriter()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtk::patchWriter::beginCellData(label nFields)
{
if (legacy_)
{
legacy::dataHeader
(
os(),
vtk::fileTag::CELL_DATA,
nFaces_,
nFields
);
}
else
{
format().tag(vtk::fileTag::CELL_DATA);
}
}
void Foam::vtk::patchWriter::endCellData()
{
if (!legacy_)
{
format().endTag(vtk::fileTag::CELL_DATA);
}
}
void Foam::vtk::patchWriter::beginPointData(label nFields)
{
if (legacy_)
{
legacy::dataHeader
(
os(),
vtk::fileTag::POINT_DATA,
nPoints_,
nFields
);
}
else
{
format().tag(vtk::fileTag::POINT_DATA);
}
}
void Foam::vtk::patchWriter::endPointData()
{
if (!legacy_)
{
format().endTag(vtk::fileTag::POINT_DATA);
}
}
void Foam::vtk::patchWriter::writeFooter()
{
if (!legacy_)
{
// slight cheat. </Piece> too
format().endTag(vtk::fileTag::PIECE);
format().endTag(vtk::fileTag::POLY_DATA)
.endVTKFile();
}
}
void Foam::vtk::patchWriter::writePatchIDs()
{
// 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);
for (const label patchId : patchIDs_)
{
const label sz = mesh_.boundaryMesh()[patchId].size();
for (label facei = 0; facei < sz; ++facei)
{
format().write(patchId);
}
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
// ************************************************************************* //

View File

@ -0,0 +1,230 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::vtk::patchWriter
Description
Write patch fields
SourceFiles
foamVtkPatchWriter.C
foamVtkPatchWriterTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef foamVtkPatchWriter_H
#define foamVtkPatchWriter_H
#include "pointMesh.H"
#include "OFstream.H"
#include "volFields.H"
#include "pointFields.H"
#include "indirectPrimitivePatch.H"
#include "PrimitivePatchInterpolation.H"
#include "foamVtkOutputOptions.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class volPointInterpolation;
namespace vtk
{
/*---------------------------------------------------------------------------*\
Class patchWriter Declaration
\*---------------------------------------------------------------------------*/
class patchWriter
{
// Private Member Data
//- Reference to the OpenFOAM mesh (or subset)
const fvMesh& mesh_;
//- Commonly used query
const bool legacy_;
autoPtr<vtk::formatter> format_;
const bool nearCellValue_;
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;
public:
// Constructors
//- Construct from components
patchWriter
(
const fvMesh& mesh,
const fileName& baseName,
const vtk::outputOptions outOpts,
const bool nearCellValue,
const labelList& patchIDs
);
//- Destructor
~patchWriter();
// Member Functions
inline std::ofstream& os()
{
return os_;
}
inline vtk::formatter& format()
{
return format_();
}
inline label nPoints() const
{
return nPoints_;
}
inline label nFaces() const
{
return nFaces_;
}
//- 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();
//- Open write for PointData of count fields
// The parameters are only used for the legacy format.
void beginPointData(label nFields);
//- Close write for PointData
void endPointData();
//- Write cellIDs
void writePatchIDs();
//- Write file footer
void writeFooter();
// Write fields (individually)
//- Write volume field
template<class Type, template<class> class PatchField>
void write(const GeometricField<Type, PatchField, volMesh>& field);
//- Write point fields
template<class Type, template<class> class PatchField>
void write(const GeometricField<Type, PatchField, pointMesh>& field);
//- Write point-interpolated volume field
template<class Type>
void write
(
const PrimitivePatchInterpolation<primitivePatch>& pInterp,
const GeometricField<Type, fvPatchField, volMesh>& field
);
// Write fields (collectively)
//- Write multiple volume/point fields
template<class Type, template<class> class PatchField, class GeoMesh>
void write
(
const UPtrList
<
const GeometricField<Type, PatchField, GeoMesh>
>& flds
);
//- Write multiple point-interpolated volume fields
template<class Type>
void write
(
const PrimitivePatchInterpolation<primitivePatch>& pInterp,
const UPtrList
<
const GeometricField<Type, fvPatchField, volMesh>
>& flds
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace vtk
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "foamVtkPatchWriterTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,189 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkPatchWriter.H"
#include "foamVtkOutput.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type, template<class> class PatchField>
void Foam::vtk::patchWriter::write
(
const GeometricField<Type, PatchField, volMesh>& field
)
{
const int nCmpt(pTraits<Type>::nComponents);
const uint64_t payLoad(nFaces_ * nCmpt * sizeof(float));
if (legacy_)
{
legacy::floatField(os_, field.name(), nCmpt, nFaces_);
}
else
{
format().openDataArray<float, nCmpt>(field.name())
.closeTag();
}
format().writeSize(payLoad);
for (const label patchId : patchIDs_)
{
const auto& pfld = field.boundaryField()[patchId];
if (nearCellValue_)
{
vtk::writeList(format(), pfld.patchInternalField()());
}
else
{
vtk::writeList(format(), pfld);
}
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
template<class Type, template<class> class PatchField>
void Foam::vtk::patchWriter::write
(
const GeometricField<Type, PatchField, pointMesh>& field
)
{
const int nCmpt(pTraits<Type>::nComponents);
const uint64_t payLoad(nPoints_ * nCmpt * sizeof(float));
if (legacy_)
{
legacy::floatField(os_, field.name(), nCmpt, nPoints_);
}
else
{
format().openDataArray<float, nCmpt>(field.name())
.closeTag();
}
format().writeSize(payLoad);
for (const label patchId : patchIDs_)
{
const auto& pfld = field.boundaryField()[patchId];
vtk::writeList(format(), pfld.patchInternalField()());
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
template<class Type>
void Foam::vtk::patchWriter::write
(
const PrimitivePatchInterpolation<primitivePatch>& pInter,
const GeometricField<Type, fvPatchField, volMesh>& field
)
{
const int nCmpt(pTraits<Type>::nComponents);
const uint64_t payLoad(nPoints_ * nCmpt * sizeof(float));
if (legacy_)
{
legacy::floatField(os_, field.name(), nCmpt, nPoints_);
}
else
{
format().openDataArray<float, nCmpt>(field.name())
.closeTag();
}
format().writeSize(payLoad);
for (const label patchId : patchIDs_)
{
const auto& pfld = field.boundaryField()[patchId];
if (nearCellValue_)
{
auto tfield =
pInter.faceToPointInterpolate(pfld.patchInternalField()());
vtk::writeList(format(), tfield());
}
else
{
auto tfield = pInter.faceToPointInterpolate(pfld);
vtk::writeList(format(), tfield());
}
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
template<class Type, template<class> class PatchField, class GeoMesh>
void Foam::vtk::patchWriter::write
(
const UPtrList<const GeometricField<Type, PatchField, GeoMesh>>& flds
)
{
for (const auto& field : flds)
{
write(field);
}
}
template<class Type>
void Foam::vtk::patchWriter::write
(
const PrimitivePatchInterpolation<primitivePatch>& pInter,
const UPtrList<const GeometricField<Type, fvPatchField, volMesh>>& flds
)
{
for (const auto& field : flds)
{
write(pInter, field);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,264 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkSurfaceMeshWriter.H"
#include "foamVtkOutput.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::vtk::surfaceMeshWriter::beginPiece()
{
if (!legacy_)
{
format()
.openTag(vtk::fileTag::PIECE)
.xmlAttr(vtk::fileAttr::NUMBER_OF_POINTS, pp_.nPoints())
.xmlAttr(vtk::fileAttr::NUMBER_OF_POLYS, pp_.size())
.closeTag();
}
}
void Foam::vtk::surfaceMeshWriter::writePoints()
{
const uint64_t payLoad = (pp_.nPoints()*3*sizeof(float));
if (legacy_)
{
legacy::beginPoints(os_, pp_.nPoints());
}
else
{
format().tag(vtk::fileTag::POINTS)
.openDataArray<float, 3>(vtk::dataArrayAttr::POINTS)
.closeTag();
}
format().writeSize(payLoad);
vtk::writeList(format(), pp_.localPoints());
format().flush();
if (!legacy_)
{
format()
.endDataArray()
.endTag(vtk::fileTag::POINTS);
}
}
void Foam::vtk::surfaceMeshWriter::writePolysLegacy()
{
// connectivity count without additional storage (done internally)
uint64_t nConnectivity = 0;
forAll(pp_, facei)
{
nConnectivity += pp_[facei].size();
}
legacy::beginPolys(os_, pp_.size(), nConnectivity);
// legacy: size + connectivity together
// [nPts, id1, id2, ..., nPts, id1, id2, ...]
forAll(pp_, facei)
{
const face& f = pp_.localFaces()[facei];
format().write(f.size()); // The size prefix
vtk::writeList(format(), f);
}
format().flush();
}
void Foam::vtk::surfaceMeshWriter::writePolys()
{
//
// 'connectivity'
//
format().tag(vtk::fileTag::POLYS);
//
// 'connectivity'
//
{
// payload count
uint64_t payLoad = 0;
forAll(pp_, facei)
{
payLoad += pp_[facei].size();
}
format().openDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY)
.closeTag();
// payload size
format().writeSize(payLoad * sizeof(label));
forAll(pp_, facei)
{
const face& f = pp_.localFaces()[facei];
vtk::writeList(format(), f);
}
format().flush();
format()
.endDataArray();
}
//
// 'offsets' (connectivity offsets)
//
{
format()
.openDataArray<label>(vtk::dataArrayAttr::OFFSETS)
.closeTag();
// payload size
format().writeSize(pp_.size() * sizeof(label));
label off = 0;
forAll(pp_, facei)
{
off += pp_[facei].size();
format().write(off);
}
format().flush();
format().endDataArray();
}
format().endTag(vtk::fileTag::POLYS);
}
void Foam::vtk::surfaceMeshWriter::writeMesh()
{
writePoints();
if (legacy_)
{
writePolysLegacy();
}
else
{
writePolys();
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::vtk::surfaceMeshWriter::surfaceMeshWriter
(
const indirectPrimitivePatch& pp,
const word& name,
const fileName& baseName,
const vtk::outputOptions outOpts
)
:
pp_(pp),
legacy_(outOpts.legacy()),
format_(),
os_()
{
outputOptions opts(outOpts);
opts.legacy(true); // No append supported
os_.open((baseName + (legacy_ ? ".vtk" : ".vtp")).c_str());
format_ = opts.newFormatter(os_);
if (legacy_)
{
legacy::fileHeader(format(), name, vtk::fileTag::POLY_DATA);
}
else
{
// XML (inline)
format()
.xmlHeader()
.xmlComment(name)
.beginVTKFile(vtk::fileTag::POLY_DATA, "0.1");
}
beginPiece();
writeMesh();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::vtk::surfaceMeshWriter::~surfaceMeshWriter()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtk::surfaceMeshWriter::beginCellData(label nFields)
{
if (legacy_)
{
legacy::dataHeader(os(), vtk::fileTag::CELL_DATA, pp_.size(), nFields);
}
else
{
format().tag(vtk::fileTag::CELL_DATA);
}
}
void Foam::vtk::surfaceMeshWriter::endCellData()
{
if (!legacy_)
{
format().endTag(vtk::fileTag::CELL_DATA);
}
}
void Foam::vtk::surfaceMeshWriter::writeFooter()
{
if (!legacy_)
{
// slight cheat. </Piece> too
format().endTag(vtk::fileTag::PIECE);
format().endTag(vtk::fileTag::POLY_DATA)
.endVTKFile();
}
}
// ************************************************************************* //

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -22,48 +22,78 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::surfaceMeshWriter
Foam::vtk::surfaceMeshWriter
Description
Write faces with fields
SourceFiles
surfaceMeshWriter.C
surfaceMeshWriterTemplates.C
foamVtkSurfaceMeshWriter.C
foamVtkSurfaceMeshWriterTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef surfaceMeshWriter_H
#define surfaceMeshWriter_H
#ifndef foamVtkSurfaceMeshWriter_H
#define foamVtkSurfaceMeshWriter_H
#include "pointMesh.H"
#include "OFstream.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "indirectPrimitivePatch.H"
#include "foamVtkOutputOptions.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class volPointInterpolation;
namespace vtk
{
/*---------------------------------------------------------------------------*\
Class surfaceMeshWriter Declaration
\*---------------------------------------------------------------------------*/
class surfaceMeshWriter
{
const bool binary_;
// Private Member Data
const indirectPrimitivePatch& pp_;
const fileName fName_;
//- Commonly used query
const bool legacy_;
autoPtr<vtk::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:
// Constructors
@ -71,47 +101,81 @@ public:
//- Construct from components
surfaceMeshWriter
(
const bool binary,
const indirectPrimitivePatch& pp,
const word& name,
const fileName&
const fileName& baseName,
const vtk::outputOptions outOpts
);
//- Destructor
~surfaceMeshWriter();
// Member Functions
std::ofstream& os()
inline std::ofstream& os()
{
return os_;
}
//- Extract face data
inline vtk::formatter& format()
{
return format_();
}
//- Open write for CellData of count fields.
// The parameters are only used for the legacy format.
void beginCellData(label nFields);
//- Close write for CellData
void endCellData();
//- Write file footer
void writeFooter();
//- Get face field (internal face or boundary face)
template<class Type>
tmp<Field<Type>> getFaceField
(
const GeometricField<Type, fvsPatchField, surfaceMesh>&
const GeometricField<Type, fvsPatchField, surfaceMesh>& sfld
) const;
//- Write surfaceFields
// Write fields (individually)
//- Write surface field
template<class Type>
void write
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& field
);
// Write fields (collectively)
//- Write surface fields
template<class Type>
void write
(
const UPtrList
<
const GeometricField<Type, fvsPatchField, surfaceMesh>
>&
>& sflds
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace vtk
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "surfaceMeshWriterTemplates.C"
#include "foamVtkSurfaceMeshWriterTemplates.C"
#endif

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.
@ -23,14 +23,13 @@ License
\*---------------------------------------------------------------------------*/
#include "surfaceMeshWriter.H"
#include "writeFuns.H"
#include "foamVtkSurfaceMeshWriter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::surfaceMeshWriter::getFaceField
Foam::vtk::surfaceMeshWriter::getFaceField
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& sfld
) const
@ -42,9 +41,8 @@ Foam::surfaceMeshWriter::getFaceField
forAll(pp_.addressing(), i)
{
label facei = pp_.addressing()[i];
label patchi = patches.whichPatch(facei);
const label facei = pp_.addressing()[i];
const label patchi = patches.whichPatch(facei);
if (patchi == -1)
{
@ -52,7 +50,7 @@ Foam::surfaceMeshWriter::getFaceField
}
else
{
label localFacei = facei - patches[patchi].start();
const label localFacei = facei - patches[patchi].start();
fld[i] = sfld.boundaryField()[patchi][localFacei];
}
}
@ -62,7 +60,38 @@ Foam::surfaceMeshWriter::getFaceField
template<class Type>
void Foam::surfaceMeshWriter::write
void Foam::vtk::surfaceMeshWriter::write
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& field
)
{
const int nCmpt(pTraits<Type>::nComponents);
const uint64_t payLoad(pp_.size() * nCmpt * sizeof(float));
if (legacy_)
{
legacy::floatField(os(), field.name(), nCmpt, pp_.size());
}
else
{
format().openDataArray<float, nCmpt>(field.name())
.closeTag();
}
format().writeSize(payLoad);
vtk::writeList(format(), getFaceField(field)());
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
template<class Type>
void Foam::vtk::surfaceMeshWriter::write
(
const UPtrList
<
@ -70,18 +99,9 @@ void Foam::surfaceMeshWriter::write
>& sflds
)
{
forAll(sflds, fieldi)
for (const auto& field : sflds)
{
const GeometricField<Type, fvsPatchField, surfaceMesh>& fld =
sflds[fieldi];
os_ << fld.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< pp_.size() << " float" << std::endl;
DynamicList<floatScalar> fField(pTraits<Type>::nComponents*pp_.size());
writeFuns::insert(getFaceField(fld)(), fField);
writeFuns::write(os_, binary_, fField);
write(field);
}
}

View File

@ -0,0 +1,172 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkWriteSurfFields.H"
#include "OFstream.H"
#include "emptyFvsPatchFields.H"
#include "fvsPatchFields.H"
#include "surfaceFields.H"
#include "foamVtkOutput.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
void Foam::vtk::writeSurfFields
(
const fvMesh& mesh,
const fileName& baseName,
const vtk::outputOptions outOpts,
const UPtrList<const surfaceVectorField>& surfVectorFields
)
{
outputOptions opts(outOpts);
opts.append(false); // No append supported
const bool legacy_(opts.legacy());
std::ofstream os((baseName + (legacy_ ? ".vtk" : ".vtp")).c_str());
autoPtr<vtk::formatter> format = opts.newFormatter(os);
// Same payload size for points and vector fields!
const int nCmpt(3); // vector
const uint64_t payLoad(mesh.nFaces() * 3 * sizeof(float));
if (legacy_)
{
legacy::fileHeader(format(), "surfaceFields", vtk::fileTag::POLY_DATA);
legacy::beginPoints(os, mesh.nFaces());
}
else
{
// XML (inline)
format()
.xmlHeader()
.xmlComment("surfaceFields")
.beginVTKFile(vtk::fileTag::POLY_DATA, "0.1");
// Tricky - hide in beginPiece()
format()
.openTag(vtk::fileTag::PIECE)
.xmlAttr(vtk::fileAttr::NUMBER_OF_POINTS, mesh.nFaces())
.closeTag();
format().tag(vtk::fileTag::POINTS)
.openDataArray<float,3>(vtk::dataArrayAttr::POINTS)
.closeTag();
}
const pointField& fc = mesh.faceCentres();
format().writeSize(payLoad);
vtk::writeList(format(), fc);
format().flush();
if (!legacy_)
{
format()
.endDataArray()
.endTag(vtk::fileTag::POINTS);
}
// Fields
if (legacy_)
{
legacy::dataHeader
(
os,
vtk::fileTag::POINT_DATA,
mesh.nFaces(),
surfVectorFields.size()
);
}
else
{
format().tag(vtk::fileTag::POINT_DATA);
}
// surfVectorFields
forAll(surfVectorFields, fieldi)
{
const auto& fld = surfVectorFields[fieldi];
if (legacy_)
{
legacy::floatField(os, fld.name(), nCmpt, mesh.nFaces());
}
else
{
format().openDataArray<float, nCmpt>(fld.name())
.closeTag();
}
format().writeSize(payLoad);
for (label facei=0; facei < mesh.nInternalFaces(); ++facei)
{
vtk::write(format(), fld[facei]);
}
forAll(fld.boundaryField(), patchi)
{
const fvPatch& pp = mesh.boundary()[patchi];
const auto& pf = fld.boundaryField()[patchi];
if (isA<emptyFvsPatchVectorField>(pf))
{
// Note: loop over polypatch size, not fvpatch size.
forAll(pp.patch(), i)
{
vtk::write(format(), vector::zero);
}
}
else
{
vtk::writeList(format(), pf);
}
}
format().flush();
if (!legacy_)
{
format().endDataArray();
}
}
if (!legacy_)
{
format().endTag(vtk::fileTag::POINT_DATA);
// slight cheat. </Piece> too
format().endTag(vtk::fileTag::PIECE);
format().endTag(vtk::fileTag::POLY_DATA)
.endVTKFile();
}
}
// ************************************************************************* //

View File

@ -21,38 +21,42 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
InClass
Foam::writeSurfFields
InNamespace
Foam::vtk
Description
Write a patch with its data.
Write surface fields as vectors
SourceFiles
writeSurfFields.C
foamVtkWriteSurfFields.C
\*---------------------------------------------------------------------------*/
#ifndef writeSurfFields_H
#define writeSurfFields_H
#ifndef foamVtkWriteSurfFields_H
#define foamVtkWriteSurfFields_H
#include "fvMesh.H"
#include "surfaceMesh.H"
#include "surfaceFieldsFwd.H"
#include "foamVtkOutputOptions.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace vtk
{
// Write surface vector fields
//- Write surface vector fields
void writeSurfFields
(
const bool binary,
const fvMesh&,
const fileName& fileName,
const fvMesh& mesh,
const fileName& baseName,
const vtk::outputOptions outOpts,
const UPtrList<const surfaceVectorField>& surfVectorFields
);
} // End namespace vtk
} // End namespace Foam

View File

@ -1,649 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkCells.H"
#include "polyMesh.H"
#include "cellShape.H"
#include "cellModeller.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::foamVtkCells::correct()
{
// Clear derived data
// clearGeom();
const cellModel& tet = *(cellModeller::lookup("tet"));
const cellModel& pyr = *(cellModeller::lookup("pyr"));
const cellModel& prism = *(cellModeller::lookup("prism"));
const cellModel& wedge = *(cellModeller::lookup("wedge"));
const cellModel& tetWedge = *(cellModeller::lookup("tetWedge"));
const cellModel& hex = *(cellModeller::lookup("hex"));
const cellShapeList& cellShapes = mesh_.cellShapes();
// face owner is needed to determine the face orientation
const labelList& owner = mesh_.faceOwner();
// Unique vertex labels per polyhedral
HashSet<label> hashUniqId(2*256);
// =======================
// PASS 1: Determine sizes
label nVertLabels = 0;
label nFaceLabels = 0;
label nAddPoints = 0;
label nAddCells = 0;
label nAddVerts = 0;
forAll(cellShapes, cellI)
{
const cellShape& shape = cellShapes[cellI];
const cellModel& model = shape.model();
if
(
model == tet
|| model == pyr
|| model == prism
|| model == hex
)
{
// normal primitives
nVertLabels += shape.size();
}
else if (model == tetWedge && decompose_.requested())
{
// Treat as squeezed prism (VTK_WEDGE)
nVertLabels += 6;
}
else if (model == wedge && decompose_.requested())
{
// Treat as squeezed hex
nVertLabels += 8;
}
else if (decompose_.requested())
{
// Polyhedral: Decompose into tets + pyramids.
// Count vertices in first decomposed cell
bool first = true;
const cell& cFaces = mesh_.cells()[cellI];
forAll(cFaces, cFaceI)
{
const face& f = mesh_.faces()[cFaces[cFaceI]];
// Face decomposed into triangles and quads
// Tri -> Tet, Quad -> Pyr
label nTria = 0, nQuad = 0;
f.nTrianglesQuads(mesh_.points(), nTria, nQuad);
nAddCells += nTria + nQuad;
nAddVerts += (nTria * 4) + (nQuad * 5);
if (first)
{
const label nvrt = (nQuad ? 5 : 4);
nAddCells--;
nAddVerts -= nvrt;
nVertLabels += nvrt;
first = false;
}
}
++nAddPoints;
}
else
{
// Polyhedral: Not decomposed.
const labelList& cFaces = mesh_.cells()[cellI];
// establish unique node ids used (only needed for XML)
hashUniqId.clear();
// determing sizing for face stream
// number of faces, size of each face, vertices per face
// [nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...]
forAll(cFaces, cFaceI)
{
const face& f = mesh_.faces()[cFaces[cFaceI]];
nFaceLabels += f.size();
forAll(f, fp)
{
hashUniqId.insert(f[fp]);
}
}
nVertLabels += hashUniqId.size();
nFaceLabels += 1 + cFaces.size();
}
}
//
// adjust/reserve sizes
//
// Cell types (including added cells) in vtk numbering
cellTypes_.setSize(cellShapes.size() + nAddCells);
// List of vertex labels in VTK ordering
vertLabels_.setSize(nVertLabels + nAddVerts);
vertOffset_.setSize(cellShapes.size() + nAddCells);
faceLabels_.clear();
faceOffset_.clear();
if (nFaceLabels)
{
faceLabels_.setSize(nFaceLabels);
// only need nCells (without nAddCells)
// set to -1 (primitive)
faceOffset_.setSize(cellShapes.size(), -1);
}
if (decompose_.requested())
{
decompose_.addPointCellLabels_.setSize(nAddPoints);
decompose_.superCells_.setSize(nAddCells);
}
// ======================
// PASS 2: Fill in arrays
// Need this offset later, but only for decomposed polys
const label offsetAddVerts = nVertLabels;
// Reset counters
nVertLabels = 0;
nFaceLabels = 0;
nAddPoints = 0;
nAddCells = 0;
nAddVerts = 0;
forAll(cellShapes, cellI)
{
const cellShape& shape = cellShapes[cellI];
const cellModel& model = shape.model();
if (model == tet)
{
cellTypes_[cellI] = foamVtkCore::VTK_TETRA;
forAll(shape, i)
{
vertLabels_[nVertLabels++] = shape[i];
}
vertOffset_[cellI] = nVertLabels;
}
else if (model == pyr)
{
cellTypes_[cellI] = foamVtkCore::VTK_PYRAMID;
forAll(shape, i)
{
vertLabels_[nVertLabels++] = shape[i];
}
vertOffset_[cellI] = nVertLabels;
}
else if (model == hex)
{
cellTypes_[cellI] = foamVtkCore::VTK_HEXAHEDRON;
forAll(shape, i)
{
vertLabels_[nVertLabels++] = shape[i];
}
vertOffset_[cellI] = nVertLabels;
}
else if (model == prism)
{
cellTypes_[cellI] = foamVtkCore::VTK_WEDGE;
// VTK_WEDGE triangles point outwards (swap 1<->2, 4<->5)
vertLabels_[nVertLabels++] = shape[0];
vertLabels_[nVertLabels++] = shape[2];
vertLabels_[nVertLabels++] = shape[1];
vertLabels_[nVertLabels++] = shape[3];
vertLabels_[nVertLabels++] = shape[5];
vertLabels_[nVertLabels++] = shape[4];
vertOffset_[cellI] = nVertLabels;
}
else if (model == tetWedge && decompose_.requested())
{
// Treat as squeezed prism (VTK_WEDGE)
cellTypes_[cellI] = foamVtkCore::VTK_WEDGE;
vertLabels_[nVertLabels++] = shape[0];
vertLabels_[nVertLabels++] = shape[2];
vertLabels_[nVertLabels++] = shape[1];
vertLabels_[nVertLabels++] = shape[3];
vertLabels_[nVertLabels++] = shape[4];
vertLabels_[nVertLabels++] = shape[3];
vertOffset_[cellI] = nVertLabels;
}
else if (model == wedge && decompose_.requested())
{
// Treat as squeezed hex
cellTypes_[cellI] = foamVtkCore::VTK_HEXAHEDRON;
vertLabels_[nVertLabels++] = shape[0];
vertLabels_[nVertLabels++] = shape[1];
vertLabels_[nVertLabels++] = shape[2];
vertLabels_[nVertLabels++] = shape[2];
vertLabels_[nVertLabels++] = shape[3];
vertLabels_[nVertLabels++] = shape[4];
vertLabels_[nVertLabels++] = shape[5];
vertLabels_[nVertLabels++] = shape[6];
vertOffset_[cellI] = nVertLabels;
}
else if (decompose_.requested())
{
// Polyhedral cell - decompose into tet/pyr.
// Ensure we have the correct orientation for the base of the
// primitive cell shape.
// If the cell is face owner, the orientation needs to be flipped
// to avoid defining negative cells.
// VTK doesn't seem to care, but we'll do it anyhow for safety.
// The new vertex from the cell-centre
const label newVertexLabel = mesh_.nPoints() + nAddPoints;
// Mapping from additional point to cell
decompose_.addPointCellLabels_[nAddPoints++] = cellI;
// Whether to insert cell in place of original or not.
bool first = true;
const labelList& cFaces = mesh_.cells()[cellI];
forAll(cFaces, cFaceI)
{
const face& f = mesh_.faces()[cFaces[cFaceI]];
const bool isOwner = (owner[cFaces[cFaceI]] == cellI);
// Count triangles/quads in decomposition
label nTria = 0;
label nQuad = 0;
f.nTrianglesQuads(mesh_.points(), nTria, nQuad);
// Do actual decomposition
faceList faces3(nTria);
faceList faces4(nQuad);
nTria = 0, nQuad = 0;
f.trianglesQuads(mesh_.points(), nTria, nQuad, faces3, faces4);
forAll(faces4, fci)
{
const face& quad = faces4[fci];
label celLoc;
label vrtLoc;
if (first)
{
celLoc = cellI;
vrtLoc = nVertLabels;
nVertLabels += 5;
vertOffset_[celLoc] = nVertLabels;
first = false;
}
else
{
celLoc = mesh_.nCells() + nAddCells;
vrtLoc = offsetAddVerts + nAddVerts;
nAddVerts += 5;
vertOffset_[celLoc] = nAddVerts;
decompose_.superCells_[nAddCells++] = cellI;
}
cellTypes_[celLoc] = foamVtkCore::VTK_PYRAMID;
// See note above about the orientation.
if (isOwner)
{
vertLabels_[vrtLoc++] = quad[3];
vertLabels_[vrtLoc++] = quad[2];
vertLabels_[vrtLoc++] = quad[1];
vertLabels_[vrtLoc++] = quad[0];
}
else
{
vertLabels_[vrtLoc++] = quad[0];
vertLabels_[vrtLoc++] = quad[1];
vertLabels_[vrtLoc++] = quad[2];
vertLabels_[vrtLoc++] = quad[3];
}
vertLabels_[vrtLoc++] = newVertexLabel;
}
forAll(faces3, fci)
{
const face& tria = faces3[fci];
label celLoc;
label vrtLoc;
if (first)
{
celLoc = cellI;
vrtLoc = nVertLabels;
nVertLabels += 4;
vertOffset_[celLoc] = nVertLabels;
first = false;
}
else
{
celLoc = mesh_.nCells() + nAddCells;
vrtLoc = offsetAddVerts + nAddVerts;
nAddVerts += 4;
vertOffset_[celLoc] = nAddVerts;
decompose_.superCells_[nAddCells++] = cellI;
}
cellTypes_[celLoc] = foamVtkCore::VTK_TETRA;
// See note above about the orientation.
if (isOwner)
{
vertLabels_[vrtLoc++] = tria[2];
vertLabels_[vrtLoc++] = tria[1];
vertLabels_[vrtLoc++] = tria[0];
}
else
{
vertLabels_[vrtLoc++] = tria[0];
vertLabels_[vrtLoc++] = tria[1];
vertLabels_[vrtLoc++] = tria[2];
}
vertLabels_[vrtLoc++] = newVertexLabel;
}
}
}
else
{
// Polyhedral cell - not decomposed
hashUniqId.clear(); // unique node ids used (only needed for XML)
// face-stream
// [nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...]
cellTypes_[cellI] = foamVtkCore::VTK_POLYHEDRON;
const labelList& cFaces = mesh_.cells()[cellI];
faceLabels_[nFaceLabels++] = cFaces.size();
forAll(cFaces, cFaceI)
{
const face& f = mesh_.faces()[cFaces[cFaceI]];
const bool isOwner = (owner[cFaces[cFaceI]] == cellI);
forAll(f, fp)
{
hashUniqId.insert(f[fp]);
}
// number of labels for this face
faceLabels_[nFaceLabels++] = f.size();
if (isOwner)
{
forAll(f, fp)
{
faceLabels_[nFaceLabels++] = f[fp];
}
}
else
{
// fairly immaterial if we reverse the list
// or use face::reverseFace()
forAllReverse(f, fp)
{
faceLabels_[nFaceLabels++] = f[fp];
}
}
}
faceOffset_[cellI] = nFaceLabels;
const labelList uniq = hashUniqId.sortedToc();
forAll(uniq, i)
{
vertLabels_[nVertLabels++] = uniq[i];
}
vertOffset_[cellI] = nVertLabels;
}
}
// ===========================================
// PASS 3: Repair offsets for additional cells
// Info<<"vertOffset: " << vertOffset_.size() << " VS. " << (mesh_.nCells()) << endl;
// Info<<"nAddCells: " << nAddCells << " VS. " << (mesh_.nCells()) << endl;
if (nAddCells)
{
const label beg = mesh_.nCells();
const label add = vertOffset_[beg-1];
for (label i = beg; i < vertOffset_.size(); ++i)
{
vertOffset_[i] += add;
}
}
// Some basic programming/sanity checks
if ((nVertLabels + nAddVerts) != vertOffset_[mesh_.nCells()-1 + nAddCells])
{
WarningInFunction
<< "predicted offsets (" << nVertLabels << " + " << nAddVerts << ") != "
<< vertOffset_[mesh_.nCells()-1 + nAddCells]
<< endl;
}
if (offsetAddVerts != vertOffset_[mesh_.nCells()-1])
{
WarningInFunction
<< "predicted regular offset " << offsetAddVerts
<< " != " << vertOffset_[mesh_.nCells()]
<< endl;
}
// nFaceLabels = 0;
// nAddPoints = 0;
// nAddCells = 0;
// Pout<<"vertLabels: " << vertLabels_.size() << " vs. " << (nVertLabels + nAddVerts) << endl;
// Pout<<"faceLabels: " << faceLabels_.size() << " vs. " << nFaceLabels << endl;
#if 0
if (decompose_.requested())
{
Pout<< " Original cells:" << mesh_.nCells()
<< " points:" << mesh_.nPoints()
<< " Additional cells:" << decompose_.superCells_.size()
<< " additional points:" << decompose_.addPointCellLabels_.size()
<< nl << endl;
}
#endif
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::foamVtkCells::decomp::decomp(const bool decomposePoly)
:
addPointCellLabels_(),
superCells_(),
pointMap_(),
requested_(decomposePoly)
{}
Foam::foamVtkCells::foamVtkCells
(
const polyMesh& mesh,
const bool decomposePoly,
const bool lazy
)
:
mesh_(mesh),
cellTypes_(),
vertLabels_(),
vertOffset_(),
faceLabels_(),
faceOffset_(),
decompose_(decomposePoly),
needsUpdate_(true)
{
if (!lazy)
{
correct();
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::foamVtkCells::decomp::~decomp()
{}
Foam::foamVtkCells::~foamVtkCells()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::foamVtkCells::decomp::clear()
{
superCells_.clear();
addPointCellLabels_.clear();
pointMap_.clear();
}
Foam::label Foam::foamVtkCells::nFieldPoints() const
{
return mesh_.nPoints() + decompose_.addPointCellLabels_.size();
}
Foam::label Foam::foamVtkCells::legacyCellPayLoad() const
{
label payLoad = cellTypes_.size();
if (faceOffset_.size())
{
// also has polys with face streams
label begVert = 0;
label begFace = 0;
forAll(faceOffset_, i)
{
label endFace = faceOffset_[i];
label endVert = vertOffset_[i];
if (endFace > 0)
{
// poly with face stream
payLoad += endFace - begFace;
begFace = endFace;
}
else
{
// primitive without face stream
payLoad += endVert - begVert;
}
begVert = endVert;
}
}
else if (vertOffset_.size())
{
// primitives only, trivial
payLoad += vertOffset_[vertOffset_.size()-1];
}
return payLoad;
}
bool Foam::foamVtkCells::needsUpdate() const
{
return needsUpdate_;
}
bool Foam::foamVtkCells::expire()
{
// Clear any stored topologies
// Clear derived data
// clearGeom();
// already marked as expired
if (needsUpdate_)
{
return false;
}
needsUpdate_ = true;
return true;
}
bool Foam::foamVtkCells::update()
{
if (!needsUpdate_)
{
return false;
}
correct();
needsUpdate_ = false;
return true;
}
// ************************************************************************* //

View File

@ -1,350 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::foamVtkCells
Description
The deep-copy description of an OpenFOAM volume mesh in data structures
corresponding to an VTK UnstructuredGrid, including the possiblity of
decomposing polyhedral cells into primitive cell types.
Knowledge of the vtkUnstructuredGrid and the corresponding \c .vtu
xml file-format aids in understanding this class.
For flexibilty, support for the legacy vtk file-format is also provided.
Primitive cell types are straighforward, polyhedral cells are represented
by a face stream:
\verbatim
[nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...]
\endverbatim
For the legacy format, the face stream is simply passed as vertex labels
(connectivity).
For the xml format, the face stream is saved separately:
\verbatim
"connectivity"
== the unique vertex labels used by the cell (optionally sorted).
"offsets":
== offset + sizeof(connectivity)
"faces":
[nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...]
"faceoffsets":
== faceoffsets + sizeof(faces)
\endverbatim
The storage of "connectivity" and "offsets" strongly resembles a
CompactListList, but the "offsets" point to the end of the respective
sub-lists.
SourceFiles
foamVtkCells.C
\*---------------------------------------------------------------------------*/
#ifndef foamVtkCells_H
#define foamVtkCells_H
#include "foamVtkCore.H"
#include "DynamicList.H"
#include "SubList.H"
#include "labelList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class polyMesh;
/*---------------------------------------------------------------------------*\
Class foamVtkCells Declaration
\*---------------------------------------------------------------------------*/
class foamVtkCells
:
public fileFormats::foamVtkCore
{
public:
//- Bookkeeping for polyhedral cell decomposition
class decomp
{
private:
friend foamVtkCells;
// Private data
//- Cell-centre labels for additional points of decomposed cells
DynamicList<label> addPointCellLabels_;
//- Label of original cell for decomposed cells
DynamicList<label> superCells_;
//- Point labels for subsetted meshes
DynamicList<label> pointMap_;
//- Track if decomposition was requested
const bool requested_;
// Private Member Functions
//- Disallow default bitwise copy construct
decomp(const decomp&) = delete;
//- Disallow default bitwise assignment
void operator=(const decomp&) = delete;
public:
// Constructors
//- Construct null
decomp(const bool decomposePoly = false);
//- Destructor
~decomp();
// Member Functions
// Access
//- Polyhedral decomposition requested
inline bool requested() const;
//- Polyhedral decomposition used
inline bool used() const;
//- Label of original cell for decomposed cells
inline const labelList& superCells() const;
//- Cell-centre labels for additional points of decomposed cells
inline const labelList& addPointCellLabels() const;
//- Point labels for subsetted meshes
inline const labelList& pointMap() const;
// Edit
//- Clear
void clear();
};
private:
// Private data
//- Reference to underlying mesh or mesh sub-set
const polyMesh& mesh_;
//- Cell types (including added cells) in vtk numbering
// Range is 1-255
List<uint8_t> cellTypes_;
//- Vertices per cell (including added cells) in vtk ordering
DynamicList<label> vertLabels_;
//- Vertices per cell (including added cells) in vtk ordering
DynamicList<label> vertOffset_;
//- Face lists per polyhedral cell
DynamicList<label> faceLabels_;
//- Face label offsets
DynamicList<label> faceOffset_;
//- Bookkeeping for polyhedral cell decomposition
decomp decompose_;
//- Needs update
bool needsUpdate_;
// Private Member Functions
//- Create the geometry
void correct();
//- Disallow default bitwise copy construct
foamVtkCells(const foamVtkCells&) = delete;
//- Disallow default bitwise assignment
void operator=(const foamVtkCells&) = delete;
public:
// Constructors
//- Construct from components.
// Optionally with polyhedral decomposition and/or lazy evaluation.
// A 'lazy' evaluation avoids fully creation within the constructor.
foamVtkCells
(
const polyMesh&,
const bool decomposePoly = false,
const bool lazy = false
);
//- Destructor
~foamVtkCells();
// Member Functions
// Access
//- Query the poly decompose flag.
inline bool decomposeRequested() const;
//- Values for "connectivity" (XML) or basis for "CELLS" (legacy)
// In the legacy format, the size (offset) must be prefixed.
inline const labelList& vertLabels() const;
//- Values for "offsets" (XML)
// or sizes to prefix for for "CELLS" (legacy)
inline const labelList& vertOffsets() const;
//- Values for "types" (XML) and "CELL_TYPES" (legacy)
inline const List<uint8_t>& cellTypes() const;
//- Values for "faces" (XML)
inline const labelList& faceLabels() const;
//- Values for "faceoffsets" (XML)
inline const labelList& faceOffsets() const;
//- Additional point addressing (from added point to original cell)
inline const labelList& addPointCellLabels() const;
//- Additional cells mapping (from added cell to original cell)
inline const labelList& superCells() const;
//- Number of field cells
inline label nFieldCells() const;
//- Number of field points
label nFieldPoints() const;
//- The field size for legacy "CELLS".
// In the legacy format, the size (offset) must be prefixed.
label legacyCellPayLoad() const;
//- Does the mapping need an update?
bool needsUpdate() const;
//- Mark as needing an update.
// May also free up unneeded data.
// Return false if it was already marked as expired.
bool expire();
//- Update the description (and decomposition) as required.
// Do nothing (and return false) if no update was required
bool update();
//- The const_iterator for foamVtkCells
class const_iterator
{
friend class foamVtkCells;
protected:
// Protected Data
//- Reference to parent list
const foamVtkCells& parent_;
//- Element index
label index_;
//- Begin of connectivity sub-list
mutable label begVert_;
//- Begin of faces sub-list
mutable label begFace_;
//- On-demand legacy pointer
mutable autoPtr<SubList<label>> legacy_;
// Constructors
//- Construct begin/end iterator
inline const_iterator
(
const foamVtkCells&,
bool isEnd = false
);
public:
// Member operators
//- On-demand legacy cell labels (primitive or faces)
inline const labelUList& legacyCell() const;
//- Compare position
inline bool operator!=(const const_iterator&) const;
//- Pre-increment iterator
inline const_iterator& operator++();
};
//- const_iterator set to the beginning
inline const_iterator begin() const;
//- const_iterator set to beyond the end
inline const_iterator end() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "foamVtkCellsI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,239 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkCells.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
inline bool Foam::foamVtkCells::decomp::requested() const
{
return requested_;
}
inline bool Foam::foamVtkCells::decomp::used() const
{
return !superCells_.empty();
}
inline const Foam::labelList&
Foam::foamVtkCells::decomp::superCells() const
{
return superCells_;
}
inline const Foam::labelList&
Foam::foamVtkCells::decomp::addPointCellLabels() const
{
return addPointCellLabels_;
}
inline const Foam::labelList&
Foam::foamVtkCells::decomp::pointMap() const
{
return pointMap_;
}
inline bool Foam::foamVtkCells::decomposeRequested() const
{
return decompose_.requested();
}
inline const Foam::labelList&
Foam::foamVtkCells::vertLabels() const
{
return vertLabels_;
}
inline const Foam::labelList&
Foam::foamVtkCells::vertOffsets() const
{
return vertOffset_;
}
inline const Foam::List<uint8_t>&
Foam::foamVtkCells::cellTypes() const
{
return cellTypes_;
}
inline const Foam::labelList&
Foam::foamVtkCells::faceLabels() const
{
return faceLabels_;
}
inline const Foam::labelList&
Foam::foamVtkCells::faceOffsets() const
{
return faceOffset_;
}
inline const Foam::labelList&
Foam::foamVtkCells::addPointCellLabels() const
{
return decompose_.addPointCellLabels();
}
inline const Foam::labelList&
Foam::foamVtkCells::superCells() const
{
return decompose_.superCells();
}
inline Foam::label
Foam::foamVtkCells::nFieldCells() const
{
return cellTypes_.size();
}
inline Foam::foamVtkCells::const_iterator
Foam::foamVtkCells::begin() const
{
return const_iterator(*this);
}
inline Foam::foamVtkCells::const_iterator
Foam::foamVtkCells::end() const
{
return const_iterator(*this, true);
}
// * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * //
inline Foam::foamVtkCells::const_iterator::const_iterator
(
const foamVtkCells& cells,
bool isEnd
)
:
parent_(cells),
index_(0),
begVert_(0),
begFace_(0),
legacy_()
{
if (isEnd)
{
index_ = parent_.vertOffsets().size();
}
}
inline
Foam::foamVtkCells::const_iterator&
Foam::foamVtkCells::const_iterator::operator++()
{
++index_;
legacy_.clear();
return *this;
}
inline
const Foam::UList<Foam::label>&
Foam::foamVtkCells::const_iterator::legacyCell() const
{
if
(
legacy_.valid()
|| index_ >= parent_.vertOffsets().size()
)
{
return legacy_();
}
const label endVert = parent_.vertOffsets()[index_];
const label endFace =
(
parent_.faceOffsets().size()
? parent_.faceOffsets()[index_]
: -1
);
if (endFace > 0)
{
// poly with face stream
legacy_.reset
(
new SubList<label>
(
parent_.faceLabels(),
endFace - begFace_,
begFace_
)
);
begFace_ = endFace;
}
else
{
// primitive without face stream
legacy_.reset
(
new SubList<label>
(
parent_.vertLabels(),
endVert - begVert_,
begVert_
)
);
}
begVert_ = endVert;
return legacy_();
}
inline bool
Foam::foamVtkCells::const_iterator::operator!=
(
const const_iterator& rhs
) const
{
return (index_ != rhs.index_);
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -23,33 +23,21 @@ License
\*---------------------------------------------------------------------------*/
inline bool Foam::foamVtkOutputOptions::legacy() const
#include "foamVtkMeshMaps.H"
#include "ListOps.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::foamVtkMeshMaps::renumberCells(const UList<label>& mapping)
{
return (type_ & LEGACY);
inplaceRenumber(mapping, cellMap_);
inplaceRenumber(mapping, additionalIds_);
}
inline bool Foam::foamVtkOutputOptions::xml() const
void Foam::foamVtkMeshMaps::renumberPoints(const UList<label>& mapping)
{
return !legacy();
}
inline bool Foam::foamVtkOutputOptions::append() const
{
return (type_ & APPEND);
}
inline bool Foam::foamVtkOutputOptions::insitu() const
{
return !(type_ & APPEND);
}
inline bool Foam::foamVtkOutputOptions::ascii() const
{
return !(type_ & (BINARY | BASE64));
inplaceRenumber(mapping, pointMap_);
}

View File

@ -0,0 +1,143 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::foamVtkMeshMaps
Description
Bookkeeping for mesh subsetting and/or polyhedral cell decomposition.
Although the main use case is for handling vtk meshes, it is not specific
to VTK alone.
The cellMap is a local-to-global lookup for normal and decomposed cells.
The pointMap is an optional local-to-global lookup for point ids.
The additional ids is typically used to store the cell-centre labels
for additional points of decomposed cells
SourceFiles
foamVtkMeshMapsI.H
\*---------------------------------------------------------------------------*/
#ifndef foamVtkMeshMaps_H
#define foamVtkMeshMaps_H
#include "DynamicList.H"
#include "labelList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class foamVtkMeshMaps Declaration
\*---------------------------------------------------------------------------*/
class foamVtkMeshMaps
{
// Private data
//- Original cell ids for all cells (regular and decomposed)
DynamicList<label> cellMap_;
//- Point labels for subsetted meshes
DynamicList<label> pointMap_;
//- Any additional (user) labels.
// Eg, cell-centre labels for additional points of decomposed cells
DynamicList<label> additionalIds_;
public:
// Constructors
//- Construct null
inline foamVtkMeshMaps(const label size = 0);
//- Destructor
inline ~foamVtkMeshMaps();
// Member Functions
// Access
//- Original cell ids for all cells (regular and decomposed).
// A regular mesh comprising only primitive cell types, this will just
// be an identity list. However, for subsetted meshes and decomposed
// cells this becomes a useful means of mapping from the original mesh.
inline const labelList& cellMap() const;
//- Point labels for subsetted meshes
inline const labelList& pointMap() const;
//- Any additional (user) labels.
// Eg, cell-centre labels for additional points of decomposed cells
inline const labelList& additionalIds() const;
// Edit
//- Clear
inline void clear();
//- Renumber cell ids (cellMap and additionalIds) to account for
// subset meshes
void renumberCells(const UList<label>& mapping);
//- Renumber point ids (pointMap) to account for subset meshes
void renumberPoints(const UList<label>& mapping);
//- Original cell ids for all cells (regular and decomposed).
// For a regular mesh comprising only primitive cell types, this
// will simply be an identity list. However, for subsetted meshes
// and decomposed cells this becomes a useful means of mapping from
// the original mesh.
inline DynamicList<label>& cellMap();
//- Point labels for subsetted meshes
inline DynamicList<label>& pointMap();
//- Any additional (user) labels.
// Eg, cell-centre labels for additional points of decomposed cells
inline DynamicList<label>& additionalIds();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "foamVtkMeshMapsI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -23,56 +23,73 @@ License
\*---------------------------------------------------------------------------*/
#include "surfaceMeshWriter.H"
#include "writeFuns.H"
#include "foamVtkMeshMaps.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::surfaceMeshWriter::surfaceMeshWriter
(
const bool binary,
const indirectPrimitivePatch& pp,
const word& name,
const fileName& fName
)
inline Foam::foamVtkMeshMaps::foamVtkMeshMaps(const label size)
:
binary_(binary),
pp_(pp),
fName_(fName),
os_(fName.c_str())
cellMap_(size),
pointMap_(size),
additionalIds_(size)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
inline Foam::foamVtkMeshMaps::~foamVtkMeshMaps()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline void Foam::foamVtkMeshMaps::clear()
{
// Write header
writeFuns::writeHeader(os_, binary_, name);
os_ << "DATASET POLYDATA" << std::endl;
// Write topology
label nFaceVerts = 0;
forAll(pp, facei)
{
nFaceVerts += pp[facei].size() + 1;
}
os_ << "POINTS " << pp.nPoints() << " float" << std::endl;
DynamicList<floatScalar> ptField(3*pp.nPoints());
writeFuns::insert(pp.localPoints(), ptField);
writeFuns::write(os_, binary, ptField);
cellMap_.clear();
pointMap_.clear();
additionalIds_.clear();
}
os_ << "POLYGONS " << pp.size() << ' ' << nFaceVerts << std::endl;
inline const Foam::labelList&
Foam::foamVtkMeshMaps::cellMap() const
{
return cellMap_;
}
DynamicList<label> vertLabels(nFaceVerts);
forAll(pp, facei)
{
const face& f = pp.localFaces()[facei];
inline Foam::DynamicList<Foam::label>&
Foam::foamVtkMeshMaps::cellMap()
{
return cellMap_;
}
vertLabels.append(f.size());
writeFuns::insert(f, vertLabels);
}
writeFuns::write(os_, binary_, vertLabels);
inline const Foam::labelList&
Foam::foamVtkMeshMaps::pointMap() const
{
return pointMap_;
}
inline Foam::DynamicList<Foam::label>&
Foam::foamVtkMeshMaps::pointMap()
{
return pointMap_;
}
inline const Foam::labelList&
Foam::foamVtkMeshMaps::additionalIds() const
{
return additionalIds_;
}
inline Foam::DynamicList<Foam::label>&
Foam::foamVtkMeshMaps::additionalIds()
{
return additionalIds_;
}

View File

@ -0,0 +1,186 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-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/>.
\*---------------------------------------------------------------------------*/
#include "polyMesh.H"
#include "foamVtuCells.H"
#include "foamVtkOutputOptions.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::vtk::vtuCells::vtuCells
(
const contentType output,
const bool decompose
)
:
vtk::vtuSizing(),
output_(output),
decomposeRequest_(decompose),
cellTypes_(),
vertLabels_(),
vertOffset_(),
faceLabels_(),
faceOffset_(),
maps_()
{}
Foam::vtk::vtuCells::vtuCells
(
const polyMesh& mesh,
const contentType output,
const bool decompose
)
:
vtuCells(output, decompose)
{
reset(mesh);
}
Foam::vtk::vtuCells::vtuCells
(
const vtk::outputOptions outOpts,
const bool decompose
)
:
vtuCells
(
(outOpts.legacy() ? contentType::LEGACY : contentType::XML),
decompose
)
{}
Foam::vtk::vtuCells::vtuCells
(
const polyMesh& mesh,
const vtk::outputOptions outOpts,
const bool decompose
)
:
vtuCells(outOpts, decompose)
{
reset(mesh);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::vtk::vtuCells::~vtuCells()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtk::vtuCells::clear()
{
vtuSizing::clear();
cellTypes_.clear();
vertLabels_.clear();
vertOffset_.clear();
faceLabels_.clear();
faceOffset_.clear();
maps_.clear();
}
void Foam::vtk::vtuCells::reset(const polyMesh& mesh)
{
vtuSizing::reset(mesh, decomposeRequest_);
cellTypes_.setSize(nFieldCells());
vertLabels_.setSize(sizeOf(output_, slotType::CELLS));
vertOffset_.setSize(sizeOf(output_, slotType::CELLS_OFFSETS));
faceLabels_.setSize(sizeOf(output_, slotType::FACES));
faceOffset_.setSize(sizeOf(output_, slotType::FACES_OFFSETS));
switch (output_)
{
case contentType::LEGACY:
populateLegacy
(
mesh,
cellTypes_,
vertLabels_,
maps_
);
break;
case contentType::XML:
populateXml
(
mesh,
cellTypes_,
vertLabels_,
vertOffset_,
faceLabels_,
faceOffset_,
maps_
);
break;
case contentType::INTERNAL:
populateInternal
(
mesh,
cellTypes_,
vertLabels_,
vertOffset_,
faceLabels_,
faceOffset_,
maps_
);
break;
}
}
void Foam::vtk::vtuCells::reset
(
const polyMesh& mesh,
const enum contentType output,
const bool decompose
)
{
output_ = output;
decomposeRequest_ = decompose;
reset(mesh);
}
void Foam::vtk::vtuCells::renumberCells(const UList<label>& mapping)
{
maps_.renumberCells(mapping);
}
void Foam::vtk::vtuCells::renumberPoints(const UList<label>& mapping)
{
maps_.renumberPoints(mapping);
}
// ************************************************************************* //

View File

@ -0,0 +1,242 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-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/>.
Class
Foam::vtk::vtuCells
Description
A deep-copy description of an OpenFOAM volume mesh in data structures
suitable for VTK UnstructuredGrid, including the possibility of
decomposing polyhedral cells into primitive cell types.
Knowledge of the vtkUnstructuredGrid and the corresponding \c .vtu
xml file-format aids in understanding this class.
The class can be used for the VTK xml format, legacy format, as well as a
VTK internal representation. The internal representation is somewhat
related to the xml format, but not entirely.
SeeAlso
Foam::vtk::vtuSizing
SourceFiles
foamVtuCells.C
foamVtuCellsI.H
\*---------------------------------------------------------------------------*/
#ifndef foamVtuCells_H
#define foamVtuCells_H
#include "foamVtkCore.H"
#include "foamVtkMeshMaps.H"
#include "foamVtuSizing.H"
#include "DynamicList.H"
#include "labelList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class polyMesh;
namespace vtk
{
// Forward declaration of classes
class outputOptions;
/*---------------------------------------------------------------------------*\
Class Foam::vtk::vtuCells Declaration
\*---------------------------------------------------------------------------*/
class vtuCells
:
public vtuSizing
{
// Private Member Data
// Requested output types
//- Output content type
contentType output_;
//- Bookkeeping for polyhedral cell decomposition
bool decomposeRequest_;
// Storage of output
//- Cell types (including added cells) in vtk numbering
// Range is 1-255
List<uint8_t> cellTypes_;
//- Vertices per cell (including added cells) in vtk ordering
List<label> vertLabels_;
//- Connectivity (vertices) offset for the end of each cell
List<label> vertOffset_;
//- Face lists per polyhedral cell
List<label> faceLabels_;
//- Face label offsets
List<label> faceOffset_;
//- Bookkeeping for polyhedral cell decomposition
foamVtkMeshMaps maps_;
// Private Member Functions
//- Disallow default bitwise copy construct
vtuCells(const vtuCells&) = delete;
//- Disallow default bitwise assignment
void operator=(const vtuCells&) = delete;
public:
// Constructors
//- Construct from components.
// Optionally with polyhedral decomposition.
vtuCells
(
const enum contentType output = contentType::XML,
const bool decompose = false
);
//- Construct from components and create the output information
// immediately
vtuCells
(
const polyMesh& mesh,
const enum contentType output = contentType::XML,
const bool decompose = false
);
//- Construct from components.
// Optionally with polyhedral decomposition.
vtuCells
(
const vtk::outputOptions outOpts,
const bool decompose = false
);
//- Construct from components and create the output information
// immediately
vtuCells
(
const polyMesh& mesh,
const vtk::outputOptions outOpts,
const bool decompose = false
);
//- Destructor
~vtuCells();
// Member Functions
// Access
//- The output content type
inline enum contentType content() const;
//- Query the polyhedral decompose requested flag.
inline bool decomposeRequested() const;
//- True if no cellTypes are populated.
inline bool empty() const;
//- The size of populated cellTypes.
inline label size() const;
// Edit
//- Reset all sizes to zero.
void clear();
//- Create the geometry using the previously requested output and
// decomposition types.
void reset(const polyMesh& mesh);
//- Respecify requested output and decomposition type prior to
// creating the geometry
void reset
(
const polyMesh& mesh,
const enum contentType output,
const bool decompose
);
//- Renumber cell ids to account for subset meshes
void renumberCells(const UList<label>& mapping);
//- Renumber point ids to account for subset meshes
void renumberPoints(const UList<label>& mapping);
// Storage Access
//- Values for "types" (XML) and "CELL_TYPES" (legacy)
inline const List<uint8_t>& cellTypes() const;
//- Values for "connectivity" (XML) or "CELLS" (legacy)
inline const labelList& vertLabels() const;
//- Values for "offsets" (XML only)
inline const labelList& vertOffsets() const;
//- Values for "faces" (XML only)
inline const labelList& faceLabels() const;
//- Values for "faceoffset" (XML only)
inline const labelList& faceOffsets() const;
//- Additional point addressing (from added point to original cell)
inline const labelList& addPointCellLabels() const;
//- Original cell ids for all cells (regular and decomposed).
inline const labelList& cellMap() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace vtk
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "foamVtuCellsI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,105 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-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/>.
\*---------------------------------------------------------------------------*/
#include "foamVtuCells.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline enum Foam::vtk::vtuCells::contentType
Foam::vtk::vtuCells::content() const
{
return output_;
}
inline bool Foam::vtk::vtuCells::decomposeRequested() const
{
return decomposeRequest_;
}
inline bool Foam::vtk::vtuCells::empty() const
{
return cellTypes_.empty();
}
inline Foam::label Foam::vtk::vtuCells::size() const
{
return cellTypes_.size();
}
inline const Foam::List<uint8_t>&
Foam::vtk::vtuCells::cellTypes() const
{
return cellTypes_;
}
inline const Foam::labelList&
Foam::vtk::vtuCells::vertLabels() const
{
return vertLabels_;
}
inline const Foam::labelList&
Foam::vtk::vtuCells::vertOffsets() const
{
return vertOffset_;
}
inline const Foam::labelList&
Foam::vtk::vtuCells::faceLabels() const
{
return faceLabels_;
}
inline const Foam::labelList&
Foam::vtk::vtuCells::faceOffsets() const
{
return faceOffset_;
}
inline const Foam::labelList&
Foam::vtk::vtuCells::addPointCellLabels() const
{
return maps_.additionalIds();
}
inline const Foam::labelList&
Foam::vtk::vtuCells::cellMap() const
{
return maps_.cellMap();
}
// ************************************************************************* //

View File

@ -0,0 +1,578 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-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/>.
\*---------------------------------------------------------------------------*/
#include "foamVtuSizing.H"
#include "foamVtkCore.H"
#include "polyMesh.H"
#include "cellShape.H"
#include "cellModeller.H"
// Only used in this file
#include "foamVtuSizingTemplates.C"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::vtk::vtuSizing::presizeMaps(foamVtkMeshMaps& maps) const
{
maps.cellMap().setSize(this->nFieldCells());
maps.additionalIds().setSize(this->nAddPoints());
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::vtk::vtuSizing::vtuSizing
(
const polyMesh& mesh,
const bool decompose
)
{
clear();
reset(mesh, decompose);
}
Foam::vtk::vtuSizing::vtuSizing()
{
clear();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::vtk::vtuSizing::~vtuSizing()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtk::vtuSizing::reset
(
const polyMesh& mesh,
const bool decompose
)
{
const cellModel& tet = *(cellModeller::lookup("tet"));
const cellModel& pyr = *(cellModeller::lookup("pyr"));
const cellModel& prism = *(cellModeller::lookup("prism"));
const cellModel& wedge = *(cellModeller::lookup("wedge"));
const cellModel& tetWedge = *(cellModeller::lookup("tetWedge"));
const cellModel& hex = *(cellModeller::lookup("hex"));
const cellShapeList& shapes = mesh.cellShapes();
// Unique vertex labels per polyhedral
HashSet<label> hashUniqId(2*256);
decompose_ = decompose;
nCells_ = mesh.nCells();
nPoints_ = mesh.nPoints();
nAddCells_ = 0;
nAddVerts_ = 0;
nCellsPoly_ = nCells_;
nVertLabels_ = 0;
nFaceLabels_ = 0;
nVertPoly_ = 0;
forAll(shapes, celli)
{
const cellShape& shape = shapes[celli];
const cellModel& model = shape.model();
if
(
model == tet
|| model == pyr
|| model == prism
|| model == hex
)
{
// Normal primitive - not a poly
--nCellsPoly_;
nVertLabels_ += shape.size();
}
else if (model == tetWedge && decompose)
{
nVertLabels_ += 6; // Treat as squeezed prism (VTK_WEDGE)
}
else if (model == wedge && decompose)
{
nVertLabels_ += 8; // Treat as squeezed hex
}
else if (decompose)
{
// Polyhedral: Decompose into tets + pyramids.
++nAddPoints_;
// Count vertices into first decomposed cell
bool first = true;
const cell& cFaces = mesh.cells()[celli];
forAll(cFaces, cFaceI)
{
const face& f = mesh.faces()[cFaces[cFaceI]];
// Face decomposed into triangles and quads
// Tri -> Tet, Quad -> Pyr
label nTria = 0, nQuad = 0;
f.nTrianglesQuads(mesh.points(), nTria, nQuad);
nAddCells_ += nTria + nQuad;
nAddVerts_ += (nTria * 4) + (nQuad * 5);
if (first)
{
first = false;
--nAddCells_;
const label nvrt = (nQuad ? 5 : 4);
nAddVerts_ -= nvrt;
nVertLabels_ += nvrt;
}
}
}
else
{
// Polyhedral: Not decomposed
const labelList& cFaces = mesh.cells()[celli];
// Unique node ids used (XML/INTERNAL, not needed for LEGACY)
hashUniqId.clear();
// Face stream sizing:
// number of faces, size of each face, vertices per face
// [nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...]
forAll(cFaces, cFaceI)
{
const face& f = mesh.faces()[cFaces[cFaceI]];
nFaceLabels_ += f.size();
hashUniqId.insert(f);
}
// Legacy format only uses the face-stream.
// - track what *NOT* to use for legacy
nVertLabels_ += hashUniqId.size();
nVertPoly_ += hashUniqId.size();
nFaceLabels_ += 1 + cFaces.size();
}
}
// decompose requested and needed
decompose_ = (decompose && nCellsPoly_);
}
Foam::label Foam::vtk::vtuSizing::sizeOf
(
const enum contentType output,
const enum slotType slot
) const
{
switch (output)
{
case contentType::LEGACY:
{
switch (slot)
{
case slotType::CELLS:
// legacy uses connectivity for primitives, but directly
// stores face streams into connectivity as well.
// size-prefix per cell
return
(
nVertLabels() + nAddVerts() - nVertPoly() // primitives
+ nFaceLabels() // face-stream (poly)
+ nFieldCells() // nFieldCells (size prefix)
);
break;
default:
break;
}
break;
}
case contentType::XML:
{
switch (slot)
{
case slotType::CELLS:
return (nVertLabels() + nAddVerts());
break;
case slotType::CELLS_OFFSETS:
return nFieldCells();
break;
case slotType::FACES:
return nFaceLabels();
break;
case slotType::FACES_OFFSETS:
return nFaceLabels() ? nFieldCells() : 0;
break;
}
break;
}
case contentType::INTERNAL:
{
switch (slot)
{
case slotType::CELLS:
// size-prefix per cell
return (nVertLabels() + nAddVerts() + nFieldCells());
break;
case slotType::CELLS_OFFSETS:
return nFieldCells();
break;
case slotType::FACES:
return nFaceLabels();
break;
case slotType::FACES_OFFSETS:
return nFaceLabels() ? nFieldCells() : 0;
break;
}
break;
}
}
return 0;
}
void Foam::vtk::vtuSizing::populateLegacy
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<label>& vertLabels,
foamVtkMeshMaps& maps
) const
{
// Leave as zero-sized so that populateArrays doesn't fill it.
List<label> unused;
presizeMaps(maps);
populateArrays
(
mesh,
*this,
cellTypes,
vertLabels,
unused, // offsets
unused, // faces
unused, // facesOffsets
contentType::LEGACY,
maps.cellMap(),
maps.additionalIds()
);
}
void Foam::vtk::vtuSizing::populateXml
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<label>& connectivity,
UList<label>& offsets,
UList<label>& faces,
UList<label>& facesOffsets,
foamVtkMeshMaps& maps
) const
{
presizeMaps(maps);
populateArrays
(
mesh,
*this,
cellTypes,
connectivity,
offsets,
faces,
facesOffsets,
contentType::XML,
maps.cellMap(),
maps.additionalIds()
);
}
void Foam::vtk::vtuSizing::populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<int>& connectivity,
UList<int>& offsets,
UList<int>& faces,
UList<int>& facesOffsets,
foamVtkMeshMaps& maps
) const
{
presizeMaps(maps);
populateArrays
(
mesh,
*this,
cellTypes,
connectivity,
offsets,
faces,
facesOffsets,
contentType::INTERNAL,
maps.cellMap(),
maps.additionalIds()
);
}
void Foam::vtk::vtuSizing::populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<long>& connectivity,
UList<long>& offsets,
UList<long>& faces,
UList<long>& facesOffsets,
foamVtkMeshMaps& maps
) const
{
presizeMaps(maps);
populateArrays
(
mesh,
*this,
cellTypes,
connectivity,
offsets,
faces,
facesOffsets,
contentType::INTERNAL,
maps.cellMap(),
maps.additionalIds()
);
}
void Foam::vtk::vtuSizing::populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<long long>& connectivity,
UList<long long>& offsets,
UList<long long>& faces,
UList<long long>& facesOffsets,
foamVtkMeshMaps& maps
) const
{
presizeMaps(maps);
populateArrays
(
mesh,
*this,
cellTypes,
connectivity,
offsets,
faces,
facesOffsets,
contentType::INTERNAL,
maps.cellMap(),
maps.additionalIds()
);
}
void Foam::vtk::vtuSizing::populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<int>& connectivity,
UList<int>& offsets,
UList<int>& faces,
UList<int>& facesOffsets,
UList<label>& cellMap,
UList<label>& addPointsIds
) const
{
populateArrays
(
mesh,
*this,
cellTypes,
connectivity,
offsets,
faces,
facesOffsets,
contentType::INTERNAL,
cellMap,
addPointsIds
);
}
void Foam::vtk::vtuSizing::populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<long>& connectivity,
UList<long>& offsets,
UList<long>& faces,
UList<long>& facesOffsets,
UList<label>& cellMap,
UList<label>& addPointsIds
) const
{
populateArrays
(
mesh,
*this,
cellTypes,
connectivity,
offsets,
faces,
facesOffsets,
contentType::INTERNAL,
cellMap,
addPointsIds
);
}
void Foam::vtk::vtuSizing::populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<long long>& connectivity,
UList<long long>& offsets,
UList<long long>& faces,
UList<long long>& facesOffsets,
UList<label>& cellMap,
UList<label>& addPointsIds
) const
{
populateArrays
(
mesh,
*this,
cellTypes,
connectivity,
offsets,
faces,
facesOffsets,
contentType::INTERNAL,
cellMap,
addPointsIds
);
}
void Foam::vtk::vtuSizing::clear()
{
decompose_ = false;
nCells_ = 0;
nPoints_ = 0;
nVertLabels_ = 0;
nFaceLabels_ = 0;
nCellsPoly_ = 0;
nVertPoly_ = 0;
nAddCells_ = 0;
nAddPoints_ = 0;
nAddVerts_ = 0;
}
void Foam::vtk::vtuSizing::info(Ostream& os) const
{
os << "nFieldCells:" << nFieldCells();
if (nAddCells_)
{
os << " (" << nCells_
<< "+" << nAddCells_ << ")";
}
else
{
os << " (poly:" << nCellsPoly_ << ")";
}
os << " nFieldPoints:" << nFieldPoints();
if (nAddPoints_)
{
os << " (" << nPoints_ << "+" << nAddPoints_ << ")";
}
os << " nVertLabels:" << (nVertLabels_ + nAddVerts_);
if (nAddVerts_)
{
os << " (" << nVertLabels_ << "+" << nAddVerts_ << ")";
}
else if (nVertPoly_)
{
os << " (poly:" << nVertPoly_ << ")";
}
os << " nFaceLabels:" << nFaceLabels_;
os << " legacy-count:" << sizeLegacy();
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
bool Foam::vtk::vtuSizing::operator==(const vtuSizing& rhs) const
{
return
(
decompose() == rhs.decompose()
&& nCells() == rhs.nCells()
&& nPoints() == rhs.nPoints()
&& nVertLabels() == rhs.nVertLabels()
&& nFaceLabels() == rhs.nFaceLabels()
&& nCellsPoly() == rhs.nCellsPoly()
&& nVertPoly() == rhs.nVertPoly()
&& nAddCells() == rhs.nAddCells()
&& nAddPoints() == rhs.nAddPoints()
&& nAddVerts() == rhs.nAddVerts()
);
}
bool Foam::vtk::vtuSizing::operator!=(const vtuSizing& rhs) const
{
return !operator==(rhs);
}
// ************************************************************************* //

View File

@ -0,0 +1,413 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-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/>.
Class
Foam::vtk::vtuSizing
Description
Sizing descriptions and routines for transcribing an OpenFOAM volume mesh
into a VTK unstructured grid, with possible decomposition of polyhedral
cells into primitive cell types.
This class is intended to populate externally allocated arrays with content
that is compatible with what VTK expects. This approach allows an improved
separation of the OpenFOAM mesh description and the storage, and allows
support of alternative storage containers (eg, std::vector, vtkDataArray).
The ideal goal would be a zero-copy mechanism, but this does not work for
several reasons:
\par
- OpenFOAM and VTK have different point ordering for prism
- polyhedral decomposition
- face-stream are required for VTK
- VTK internal storage includes list size as part of the data
- VTK includes storage may be a different base size (eg, long long)
compared to the OpenFOAM label.
\par Data Entries (slots)
These are the storage entries normally associate with each output-type:
\table
legacy output
\c types | vtk cell type (1-255)
\c cells | nLabels and unique vertex labels used by the cell, or
| [nLabels nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...]
\endtable
\table
xml output
\c types | vtk cell type (1-255)
\c connectivity | unique vertex labels used by the cell
\c offsets | end offset for each of \c connectivity
\c faces | face stream for polyhedral cells
| [nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...]
\c faceoffsets | end offset for each of \c faces, with -1 for primitive cells
\endtable
\table
internal storage
\c types | vtk cell type (1-255)
\c connectivity | nLabels and unique vertex labels used by the cell
\c location | begin location for each of \c connectivity
\c faces | face stream for polyhedral cells
| [nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...]
\c facelocation | begin location for each of \c faces, with -1 for primitive cells
\endtable
The VTK storage concept for "connectivity" and "faces" somewhat resemble
a CompactListList.
SourceFiles
foamVtuSizing.C
foamVtuSizingI.H
\*---------------------------------------------------------------------------*/
#ifndef foamVtuSizing_H
#define foamVtuSizing_H
#include "label.H"
#include "labelList.H"
#include "foamVtkMeshMaps.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class polyMesh;
namespace vtk
{
/*---------------------------------------------------------------------------*\
Class Foam::vtk::vtuSizing Declaration
\*---------------------------------------------------------------------------*/
class vtuSizing
{
public:
// Public data
//- Types of content that the storage may represent
enum contentType
{
LEGACY, //!< Legacy VTK content
XML, //!< XML (VTU) content
INTERNAL //!< Internal vtkUnstructuredGrid content
};
//- The possible storage 'slots' that can be used
enum slotType
{
CELLS, //!< Cell connectivity (ALL)
CELLS_OFFSETS, //!< End-offsets (XML) or locations (INTERNAL) for cells
FACES, //!< Face-stream (XML, INTERNAL)
FACES_OFFSETS //!< End-offsets (XML) or locations (INTERNAL) for faces
};
private:
// Private Member Data
//- Polyhedral decomposition requested
bool decompose_;
//- Number of cells in the mesh
label nCells_;
//- Number of points in the mesh
label nPoints_;
//- Number of vertex labels to represent the mesh
label nVertLabels_;
// Polyhedrals
//- Number of polyhedral face labels for the mesh
label nFaceLabels_;
//- Number of polyhedral cells (informational)
label nCellsPoly_;
//- Number of vertex labels used by polyhedrals
label nVertPoly_;
// Decomposed polyhedrals
//- Number of additional (decomposed) cells for the mesh
label nAddCells_;
//- Number of additional (decomposed) points for the mesh
label nAddPoints_;
//- Number of additional (decomposed) vertices for the mesh
label nAddVerts_;
// Private Member Functions
//- set-size for cellMap and additionalIds
void presizeMaps(foamVtkMeshMaps& maps) const;
//- Populate lists for internal VTK representation
template<class LabelType, class LabelType2>
static void populateArrays
(
const polyMesh& mesh,
const vtk::vtuSizing& sizing,
UList<uint8_t>& cellTypes,
UList<LabelType>& vertLabels,
UList<LabelType>& vertOffset,
UList<LabelType>& faceLabels,
UList<LabelType>& faceOffset,
const enum contentType output,
UList<LabelType2>& cellMap,
UList<LabelType2>& addPointsIds
);
// Allow default bitwise copy/assignment
public:
// Constructors
//- Construct null.
vtuSizing();
//- Construct sizes by analyzing the mesh,
// optionally with polyhedral decomposition.
vtuSizing(const polyMesh& mesh, const bool decompose=false);
//- Destructor
~vtuSizing();
// Member Functions
// Edit
//- Construct sizes by analyzing the mesh,
// optionally with polyhedral decomposition.
void reset(const polyMesh& mesh, const bool decompose=false);
//- Reset all sizes to zero.
void clear();
// Access
//- Query the decompose flag
inline bool decompose() const;
//- Number of cells for the mesh
inline label nCells() const;
//- Number of points for the mesh
inline label nPoints() const;
//- Number of vertex labels for the mesh
inline label nVertLabels() const;
//- Number of polyhedral face labels for the mesh
inline label nFaceLabels() const;
//- Number of polyhedral cells for the mesh
inline label nCellsPoly() const;
//- Number of vertex labels for polyhedral cells of the mesh
inline label nVertPoly() const;
//- Number of additional (decomposed) cells for the mesh
inline label nAddCells() const;
//- Number of additional (decomposed) points for the mesh
inline label nAddPoints() const;
//- Number of additional (decomposed) vertices for the mesh
inline label nAddVerts() const;
//- Number of field cells = nCells + nAddCells
inline label nFieldCells() const;
//- Number of field points = nPoints + nAddPoints
inline label nFieldPoints() const;
// Derived sizes
//- Return the required size for the storage slot
label sizeOf
(
const enum contentType output,
const enum slotType slot
) const;
//- The calculated size for legacy storage
inline label sizeLegacy() const;
//- The calculated size for legacy storage of the specified slot
inline label sizeLegacy(const enum slotType slot) const;
//- The calculated size for xml storage of the specified slot
inline label sizeXml(const enum slotType slot) const;
//- The calculated size for vtk-internal storage of the specified slot
inline label sizeInternal(const enum slotType slot) const;
// Utilty routines
//- Populate lists for Legacy output
void populateLegacy
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<label>& connectivity,
foamVtkMeshMaps& maps
) const;
//- Populate lists for XML output
void populateXml
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<label>& connectivity,
UList<label>& offsets,
UList<label>& faces,
UList<label>& facesOffsets,
foamVtkMeshMaps& maps
) const;
//- Populate lists for Internal VTK format
void populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<int>& connectivity,
UList<int>& offsets,
UList<int>& faces,
UList<int>& facesOffsets,
foamVtkMeshMaps& maps
) const;
//- Populate lists for Internal VTK format
void populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<long>& connectivity,
UList<long>& offsets,
UList<long>& faces,
UList<long>& facesOffsets,
foamVtkMeshMaps& maps
) const;
//- Populate lists for Internal VTK format
void populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<long long>& connectivity,
UList<long long>& offsets,
UList<long long>& faces,
UList<long long>& facesOffsets,
foamVtkMeshMaps& maps
) const;
//- Populate lists for Internal VTK format
void populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<int>& connectivity,
UList<int>& offsets,
UList<int>& faces,
UList<int>& facesOffsets,
UList<label>& cellMap,
UList<label>& addPointsIds
) const;
//- Populate lists for Internal VTK format
void populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<long>& connectivity,
UList<long>& offsets,
UList<long>& faces,
UList<long>& facesOffsets,
UList<label>& cellMap,
UList<label>& addPointsIds
) const;
//- Populate lists for Internal VTK format
void populateInternal
(
const polyMesh& mesh,
UList<uint8_t>& cellTypes,
UList<long long>& connectivity,
UList<long long>& offsets,
UList<long long>& faces,
UList<long long>& facesOffsets,
UList<label>& cellMap,
UList<label>& addPointsIds
) const;
// Write
//- Report some information
void info(Ostream& os) const;
// Member Operators
//- Test equality
bool operator==(const vtuSizing& rhs) const;
//- Test inequality
bool operator!=(const vtuSizing& rhs) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace vtk
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "foamVtuSizingI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,135 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
\*---------------------------------------------------------------------------*/
#include "foamVtuSizing.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::vtk::vtuSizing::decompose() const
{
return decompose_;
}
inline Foam::label Foam::vtk::vtuSizing::nCells() const
{
return nCells_;
}
inline Foam::label Foam::vtk::vtuSizing::nPoints() const
{
return nPoints_;
}
inline Foam::label Foam::vtk::vtuSizing::nVertLabels() const
{
return nVertLabels_;
}
inline Foam::label Foam::vtk::vtuSizing::nFaceLabels() const
{
return nFaceLabels_;
}
inline Foam::label Foam::vtk::vtuSizing::nCellsPoly() const
{
return nCellsPoly_;
}
inline Foam::label Foam::vtk::vtuSizing::nVertPoly() const
{
return nVertPoly_;
}
inline Foam::label Foam::vtk::vtuSizing::nAddCells() const
{
return nAddCells_;
}
inline Foam::label Foam::vtk::vtuSizing::nAddPoints() const
{
return nAddPoints_;
}
inline Foam::label Foam::vtk::vtuSizing::nAddVerts() const
{
return nAddVerts_;
}
inline Foam::label Foam::vtk::vtuSizing::nFieldCells() const
{
return nCells_ + nAddCells_;
}
inline Foam::label Foam::vtk::vtuSizing::nFieldPoints() const
{
return nPoints_ + nAddPoints_;
}
inline Foam::label Foam::vtk::vtuSizing::sizeLegacy() const
{
return sizeOf(contentType::LEGACY, slotType::CELLS);
}
inline Foam::label Foam::vtk::vtuSizing::sizeLegacy
(
const enum slotType slot
) const
{
return sizeOf(contentType::LEGACY, slot);
}
inline Foam::label Foam::vtk::vtuSizing::sizeXml
(
const enum slotType slot
) const
{
return sizeOf(contentType::XML, slot);
}
inline Foam::label Foam::vtk::vtuSizing::sizeInternal
(
const enum slotType slot
) const
{
return sizeOf(contentType::INTERNAL, slot);
}
// ************************************************************************* //

View File

@ -0,0 +1,668 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-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/>.
\*---------------------------------------------------------------------------*/
#include "foamVtuSizing.H"
#include "foamVtkCore.H"
#include "polyMesh.H"
#include "cellShape.H"
#include "cellModeller.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class LabelType, class LabelType2>
void Foam::vtk::vtuSizing::populateArrays
(
const polyMesh& mesh,
const vtk::vtuSizing& sizing,
UList<uint8_t>& cellTypes,
UList<LabelType>& vertLabels,
UList<LabelType>& vertOffset,
UList<LabelType>& faceLabels,
UList<LabelType>& faceOffset,
const enum contentType output,
UList<LabelType2>& cellMap,
UList<LabelType2>& addPointsIds
)
{
// STAGE 1: Verify storage sizes
if (cellTypes.size() != sizing.nFieldCells())
{
FatalErrorInFunction
<< " cellTypes size=" << cellTypes.size()
<< " expected " << sizing.nFieldCells()
<< exit(FatalError);
}
if (cellMap.size() != sizing.nFieldCells())
{
FatalErrorInFunction
<< " cellMap size=" << cellMap.size()
<< " expected " << sizing.nFieldCells()
<< exit(FatalError);
}
if (addPointsIds.size() != sizing.nAddPoints())
{
FatalErrorInFunction
<< " addPointsIds size=" << addPointsIds.size()
<< " expected " << sizing.nAddPoints()
<< exit(FatalError);
}
// Prefix vertLabels with the size too?
// Also use as the size of the prefixed information
const int prefix = (output != contentType::XML) ? 1 : 0;
switch (output)
{
case contentType::LEGACY:
{
if (vertLabels.size() != sizing.sizeLegacy())
{
FatalErrorInFunction
<< " legacy size=" << vertLabels.size()
<< " expected " << sizing.sizeLegacy()
<< exit(FatalError);
}
break;
}
case contentType::XML:
{
// XML uses connectivity/offset pair.
if
(
vertLabels.size()
!= sizing.sizeXml(slotType::CELLS)
)
{
FatalErrorInFunction
<< " connectivity size=" << vertLabels.size()
<< " expected "
<< sizing.sizeXml(slotType::CELLS)
<< exit(FatalError);
}
if
(
vertOffset.size()
!= sizing.sizeXml(slotType::CELLS_OFFSETS)
)
{
FatalErrorInFunction
<< " offsets size=" << vertOffset.size()
<< " expected "
<< sizing.sizeXml(slotType::CELLS_OFFSETS)
<< exit(FatalError);
}
if (sizing.nFaceLabels())
{
if
(
faceLabels.size()
!= sizing.sizeXml(slotType::FACES)
)
{
FatalErrorInFunction
<< " faces size=" << faceLabels.size()
<< " expected "
<< sizing.sizeXml(slotType::FACES)
<< exit(FatalError);
}
if
(
faceOffset.size()
!= sizing.sizeXml(slotType::FACES_OFFSETS)
)
{
FatalErrorInFunction
<< " facesOffsets size=" << faceOffset.size()
<< " expected "
<< sizing.sizeXml(slotType::FACES_OFFSETS)
<< exit(FatalError);
}
}
break;
}
case contentType::INTERNAL:
{
// VTK-internal connectivity/offset pair.
if
(
vertLabels.size()
!= sizing.sizeInternal(slotType::CELLS)
)
{
FatalErrorInFunction
<< " connectivity size=" << vertLabels.size()
<< " expected "
<< sizing.sizeInternal(slotType::CELLS)
<< exit(FatalError);
}
if
(
vertOffset.size()
!= sizing.sizeInternal(slotType::CELLS_OFFSETS)
)
{
FatalErrorInFunction
<< " offsets size=" << vertOffset.size()
<< " expected "
<< sizing.sizeInternal(slotType::CELLS_OFFSETS)
<< exit(FatalError);
}
if (sizing.nFaceLabels())
{
if
(
faceLabels.size()
!= sizing.sizeInternal(slotType::FACES)
)
{
FatalErrorInFunction
<< " faces size=" << faceLabels.size()
<< " expected "
<< sizing.sizeInternal(slotType::FACES)
<< exit(FatalError);
}
if
(
faceOffset.size()
!= sizing.sizeInternal(slotType::FACES_OFFSETS)
)
{
FatalErrorInFunction
<< " facesOffsets size=" << faceOffset.size()
<< " expected "
<< sizing.sizeInternal(slotType::FACES_OFFSETS)
<< exit(FatalError);
}
}
break;
}
}
faceOffset = -1;
const cellModel& tet = *(cellModeller::lookup("tet"));
const cellModel& pyr = *(cellModeller::lookup("pyr"));
const cellModel& prism = *(cellModeller::lookup("prism"));
const cellModel& wedge = *(cellModeller::lookup("wedge"));
const cellModel& tetWedge = *(cellModeller::lookup("tetWedge"));
const cellModel& hex = *(cellModeller::lookup("hex"));
const cellShapeList& shapes = mesh.cellShapes();
// face owner is needed to determine the face orientation
const labelList& owner = mesh.faceOwner();
// Unique vertex labels per polyhedral
HashSet<label> hashUniqId(2*256);
// Index into vertLabels, faceLabels for normal cells
label nVertLabels = 0;
label nFaceLabels = 0;
// Index into vertLabels for decomposed polys
label nVertDecomp = sizing.nVertLabels() + prefix*sizing.nCells();
// Placement of decomposed cells
label nCellDecomp = mesh.nCells();
// Placement of additional point labels
label nPointDecomp = 0;
// Non-decomposed polyhedral are represented as a face-stream.
// For legacy format, this stream replaces the normal connectivity
// information. Use references to alias where the face output should land.
UList<LabelType>& faceOutput =
(
output == contentType::LEGACY
? vertLabels
: faceLabels
);
label& faceIndexer =
(
output == contentType::LEGACY
? nVertLabels
: nFaceLabels
);
// ===========================================
// STAGE 2: Rewrite in VTK form
// During this stage, the vertOffset contains the *size* associated with
// the per-cell vertLabels entries, and the faceOffset contains the *size*
// associated with the per-cell faceLabels.
forAll(shapes, celli)
{
const cellShape& shape = shapes[celli];
const cellModel& model = shape.model();
cellMap[celli] = celli;
if (model == tet)
{
cellTypes[celli] = vtk::cellType::VTK_TETRA;
if (vertOffset.size())
{
vertOffset[celli] = shape.size();
}
if (prefix)
{
vertLabels[nVertLabels++] = shape.size();
}
forAll(shape, i)
{
vertLabels[nVertLabels++] = shape[i];
}
}
else if (model == pyr)
{
cellTypes[celli] = vtk::cellType::VTK_PYRAMID;
if (vertOffset.size())
{
vertOffset[celli] = shape.size();
}
if (prefix)
{
vertLabels[nVertLabels++] = shape.size();
}
forAll(shape, i)
{
vertLabels[nVertLabels++] = shape[i];
}
}
else if (model == hex)
{
cellTypes[celli] = vtk::cellType::VTK_HEXAHEDRON;
if (vertOffset.size())
{
vertOffset[celli] = shape.size();
}
if (prefix)
{
vertLabels[nVertLabels++] = shape.size();
}
forAll(shape, i)
{
vertLabels[nVertLabels++] = shape[i];
}
}
else if (model == prism)
{
cellTypes[celli] = vtk::cellType::VTK_WEDGE;
if (vertOffset.size())
{
vertOffset[celli] = shape.size();
}
if (prefix)
{
vertLabels[nVertLabels++] = shape.size();
}
// VTK_WEDGE triangles point outwards (swap 1<->2, 4<->5)
vertLabels[nVertLabels++] = shape[0];
vertLabels[nVertLabels++] = shape[2];
vertLabels[nVertLabels++] = shape[1];
vertLabels[nVertLabels++] = shape[3];
vertLabels[nVertLabels++] = shape[5];
vertLabels[nVertLabels++] = shape[4];
}
else if (model == tetWedge && sizing.decompose())
{
// Treat as squeezed prism
cellTypes[celli] = vtk::cellType::VTK_WEDGE;
if (vertOffset.size())
{
vertOffset[celli] = 6;
}
if (prefix)
{
vertLabels[nVertLabels++] = 6;
}
vertLabels[nVertLabels++] = shape[0];
vertLabels[nVertLabels++] = shape[2];
vertLabels[nVertLabels++] = shape[1];
vertLabels[nVertLabels++] = shape[3];
vertLabels[nVertLabels++] = shape[4];
vertLabels[nVertLabels++] = shape[3];
}
else if (model == wedge && sizing.decompose())
{
// Treat as squeezed hex
cellTypes[celli] = vtk::cellType::VTK_HEXAHEDRON;
if (vertOffset.size())
{
vertOffset[celli] = 8;
}
if (prefix)
{
vertLabels[nVertLabels++] = 8;
}
vertLabels[nVertLabels++] = shape[0];
vertLabels[nVertLabels++] = shape[1];
vertLabels[nVertLabels++] = shape[2];
vertLabels[nVertLabels++] = shape[2];
vertLabels[nVertLabels++] = shape[3];
vertLabels[nVertLabels++] = shape[4];
vertLabels[nVertLabels++] = shape[5];
vertLabels[nVertLabels++] = shape[6];
}
else if (sizing.decompose())
{
// Polyhedral cell - decompose into tet/pyr.
// Ensure we have the correct orientation for the base of the
// primitive cell shape.
// If the cell is face owner, the orientation needs to be flipped
// to avoid defining negative cells.
// VTK may not care, but we'll do it anyhow for safety.
// Mapping from additional point to cell, and the new vertex from
// the cell-centre
const label newVertexLabel = mesh.nPoints() + nPointDecomp;
addPointsIds[nPointDecomp++] = celli;
// Whether to insert cell in place of original or not.
bool first = true;
const labelList& cFaces = mesh.cells()[celli];
forAll(cFaces, cFaceI)
{
const face& f = mesh.faces()[cFaces[cFaceI]];
const bool isOwner = (owner[cFaces[cFaceI]] == celli);
// Count triangles/quads in decomposition
label nTria = 0, nQuad = 0;
f.nTrianglesQuads(mesh.points(), nTria, nQuad);
// Do actual decomposition
faceList faces3(nTria);
faceList faces4(nQuad);
nTria = 0, nQuad = 0;
f.trianglesQuads(mesh.points(), nTria, nQuad, faces3, faces4);
forAll(faces4, fci)
{
// Quad becomes a pyramid
const face& quad = faces4[fci];
const label nShapePoints = 5; // pyr (5 vertices)
label celLoc, vrtLoc;
if (first)
{
first = false;
celLoc = celli;
vrtLoc = nVertLabels;
nVertLabels += prefix + nShapePoints;
}
else
{
celLoc = nCellDecomp++;
vrtLoc = nVertDecomp;
nVertDecomp += prefix + nShapePoints;
}
cellMap[celLoc] = celli;
cellTypes[celLoc] = vtk::cellType::VTK_PYRAMID;
if (vertOffset.size())
{
vertOffset[celLoc] = nShapePoints;
}
if (prefix)
{
vertLabels[vrtLoc++] = nShapePoints;
}
// See note above about the orientation.
if (isOwner)
{
vertLabels[vrtLoc++] = quad[3];
vertLabels[vrtLoc++] = quad[2];
vertLabels[vrtLoc++] = quad[1];
vertLabels[vrtLoc++] = quad[0];
}
else
{
vertLabels[vrtLoc++] = quad[0];
vertLabels[vrtLoc++] = quad[1];
vertLabels[vrtLoc++] = quad[2];
vertLabels[vrtLoc++] = quad[3];
}
vertLabels[vrtLoc++] = newVertexLabel; // apex
}
forAll(faces3, fci)
{
// Triangle becomes a tetrahedral
const face& tria = faces3[fci];
const label nShapePoints = 4; // tet (4 vertices)
label celLoc, vrtLoc;
if (first)
{
first = false;
celLoc = celli;
vrtLoc = nVertLabels;
nVertLabels += prefix + nShapePoints;
}
else
{
celLoc = nCellDecomp++;
vrtLoc = nVertDecomp;
nVertDecomp += prefix + nShapePoints;
}
cellMap[celLoc] = celli;
cellTypes[celLoc] = vtk::cellType::VTK_TETRA;
if (vertOffset.size())
{
vertOffset[celLoc] = nShapePoints;
}
if (prefix)
{
vertLabels[vrtLoc++] = nShapePoints;
}
cellTypes[celLoc] = vtk::cellType::VTK_TETRA;
// See note above about the orientation.
if (isOwner)
{
vertLabels[vrtLoc++] = tria[2];
vertLabels[vrtLoc++] = tria[1];
vertLabels[vrtLoc++] = tria[0];
}
else
{
vertLabels[vrtLoc++] = tria[0];
vertLabels[vrtLoc++] = tria[1];
vertLabels[vrtLoc++] = tria[2];
}
vertLabels[vrtLoc++] = newVertexLabel; // apex
}
}
}
else
{
// Polyhedral cell - not decomposed
hashUniqId.clear(); // unique node ids used (XML, INTERNAL)
// face-stream
// [nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...]
cellTypes[celli] = vtk::cellType::VTK_POLYHEDRON;
const labelList& cFaces = mesh.cells()[celli];
const label startLabel = faceIndexer;
if (output == contentType::LEGACY)
{
faceOutput[startLabel] = 0; // placeholder for size
++faceIndexer;
}
faceOutput[faceIndexer++] = cFaces.size();
forAll(cFaces, cFaceI)
{
const face& f = mesh.faces()[cFaces[cFaceI]];
const bool isOwner = (owner[cFaces[cFaceI]] == celli);
forAll(f, fp)
{
hashUniqId.insert(f[fp]);
}
// number of labels for this face
faceOutput[faceIndexer++] = f.size();
if (isOwner)
{
forAll(f, fp)
{
faceOutput[faceIndexer++] = f[fp];
}
}
else
{
// fairly immaterial if we reverse the list
// or use face::reverseFace()
forAllReverse(f, fp)
{
faceOutput[faceIndexer++] = f[fp];
}
}
}
if (output == contentType::LEGACY)
{
// Update size for legacy face stream
faceOutput[startLabel] = (faceIndexer - startLabel);
}
else
{
// Size for face stream
faceOffset[celli] = (faceIndexer - startLabel);
vertOffset[celli] = hashUniqId.size();
if (prefix)
{
vertLabels[nVertLabels++] = hashUniqId.size();
}
const labelList uniq = hashUniqId.sortedToc();
forAll(uniq, i)
{
vertLabels[nVertLabels++] = uniq[i];
}
}
}
}
// ===========================================
// STAGE 3: Adjust vertOffset for all cells
// A second pass is needed for several reasons.
// - Additional (decomposed) cells are placed out of sequence
// - Internal format has the size prefixed, XML format does not.
// - XML format expects end-offsets, Internal expects begin-offsets
switch (output)
{
case contentType::LEGACY: // nothing to do
break;
case contentType::XML:
{
// No prefix, determine end offsets
// vertOffset[0] already contains its size
for (label i = 1; i < vertOffset.size(); ++i)
{
vertOffset[i] += vertOffset[i-1];
}
if (sizing.nFaceLabels())
{
// End face offsets, leaving -1 untouched
label prev = 0;
forAll(faceOffset, i)
{
const label sz = faceOffset[i];
if (sz > 0)
{
prev += sz;
faceOffset[i] = prev;
}
}
}
break;
}
case contentType::INTERNAL:
{
// Has prefix, determine begin offsets
label beg = 0;
forAll(vertOffset, i)
{
const label sz = vertOffset[i];
vertOffset[i] = beg;
beg += 1 + sz;
}
// Begin face offsets, leaving -1 untouched
if (sizing.nFaceLabels())
{
beg = 0;
forAll(faceOffset, i)
{
const label sz = faceOffset[i];
if (sz > 0)
{
faceOffset[i] = beg;
beg += sz;
}
}
}
break;
}
}
}
// ************************************************************************* //

Some files were not shown because too many files have changed in this diff Show More