Compile reverse connectivity builder into vtkm_cont library

Because `CellSetExplicit` is a templated class, the implementation of
most of its features is part of the header files. One of the things that
was included was the code to build the reverse connectivity links. That
is, it figured out which cells were incident on each point using the
standard connections of which points comprise which cells.

Of course, building these links is non-trivial, and it used multiple
DPPs to engage the device. It meant that header had to include the
device adapter algorithms and therefore required a device compiler. We
want to minimize this where possible.

To get around this issue, a non-templated function was added to find the
reverse connections of a `CellSetExplicit`. It does this by passing in
`UnknownArrayHandle`s for the input arrays. (The output visit-points-
with-cells arrays are standard across all template instances.) The
implementation first iterates over all `CellSetExplicit` versions in
`VTKM_DEFAULT_CELL_SETS` and attempts to retrieve arrays of those types.
In the unlikely event that none of these arrays work, it copies the data
to `ArrayHandle<vtkm::Id>` and uses those.
This commit is contained in:
Kenneth Moreland 2021-08-18 13:55:19 -06:00
parent 585ac97043
commit e74c0732c5
7 changed files with 326 additions and 227 deletions

@ -0,0 +1,21 @@
# Compile reverse connectivity builder into vtkm_cont library
Because `CellSetExplicit` is a templated class, the implementation of
most of its features is part of the header files. One of the things that
was included was the code to build the reverse connectivity links. That
is, it figured out which cells were incident on each point using the
standard connections of which points comprise which cells.
Of course, building these links is non-trivial, and it used multiple
DPPs to engage the device. It meant that header had to include the
device adapter algorithms and therefore required a device compiler. We
want to minimize this where possible.
To get around this issue, a non-templated function was added to find the
reverse connections of a `CellSetExplicit`. It does this by passing in
`UnknownArrayHandle`s for the input arrays. (The output visit-points-
with-cells arrays are standard across all template instances.) The
implementation first iterates over all `CellSetExplicit` versions in
`VTKM_DEFAULT_CELL_SETS` and attempts to retrieve arrays of those types.
In the unlikely event that none of these arrays work, it copies the data
to `ArrayHandle<vtkm::Id>` and uses those.

@ -11,6 +11,91 @@
#include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/DefaultTypes.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/internal/ReverseConnectivityBuilder.h>
namespace
{
template <typename ConnectStorage, typename OffsetStorage>
void DoBuildReverseConnectivity(
const vtkm::cont::ArrayHandle<vtkm::Id, ConnectStorage>& connections,
const vtkm::cont::ArrayHandle<vtkm::Id, OffsetStorage>& offsets,
vtkm::Id numberOfPoints,
vtkm::cont::detail::DefaultVisitPointsWithCellsConnectivityExplicit& visitPointsWithCells,
vtkm::cont::DeviceAdapterId suggestedDevice)
{
using CellsWithPointsConnectivity = vtkm::cont::internal::
ConnectivityExplicitInternals<VTKM_DEFAULT_STORAGE_TAG, ConnectStorage, OffsetStorage>;
// Make a fake visitCellsWithPoints to pass to ComputeRConnTable. This is a bit of a
// patchwork from changing implementation.
CellsWithPointsConnectivity visitCellsWithPoints;
visitCellsWithPoints.ElementsValid = true;
visitCellsWithPoints.Connectivity = connections;
visitCellsWithPoints.Offsets = offsets;
bool success =
vtkm::cont::TryExecuteOnDevice(suggestedDevice, [&](vtkm::cont::DeviceAdapterId realDevice) {
vtkm::cont::internal::ComputeRConnTable(
visitPointsWithCells, visitCellsWithPoints, numberOfPoints, realDevice);
return true;
});
if (!success)
{
throw vtkm::cont::ErrorExecution("Failed to run CellSetExplicit reverse "
"connectivity builder.");
}
}
struct BuildReverseConnectivityForCellSetType
{
template <typename ShapeStorage, typename ConnectStorage, typename OffsetStorage>
void operator()(
const vtkm::cont::CellSetExplicit<ShapeStorage, ConnectStorage, OffsetStorage>&,
const vtkm::cont::UnknownArrayHandle& connections,
const vtkm::cont::UnknownArrayHandle& offsets,
vtkm::Id numberOfPoints,
vtkm::cont::detail::DefaultVisitPointsWithCellsConnectivityExplicit& visitPointsWithCells,
vtkm::cont::DeviceAdapterId device)
{
if (visitPointsWithCells.ElementsValid)
{
return; // Already computed reverse
}
using ConnectArrayType = vtkm::cont::ArrayHandle<vtkm::Id, ConnectStorage>;
using OffsetArrayType = vtkm::cont::ArrayHandle<vtkm::Id, OffsetStorage>;
if (connections.CanConvert<ConnectArrayType>() && offsets.CanConvert<OffsetArrayType>())
{
DoBuildReverseConnectivity(connections.AsArrayHandle<ConnectArrayType>(),
offsets.AsArrayHandle<OffsetArrayType>(),
numberOfPoints,
visitPointsWithCells,
device);
}
}
template <typename CellSetType>
void operator()(const CellSetType&,
const vtkm::cont::UnknownArrayHandle&,
const vtkm::cont::UnknownArrayHandle&,
vtkm::Id,
vtkm::cont::detail::DefaultVisitPointsWithCellsConnectivityExplicit&,
vtkm::cont::DeviceAdapterId)
{
// Not an explicit cell set, so skip.
}
};
} // anonymous namespace
namespace vtkm
{
namespace cont
@ -21,5 +106,45 @@ template class VTKM_CONT_EXPORT
CellSetExplicit<typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag,
VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag>;
namespace detail
{
void BuildReverseConnectivity(
const vtkm::cont::UnknownArrayHandle& connections,
const vtkm::cont::UnknownArrayHandle& offsets,
vtkm::Id numberOfPoints,
vtkm::cont::detail::DefaultVisitPointsWithCellsConnectivityExplicit& visitPointsWithCells,
vtkm::cont::DeviceAdapterId device)
{
if (visitPointsWithCells.ElementsValid)
{
return; // Already computed
}
vtkm::ListForEach(BuildReverseConnectivityForCellSetType{},
VTKM_DEFAULT_CELL_SET_LIST{},
connections,
offsets,
numberOfPoints,
visitPointsWithCells,
device);
if (!visitPointsWithCells.ElementsValid)
{
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
"BuildReverseConnectivity failed for all known cell set types. "
"Attempting to copy connectivity arrays.");
vtkm::cont::ArrayHandle<vtkm::Id> connectionsCopy;
vtkm::cont::ArrayCopy(connections, connectionsCopy);
vtkm::cont::ArrayHandle<vtkm::Id> offsetsCopy;
vtkm::cont::ArrayCopy(offsets, offsetsCopy);
DoBuildReverseConnectivity(
connectionsCopy, offsetsCopy, numberOfPoints, visitPointsWithCells, device);
}
}
}
} // namespace vtkm::cont::detail
} // namespace vtkm::cont
} // namespace vtkm

@ -11,6 +11,7 @@
#define vtk_m_cont_CellSetExplicit_h
#include <vtkm/CellShape.h>
#include <vtkm/Deprecated.h>
#include <vtkm/TopologyElementTag.h>
#include <vtkm/cont/ArrayGetValues.h>
#include <vtkm/cont/ArrayHandleCast.h>
@ -18,6 +19,7 @@
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleOffsetsToNumComponents.h>
#include <vtkm/cont/CellSet.h>
#include <vtkm/cont/UnknownArrayHandle.h>
#include <vtkm/cont/internal/ConnectivityExplicitInternals.h>
#include <vtkm/exec/ConnectivityExplicit.h>
@ -37,6 +39,20 @@ struct CellSetExplicitConnectivityChooser
using ConnectivityType = vtkm::cont::internal::ConnectivityExplicitInternals<>;
};
// The connectivity generally used for the visit-points-with-cells connectivity.
// This type of connectivity does not have variable shape types, and since it is
// never really provided externally we can use the defaults for the other arrays.
using DefaultVisitPointsWithCellsConnectivityExplicit =
vtkm::cont::internal::ConnectivityExplicitInternals<
typename ArrayHandleConstant<vtkm::UInt8>::StorageTag>;
VTKM_CONT_EXPORT void BuildReverseConnectivity(
const vtkm::cont::UnknownArrayHandle& connections,
const vtkm::cont::UnknownArrayHandle& offsets,
vtkm::Id numberOfPoints,
vtkm::cont::detail::DefaultVisitPointsWithCellsConnectivityExplicit& visitPointsWithCells,
vtkm::cont::DeviceAdapterId device);
} // namespace detail
#ifndef VTKM_DEFAULT_SHAPES_STORAGE_TAG
@ -229,11 +245,22 @@ public:
protected:
VTKM_CONT void BuildConnectivity(vtkm::cont::DeviceAdapterId,
vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagPoint) const;
vtkm::TopologyElementTagPoint) const
{
VTKM_ASSERT(this->Data->CellPointIds.ElementsValid);
// no-op
}
VTKM_CONT void BuildConnectivity(vtkm::cont::DeviceAdapterId,
VTKM_CONT void BuildConnectivity(vtkm::cont::DeviceAdapterId device,
vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell) const;
vtkm::TopologyElementTagCell) const
{
detail::BuildReverseConnectivity(this->Data->CellPointIds.Connectivity,
this->Data->CellPointIds.Offsets,
this->Data->NumberOfPoints,
this->Data->PointCellIds,
device);
}
VTKM_CONT bool HasConnectivityImpl(vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagPoint) const
@ -336,8 +363,7 @@ struct CellSetExplicitConnectivityChooser<CellSetType,
{
//only specify the shape type as it will be constant as everything
//is a vertex. otherwise use the defaults.
using ConnectivityType = vtkm::cont::internal::ConnectivityExplicitInternals<
typename ArrayHandleConstant<vtkm::UInt8>::StorageTag>;
using ConnectivityType = vtkm::cont::detail::DefaultVisitPointsWithCellsConnectivityExplicit;
};
} // namespace detail

@ -9,14 +9,10 @@
//============================================================================
#ifndef vtk_m_cont_CellSetExplicit_hxx
#define vtk_m_cont_CellSetExplicit_hxx
#include <vtkm/Deprecated.h>
#include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayGetValues.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/TryExecute.h>
// This file uses a lot of very verbose identifiers and the clang formatted
// code quickly becomes unreadable. Stick with manual formatting for now.
@ -478,74 +474,6 @@ void CellSetExplicit<SST, CST, OST>::DeepCopy(const CellSet* src)
this->Fill(other->GetNumberOfPoints(), shapes, conn, offsets);
}
//----------------------------------------------------------------------------
namespace detail
{
template <typename CellPointIdsT, typename PointCellIdsT>
struct BuildPointCellIdsFunctor
{
BuildPointCellIdsFunctor(CellPointIdsT &cellPointIds,
PointCellIdsT &pointCellIds,
vtkm::Id numberOfPoints)
: CellPointIds(cellPointIds)
, PointCellIds(pointCellIds)
, NumberOfPoints(numberOfPoints)
{
}
template <typename Device>
bool operator()(Device) const
{
internal::ComputeRConnTable(this->PointCellIds,
this->CellPointIds,
this->NumberOfPoints,
Device{});
return true;
}
CellPointIdsT &CellPointIds;
PointCellIdsT &PointCellIds;
vtkm::Id NumberOfPoints;
};
} // detail
template <typename SST, typename CST, typename OST>
VTKM_CONT
void CellSetExplicit<SST, CST, OST>
::BuildConnectivity(vtkm::cont::DeviceAdapterId,
vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagPoint) const
{
VTKM_ASSERT(this->Data->CellPointIds.ElementsValid);
// no-op
}
template <typename SST, typename CST, typename OST>
VTKM_CONT
void CellSetExplicit<SST, CST, OST>
::BuildConnectivity(vtkm::cont::DeviceAdapterId device,
vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell) const
{
if (!this->Data->PointCellIds.ElementsValid)
{
auto self = const_cast<Thisclass*>(this);
using Func = detail::BuildPointCellIdsFunctor<CellPointIdsType, PointCellIdsType>;
auto functor = Func(self->Data->CellPointIds,
self->Data->PointCellIds,
self->Data->NumberOfPoints);
if (!vtkm::cont::TryExecuteOnDevice(device, functor))
{
throw vtkm::cont::ErrorExecution("Failed to run CellSetExplicit reverse "
"connectivity builder.");
}
}
}
}
} // vtkm::cont

@ -21,6 +21,7 @@
#include <vtkm/cont/Invoker.h>
#include <vtkm/cont/internal/ConnectivityExplicitInternals.h>
#include <vtkm/cont/internal/ConvertNumComponentsToOffsetsTemplate.h>
#include <vtkm/cont/internal/ReverseConnectivityBuilder.h>
#include <vtkm/internal/ConnectivityStructuredInternals.h>
#include <vtkm/worklet/WorkletMapTopology.h>

@ -11,14 +11,10 @@
#define vtk_m_cont_internal_ConnectivityExplicitInternals_h
#include <vtkm/CellShape.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayGetValues.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/internal/ReverseConnectivityBuilder.h>
#include <vtkm/exec/ExecutionWholeArray.h>
namespace vtkm
{
@ -82,151 +78,6 @@ struct ConnectivityExplicitInternals
}
}
};
// Pass through (needed for ReverseConnectivityBuilder)
struct PassThrough
{
VTKM_EXEC vtkm::Id operator()(const vtkm::Id& val) const { return val; }
};
// Compute cell id from input connectivity:
// Find the upper bound of the conn idx in the offsets table and subtract 1
//
// Example:
// Offsets: | 0 | 3 | 6 | 10 |
// Conn: | 0 1 2 | 0 1 3 | 2 4 5 6 | 1 3 5 |
// ConnIdx: | 0 1 2 | 3 4 5 | 6 7 8 9 | 10 11 12 |
// UpprBnd: | 1 1 1 | 2 2 2 | 3 3 3 3 | 4 4 4 |
// CellIdx: | 0 0 0 | 1 1 1 | 2 2 2 2 | 3 3 3 |
template <typename OffsetsPortalType>
struct ConnIdxToCellIdCalc
{
OffsetsPortalType Offsets;
VTKM_CONT
ConnIdxToCellIdCalc(const OffsetsPortalType& offsets)
: Offsets(offsets)
{
}
VTKM_EXEC
vtkm::Id operator()(vtkm::Id inIdx) const
{
// Compute the upper bound index:
vtkm::Id upperBoundIdx;
{
vtkm::Id first = 0;
vtkm::Id length = this->Offsets.GetNumberOfValues();
while (length > 0)
{
vtkm::Id halfway = length / 2;
vtkm::Id pos = first + halfway;
vtkm::Id val = this->Offsets.Get(pos);
if (val <= inIdx)
{
first = pos + 1;
length -= halfway + 1;
}
else
{
length = halfway;
}
}
upperBoundIdx = first;
}
return upperBoundIdx - 1;
}
};
// Much easier for CellSetSingleType:
struct ConnIdxToCellIdCalcSingleType
{
vtkm::IdComponent CellSize;
VTKM_CONT
ConnIdxToCellIdCalcSingleType(vtkm::IdComponent cellSize)
: CellSize(cellSize)
{
}
VTKM_EXEC
vtkm::Id operator()(vtkm::Id inIdx) const { return inIdx / this->CellSize; }
};
template <typename ConnTableT, typename RConnTableT>
void ComputeRConnTable(RConnTableT& rConnTable,
const ConnTableT& connTable,
vtkm::Id numberOfPoints,
vtkm::cont::DeviceAdapterId device)
{
if (rConnTable.ElementsValid)
{
return;
}
const auto& conn = connTable.Connectivity;
auto& rConn = rConnTable.Connectivity;
auto& rOffsets = rConnTable.Offsets;
const vtkm::Id rConnSize = conn.GetNumberOfValues();
{
vtkm::cont::Token token;
const auto offInPortal = connTable.Offsets.PrepareForInput(device, token);
PassThrough idxCalc{};
ConnIdxToCellIdCalc<decltype(offInPortal)> cellIdCalc{ offInPortal };
vtkm::cont::internal::ReverseConnectivityBuilder builder;
builder.Run(conn, rConn, rOffsets, idxCalc, cellIdCalc, numberOfPoints, rConnSize, device);
}
rConnTable.Shapes = vtkm::cont::make_ArrayHandleConstant(
static_cast<vtkm::UInt8>(CELL_SHAPE_VERTEX), numberOfPoints);
rConnTable.ElementsValid = true;
}
// Specialize for CellSetSingleType:
template <typename RConnTableT, typename ConnectivityStorageTag>
void ComputeRConnTable(RConnTableT& rConnTable,
const ConnectivityExplicitInternals< // SingleType specialization types:
typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag,
ConnectivityStorageTag,
typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag>& connTable,
vtkm::Id numberOfPoints,
vtkm::cont::DeviceAdapterId device)
{
if (rConnTable.ElementsValid)
{
return;
}
const auto& conn = connTable.Connectivity;
auto& rConn = rConnTable.Connectivity;
auto& rOffsets = rConnTable.Offsets;
const vtkm::Id rConnSize = conn.GetNumberOfValues();
const vtkm::IdComponent cellSize = [&]() -> vtkm::IdComponent {
if (connTable.Offsets.GetNumberOfValues() >= 2)
{
const auto firstTwo = vtkm::cont::ArrayGetValues({ 0, 1 }, connTable.Offsets);
return static_cast<vtkm::IdComponent>(firstTwo[1] - firstTwo[0]);
}
return 0;
}();
PassThrough idxCalc{};
ConnIdxToCellIdCalcSingleType cellIdCalc{ cellSize };
vtkm::cont::internal::ReverseConnectivityBuilder builder;
builder.Run(conn, rConn, rOffsets, idxCalc, cellIdCalc, numberOfPoints, rConnSize, device);
rConnTable.Shapes = vtkm::cont::make_ArrayHandleConstant(
static_cast<vtkm::UInt8>(CELL_SHAPE_VERTEX), numberOfPoints);
rConnTable.ElementsValid = true;
}
}
}
} // namespace vtkm::cont::internal

@ -14,6 +14,7 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/AtomicArray.h>
#include <vtkm/exec/FunctorBase.h>
@ -211,6 +212,152 @@ public:
}
}
};
// Pass through (needed for ReverseConnectivityBuilder)
struct PassThrough
{
VTKM_EXEC vtkm::Id operator()(const vtkm::Id& val) const { return val; }
};
// Compute cell id from input connectivity:
// Find the upper bound of the conn idx in the offsets table and subtract 1
//
// Example:
// Offsets: | 0 | 3 | 6 | 10 |
// Conn: | 0 1 2 | 0 1 3 | 2 4 5 6 | 1 3 5 |
// ConnIdx: | 0 1 2 | 3 4 5 | 6 7 8 9 | 10 11 12 |
// UpprBnd: | 1 1 1 | 2 2 2 | 3 3 3 3 | 4 4 4 |
// CellIdx: | 0 0 0 | 1 1 1 | 2 2 2 2 | 3 3 3 |
template <typename OffsetsPortalType>
struct ConnIdxToCellIdCalc
{
OffsetsPortalType Offsets;
VTKM_CONT
ConnIdxToCellIdCalc(const OffsetsPortalType& offsets)
: Offsets(offsets)
{
}
VTKM_EXEC
vtkm::Id operator()(vtkm::Id inIdx) const
{
// Compute the upper bound index:
vtkm::Id upperBoundIdx;
{
vtkm::Id first = 0;
vtkm::Id length = this->Offsets.GetNumberOfValues();
while (length > 0)
{
vtkm::Id halfway = length / 2;
vtkm::Id pos = first + halfway;
vtkm::Id val = this->Offsets.Get(pos);
if (val <= inIdx)
{
first = pos + 1;
length -= halfway + 1;
}
else
{
length = halfway;
}
}
upperBoundIdx = first;
}
return upperBoundIdx - 1;
}
};
// Much easier for CellSetSingleType:
struct ConnIdxToCellIdCalcSingleType
{
vtkm::IdComponent CellSize;
VTKM_CONT
ConnIdxToCellIdCalcSingleType(vtkm::IdComponent cellSize)
: CellSize(cellSize)
{
}
VTKM_EXEC
vtkm::Id operator()(vtkm::Id inIdx) const { return inIdx / this->CellSize; }
};
template <typename ConnTableT, typename RConnTableT>
void ComputeRConnTable(RConnTableT& rConnTable,
const ConnTableT& connTable,
vtkm::Id numberOfPoints,
vtkm::cont::DeviceAdapterId device)
{
if (rConnTable.ElementsValid)
{
return;
}
const auto& conn = connTable.Connectivity;
auto& rConn = rConnTable.Connectivity;
auto& rOffsets = rConnTable.Offsets;
const vtkm::Id rConnSize = conn.GetNumberOfValues();
{
vtkm::cont::Token token;
const auto offInPortal = connTable.Offsets.PrepareForInput(device, token);
PassThrough idxCalc{};
ConnIdxToCellIdCalc<decltype(offInPortal)> cellIdCalc{ offInPortal };
vtkm::cont::internal::ReverseConnectivityBuilder builder;
builder.Run(conn, rConn, rOffsets, idxCalc, cellIdCalc, numberOfPoints, rConnSize, device);
}
rConnTable.Shapes = vtkm::cont::make_ArrayHandleConstant(
static_cast<vtkm::UInt8>(CELL_SHAPE_VERTEX), numberOfPoints);
rConnTable.ElementsValid = true;
}
// Specialize for CellSetSingleType:
template <typename RConnTableT, typename ConnectivityStorageTag>
void ComputeRConnTable(RConnTableT& rConnTable,
const ConnectivityExplicitInternals< // SingleType specialization types:
typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag,
ConnectivityStorageTag,
typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag>& connTable,
vtkm::Id numberOfPoints,
vtkm::cont::DeviceAdapterId device)
{
if (rConnTable.ElementsValid)
{
return;
}
const auto& conn = connTable.Connectivity;
auto& rConn = rConnTable.Connectivity;
auto& rOffsets = rConnTable.Offsets;
const vtkm::Id rConnSize = conn.GetNumberOfValues();
const vtkm::IdComponent cellSize = [&]() -> vtkm::IdComponent {
if (connTable.Offsets.GetNumberOfValues() >= 2)
{
const auto firstTwo = vtkm::cont::ArrayGetValues({ 0, 1 }, connTable.Offsets);
return static_cast<vtkm::IdComponent>(firstTwo[1] - firstTwo[0]);
}
return 0;
}();
PassThrough idxCalc{};
ConnIdxToCellIdCalcSingleType cellIdCalc{ cellSize };
vtkm::cont::internal::ReverseConnectivityBuilder builder;
builder.Run(conn, rConn, rOffsets, idxCalc, cellIdCalc, numberOfPoints, rConnSize, device);
rConnTable.Shapes = vtkm::cont::make_ArrayHandleConstant(
static_cast<vtkm::UInt8>(CELL_SHAPE_VERTEX), numberOfPoints);
rConnTable.ElementsValid = true;
}
}
}
} // end namespace vtkm::cont::internal