ENH: adjust wrapping routines for new vtkCellArray definition

- the vtkCellArray internal structure was still largely oriented on
  the VTK legacy format, but has now been revised.
  https://gitlab.kitware.com/vtk/vtk/merge_requests/5682

  The `VTK_CELL_ARRAY_V2` define from vtkCellArray.h indicates
  that the newer version is being used.

* In VTK-8.2.0 and older, sizes are interwoven (prefixed) in the
  connectivity.

  Connectivity: [n1, verts..., n2, verts... ]

  When using these in vtkUnstructuredGrid, also needed a secondary
  list of offsets for each of the starting locations.

* The update version now resembles a CompactListList. For example

  Connectivity: [verts..., verts... ]
  Offsets:      [0, n1, n1+n2, n1+n2+n3... ]

  The offsets are properly handled within vtkCellArray, and dropped as
  an additional input for vtkUnstructuredGrid.
This commit is contained in:
Mark Olesen
2020-01-24 13:01:38 +01:00
parent f4ee841c6d
commit 9338f0b860
14 changed files with 648 additions and 461 deletions

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2019 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -70,8 +70,6 @@ class vtkDataSet;
class vtkCellData;
class vtkPointData;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace vtk
@ -185,15 +183,6 @@ namespace Tools
const label size
);
//- Wrap vtkCellArray as a UList
inline UList<vtkIdType> asUList
(
vtkCellArray* cells,
const label nCells,
const label size
);
//- Return a list of points as vtkPoints
inline vtkSmartPointer<vtkPoints> Points
(

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2019 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -25,6 +25,8 @@ License
\*---------------------------------------------------------------------------*/
#include <numeric>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
inline Foam::UList<uint8_t> Foam::vtk::Tools::asUList
@ -53,19 +55,6 @@ inline Foam::UList<vtkIdType> Foam::vtk::Tools::asUList
}
inline Foam::UList<vtkIdType> Foam::vtk::Tools::asUList
(
vtkCellArray* cells,
const label nCells,
const label size
)
{
cells->GetData()->SetNumberOfTuples(size);
return UList<vtkIdType>(cells->WritePointer(nCells, size), size);
}
inline vtkSmartPointer<vtkPoints>
Foam::vtk::Tools::Points(const UList<point>& pts)
{
@ -150,20 +139,72 @@ inline vtkSmartPointer<vtkCellArray> Foam::vtk::Tools::identityVertices
const label size
)
{
// VTK_VERTEX: need 2 values (size=1 and index=id) per vertex
auto cells = vtkSmartPointer<vtkCellArray>::New();
UList<vtkIdType> list = asUList(cells, size, 2*size);
#ifdef VTK_CELL_ARRAY_V2
// Offsets
// [0, n1, n1+n2, n1+n2+n3... ]
auto offsets = vtkSmartPointer<vtkIdTypeArray>::New();
{
const vtkIdType nOffsets(size+1);
offsets->SetNumberOfTuples(nOffsets);
vtkIdType* iter = offsets->WritePointer(0, nOffsets);
std::iota(iter, (iter + nOffsets), vtkIdType(0));
}
auto connect = vtkSmartPointer<vtkIdTypeArray>::New();
// Connectivity
{
const vtkIdType nConnect(size);
connect->SetNumberOfTuples(nConnect);
vtkIdType* iter = connect->WritePointer(0, nConnect);
std::iota(iter, (iter + nConnect), vtkIdType(0));
}
// Move into a vtkCellArray
cells->SetData(offsets, connect);
#else
// In VTK-8.2.0 and older,
// sizes are interwoven (prefixed) in the connectivity
// Connectivity size, with prefixed size information
// Cell connectivity for vertex
// [size, ids.., size, ids...] -> therefore [1, id, 1, id, ...]
auto iter = list.begin();
for (label id=0; id < size; ++id)
const vtkIdType nElem(size);
const vtkIdType nConnect(2*size);
{
*(iter++) = 1;
*(iter++) = id;
cells->GetData()->SetNumberOfTuples(nConnect);
vtkIdType* iter = cells->WritePointer(nElem, nConnect);
// Fill in the connectivity array, with prefixed size information
for (vtkIdType id = 0; id < nElem; ++id)
{
*(iter++) = 1;
*(iter++) = id;
}
}
#endif
return cells;
};

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2019 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -43,30 +43,99 @@ template<class Face>
vtkSmartPointer<vtkCellArray>
Foam::vtk::Tools::Faces(const UList<Face>& faces)
{
label nAlloc = faces.size();
for (const auto& f : faces)
auto cells = vtkSmartPointer<vtkCellArray>::New();
#ifdef VTK_CELL_ARRAY_V2
// Offsets
// [0, n1, n1+n2, n1+n2+n3... ]
const vtkIdType nOffsets(faces.size()+1);
auto offsets = vtkSmartPointer<vtkIdTypeArray>::New();
vtkIdType nConnect(0);
{
nAlloc += f.size();
}
offsets->SetNumberOfTuples(nOffsets);
auto vtkcells = vtkSmartPointer<vtkCellArray>::New();
vtkIdType* iter = offsets->WritePointer(0, nOffsets);
UList<vtkIdType> list = asUList(vtkcells, faces.size(), nAlloc);
// Assign offsets, determine overall connectivity size
// Cell connectivity for polygons
// [size, verts..., size, verts... ]
auto iter = list.begin();
for (const auto& f : faces)
{
*(iter++) = f.size();
for (const label verti : f)
*iter = 0;
for (const auto& f : faces)
{
*(iter++) = verti;
nConnect += f.size();
*(++iter) = nConnect;
}
}
return vtkcells;
// Cell connectivity for polygons
// [verts..., verts... ]
auto connect = vtkSmartPointer<vtkIdTypeArray>::New();
{
connect->SetNumberOfTuples(nConnect);
vtkIdType* iter = connect->WritePointer(0, nConnect);
// Fill in the connectivity array
for (const auto& f : faces)
{
for (const label verti : f)
{
*(iter++) = verti;
}
}
}
// Move into a vtkCellArray
cells->SetData(offsets, connect);
#else
// In VTK-8.2.0 and older,
// sizes are interwoven (prefixed) in the connectivity
// Cell connectivity for polygons
// [n1, verts..., n2, verts... ]
const vtkIdType nElem(faces.size());
// Connectivity size, with prefixed size information
vtkIdType nConnect(faces.size());
for (const auto& f : faces)
{
nConnect += f.size();
}
{
cells->GetData()->SetNumberOfTuples(nConnect);
vtkIdType* iter = cells->WritePointer(nElem, nConnect);
// Fill in the connectivity array, with prefixed size information
for (const auto& f : faces)
{
*(iter++) = f.size();
for (const label verti : f)
{
*(iter++) = verti;
}
}
}
#endif
return cells;
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2019 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -52,20 +52,15 @@ SourceFiles
#include "foamVtkMeshMaps.H"
#include "foamVtuSizing.H"
#include "vtkSmartPointer.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkUnstructuredGrid.h"
#include "vtkMultiBlockDataSet.h"
// * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
class vtkCellArray;
// Forward Declarations
class vtkDataSet;
class vtkFloatArray;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace vtk

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2019 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -103,89 +103,127 @@ Foam::vtk::vtuAdaptor::internal
const bool decompPoly
)
{
const vtk::vtuSizing::contentType output
(
#ifdef VTK_CELL_ARRAY_V2
vtk::vtuSizing::contentType::INTERNAL2
#else
vtk::vtuSizing::contentType::INTERNAL1
#endif
);
vtk::vtuSizing sizing(mesh, decompPoly);
auto vtkmesh = vtkSmartPointer<vtkUnstructuredGrid>::New();
auto cellTypes = vtkSmartPointer<vtkUnsignedCharArray>::New();
UList<uint8_t> cellTypesUL
(
vtk::Tools::asUList(cellTypes, sizing.nFieldCells())
);
auto cells = vtkSmartPointer<vtkCellArray>::New();
auto faces = vtkSmartPointer<vtkIdTypeArray>::New();
auto cellLocations = vtkSmartPointer<vtkIdTypeArray>::New();
auto cellOffsets = vtkSmartPointer<vtkIdTypeArray>::New();
auto faceLocations = vtkSmartPointer<vtkIdTypeArray>::New();
UList<uint8_t> cellTypesUL =
vtk::Tools::asUList(cellTypes, sizing.nFieldCells());
const auto nConnect
(
sizing.sizeOf(output, vtk::vtuSizing::slotType::CELLS)
);
UList<vtkIdType> cellsUL =
UList<vtkIdType> cellOffsetsUL
(
vtk::Tools::asUList
(
cells,
sizing.nFieldCells(),
sizing.sizeInternal(vtk::vtuSizing::slotType::CELLS)
);
cellOffsets,
sizing.sizeOf(output, vtk::vtuSizing::slotType::CELLS_OFFSETS)
)
);
UList<vtkIdType> cellLocationsUL =
vtk::Tools::asUList
(
cellLocations,
sizing.sizeInternal(vtk::vtuSizing::slotType::CELLS_OFFSETS)
);
#ifdef VTK_CELL_ARRAY_V2
UList<vtkIdType> facesUL =
auto cellConnect = vtkSmartPointer<vtkIdTypeArray>::New();
UList<vtkIdType> cellsUL
(
vtk::Tools::asUList(cellConnect, nConnect)
);
#else
cells->GetData()->SetNumberOfTuples(sizing.nFieldCells());
UList<vtkIdType> cellsUL
(
cells->WritePointer(sizing.nFieldCells(), nConnect),
nConnect
);
#endif
UList<vtkIdType> facesUL
(
vtk::Tools::asUList
(
faces,
sizing.sizeInternal(vtk::vtuSizing::slotType::FACES)
);
sizing.sizeOf(output, vtk::vtuSizing::slotType::FACES)
)
);
UList<vtkIdType> faceLocationsUL =
UList<vtkIdType> faceLocationsUL
(
vtk::Tools::asUList
(
faceLocations,
sizing.sizeInternal(vtk::vtuSizing::slotType::FACES_OFFSETS)
);
sizing.sizeOf(output, vtk::vtuSizing::slotType::FACES_OFFSETS)
)
);
sizing.populateInternal
(
mesh,
cellTypesUL,
cellsUL,
cellLocationsUL,
facesUL,
faceLocationsUL,
static_cast<foamVtkMeshMaps&>(*this)
cellsUL, cellOffsetsUL,
facesUL, faceLocationsUL,
static_cast<foamVtkMeshMaps&>(*this),
output
);
auto vtkmesh = vtkSmartPointer<vtkUnstructuredGrid>::New();
// Convert OpenFOAM mesh vertices to VTK
// - can only do this *after* populating the decompInfo with cell-ids
// for any additional points (ie, mesh cell-centres)
vtkmesh->SetPoints(this->points(mesh));
#ifdef VTK_CELL_ARRAY_V2
// Move into a vtkCellArray
cells->SetData(cellOffsets, cellConnect);
if (facesUL.size())
{
vtkmesh->SetCells
(
cellTypes,
cellLocations,
cells,
faceLocations,
faces
);
vtkmesh->SetCells(cellTypes, cells, faceLocations, faces);
}
else
{
vtkmesh->SetCells
(
cellTypes,
cellLocations,
cells,
nullptr,
nullptr
);
vtkmesh->SetCells(cellTypes, cells, nullptr, nullptr);
}
#else
if (facesUL.size())
{
vtkmesh->SetCells(cellTypes, cellOffsets, cells, faceLocations, faces);
}
else
{
vtkmesh->SetCells(cellTypes, cellOffsets, cells, nullptr, nullptr);
}
#endif
return vtkmesh;
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,6 +37,7 @@ Description
for additional points of decomposed cells
SourceFiles
foamVtkMeshMaps.C
foamVtkMeshMapsI.H
\*---------------------------------------------------------------------------*/
@ -74,12 +75,11 @@ public:
// Constructors
//- Construct null
inline explicit foamVtkMeshMaps(const label size = 0);
//- Default construct: zero-sized, no reserved size
inline foamVtkMeshMaps();
//- Destructor
~foamVtkMeshMaps() = default;
//- Construct with reserved size
inline explicit foamVtkMeshMaps(const label size);
// Member Functions
@ -92,17 +92,26 @@ public:
// cells this becomes a useful means of mapping from the original mesh.
inline const labelList& cellMap() const;
//- Write access to original cell ids
inline DynamicList<label>& cellMap();
//- Point labels for subsetted meshes
inline const labelList& pointMap() const;
//- Write access to point labels for subsetted meshes
inline DynamicList<label>& pointMap();
//- Any additional (user) labels.
// Eg, cell-centre labels for additional points of decomposed cells
inline const labelList& additionalIds() const;
//- Write access to additional (user) labels.
inline DynamicList<label>& additionalIds();
// Edit
//- Clear
//- Clear sizing
inline void clear();
//- Renumber cell ids (cellMap and additionalIds) to account for
@ -111,22 +120,6 @@ public:
//- Renumber point ids (pointMap) to account for subset meshes
void renumberPoints(const labelUList& 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();
};

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,6 +29,14 @@ License
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::foamVtkMeshMaps::foamVtkMeshMaps()
:
cellMap_(0),
pointMap_(0),
additionalIds_(0)
{}
inline Foam::foamVtkMeshMaps::foamVtkMeshMaps(const label size)
:
cellMap_(size),

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2018 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -108,15 +108,16 @@ void Foam::vtk::vtuCells::repopulate(const polyMesh& mesh)
{
// vtuSizing::reset() called prior to this method
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));
cellTypes_.resize(nFieldCells());
vertLabels_.resize(sizeOf(output_, slotType::CELLS));
vertOffset_.resize(sizeOf(output_, slotType::CELLS_OFFSETS));
faceLabels_.resize(sizeOf(output_, slotType::FACES));
faceOffset_.resize(sizeOf(output_, slotType::FACES_OFFSETS));
switch (output_)
{
case contentType::LEGACY:
{
populateLegacy
(
mesh,
@ -125,7 +126,10 @@ void Foam::vtk::vtuCells::repopulate(const polyMesh& mesh)
maps_
);
break;
}
case contentType::XML:
{
populateXml
(
mesh,
@ -137,7 +141,11 @@ void Foam::vtk::vtuCells::repopulate(const polyMesh& mesh)
maps_
);
break;
case contentType::INTERNAL:
}
case contentType::INTERNAL1:
case contentType::INTERNAL2:
{
populateInternal
(
mesh,
@ -146,9 +154,11 @@ void Foam::vtk::vtuCells::repopulate(const polyMesh& mesh)
vertOffset_,
faceLabels_,
faceOffset_,
maps_
maps_,
output_
);
break;
}
}
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2019 OpenCFD Ltd.
Copyright (C) 2014-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -52,7 +52,6 @@ SourceFiles
#include "foamVtkCore.H"
#include "foamVtkMeshMaps.H"
#include "foamVtuSizing.H"
#include "DynamicList.H"
#include "labelList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -60,12 +59,12 @@ SourceFiles
namespace Foam
{
// Forward declarations
// Forward Declarations
class polyMesh;
namespace vtk
{
// Forward declarations
// Forward Declarations
class outputOptions;
/*---------------------------------------------------------------------------*\
@ -76,7 +75,7 @@ class vtuCells
:
public vtuSizing
{
// Private Member Data
// Private Data
// Requested output types
@ -112,7 +111,7 @@ class vtuCells
// Private Member Functions
//- Create the geometry using the previously requested output and
// decomposition types.
//- decomposition types.
void repopulate(const polyMesh& mesh);
//- No copy construct
@ -126,17 +125,15 @@ public:
// Constructors
//- Construct from components.
// Optionally with polyhedral decomposition.
vtuCells
//- Default construct (XML format, no polyhedral decomposition)
explicit vtuCells
(
const enum contentType output = contentType::XML,
const bool decompose = false
);
//- Construct from components and create the output information
//- immediately
vtuCells
//- Construct from components, create output information immediately
explicit vtuCells
(
const polyMesh& mesh,
const enum contentType output = contentType::XML,
@ -145,14 +142,13 @@ public:
//- Construct from components.
// Optionally with polyhedral decomposition.
vtuCells
explicit vtuCells
(
const vtk::outputOptions opts,
const bool decompose = false
);
//- Construct from components, and create the output information
//- immediately
//- Construct from components, create output information immediately
vtuCells
(
const polyMesh& mesh,
@ -161,10 +157,6 @@ public:
);
//- Destructor
~vtuCells() = default;
// Member Functions
// Access
@ -229,7 +221,6 @@ public:
//- Original cell ids for all cells (regular and decomposed).
inline const labelList& cellMap() const;
};

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2019 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,7 +29,6 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline enum Foam::vtk::vtuCells::contentType
Foam::vtk::vtuCells::content() const
{

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2018 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,14 +37,14 @@ License
void Foam::vtk::vtuSizing::presizeMaps(foamVtkMeshMaps& maps) const
{
maps.cellMap().setSize(this->nFieldCells());
maps.additionalIds().setSize(this->nAddPoints());
maps.cellMap().resize(this->nFieldCells());
maps.additionalIds().resize(this->nAddPoints());
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::vtk::vtuSizing::vtuSizing()
Foam::vtk::vtuSizing::vtuSizing() noexcept
{
clear();
}
@ -63,7 +63,7 @@ Foam::vtk::vtuSizing::vtuSizing
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtk::vtuSizing::clear()
void Foam::vtk::vtuSizing::clear() noexcept
{
decompose_ = false;
nCells_ = 0;
@ -232,6 +232,7 @@ Foam::label Foam::vtk::vtuSizing::sizeOf
}
break;
}
case contentType::XML:
{
switch (slot)
@ -254,7 +255,8 @@ Foam::label Foam::vtk::vtuSizing::sizeOf
}
break;
}
case contentType::INTERNAL:
case contentType::INTERNAL1:
{
switch (slot)
{
@ -277,6 +279,29 @@ Foam::label Foam::vtk::vtuSizing::sizeOf
}
break;
}
case contentType::INTERNAL2:
{
switch (slot)
{
case slotType::CELLS:
return (nVertLabels() + nAddVerts());
break;
case slotType::CELLS_OFFSETS:
return (nFieldCells() + 1);
break;
case slotType::FACES:
return nFaceLabels();
break;
case slotType::FACES_OFFSETS:
return nFaceLabels() ? nFieldCells() : 0;
break;
}
break;
}
}
return 0;
@ -343,175 +368,73 @@ void Foam::vtk::vtuSizing::populateXml
}
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()
);
}
#undef definePopulateInternalMethod
#define definePopulateInternalMethod(Type) \
\
void Foam::vtk::vtuSizing::populateInternal \
( \
const polyMesh& mesh, \
UList<uint8_t>& cellTypes, \
UList<Type>& connectivity, \
UList<Type>& offsets, \
UList<Type>& faces, \
UList<Type>& facesOffsets, \
foamVtkMeshMaps& maps, \
const enum contentType output \
) const \
{ \
presizeMaps(maps); \
\
populateArrays \
( \
mesh, \
*this, \
cellTypes, \
connectivity, \
offsets, \
faces, \
facesOffsets, \
output, \
maps.cellMap(), \
maps.additionalIds() \
); \
} \
\
void Foam::vtk::vtuSizing::populateInternal \
( \
const polyMesh& mesh, \
UList<uint8_t>& cellTypes, \
UList<Type>& connectivity, \
UList<Type>& offsets, \
UList<Type>& faces, \
UList<Type>& facesOffsets, \
labelUList& cellMap, \
labelUList& addPointsIds, \
const enum contentType output \
) const \
{ \
populateArrays \
( \
mesh, \
*this, \
cellTypes, \
connectivity, \
offsets, \
faces, \
facesOffsets, \
output, \
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,
foamVtkMeshMaps& maps
) const
{
presizeMaps(maps);
populateArrays
(
mesh,
*this,
cellTypes,
connectivity,
offsets,
faces,
facesOffsets,
contentType::INTERNAL,
maps.cellMap(),
maps.additionalIds()
);
}
definePopulateInternalMethod(int);
definePopulateInternalMethod(long);
definePopulateInternalMethod(long long);
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,
labelUList& cellMap,
labelUList& 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,
labelUList& cellMap,
labelUList& 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,
labelUList& cellMap,
labelUList& addPointsIds
) const
{
populateArrays
(
mesh,
*this,
cellTypes,
connectivity,
offsets,
faces,
facesOffsets,
contentType::INTERNAL,
cellMap,
addPointsIds
);
}
#undef definePopulateInternalMethod
// * * * * * * * * * * * * * * Renumber vertices * * * * * * * * * * * * * * //
@ -559,7 +482,7 @@ void Foam::vtk::vtuSizing::renumberVertLabelsLegacy
// Therefore anything with 18 labels or more must be a poly
auto iter = vertLabels.begin();
auto last = vertLabels.end();
const auto last = vertLabels.end();
while (iter < last)
{
@ -671,7 +594,7 @@ void Foam::vtk::vtuSizing::renumberFaceLabelsXml
// [nFaces, nFace0Pts, id1,id2,..., nFace1Pts, id1,id2,...]
auto iter = faceLabels.begin();
auto last = faceLabels.end();
const auto last = faceLabels.end();
while (iter < last)
{

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2018 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -66,7 +66,7 @@ Description
\endtable
\table
internal storage
internal1 storage (VTK-8 and earlier)
\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
@ -75,6 +75,16 @@ Description
\c facelocation | begin location for each of \c faces, with -1 for primitive cells
\endtable
\table
internal2 storage (with VTK_CELL_ARRAY_V2)
\c types | vtk cell type (1-255)
\c connectivity | unique vertex labels used by the cell
\c offsets | begin/end offsets for \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.
@ -85,6 +95,10 @@ Note
since it likely more efficient to use VTK point-blanking to mark duplicate
points instead of merging points ourselves.
Note
The VTK_CELL_ARRAY_V2 define (from vtkCellArray.h) indicates if the new
(internal2) new format is being used.
SourceFiles
foamVtuSizing.C
foamVtuSizingI.H
@ -103,7 +117,7 @@ SourceFiles
namespace Foam
{
// Forward declarations
// Forward Declarations
class polyMesh;
namespace vtk
@ -117,23 +131,25 @@ class vtuSizing
{
public:
// Public data
// Public Data
//- Types of content that the storage may represent
enum contentType
{
LEGACY, //!< Legacy VTK content
XML, //!< XML (VTU) content
INTERNAL //!< Internal vtkUnstructuredGrid content
INTERNAL1, //!< Internal vtkUnstructuredGrid content
INTERNAL2 //!< Internal vtkUnstructuredGrid content, VTK_CELL_ARRAY_V2
};
//- The possible storage 'slots' that can be used
enum slotType
{
CELLS, //!< Cell connectivity (ALL)
CELLS_OFFSETS, //!< End-offsets (XML) or locations (INTERNAL) for cells
CELLS_OFFSETS, //!< Cell end-offsets (XML), locations (INTERNAL1)
//!< or begin/end offsets (INTERNAL2)
FACES, //!< Face-stream (XML, INTERNAL)
FACES_OFFSETS //!< End-offsets (XML) or locations (INTERNAL) for faces
FACES_OFFSETS //!< Faces end-offsets (XML) or locations (INTERNAL1)
};
@ -153,6 +169,7 @@ private:
//- Number of vertex labels to represent the mesh
label nVertLabels_;
// Polyhedrals
//- Number of polyhedral face labels for the mesh
@ -164,6 +181,7 @@ private:
//- Number of vertex labels used by polyhedrals
label nVertPoly_;
// Decomposed polyhedrals
//- Number of additional (decomposed) cells for the mesh
@ -202,8 +220,8 @@ public:
// Constructors
//- Construct null.
vtuSizing();
//- Default construct
vtuSizing() noexcept;
//- Construct sizing by analyzing the mesh.
// No polyhedral decomposition.
@ -214,10 +232,6 @@ public:
vtuSizing(const polyMesh& mesh, const bool decompose);
//- Destructor
~vtuSizing() = default;
// Member Functions
// Edit
@ -227,7 +241,7 @@ public:
void reset(const polyMesh& mesh, const bool decompose=false);
//- Reset all sizes to zero.
void clear();
void clear() noexcept;
// Access
@ -290,7 +304,10 @@ public:
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;
inline label sizeInternal1(const enum slotType slot) const;
//- The calculated size for vtk-internal storage of the specified slot
inline label sizeInternal2(const enum slotType slot) const;
// Routines for populating the output lists
@ -316,80 +333,45 @@ public:
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;
// Internal types. The size of vtkIdType is unknown here
//- 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;
#undef declarePopulateInternalMethod
#define declarePopulateInternalMethod(Type) \
\
/*! Populate lists for Internal VTK format */ \
void populateInternal \
( \
const polyMesh& mesh, \
UList<uint8_t>& cellTypes, \
UList<Type>& connectivity, \
UList<Type>& offsets, \
UList<Type>& faces, \
UList<Type>& facesOffsets, \
foamVtkMeshMaps& maps, \
const enum contentType output \
) const; \
\
/*! Populate lists for Internal VTK format */ \
void populateInternal \
( \
const polyMesh& mesh, \
UList<uint8_t>& cellTypes, \
UList<Type>& connectivity, \
UList<Type>& offsets, \
UList<Type>& faces, \
UList<Type>& facesOffsets, \
labelUList& cellMap, \
labelUList& addPointsIds, \
const enum contentType output \
) 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,
labelUList& cellMap,
labelUList& 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,
labelUList& cellMap,
labelUList& addPointsIds
) const;
declarePopulateInternalMethod(int);
declarePopulateInternalMethod(long);
declarePopulateInternalMethod(long long);
//- 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,
labelUList& cellMap,
labelUList& addPointsIds
) const;
#undef declarePopulateInternalMethod
// Routines for renumber vertices with a global point offset
@ -465,7 +447,6 @@ public:
//- Test inequality
bool operator!=(const vtuSizing& rhs) const;
};

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2018 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -125,12 +125,21 @@ inline Foam::label Foam::vtk::vtuSizing::sizeXml
}
inline Foam::label Foam::vtk::vtuSizing::sizeInternal
inline Foam::label Foam::vtk::vtuSizing::sizeInternal1
(
const enum slotType slot
) const
{
return sizeOf(contentType::INTERNAL, slot);
return sizeOf(contentType::INTERNAL1, slot);
}
inline Foam::label Foam::vtk::vtuSizing::sizeInternal2
(
const enum slotType slot
) const
{
return sizeOf(contentType::INTERNAL2, slot);
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -47,6 +47,17 @@ void Foam::vtk::vtuSizing::populateArrays
UList<LabelType2>& addPointsIds
)
{
// Characteristics
// Are vertLabels prefixed with the size?
// Also use as the size of the prefixed information
const int prefix =
(
output == contentType::LEGACY
|| output == contentType::INTERNAL1
) ? 1 : 0;
// STAGE 1: Verify storage sizes
if (cellTypes.size() != sizing.nFieldCells())
@ -73,10 +84,6 @@ void Foam::vtk::vtuSizing::populateArrays
<< 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:
@ -90,6 +97,7 @@ void Foam::vtk::vtuSizing::populateArrays
}
break;
}
case contentType::XML:
{
// XML uses connectivity/offset pair.
@ -149,32 +157,33 @@ void Foam::vtk::vtuSizing::populateArrays
}
break;
}
case contentType::INTERNAL:
case contentType::INTERNAL1:
{
// VTK-internal connectivity/offset pair.
// VTK-internal1 connectivity/offset pair.
if
(
vertLabels.size()
!= sizing.sizeInternal(slotType::CELLS)
!= sizing.sizeInternal1(slotType::CELLS)
)
{
FatalErrorInFunction
<< " connectivity size=" << vertLabels.size()
<< " expected "
<< sizing.sizeInternal(slotType::CELLS)
<< sizing.sizeInternal1(slotType::CELLS)
<< exit(FatalError);
}
if
(
vertOffset.size()
!= sizing.sizeInternal(slotType::CELLS_OFFSETS)
!= sizing.sizeInternal1(slotType::CELLS_OFFSETS)
)
{
FatalErrorInFunction
<< " offsets size=" << vertOffset.size()
<< " expected "
<< sizing.sizeInternal(slotType::CELLS_OFFSETS)
<< sizing.sizeInternal1(slotType::CELLS_OFFSETS)
<< exit(FatalError);
}
@ -183,26 +192,86 @@ void Foam::vtk::vtuSizing::populateArrays
if
(
faceLabels.size()
!= sizing.sizeInternal(slotType::FACES)
!= sizing.sizeInternal1(slotType::FACES)
)
{
FatalErrorInFunction
<< " faces size=" << faceLabels.size()
<< " expected "
<< sizing.sizeInternal(slotType::FACES)
<< sizing.sizeInternal1(slotType::FACES)
<< exit(FatalError);
}
if
(
faceOffset.size()
!= sizing.sizeInternal(slotType::FACES_OFFSETS)
!= sizing.sizeInternal1(slotType::FACES_OFFSETS)
)
{
FatalErrorInFunction
<< " facesOffsets size=" << faceOffset.size()
<< " expected "
<< sizing.sizeInternal(slotType::FACES_OFFSETS)
<< sizing.sizeInternal1(slotType::FACES_OFFSETS)
<< exit(FatalError);
}
}
break;
}
case contentType::INTERNAL2:
{
// VTK-internal2 connectivity/offset pair.
if
(
vertLabels.size()
!= sizing.sizeInternal2(slotType::CELLS)
)
{
FatalErrorInFunction
<< " connectivity size=" << vertLabels.size()
<< " expected "
<< sizing.sizeInternal2(slotType::CELLS)
<< exit(FatalError);
}
if
(
vertOffset.size()
!= sizing.sizeInternal2(slotType::CELLS_OFFSETS)
)
{
FatalErrorInFunction
<< " offsets size=" << vertOffset.size()
<< " expected "
<< sizing.sizeInternal2(slotType::CELLS_OFFSETS)
<< exit(FatalError);
}
if (sizing.nFaceLabels())
{
if
(
faceLabels.size()
!= sizing.sizeInternal2(slotType::FACES)
)
{
FatalErrorInFunction
<< " faces size=" << faceLabels.size()
<< " expected "
<< sizing.sizeInternal2(slotType::FACES)
<< exit(FatalError);
}
if
(
faceOffset.size()
!= sizing.sizeInternal2(slotType::FACES_OFFSETS)
)
{
FatalErrorInFunction
<< " facesOffsets size=" << faceOffset.size()
<< " expected "
<< sizing.sizeInternal2(slotType::FACES_OFFSETS)
<< exit(FatalError);
}
}
@ -211,8 +280,20 @@ void Foam::vtk::vtuSizing::populateArrays
}
// Initialization
faceOffset = -1;
// For INTERNAL2, the vertOffset is (nFieldCells+1), which means that
// the last entry is never visited. Set as zero now.
if (vertOffset.size())
{
vertOffset.first() = 0;
vertOffset.last() = 0;
}
const cellModel& tet = cellModel::ref(cellModel::TET);
const cellModel& pyr = cellModel::ref(cellModel::PYR);
const cellModel& prism = cellModel::ref(cellModel::PRISM);
@ -222,11 +303,11 @@ void Foam::vtk::vtuSizing::populateArrays
const cellShapeList& shapes = mesh.cellShapes();
// face owner is needed to determine the face orientation
// The face owner is needed to determine the face orientation
const labelList& owner = mesh.faceOwner();
// Unique vertex labels per polyhedral
labelHashSet hashUniqId(2*256);
labelHashSet hashUniqId(512);
// Index into vertLabels, faceLabels for normal cells
label nVertLabels = 0;
@ -277,13 +358,15 @@ void Foam::vtk::vtuSizing::populateArrays
if (model == tet)
{
cellTypes[celli] = vtk::cellType::VTK_TETRA;
constexpr label nShapePoints = 4; // OR shape.size();
if (vertOffset.size())
{
vertOffset[celli] = shape.size();
vertOffset[celli] = nShapePoints;
}
if (prefix)
{
vertLabels[nVertLabels++] = shape.size();
vertLabels[nVertLabels++] = nShapePoints;
}
for (const label cpi : shape)
@ -294,13 +377,15 @@ void Foam::vtk::vtuSizing::populateArrays
else if (model == pyr)
{
cellTypes[celli] = vtk::cellType::VTK_PYRAMID;
constexpr label nShapePoints = 5; // OR shape.size();
if (vertOffset.size())
{
vertOffset[celli] = shape.size();
vertOffset[celli] = nShapePoints;
}
if (prefix)
{
vertLabels[nVertLabels++] = shape.size();
vertLabels[nVertLabels++] = nShapePoints;
}
for (const label cpi : shape)
@ -311,13 +396,15 @@ void Foam::vtk::vtuSizing::populateArrays
else if (model == hex)
{
cellTypes[celli] = vtk::cellType::VTK_HEXAHEDRON;
constexpr label nShapePoints = 8; // OR shape.size();
if (vertOffset.size())
{
vertOffset[celli] = shape.size();
vertOffset[celli] = nShapePoints;
}
if (prefix)
{
vertLabels[nVertLabels++] = shape.size();
vertLabels[nVertLabels++] = nShapePoints;
}
for (const label cpi : shape)
@ -328,13 +415,15 @@ void Foam::vtk::vtuSizing::populateArrays
else if (model == prism)
{
cellTypes[celli] = vtk::cellType::VTK_WEDGE;
constexpr label nShapePoints = 6; // OR shape.size();
if (vertOffset.size())
{
vertOffset[celli] = shape.size();
vertOffset[celli] = nShapePoints;
}
if (prefix)
{
vertLabels[nVertLabels++] = shape.size();
vertLabels[nVertLabels++] = nShapePoints;
}
// VTK_WEDGE triangles point outwards (swap 1<->2, 4<->5)
@ -349,13 +438,15 @@ void Foam::vtk::vtuSizing::populateArrays
{
// Treat as squeezed prism
cellTypes[celli] = vtk::cellType::VTK_WEDGE;
constexpr label nShapePoints = 6;
if (vertOffset.size())
{
vertOffset[celli] = 6;
vertOffset[celli] = nShapePoints;
}
if (prefix)
{
vertLabels[nVertLabels++] = 6;
vertLabels[nVertLabels++] = nShapePoints;
}
vertLabels[nVertLabels++] = shape[0];
@ -369,13 +460,15 @@ void Foam::vtk::vtuSizing::populateArrays
{
// Treat as squeezed hex
cellTypes[celli] = vtk::cellType::VTK_HEXAHEDRON;
constexpr label nShapePoints = 8;
if (vertOffset.size())
{
vertOffset[celli] = 8;
vertOffset[celli] = nShapePoints;
}
if (prefix)
{
vertLabels[nVertLabels++] = 8;
vertLabels[nVertLabels++] = nShapePoints;
}
vertLabels[nVertLabels++] = shape[0];
@ -427,7 +520,7 @@ void Foam::vtk::vtuSizing::populateArrays
{
// Quad becomes a pyramid
const label nShapePoints = 5; // pyr (5 vertices)
constexpr label nShapePoints = 5; // pyr (5 vertices)
label celLoc, vrtLoc;
if (first)
@ -479,7 +572,7 @@ void Foam::vtk::vtuSizing::populateArrays
{
// Triangle becomes a tetrahedral
const label nShapePoints = 4; // tet (4 vertices)
constexpr label nShapePoints = 4; // tet (4 vertices)
label celLoc, vrtLoc;
if (first)
@ -604,8 +697,12 @@ void Foam::vtk::vtuSizing::populateArrays
// 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
// - INTERNAL1 connectivity has size prefixed
//
// Cell offsets:
// - XML format expects end-offsets,
// - INTERNAL1 expects begin-offsets
// - INTERNAL2 expects begin/end-offsets
switch (output)
{
@ -614,17 +711,19 @@ void Foam::vtk::vtuSizing::populateArrays
case contentType::XML:
{
// No prefix, determine end offsets
// vertOffset[0] already contains its size
// Transform cell sizes (vertOffset) into begin offsets
// vertOffset[0] already contains its size, leave untouched
for (label i = 1; i < vertOffset.size(); ++i)
{
vertOffset[i] += vertOffset[i-1];
}
// The end face offsets, leaving -1 untouched
if (sizing.nFaceLabels())
{
// End face offsets, leaving -1 untouched
LabelType prev = 0;
LabelType prev(0);
for (LabelType& off : faceOffset)
{
const auto sz = off;
@ -637,21 +736,63 @@ void Foam::vtk::vtuSizing::populateArrays
}
break;
}
case contentType::INTERNAL:
case contentType::INTERNAL1:
{
// Has prefix, determine begin offsets
label beg = 0;
for (LabelType& off : vertOffset)
// Transform cell sizes (vertOffset) into begin offsets
{
const auto sz = off;
off = beg;
beg += 1 + sz;
LabelType beg(0);
for (LabelType& off : vertOffset)
{
const auto sz = off;
off = beg;
beg += 1 + sz; // Additional 1 to skip embedded prefix
}
}
// Begin face offsets, leaving -1 untouched
// The begin face offsets, leaving -1 untouched
if (sizing.nFaceLabels())
{
beg = 0;
LabelType beg(0);
for (LabelType& off : faceOffset)
{
const auto sz = off;
if (sz > 0)
{
off = beg;
beg += sz;
}
}
}
break;
}
case contentType::INTERNAL2:
{
// Transform cell sizes (vertOffset) into begin/end offsets
// input [n1, n2, n3, ..., 0]
// becomes [0, n1, n1+n2, n1+n2+n3, ..., nTotal]
// The last entry of vertOffset was initialized as zero and
// never revisited, so the following loop is OK
{
LabelType total(0);
for (LabelType& off : vertOffset)
{
const auto sz = off;
off = total;
total += sz;
}
}
// The begin face offsets, leaving -1 untouched
if (sizing.nFaceLabels())
{
LabelType beg(0);
for (LabelType& off : faceOffset)
{
const auto sz = off;